diff --git a/docs/Design.odt b/docs/Design.odt new file mode 100644 index 0000000..840acbf Binary files /dev/null and b/docs/Design.odt differ diff --git a/pglab/CodeEditor.cpp b/pglab/CodeEditor.cpp new file mode 100644 index 0000000..6c8c44d --- /dev/null +++ b/pglab/CodeEditor.cpp @@ -0,0 +1,112 @@ +#include "CodeEditor.h" +#include "EditorGutter.h" +#include +#include +// +// 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 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; + } +} diff --git a/pglab/CodeEditor.h b/pglab/CodeEditor.h new file mode 100644 index 0000000..f2a86d4 --- /dev/null +++ b/pglab/CodeEditor.h @@ -0,0 +1,31 @@ +#ifndef CODEEDITOR_H +#define CODEEDITOR_H + +#include + +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 diff --git a/pglab/EditorGutter.cpp b/pglab/EditorGutter.cpp new file mode 100644 index 0000000..7b98180 --- /dev/null +++ b/pglab/EditorGutter.cpp @@ -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); +} diff --git a/pglab/EditorGutter.h b/pglab/EditorGutter.h new file mode 100644 index 0000000..2050a37 --- /dev/null +++ b/pglab/EditorGutter.h @@ -0,0 +1,28 @@ +#ifndef EDITORGUTTER_H +#define EDITORGUTTER_H + +#include +//#include + +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 diff --git a/pglab/Module.cpp b/pglab/Module.cpp new file mode 100644 index 0000000..66ff01e --- /dev/null +++ b/pglab/Module.cpp @@ -0,0 +1,8 @@ +#include "Module.h" + +using namespace Leon; + +Module::Module() +{ + +} diff --git a/pglab/Module.h b/pglab/Module.h new file mode 100644 index 0000000..62065c7 --- /dev/null +++ b/pglab/Module.h @@ -0,0 +1,15 @@ +#ifndef MODULE_H +#define MODULE_H + +namespace Leon { + +class Module +{ +public: + Module(); + +}; + +} + +#endif // MODULE_H diff --git a/pglab/PglPage.cpp b/pglab/PglPage.cpp new file mode 100644 index 0000000..a42347d --- /dev/null +++ b/pglab/PglPage.cpp @@ -0,0 +1,6 @@ +#include "PglPage.h" + +//PglPage::PglPage() +//{ + +//} diff --git a/pglab/PglPage.h b/pglab/PglPage.h new file mode 100644 index 0000000..8e7438d --- /dev/null +++ b/pglab/PglPage.h @@ -0,0 +1,24 @@ +#ifndef PGLPAGE_H +#define PGLPAGE_H + +#include + +/// 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 diff --git a/pglab/QueryTab.cpp b/pglab/QueryTab.cpp index 3ec0828..1e1c378 100644 --- a/pglab/QueryTab.cpp +++ b/pglab/QueryTab.cpp @@ -22,7 +22,7 @@ #include "GlobalIoService.h" QueryTab::QueryTab(MainWindow *win, QWidget *parent) : - QWidget(parent), + PglPage(parent), ui(new Ui::QueryTab), m_win(win), m_dbConnection(*getGlobalAsioIoService()) diff --git a/pglab/QueryTab.h b/pglab/QueryTab.h index 73175d2..89bf7ff 100644 --- a/pglab/QueryTab.h +++ b/pglab/QueryTab.h @@ -8,6 +8,7 @@ #include "tuplesresultwidget.h" #include +#include "PglPage.h" #include namespace Ui { @@ -27,7 +28,7 @@ class OpenDatabase; class QueryParamListController; class PgDatabaseCatalog; -class QueryTab : public QWidget { +class QueryTab : public PglPage { Q_OBJECT public: QueryTab(MainWindow *win, QWidget *parent = nullptr); diff --git a/pglab/QueryTab.ui b/pglab/QueryTab.ui index ccac5ac..7d5ef68 100644 --- a/pglab/QueryTab.ui +++ b/pglab/QueryTab.ui @@ -23,7 +23,7 @@ Qt::Horizontal - + QFrame::StyledPanel @@ -213,6 +213,13 @@ + + + CodeEditor + QPlainTextEdit +
CodeEditor.h
+
+
diff --git a/pglab/pglab.pro b/pglab/pglab.pro index 8ff3b7d..1fac959 100644 --- a/pglab/pglab.pro +++ b/pglab/pglab.pro @@ -69,7 +69,11 @@ SOURCES += main.cpp\ IndexModel.cpp \ CrudTab.cpp \ CrudModel.cpp \ - PgLabItemDelegate.cpp + PgLabItemDelegate.cpp \ + Module.cpp \ + PglPage.cpp \ + EditorGutter.cpp \ + CodeEditor.cpp HEADERS += \ QueryResultModel.h \ @@ -110,7 +114,11 @@ HEADERS += \ IndexModel.h \ CrudTab.h \ CrudModel.h \ - PgLabItemDelegate.h + PgLabItemDelegate.h \ + Module.h \ + PglPage.h \ + EditorGutter.h \ + CodeEditor.h FORMS += mainwindow.ui \ ConnectionManagerWindow.ui \ diff --git a/pgsql/SqlGenerator.h b/pgsql/SqlGenerator.h new file mode 100644 index 0000000..f876ece --- /dev/null +++ b/pgsql/SqlGenerator.h @@ -0,0 +1,15 @@ +#ifndef SQLGENERATOR_H +#define SQLGENERATOR_H + +#include "Pgsql_Params.h" + +//namespace Pgsql { + +//template +//class AndCondition { +// AndCondition& add(const std::string &expr,) +//}; + +} // end of namespace Pgsql + +#endif // SQLGENERATOR_H diff --git a/pgsql/pgsql.pro b/pgsql/pgsql.pro index df08956..da88da9 100644 --- a/pgsql/pgsql.pro +++ b/pgsql/pgsql.pro @@ -51,7 +51,8 @@ HEADERS += Pgsql_Connection.h \ Pgsql_declare.h \ Pgsql_Col.h \ ArrayParser.h \ - Pgsql_oids.h + Pgsql_oids.h \ + SqlGenerator.h #FORMS +=