Made a step in removing knowledge of DatabaseWindow from QueryTab as an effort to move

in the direction of a plugin system.

DatabaseWindow now passes a Context to QueryTab and other pages that give those pages an
API for passing information up the system without knowing anything about the sytem.
This commit is contained in:
eelke 2018-12-29 18:59:54 +01:00
parent f6ea2ce0a6
commit 2a7e505dbf
13 changed files with 220 additions and 113 deletions

View file

@ -5,8 +5,8 @@
#include "UserConfiguration.h"
#include <QTextStream>
CodeGenerator::CodeGenerator(QWidget *parent) :
PlgPage(parent),
CodeGenerator::CodeGenerator(IPluginContentWidgetContext *context, QWidget *parent) :
PluginContentWidget(context, parent),
ui(new Ui::CodeGenerator)
{
ui->setupUi(this);

View file

@ -2,7 +2,7 @@
#define CODEGENERATOR_H
#include <QWidget>
#include "PlgPage.h"
#include "PluginContentWidget.h"
#include "Pgsql_declare.h"
namespace Ui {
@ -11,12 +11,12 @@ class CodeGenerator;
class PgDatabaseCatalog;
class CodeGenerator : public PlgPage
class CodeGenerator : public PluginContentWidget
{
Q_OBJECT
public:
explicit CodeGenerator(QWidget *parent = nullptr);
CodeGenerator(IPluginContentWidgetContext *context, QWidget *parent = nullptr);
~CodeGenerator();
void Init(std::shared_ptr<PgDatabaseCatalog> catalog, QString query, std::shared_ptr<const Pgsql::Result> dbres);

View file

@ -12,8 +12,8 @@
#include <set>
CrudTab::CrudTab(DatabaseWindow *parent)
: PlgPage(parent)
CrudTab::CrudTab(IPluginContentWidgetContext *context, DatabaseWindow *parent)
: PluginContentWidget(context, parent)
, ui(new Ui::CrudTab)
, m_window(parent)
{

View file

@ -3,7 +3,7 @@
#include "catalog/PgClass.h"
#include <QWidget>
#include "PlgPage.h"
#include "PluginContentWidget.h"
#include <memory>
#include <optional>
@ -15,12 +15,12 @@ class OpenDatabase;
class CrudModel;
class DatabaseWindow;
class CrudTab : public PlgPage
class CrudTab : public PluginContentWidget
{
Q_OBJECT
public:
explicit CrudTab(DatabaseWindow *parent = 0);
explicit CrudTab(IPluginContentWidgetContext *context, DatabaseWindow *parent = 0);
~CrudTab() override;
void setConfig(std::shared_ptr<OpenDatabase> db, const PgClass &table);

View file

@ -15,20 +15,61 @@
#include <QMetaMethod>
#include "QueryTab.h"
#include "util.h"
#include "PlgPage.h"
#include "PluginContentWidget.h"
#include "CodeGenerator.h"
#include "MasterController.h"
#include "CrudTab.h"
#include "WorkManager.h"
#include "ScopeGuard.h"
#include "EditTableWidget.h"
#include "IPluginContentWidgetContext.h"
namespace pg = Pgsql;
namespace DatabaseWindow_details {
class DatabaseWindowContentContext: public IPluginContentWidgetContext {
public:
explicit DatabaseWindowContentContext(DatabaseWindow *window)
: m_window(window)
{}
void setCaption(PluginContentWidget *content, const QString &caption, const QString &hint = {}) override
{
m_window->setTabCaptionForWidget(content, caption, hint);
}
void setIcon(PluginContentWidget *content, const QString &iconname) override
{
m_window->setTabIcon(content, iconname);
}
std::shared_ptr<OpenDatabase> getDatabase() override
{
return m_window->getDatabase();
}
void QueueTask(TSQueue::t_Callable c) override
{
m_window->QueueTask(c);
}
void showStatusMessage(const QString &msg) override
{
m_window->statusBar()->showMessage(msg);
}
private:
DatabaseWindow *m_window;
};
}
using namespace DatabaseWindow_details;
DatabaseWindow::DatabaseWindow(MasterController *master, QWidget *parent)
: ASyncWindow(parent)
, ui(new Ui::MainWindow)
, m_context(new DatabaseWindowContentContext(this))
, m_masterController(master)
{
ui->setupUi(this);
@ -38,12 +79,13 @@ DatabaseWindow::DatabaseWindow(MasterController *master, QWidget *parent)
DatabaseWindow::~DatabaseWindow()
{
loader.reset();
delete m_context;
delete ui;
}
QueryTab* DatabaseWindow::newSqlPage()
{
QueryTab *qt = new QueryTab(this);
QueryTab *qt = new QueryTab(m_context);
qt->setConfig(m_config, m_database->catalog());
addPage(qt, "Tab");
qt->newdoc();
@ -59,14 +101,14 @@ void DatabaseWindow::newCreateTablePage()
void DatabaseWindow::newCrudPage(const PgClass &table)
{
CrudTab *ct = new CrudTab(this);
CrudTab *ct = new CrudTab(m_context, this);
ct->setConfig(m_database, table);
addPage(ct, table.objectName());
}
void DatabaseWindow::newCodeGenPage(QString query, std::shared_ptr<const Pgsql::Result> dbres)
{
auto cgtab = new CodeGenerator(this);
auto cgtab = new CodeGenerator(m_context, this);
cgtab->Init(m_database->catalog(), query, dbres);
addPage(cgtab, "Codegen");
}
@ -195,13 +237,13 @@ void DatabaseWindow::on_actionClose_triggered()
void DatabaseWindow::on_actionAbout_triggered()
{
QMessageBox::about(this, "pgLab 0.1", tr(
"Copyrights 2016-2017, Eelke Klein, All Rights Reserved.\n"
"Copyrights 2016-2018, Eelke Klein, All Rights Reserved.\n"
"\n"
"The program is provided AS IS with NO WARRANTY OF ANY KIND, "
"INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS "
"FOR A PARTICULAR PURPOSE.\n"
"\n"
"This program is dynamically linked with Qt 5.9 Copyright (C) 2017 "
"This program is dynamically linked with Qt 5.12 Copyright (C) 2018 "
"The Qt Company Ltd. https://www.qt.io/licensing/. \n"
"\n"
"Icons by fatcow http://www.fatcow.com/free-icons provided under Creative Commons "
@ -259,7 +301,7 @@ void DatabaseWindow::on_actionNew_SQL_triggered()
void DatabaseWindow::on_tabWidget_tabCloseRequested(int index)
{
QWidget *widget = ui->tabWidget->widget(index);
PlgPage *plg_page = dynamic_cast<PlgPage*>(widget);
PluginContentWidget *plg_page = dynamic_cast<PluginContentWidget*>(widget);
if (plg_page) {
if (plg_page->canClose()) {
removePage(plg_page);
@ -325,7 +367,7 @@ void DatabaseWindow::on_actionCopy_as_raw_Cpp_string_triggered()
}
}
void DatabaseWindow::addToolBarButtonsForPage(PlgPage *page)
void DatabaseWindow::addToolBarButtonsForPage(PluginContentWidget *page)
{
std::vector<QAction*> actions = page->getToolbarActions();
QList<QAction*> list;
@ -335,7 +377,7 @@ void DatabaseWindow::addToolBarButtonsForPage(PlgPage *page)
ui->mainToolBar->addActions(list);
}
void DatabaseWindow::removeToolBarButtonsForPage(PlgPage *page)
void DatabaseWindow::removeToolBarButtonsForPage(PluginContentWidget *page)
{
std::vector<QAction*> actions = page->getToolbarActions();
for (auto act : actions) {
@ -344,7 +386,7 @@ void DatabaseWindow::removeToolBarButtonsForPage(PlgPage *page)
}
void DatabaseWindow::addPage(PlgPage* page, QString caption)
void DatabaseWindow::addPage(PluginContentWidget* page, QString caption)
{
ui->tabWidget->addTab(page, caption);
ui->tabWidget->setCurrentWidget(page);
@ -352,7 +394,7 @@ void DatabaseWindow::addPage(PlgPage* page, QString caption)
//addToolBarButtonsForPage(page);
}
void DatabaseWindow::removePage(PlgPage *)
void DatabaseWindow::removePage(PluginContentWidget *)
{
}
@ -365,10 +407,10 @@ void DatabaseWindow::on_tabWidget_currentChanged(int index)
}
// add buttons of new page
PlgPage * page = nullptr;
PluginContentWidget * page = nullptr;
if (index >= 0) {
QWidget *widget = ui->tabWidget->widget(index);
page = dynamic_cast<PlgPage*>(widget);
page = dynamic_cast<PluginContentWidget*>(widget);
if (page) {
addToolBarButtonsForPage(page);
}
@ -384,3 +426,17 @@ void DatabaseWindow::on_actionGenerate_code_triggered()
}
}
void DatabaseWindow::setTabCaptionForWidget(QWidget *widget, const QString &caption, const QString &hint)
{
auto index = ui->tabWidget->indexOf(widget);
ui->tabWidget->setTabText(index, caption);
ui->tabWidget->setTabToolTip(index, hint);
}
void DatabaseWindow::setTabIcon(QWidget *widget, const QString &iconname)
{
auto index = ui->tabWidget->indexOf(widget);
auto n = ":/icons/16x16/" + iconname;
ui->tabWidget->setTabIcon(index, QIcon(n));
}

View file

@ -33,7 +33,11 @@ class MasterController;
class QCloseEvent;
class OpenDatabase;
class PgClass;
class PlgPage;
class PluginContentWidget;
namespace DatabaseWindow_details {
class DatabaseWindowContentContext;
}
/** This is the class for windows that handle tasks for a specific database/catalog
*
@ -51,15 +55,18 @@ public:
void newCrudPage(const PgClass &table);
void newCodeGenPage(QString query, std::shared_ptr<const Pgsql::Result> dbres);
void setTabCaptionForWidget(QWidget *widget, const QString &caption, const QString &hint);
void setTabIcon(QWidget *widget, const QString &iconname);
private:
Ui::MainWindow *ui;
DatabaseWindow_details::DatabaseWindowContentContext *m_context;
ConnectionConfig m_config;
std::shared_ptr<OpenDatabase> m_database;
MasterController *m_masterController;
PlgPage *m_previousPage = nullptr; ///< tracks which pages buttons were previously being displayed
PluginContentWidget *m_previousPage = nullptr; ///< tracks which pages buttons were previously being displayed
class QLoad : public QueuedBackgroundTask {
public:
@ -99,12 +106,12 @@ private:
void catalogLoaded();
/// Called when a newly created page is added to the QTabWidget
void addPage(PlgPage* page, QString caption);
void addPage(PluginContentWidget* page, QString caption);
/// Called when a page is completely removed from the QTabWidget
void removePage(PlgPage *page);
void removePage(PluginContentWidget *page);
void addToolBarButtonsForPage(PlgPage *page);
void removeToolBarButtonsForPage(PlgPage *page);
void addToolBarButtonsForPage(PluginContentWidget *page);
void removeToolBarButtonsForPage(PluginContentWidget *page);
//class PageData
private slots:

View file

@ -0,0 +1,44 @@
#ifndef IPLUGINCONTENTWIDGETCONTEXT_H
#define IPLUGINCONTENTWIDGETCONTEXT_H
#include <QString>
#include <memory>
#include "tsqueue.h"
class OpenDatabase;
class PluginContentWidget;
/** This class serves to isolate the plugin from the actual construct in which it is
* used.
*
* It provides functions for operating on the context without needing to many details.
*/
class IPluginContentWidgetContext {
public:
virtual ~IPluginContentWidgetContext() = default;
/** Tells the context what to use as a caption for this content widget.
*
* Depending on the context the caption might not be visible or used as the caption
* of a window or tab.
*/
virtual void setCaption(PluginContentWidget *content, const QString &caption, const QString &hint = {}) = 0;
/** Tells the context what icon to use.
*
* In general the icon is used in a similar place as the caption.
* \param iconname Assumed to be the name of an iconresource. The system will look for different
* sizes under :/icons/<size>/iconname
*/
virtual void setIcon(PluginContentWidget *content, const QString &iconname) = 0;
/** Returns an OpenDatabase object the widget can use to access
* the database.
*/
virtual std::shared_ptr<OpenDatabase> getDatabase() = 0;
virtual void QueueTask(TSQueue::t_Callable c) = 0;
virtual void showStatusMessage(const QString &msg) = 0;
};
#endif // IPLUGINCONTENTWIDGETCONTEXT_H

View file

@ -1,16 +0,0 @@
#include "PlgPage.h"
//PglPage::PglPage()
//{
//}
std::vector<QAction*> PlgPage::getToolbarActions()
{
return std::vector<QAction*>();
}
bool PlgPage::canClose()
{
return true;
}

View file

@ -0,0 +1,18 @@
#include "PluginContentWidget.h"
PluginContentWidget::PluginContentWidget(IPluginContentWidgetContext *context, QWidget* parent)
: QWidget(parent)
, m_context(context)
{
}
std::vector<QAction*> PluginContentWidget::getToolbarActions()
{
return std::vector<QAction*>();
}
bool PluginContentWidget::canClose()
{
return true;
}

View file

@ -4,6 +4,8 @@
#include <QWidget>
#include <vector>
class IPluginContentWidgetContext;
/// Provides a pluggable system for toolbar buttons and menu actions
///
/// We will need several kind of actions
@ -15,13 +17,17 @@
/// Can we use same groupings for toolbars and menu's
/// How about additional toolbars?
///
class PlgPage: public QWidget{
class PluginContentWidget: public QWidget{
public:
using QWidget::QWidget;
PluginContentWidget(IPluginContentWidgetContext *context, QWidget* parent = nullptr);
/// Returns the toolbar buttons for this page
virtual std::vector<QAction*> getToolbarActions();
virtual bool canClose();
protected:
IPluginContentWidgetContext *context() { return m_context; }
private:
IPluginContentWidgetContext *m_context;
};
#endif // PGLPAGE_H

View file

@ -15,19 +15,18 @@
#include <QClipboard>
#include "ExplainTreeModelItem.h"
#include "json/json.h"
#include "DatabaseWindow.h"
#include "OpenDatabase.h"
#include "catalog/PgDatabaseCatalog.h"
#include "QueryParamListController.h"
#include "util.h"
#include "GlobalIoService.h"
#include "UserConfiguration.h"
#include "IPluginContentWidgetContext.h"
QueryTab::QueryTab(DatabaseWindow *win, QWidget *parent) :
PlgPage(parent),
ui(new Ui::QueryTab),
m_win(win),
m_dbConnection(*getGlobalAsioIoService())
QueryTab::QueryTab(IPluginContentWidgetContext *context_, QWidget *parent)
: PluginContentWidget(context_, parent)
, ui(new Ui::QueryTab)
, m_dbConnection(*getGlobalAsioIoService())
{
ui->setupUi(this);
@ -37,7 +36,7 @@ QueryTab::QueryTab(DatabaseWindow *win, QWidget *parent) :
ui->queryEdit->setFont(UserConfiguration::instance()->codeFont());
highlighter = new SqlSyntaxHighlighter(ui->queryEdit->document());
auto open_database = m_win->getDatabase();
auto open_database = context()-> getDatabase();
if (open_database) {
auto cat = open_database->catalog();
highlighter->setTypes(*cat->types());
@ -64,7 +63,7 @@ void QueryTab::setConfig(const ConnectionConfig &config,
{
m_config = config;
m_catalog = cat;
m_win->QueueTask([this]() { startConnect(); });
context()->QueueTask([this]() { startConnect(); });
}
bool QueryTab::canClose()
@ -160,7 +159,7 @@ void QueryTab::execute()
auto cb = [this](Expected<std::shared_ptr<Pgsql::Result>> res, qint64 elapsedms)
{
m_win->QueueTask([this, res, elapsedms]() { query_ready(res, elapsedms); });
context()->QueueTask([this, res, elapsedms]() { query_ready(res, elapsedms); });
};
if (m_queryParamListController->empty())
@ -203,7 +202,7 @@ void QueryTab::explain(bool analyze)
explain = ExplainRoot::createFromJson(root);
}
}
m_win->QueueTask([this, explain]() { explain_ready(explain); });
context()->QueueTask([this, explain]() { explain_ready(explain); });
}).detach();
}
}
@ -226,7 +225,7 @@ void QueryTab::setFileName(const QString &filename)
m_fileName = filename;
QFileInfo fileInfo(filename);
QString fn(fileInfo.fileName());
setTabCaption(fn, m_fileName);
context()->setCaption(this, fn, m_fileName);
}
bool QueryTab::continueWithoutSavingWarning()
@ -285,27 +284,23 @@ void QueryTab::queryTextChanged()
void QueryTab::connectionStateChanged(ASyncDBConnection::State state)
{
QTabWidget *tabwidget = getTabWidget();
if (tabwidget) {
int i = tabwidget->indexOf(this);
QString iconname;
switch (state) {
case ASyncDBConnection::State::NotConnected:
case ASyncDBConnection::State::Connecting:
iconname = ":/icons/16x16/document_red.png";
break;
case ASyncDBConnection::State::Connected:
iconname = ":/icons/16x16/document_green.png";
break;
case ASyncDBConnection::State::QuerySend:
case ASyncDBConnection::State::CancelSend:
iconname = ":/icons/16x16/document_yellow.png";
break;
case ASyncDBConnection::State::Terminating:
break;
}
tabwidget->setTabIcon(i, QIcon(iconname));
QString iconname;
switch (state) {
case ASyncDBConnection::State::NotConnected:
case ASyncDBConnection::State::Connecting:
iconname = "document_red.png";
break;
case ASyncDBConnection::State::Connected:
iconname = "document_green.png";
break;
case ASyncDBConnection::State::QuerySend:
case ASyncDBConnection::State::CancelSend:
iconname = "document_yellow.png";
break;
case ASyncDBConnection::State::Terminating:
break;
}
context()->setIcon(this, iconname);
}
@ -394,9 +389,7 @@ void QueryTab::explain_ready(ExplainRoot::SPtr explain)
ui->explainTreeView->setColumnWidth(6, 600);
ui->tabWidget->setCurrentWidget(ui->explainTab);
auto w = dynamic_cast<QMainWindow*>(this->window());
if (w)
w->statusBar()->showMessage(tr("Explain ready."));
context()->showStatusMessage(tr("Explain ready."));
}
else {
addLog("Explain no result");
@ -423,26 +416,26 @@ std::string QueryTab::getCommandUtf8() const
return getCommand().toUtf8().data();
}
QTabWidget *QueryTab::getTabWidget()
{
QWidget * w = parentWidget();
QWidget * p = w->parentWidget();
QTabWidget *tw = dynamic_cast<QTabWidget*>(p);
return tw;
}
//QTabWidget *QueryTab::getTabWidget()
//{
// QWidget * w = parentWidget();
// QWidget * p = w->parentWidget();
// QTabWidget *tw = dynamic_cast<QTabWidget*>(p);
// return tw;
//}
void QueryTab::setTabCaption(const QString &caption, const QString &tooltip)
{
QTabWidget *tabwidget = getTabWidget();
if (tabwidget) {
int i = tabwidget->indexOf(this);
if (i >= 0) {
tabwidget->setTabText(i, caption);
tabwidget->setTabToolTip(i, tooltip);
}
}
//void QueryTab::setTabCaption(const QString &caption, const QString &tooltip)
//{
// QTabWidget *tabwidget = getTabWidget();
// if (tabwidget) {
// int i = tabwidget->indexOf(this);
// if (i >= 0) {
// tabwidget->setTabText(i, caption);
// tabwidget->setTabToolTip(i, tooltip);
// }
// }
}
//}
void QueryTab::query_ready(Expected<std::shared_ptr<Pgsql::Result>> exp_res, qint64 elapsedms)
{
@ -609,7 +602,7 @@ void QueryTab::generateCode()
}
if (resultList.size() == 1) {
std::shared_ptr<const Pgsql::Result> dbres = resultList[0]->GetPgsqlResult();
m_win->newCodeGenPage(command, dbres);
//context()->newCodeGenPage(command, dbres);
}
}

View file

@ -8,7 +8,7 @@
#include "tuplesresultwidget.h"
#include <QWidget>
#include "PlgPage.h"
#include "PluginContentWidget.h"
#include <memory>
namespace Ui {
@ -22,7 +22,6 @@ namespace Pgsql {
class QTableView;
class QTabWidget;
class DatabaseWindow;
class SqlSyntaxHighlighter;
class ExplainRoot;
class QueryResultModel;
@ -32,11 +31,11 @@ class OpenDatabase;
class QueryParamListController;
class PgDatabaseCatalog;
class QueryTab : public PlgPage {
class QueryTab : public PluginContentWidget {
Q_OBJECT
public:
QueryTab(DatabaseWindow *win, QWidget *parent = nullptr);
~QueryTab();
QueryTab(IPluginContentWidgetContext *context, QWidget *parent = nullptr);
~QueryTab() override;
void setConfig(const ConnectionConfig &config, std::shared_ptr<PgDatabaseCatalog>cat);
@ -69,7 +68,6 @@ private:
using ResultTabContainer = std::vector<TuplesResultWidget*>;
Ui::QueryTab *ui;
DatabaseWindow *m_win;
SqlSyntaxHighlighter* highlighter;
ConnectionConfig m_config;
StopWatch m_stopwatch;
@ -101,8 +99,8 @@ private:
void explain_ready(ExplainRoot::SPtr explain);
void query_ready(Expected<std::shared_ptr<Pgsql::Result>> dbres, qint64 elapsedms);
QTabWidget *getTabWidget();
void setTabCaption(const QString &caption, const QString &tooltip);
//QTabWidget *getTabWidget();
//void setTabCaption(const QString &caption, const QString &tooltip);
void clearResult();
void markError(const Pgsql::ErrorDetails &details);

View file

@ -66,7 +66,6 @@ SOURCES += main.cpp\
Module.cpp \
EditorGutter.cpp \
CodeEditor.cpp \
PlgPage.cpp \
PropertyProxyModel.cpp \
CodeGenerator.cpp \
UserConfiguration.cpp \
@ -84,7 +83,8 @@ PropertyProxyModel.cpp \
SequenceModel.cpp \
SequencesPage.cpp \
DatabaseWindow.cpp \
PgLabTableView.cpp
PgLabTableView.cpp \
PluginContentWidget.cpp
HEADERS += \
QueryResultModel.h \
@ -126,7 +126,6 @@ HEADERS += \
Module.h \
EditorGutter.h \
CodeEditor.h \
PlgPage.h \
AbstractCommand.h \
PropertyProxyModel.h \
CustomDataRole.h \
@ -146,7 +145,9 @@ CustomDataRole.h \
SequenceModel.h \
SequencesPage.h \
DatabaseWindow.h \
PgLabTableView.h
PgLabTableView.h \
PluginContentWidget.h \
IPluginContentWidgetContext.h
FORMS += mainwindow.ui \
ConnectionManagerWindow.ui \