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:
parent
5e83094e6a
commit
47ee1857cd
15 changed files with 281 additions and 6 deletions
BIN
docs/Design.odt
Normal file
BIN
docs/Design.odt
Normal file
Binary file not shown.
112
pglab/CodeEditor.cpp
Normal file
112
pglab/CodeEditor.cpp
Normal 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
31
pglab/CodeEditor.h
Normal 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
19
pglab/EditorGutter.cpp
Normal 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
28
pglab/EditorGutter.h
Normal 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
8
pglab/Module.cpp
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "Module.h"
|
||||||
|
|
||||||
|
using namespace Leon;
|
||||||
|
|
||||||
|
Module::Module()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
15
pglab/Module.h
Normal file
15
pglab/Module.h
Normal 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
6
pglab/PglPage.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "PglPage.h"
|
||||||
|
|
||||||
|
//PglPage::PglPage()
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
24
pglab/PglPage.h
Normal file
24
pglab/PglPage.h
Normal 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
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
15
pgsql/SqlGenerator.h
Normal 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
|
||||||
|
|
@ -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 +=
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue