Added a gutter and currentline highlighting to the SQL editor.

Currently gutter only shows linenumbers. Code is mostly from http://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html

There is a little bit included in this commit from a first try to make toobars adept to the current tab.

Code #2
This commit is contained in:
eelke 2018-04-08 09:07:43 +02:00
parent 5e83094e6a
commit 47ee1857cd
15 changed files with 281 additions and 6 deletions

BIN
docs/Design.odt Normal file

Binary file not shown.

112
pglab/CodeEditor.cpp Normal file
View file

@ -0,0 +1,112 @@
#include "CodeEditor.h"
#include "EditorGutter.h"
#include <QPainter>
#include <QTextBlock>
//
// Adapted from codeeditor example
// http://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html
//
// Used term gutter as I want to expand it to do other things to like error
// position marking.
//
CodeEditor::CodeEditor(QWidget *parent)
: QPlainTextEdit(parent)
, gutterArea(new EditorGutter(this))
{
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateGutterAreaWidth(int)));
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateGutterArea(QRect,int)));
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
updateGutterAreaWidth(0);
highlightCurrentLine();
}
int CodeEditor::gutterAreaWidth()
{
int digits = 1;
int max = qMax(1, blockCount());
while (max >= 10) {
max /= 10;
++digits;
}
int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
return space;
}
void CodeEditor::updateGutterAreaWidth(int /* newBlockCount */)
{
setViewportMargins(gutterAreaWidth(), 0, 0, 0);
}
void CodeEditor::updateGutterArea(const QRect &rect, int dy)
{
if (dy)
gutterArea->scroll(0, dy);
else
gutterArea->update(0, rect.y(), gutterArea->width(), rect.height());
if (rect.contains(viewport()->rect()))
updateGutterAreaWidth(0);
}
void CodeEditor::resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);
QRect cr = contentsRect();
gutterArea->setGeometry(QRect(cr.left(), cr.top(), gutterAreaWidth(), cr.height()));
}
void CodeEditor::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;
if (!isReadOnly()) {
QTextEdit::ExtraSelection selection;
QColor lineColor = QColor(Qt::yellow).lighter(160);
selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = textCursor();
selection.cursor.clearSelection();
extraSelections.append(selection);
}
setExtraSelections(extraSelections);
}
void CodeEditor::gutterAreaPaintEvent(QPaintEvent *event)
{
QPainter painter(gutterArea);
painter.fillRect(event->rect(), Qt::lightGray);
QTextBlock block = firstVisibleBlock();
int blockNumber = block.blockNumber();
int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top + (int) blockBoundingRect(block).height();
// We will now loop through all visible lines and paint the line numbers in the
// extra area for each line. Notice that in a plain text edit each line will
// consist of one QTextBlock; though, if line wrapping is enabled, a line may span
// several rows in the text edit's viewport.
//
// We get the top and bottom y-coordinate of the first text block, and adjust these
// values by the height of the current text block in each iteration in the loop.
while (block.isValid() && top <= event->rect().bottom()) {
if (block.isVisible() && bottom >= event->rect().top()) {
QString number = QString::number(blockNumber + 1);
painter.setPen(Qt::black);
painter.drawText(0, top, gutterArea->width(), fontMetrics().height(),
Qt::AlignRight, number);
}
block = block.next();
top = bottom;
bottom = top + (int) blockBoundingRect(block).height();
++blockNumber;
}
}

31
pglab/CodeEditor.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef CODEEDITOR_H
#define CODEEDITOR_H
#include <QPlainTextEdit>
class CodeEditor : public QPlainTextEdit
{
Q_OBJECT
public:
explicit CodeEditor(QWidget *parent = nullptr);
void gutterAreaPaintEvent(QPaintEvent *event);
int gutterAreaWidth();
protected:
void resizeEvent(QResizeEvent *event) override;
signals:
public slots:
private slots:
void updateGutterAreaWidth(int newBlockCount);
void highlightCurrentLine();
void updateGutterArea(const QRect &, int);
private:
QWidget *gutterArea;
};
#endif // CODEEDITOR_H

19
pglab/EditorGutter.cpp Normal file
View file

@ -0,0 +1,19 @@
#include "EditorGutter.h"
#include "CodeEditor.h"
EditorGutter::EditorGutter(CodeEditor *editor)
: QWidget(editor)
, codeEditor(editor)
{
}
QSize EditorGutter::sizeHint() const
{
return QSize(codeEditor->gutterAreaWidth(), 0);
}
void EditorGutter::paintEvent(QPaintEvent *event)
{
codeEditor->gutterAreaPaintEvent(event);
}

28
pglab/EditorGutter.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef EDITORGUTTER_H
#define EDITORGUTTER_H
#include <QWidget>
//#include <QPlainTextEdit>
class CodeEditor;
class EditorGutter : public QWidget
{
Q_OBJECT
public:
explicit EditorGutter(CodeEditor *editor);
QSize sizeHint() const override;
protected:
void paintEvent(QPaintEvent *event) override;
private:
CodeEditor *codeEditor;
signals:
public slots:
};
#endif // EDITORGUTTER_H

8
pglab/Module.cpp Normal file
View file

@ -0,0 +1,8 @@
#include "Module.h"
using namespace Leon;
Module::Module()
{
}

15
pglab/Module.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef MODULE_H
#define MODULE_H
namespace Leon {
class Module
{
public:
Module();
};
}
#endif // MODULE_H

6
pglab/PglPage.cpp Normal file
View file

@ -0,0 +1,6 @@
#include "PglPage.h"
//PglPage::PglPage()
//{
//}

24
pglab/PglPage.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef PGLPAGE_H
#define PGLPAGE_H
#include <QWidget>
/// Provides a pluggable system for toolbar buttons and menu actions
///
/// We will need several kind of actions
/// - create actions, these will create a new document or load from file , always available in menu
/// - save actions available when on tab
/// - edit actions
/// - custom menu?
///
/// Can we use same groupings for toolbars and menu's
/// How about additional toolbars?
///
class PglPage: public QWidget{
public:
using QWidget::QWidget;
};
#endif // PGLPAGE_H

View file

@ -22,7 +22,7 @@
#include "GlobalIoService.h" #include "GlobalIoService.h"
QueryTab::QueryTab(MainWindow *win, QWidget *parent) : QueryTab::QueryTab(MainWindow *win, QWidget *parent) :
QWidget(parent), PglPage(parent),
ui(new Ui::QueryTab), ui(new Ui::QueryTab),
m_win(win), m_win(win),
m_dbConnection(*getGlobalAsioIoService()) m_dbConnection(*getGlobalAsioIoService())

View file

@ -8,6 +8,7 @@
#include "tuplesresultwidget.h" #include "tuplesresultwidget.h"
#include <QWidget> #include <QWidget>
#include "PglPage.h"
#include <memory> #include <memory>
namespace Ui { namespace Ui {
@ -27,7 +28,7 @@ class OpenDatabase;
class QueryParamListController; class QueryParamListController;
class PgDatabaseCatalog; class PgDatabaseCatalog;
class QueryTab : public QWidget { class QueryTab : public PglPage {
Q_OBJECT Q_OBJECT
public: public:
QueryTab(MainWindow *win, QWidget *parent = nullptr); QueryTab(MainWindow *win, QWidget *parent = nullptr);

View file

@ -23,7 +23,7 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QPlainTextEdit" name="queryEdit"/> <widget class="CodeEditor" name="queryEdit"/>
<widget class="QFrame" name="frameParams"> <widget class="QFrame" name="frameParams">
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::StyledPanel</enum>
@ -213,6 +213,13 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>CodeEditor</class>
<extends>QPlainTextEdit</extends>
<header>CodeEditor.h</header>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>

View file

@ -69,7 +69,11 @@ SOURCES += main.cpp\
IndexModel.cpp \ IndexModel.cpp \
CrudTab.cpp \ CrudTab.cpp \
CrudModel.cpp \ CrudModel.cpp \
PgLabItemDelegate.cpp PgLabItemDelegate.cpp \
Module.cpp \
PglPage.cpp \
EditorGutter.cpp \
CodeEditor.cpp
HEADERS += \ HEADERS += \
QueryResultModel.h \ QueryResultModel.h \
@ -110,7 +114,11 @@ HEADERS += \
IndexModel.h \ IndexModel.h \
CrudTab.h \ CrudTab.h \
CrudModel.h \ CrudModel.h \
PgLabItemDelegate.h PgLabItemDelegate.h \
Module.h \
PglPage.h \
EditorGutter.h \
CodeEditor.h
FORMS += mainwindow.ui \ FORMS += mainwindow.ui \
ConnectionManagerWindow.ui \ ConnectionManagerWindow.ui \

15
pgsql/SqlGenerator.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef SQLGENERATOR_H
#define SQLGENERATOR_H
#include "Pgsql_Params.h"
//namespace Pgsql {
//template <typename >
//class AndCondition {
// AndCondition& add(const std::string &expr,)
//};
} // end of namespace Pgsql
#endif // SQLGENERATOR_H

View file

@ -51,7 +51,8 @@ HEADERS += Pgsql_Connection.h \
Pgsql_declare.h \ Pgsql_declare.h \
Pgsql_Col.h \ Pgsql_Col.h \
ArrayParser.h \ ArrayParser.h \
Pgsql_oids.h Pgsql_oids.h \
SqlGenerator.h
#FORMS += #FORMS +=