DatabaseWindow has no knowledge more of the existence of QueryTab but user can still create and use them within that window.

This commit is contained in:
eelke 2019-01-05 11:12:47 +01:00
parent fd603a7434
commit d0c4dabe8b
8 changed files with 327 additions and 451 deletions

View file

@ -1,12 +1,9 @@
#include "DatabaseWindow.h" #include "DatabaseWindow.h"
//#include "ui_DatabaseWindow.h" #include "plugin_support/IPluginContentWidgetContext.h"
#include "TablesPage.h" #include "TablesPage.h"
#include "FunctionsPage.h" #include "FunctionsPage.h"
#include "SequencesPage.h" #include "SequencesPage.h"
#include "QueryTab.h"
#include "util.h" #include "util.h"
#include "plugin_support/PluginContentWidget.h"
#include "plugin_support/PluginContentWidgetContextBase.h"
#include "CodeGenerator.h" #include "CodeGenerator.h"
#include "MasterController.h" #include "MasterController.h"
#include "ScopeGuard.h" #include "ScopeGuard.h"
@ -16,171 +13,22 @@
#include <QCloseEvent> #include <QCloseEvent>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QFileDialog> #include <QFileDialog>
#include <QMenuBar>
#include <QMessageBox> #include <QMessageBox>
#include <QMetaMethod> #include <QMetaMethod>
#include <QMetaObject> #include <QMetaObject>
#include <QStandardPaths> #include <QStandardPaths>
#include <QStatusBar>
#include <QTextTable> #include <QTextTable>
#include <QToolBar>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <algorithm> #include <algorithm>
namespace pg = Pgsql; namespace pg = Pgsql;
namespace DatabaseWindow_details {
class DatabaseWindowContentContext: public PluginContentWidgetContextBase {
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 showStatusMessage(const QString &msg) override
{
m_window->statusBar()->showMessage(msg);
}
void addContentWidget(PluginContentWidget *widget) override
{
m_window->addPage(widget, "");
}
private:
DatabaseWindow *m_window;
};
}
using namespace DatabaseWindow_details;
LMainWindow::LMainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_tabWidget = new QTabWidget(this);
m_tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
m_tabWidget->setDocumentMode(true);
setCentralWidget(m_tabWidget);
// menu
auto menuBar = new QMenuBar(this);
setMenuBar(menuBar);
// tooolbar
m_mainToolBar = new QToolBar(this);
addToolBar(Qt::TopToolBarArea, m_mainToolBar);
// statusbar
auto statusBar = new QStatusBar(this);
setStatusBar(statusBar);
m_fileMenu = new QMenu("File T", this);
createActions();
m_mainToolBar->addAction(m_closeAction);
// QMetaObject::connectSlotsByName(this);
}
void LMainWindow::initModuleMenus()
{
menuBar()->addMenu(m_fileMenu);
addModuleMenuActions();
}
void LMainWindow::addModuleMenuActions()
{
auto reg = PluginRegister::getInstance();
auto mods = reg->modules();
for (auto && mod : mods) {
auto items = mod.second->menuActions();
for (auto && item : items) {
addMenuAction(item);
}
}
}
void LMainWindow::createActions()
{
{
auto action = m_closeAction = new QAction(this);
QIcon icon;
icon.addFile(QString::fromUtf8(":/icons/page_white_delete.png"), QSize(), QIcon::Normal, QIcon::On);
action->setIcon(icon);
connect(m_closeAction, &QAction::triggered, this, &DatabaseWindow::actionClose_triggered);
}
}
void LMainWindow::addMenuAction(const MenuAction &ma)
{
qDebug() << "add action " << ma.text();
//auto ac =
m_fileMenu->addAction(ma.icon(), ma.text(),
[ma, this] ()
{
ma.perform(m_context);
},
ma.shortCut());
// auto ac = new QAction(this);
// ac->
}
void LMainWindow::actionClose_triggered()
{
m_tabWidget->tabCloseRequested(m_tabWidget->currentIndex());
}
void LMainWindow::addPage(PluginContentWidget* page, QString caption)
{
m_tabWidget->addTab(page, caption);
m_tabWidget->setCurrentWidget(page);
}
void LMainWindow::setTabCaptionForWidget(QWidget *widget, const QString &caption, const QString &hint)
{
auto index = m_tabWidget->indexOf(widget);
m_tabWidget->setTabText(index, caption);
m_tabWidget->setTabToolTip(index, hint);
}
void LMainWindow::setTabIcon(QWidget *widget, const QString &iconname)
{
auto index = m_tabWidget->indexOf(widget);
auto n = ":/icons/16x16/" + iconname;
m_tabWidget->setTabIcon(index, QIcon(n));
}
DatabaseWindow::DatabaseWindow(MasterController *master, QWidget *parent) DatabaseWindow::DatabaseWindow(MasterController *master, QWidget *parent)
: LMainWindow(parent) : LMainWindow(parent)
, m_masterController(master) , m_masterController(master)
{ {
m_context = new DatabaseWindowContentContext(this);
connect(&loadWatcher, &QFutureWatcher<LoadCatalog::Result>::finished, connect(&loadWatcher, &QFutureWatcher<LoadCatalog::Result>::finished,
this, &DatabaseWindow::catalogLoaded); this, &DatabaseWindow::catalogLoaded);
@ -188,20 +36,7 @@ DatabaseWindow::DatabaseWindow(MasterController *master, QWidget *parent)
QMetaObject::connectSlotsByName(this); QMetaObject::connectSlotsByName(this);
} }
DatabaseWindow::~DatabaseWindow() DatabaseWindow::~DatabaseWindow() = default;
{
delete m_context;
}
QueryTab* DatabaseWindow::newSqlPage()
{
QueryTab *qt = new QueryTab(m_context);
qt->newdoc();
qt->focusEditor();
addPage(qt, "Tab");
return qt;
}
void DatabaseWindow::newCreateTablePage() void DatabaseWindow::newCreateTablePage()
{ {
@ -211,18 +46,11 @@ void DatabaseWindow::newCreateTablePage()
void DatabaseWindow::newCodeGenPage(QString query, std::shared_ptr<const Pgsql::Result> dbres) void DatabaseWindow::newCodeGenPage(QString query, std::shared_ptr<const Pgsql::Result> dbres)
{ {
auto cgtab = new CodeGenerator(m_context, this); auto cgtab = new CodeGenerator(context(), this);
cgtab->Init(m_database->catalog(), query, dbres); cgtab->Init(m_database->catalog(), query, dbres);
addPage(cgtab, "Codegen"); addPage(cgtab, "Codegen");
} }
QueryTab *DatabaseWindow::GetActiveQueryTab()
{
QWidget *widget = m_tabWidget->currentWidget();
QueryTab *qt = dynamic_cast<QueryTab*>(widget);
return qt;
}
void DatabaseWindow::setConfig(const ConnectionConfig &config) void DatabaseWindow::setConfig(const ConnectionConfig &config)
{ {
m_config = config; m_config = config;
@ -247,18 +75,19 @@ void DatabaseWindow::catalogLoaded()
try { try {
//SCOPE_EXIT { loadFuture = {}; }; //SCOPE_EXIT { loadFuture = {}; };
m_database = loadWatcher.future().result(); m_database = loadWatcher.future().result();
m_context->registerObject(m_database); auto ctx = context();
ctx->registerObject(m_database);
auto tt = new TablesPage(m_context, this); auto tt = new TablesPage(ctx, this);
tt->setCatalog(m_database->catalog()); tt->setCatalog(m_database->catalog());
m_tabWidget->addTab(tt, "Tables"); m_tabWidget->addTab(tt, "Tables");
auto pg_cat_tables = new TablesPage(m_context, this); auto pg_cat_tables = new TablesPage(ctx, this);
pg_cat_tables->setNamespaceFilter(TablesTableModel::PgCatalog); pg_cat_tables->setNamespaceFilter(TablesTableModel::PgCatalog);
pg_cat_tables->setCatalog(m_database->catalog()); pg_cat_tables->setCatalog(m_database->catalog());
m_tabWidget->addTab(pg_cat_tables, "pg_catalog"); m_tabWidget->addTab(pg_cat_tables, "pg_catalog");
auto info_schema_tables = new TablesPage(m_context, this); auto info_schema_tables = new TablesPage(ctx, this);
info_schema_tables->setNamespaceFilter(TablesTableModel::InformationSchema); info_schema_tables->setNamespaceFilter(TablesTableModel::InformationSchema);
info_schema_tables->setCatalog(m_database->catalog()); info_schema_tables->setCatalog(m_database->catalog());
m_tabWidget->addTab(info_schema_tables, "information_schema"); m_tabWidget->addTab(info_schema_tables, "information_schema");
@ -271,7 +100,6 @@ void DatabaseWindow::catalogLoaded()
sequences_page->setCatalog(m_database->catalog()); sequences_page->setCatalog(m_database->catalog());
m_tabWidget->addTab(sequences_page, "Sequences"); m_tabWidget->addTab(sequences_page, "Sequences");
newSqlPage();
newCreateTablePage(); newCreateTablePage();
} catch (std::runtime_error &ex) { } catch (std::runtime_error &ex) {
QMessageBox::critical(this, "Error reading database", QMessageBox::critical(this, "Error reading database",
@ -281,59 +109,11 @@ void DatabaseWindow::catalogLoaded()
} }
} }
void DatabaseWindow::on_actionLoad_SQL_triggered()
{
QString home_dir = QStandardPaths::locate(QStandardPaths::HomeLocation, "", QStandardPaths::LocateDirectory);
QString file_name = QFileDialog::getOpenFileName(this,
tr("Open sql query"), home_dir, tr("SQL files (*.sql *.txt)"));
if ( ! file_name.isEmpty()) {
QueryTab* qt = newSqlPage();
qt->load(file_name);
}
}
void DatabaseWindow::on_actionSave_SQL_triggered()
{
QueryTab *tab = GetActiveQueryTab();
if (tab) {
tab->save();
}
}
void DatabaseWindow::on_actionSave_SQL_as_triggered()
{
QueryTab *tab = GetActiveQueryTab();
if (tab) {
tab->saveAs();
}
}
void DatabaseWindow::on_actionSave_copy_of_SQL_as_triggered()
{
QueryTab *tab = GetActiveQueryTab();
if (tab) {
tab->saveCopyAs();
}
}
void DatabaseWindow::on_actionExport_data_triggered()
{
QueryTab *tab = GetActiveQueryTab();
if (tab) {
QString home_dir = QStandardPaths::locate(QStandardPaths::HomeLocation, "", QStandardPaths::LocateDirectory);
QString file_name = QFileDialog::getSaveFileName(this,
tr("Export data"), home_dir, tr("CSV file (*.csv)"));
tab->exportData(file_name);
}
}
void DatabaseWindow::on_actionAbout_triggered() void DatabaseWindow::on_actionAbout_triggered()
{ {
QMessageBox::about(this, "pgLab 0.1", tr( QMessageBox::about(this, "pgLab 0.1", tr(
"Copyrights 2016-2018, Eelke Klein, All Rights Reserved.\n" "Copyrights 2016-2019, Eelke Klein, All Rights Reserved.\n"
"\n" "\n"
"The program is provided AS IS with NO WARRANTY OF ANY KIND, " "The program is provided AS IS with NO WARRANTY OF ANY KIND, "
"INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS " "INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS "
@ -388,40 +168,6 @@ void DatabaseWindow::showEvent(QShowEvent *event)
event->accept(); event->accept();
} }
void DatabaseWindow::on_actionNew_SQL_triggered()
{
newSqlPage();
}
void DatabaseWindow::on_tabWidget_tabCloseRequested(int index)
{
QWidget *widget = m_tabWidget->widget(index);
PluginContentWidget *plg_page = dynamic_cast<PluginContentWidget*>(widget);
if (plg_page) {
if (plg_page->canClose()) {
removePage(plg_page);
m_tabWidget->removeTab(index);
delete plg_page;
}
}
else {
// old behaviour shouldn't be needed any more when all pages have been migrated
// to PlgPage
QueryTab *qt = dynamic_cast<QueryTab*>(widget);
if (qt && qt->canClose()) {
m_tabWidget->removeTab(index);
delete qt;
}
else if (index > 0) {
m_tabWidget->removeTab(index);
delete widget;
}
}
}
void DatabaseWindow::on_actionShow_connection_manager_triggered() void DatabaseWindow::on_actionShow_connection_manager_triggered()
{ {
m_masterController->showConnectionManager(); m_masterController->showConnectionManager();
@ -447,73 +193,3 @@ void DatabaseWindow::on_actionCopy_triggered()
} }
void DatabaseWindow::on_actionCopy_as_C_string_triggered()
{
// Find which edit is active, copy the selected text or all text if no selection present
// Put quote's around each line and add escapes.
QueryTab *tab = GetActiveQueryTab();
if (tab) {
tab->copyQueryAsCString();
}
}
void DatabaseWindow::on_actionCopy_as_raw_Cpp_string_triggered()
{
QueryTab *tab = GetActiveQueryTab();
if (tab) {
tab->copyQueryAsRawCppString();
}
}
void DatabaseWindow::addToolBarButtonsForPage(PluginContentWidget *page)
{
std::vector<QAction*> actions = page->getToolbarActions();
QList<QAction*> list;
for (auto act : actions) {
list.append(act);
}
m_mainToolBar->addActions(list);
}
void DatabaseWindow::removeToolBarButtonsForPage(PluginContentWidget *page)
{
std::vector<QAction*> actions = page->getToolbarActions();
for (auto act : actions) {
m_mainToolBar->removeAction(act);
}
}
void DatabaseWindow::removePage(PluginContentWidget *)
{
}
void DatabaseWindow::on_tabWidget_currentChanged(int index)
{
// remove buttons of old page
if (m_previousPage) {
removeToolBarButtonsForPage(m_previousPage);
}
// add buttons of new page
PluginContentWidget * page = nullptr;
if (index >= 0) {
QWidget *widget = m_tabWidget->widget(index);
page = dynamic_cast<PluginContentWidget*>(widget);
if (page) {
addToolBarButtonsForPage(page);
}
}
m_previousPage = page;
}
void DatabaseWindow::on_actionGenerate_code_triggered()
{
QueryTab *tab = GetActiveQueryTab();
if (tab) {
tab->generateCode();
}
}

View file

@ -4,8 +4,7 @@
#include "ASyncDBConnection.h" #include "ASyncDBConnection.h"
#include "ConnectionConfig.h" #include "ConnectionConfig.h"
#include "OpenDatabase.h" #include "OpenDatabase.h"
#include <QLabel> #include "plugin_support/LMainWindow.h"
#include <QLabel>
#include <QRunnable> #include <QRunnable>
#include <QSocketNotifier> #include <QSocketNotifier>
#include <memory> #include <memory>
@ -18,68 +17,20 @@
#include <QMutex> #include <QMutex>
#include <QWaitCondition> #include <QWaitCondition>
#include <QMainWindow>
#include <QFuture> #include <QFuture>
#include <QFutureWatcher> #include <QFutureWatcher>
//namespace Ui {
// class DatabaseWindow;
//}
namespace Pgsql { namespace Pgsql {
class Connection; class Connection;
} }
class MenuAction;
class QueryTab;
class MasterController; class MasterController;
class QCloseEvent; class QCloseEvent;
class OpenDatabase; class OpenDatabase;
class PgClass; class PgClass;
class PluginContentWidget;
class QTabWidget; class QTabWidget;
namespace DatabaseWindow_details {
class DatabaseWindowContentContext;
}
class LMainWindow : public QMainWindow {
Q_OBJECT
public:
LMainWindow(QWidget *parent = nullptr);
void initModuleMenus();
void setTabCaptionForWidget(QWidget *widget, const QString &caption, const QString &hint);
void setTabIcon(QWidget *widget, const QString &iconname);
/// Called when a newly created page is added to the QTabWidget
void addPage(PluginContentWidget* page, QString caption);
protected:
QTabWidget *m_tabWidget = nullptr;
QToolBar *m_mainToolBar = nullptr;
// Standard menu's
QMenu *m_fileMenu = nullptr;
// Standard actions
QAction *m_closeAction = nullptr;
DatabaseWindow_details::DatabaseWindowContentContext *m_context;
void addModuleMenuActions();
private:
void createActions();
void addMenuAction(const MenuAction &ma);
private slots:
void actionClose_triggered();
};
/** This is the class for windows that handle tasks for a specific database/catalog /** This is the class for windows that handle tasks for a specific database/catalog
* *
@ -102,34 +53,6 @@ private:
std::shared_ptr<OpenDatabase> m_database; std::shared_ptr<OpenDatabase> m_database;
MasterController *m_masterController; MasterController *m_masterController;
PluginContentWidget *m_previousPage = nullptr; ///< tracks which pages buttons were previously being displayed
// class QLoad : public QueuedBackgroundTask {
// public:
// explicit QLoad(ConnectionConfig config, CompletionFunction on_completion)
// : QueuedBackgroundTask(on_completion)
// , m_config(config)
// {}
// OpenDatabase::OpenDatabaseSPtr GetResult()
// {
// if (hasException()) rethrow();
// return result;
// }
// protected:
// OpenDatabase::OpenDatabaseSPtr result;
// virtual void doRun()
// {
// auto res = OpenDatabase::createOpenDatabase(m_config);
// result = res.get();
// }
// private:
// ConnectionConfig m_config;
// };
// std::shared_ptr<QLoad> loader;
class LoadCatalog: public ControllableTask<OpenDatabase::OpenDatabaseSPtr> { class LoadCatalog: public ControllableTask<OpenDatabase::OpenDatabaseSPtr> {
public: public:
@ -149,38 +72,17 @@ private:
QFutureWatcher<LoadCatalog::Result> loadWatcher; QFutureWatcher<LoadCatalog::Result> loadWatcher;
QueryTab *GetActiveQueryTab();
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
void showEvent(QShowEvent *event); void showEvent(QShowEvent *event);
QueryTab *newSqlPage();
void newCreateTablePage(); void newCreateTablePage();
/// Called when a page is completely removed from the QTabWidget
void removePage(PluginContentWidget *page);
void addToolBarButtonsForPage(PluginContentWidget *page);
void removeToolBarButtonsForPage(PluginContentWidget *page);
//class PageData
private slots: private slots:
void catalogLoaded(); void catalogLoaded();
void on_actionLoad_SQL_triggered();
void on_actionSave_SQL_triggered();
void on_actionExport_data_triggered();
void on_actionAbout_triggered(); void on_actionAbout_triggered();
void on_actionSave_SQL_as_triggered();
void on_actionSave_copy_of_SQL_as_triggered();
void on_actionNew_SQL_triggered();
void on_tabWidget_tabCloseRequested(int index);
void on_actionShow_connection_manager_triggered(); void on_actionShow_connection_manager_triggered();
void on_actionCopy_triggered(); void on_actionCopy_triggered();
void on_actionCopy_as_C_string_triggered();
void on_actionCopy_as_raw_Cpp_string_triggered();
void on_tabWidget_currentChanged(int index);
void on_actionGenerate_code_triggered();
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View file

@ -627,23 +627,15 @@ std::vector<QAction*> QueryTab::getToolbarActions()
{ {
if (actions.empty()) { if (actions.empty()) {
QAction *action; QAction *action;
// New
// action = new QAction(QIcon(":/icons/new_query_tab.png"), tr("New"), this);
// action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));
// connect(action, &QAction::triggered, this, &QueryTab::);
// actions.push_back(action);
// Load
// Save // Save
action = new QAction(QIcon(":/icons/script_save.png"), tr("Save SQL"), this); action = new QAction(QIcon(":/icons/script_save.png"), tr("Save SQL"), this);
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
connect(action, &QAction::triggered, this, &QueryTab::save); connect(action, &QAction::triggered, this, &QueryTab::save);
actions.push_back(action); actions.push_back(action);
// Save as (menu only) // Save as (menu only)
// action = new QAction(QIcon(":/icons/script_save.png"), tr("Save SQL as"), this); action = new QAction(QIcon(":/icons/script_save.png"), tr("Save SQL as"), this);
// //action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); connect(action, &QAction::triggered, this, &QueryTab::saveAs);
// connect(action, &QAction::triggered, this, &QueryTab::saveAs); actions.push_back(action);
// actions.push_back(action);
// Save copy as // Save copy as
// Copy // Copy
// Copy as C-string // Copy as C-string
@ -677,12 +669,21 @@ std::vector<QAction*> QueryTab::getToolbarActions()
void QueryToolModule::init() void QueryToolModule::init()
{ {
MenuAction ma_new("New", [this] (IPluginContentWidgetContext* context) {
{ menuAction_new(context); }); MenuAction ma("New SQL", [this] (IPluginContentWidgetContext* context)
ma_new.setMenuLocation(MenuPath("File/New")); { menuAction_new(context); });
ma_new.setIcon(QIcon(":/icons/new_query_tab.png")); ma.setMenuLocation(MenuPath("File/New"));
ma_new.setShortCut(QKeySequence(Qt::CTRL + Qt::Key_N)); ma.setIcon(QIcon(":/icons/new_query_tab.png"));
registerMenuAction(ma_new); ma.setShortCut(QKeySequence(Qt::CTRL + Qt::Key_N));
registerMenuAction(ma);
}
{
MenuAction ma("Open SQL", [this] (IPluginContentWidgetContext* context)
{ menuAction_open(context); });
ma.setMenuLocation(MenuPath("File/Open"));
ma.setIcon(QIcon(":/icons/folder.png"));
registerMenuAction(ma);
}
} }
void QueryToolModule::menuAction_new(IPluginContentWidgetContext* context) void QueryToolModule::menuAction_new(IPluginContentWidgetContext* context)
@ -692,4 +693,16 @@ void QueryToolModule::menuAction_new(IPluginContentWidgetContext* context)
ct->newdoc(); ct->newdoc();
} }
void QueryToolModule::menuAction_open(IPluginContentWidgetContext* context)
{
QString home_dir = QStandardPaths::locate(QStandardPaths::HomeLocation, "", QStandardPaths::LocateDirectory);
QString file_name = QFileDialog::getOpenFileName(context->container(),
tr("Open sql query"), home_dir, tr("SQL files (*.sql *.txt)"));
if ( ! file_name.isEmpty()) {
auto *ct = new QueryTab(context, nullptr);
context->addContentWidget(ct);
ct->load(file_name);
}
}
REGISTER_PLUGIN_MODULE(QueryToolModule, "Query tool", "pglab.querytool") REGISTER_PLUGIN_MODULE(QueryToolModule, "Query tool", "pglab.querytool")

View file

@ -120,6 +120,7 @@ public:
void init() override; void init() override;
void menuAction_new(IPluginContentWidgetContext* context); void menuAction_new(IPluginContentWidgetContext* context);
void menuAction_open(IPluginContentWidgetContext* context);
private slots: private slots:
}; };

View file

@ -88,7 +88,8 @@ PropertyProxyModel.cpp \
plugin_support/PluginRegister.cpp \ plugin_support/PluginRegister.cpp \
plugin_support/PluginContentWidget.cpp \ plugin_support/PluginContentWidget.cpp \
plugin_support/PluginContentWidgetContextBase.cpp \ plugin_support/PluginContentWidgetContextBase.cpp \
plugin_support/MenuAction.cpp plugin_support/MenuAction.cpp \
plugin_support/LMainWindow.cpp
HEADERS += \ HEADERS += \
QueryResultModel.h \ QueryResultModel.h \
@ -156,7 +157,8 @@ CustomDataRole.h \
plugin_support/ModuleActionParameters.h \ plugin_support/ModuleActionParameters.h \
plugin_support/IPluginContentWidgetContext.h \ plugin_support/IPluginContentWidgetContext.h \
plugin_support/PluginContentWidgetContextBase.h \ plugin_support/PluginContentWidgetContextBase.h \
plugin_support/MenuAction.h plugin_support/MenuAction.h \
plugin_support/LMainWindow.h
FORMS += \ FORMS += \
ConnectionManagerWindow.ui \ ConnectionManagerWindow.ui \

View file

@ -47,6 +47,10 @@ public:
virtual void addContentWidget(PluginContentWidget *widget) = 0; virtual void addContentWidget(PluginContentWidget *widget) = 0;
/** Return a widget you can use as a parent
*/
virtual QWidget* container() = 0;
template<typename T, class...Args> template<typename T, class...Args>
bool addObjects(Args&&...args); bool addObjects(Args&&...args);
template<typename T> template<typename T>

View file

@ -0,0 +1,220 @@
#include "LMainWindow.h"
#include "PluginContentWidget.h"
#include "PluginContentWidgetContextBase.h"
#include "PluginModule.h"
#include "PluginRegister.h"
#include <QDebug>
#include <QMenuBar>
#include <QStatusBar>
#include <QToolBar>
namespace LMainWindow_details {
class LMainWindowContentContext: public PluginContentWidgetContextBase {
public:
explicit LMainWindowContentContext(LMainWindow *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);
}
void showStatusMessage(const QString &msg) override
{
m_window->statusBar()->showMessage(msg);
}
void addContentWidget(PluginContentWidget *widget) override
{
m_window->addPage(widget, "");
}
QWidget* container() override
{
return m_window;
}
private:
LMainWindow *m_window;
};
}
using namespace LMainWindow_details;
LMainWindow::LMainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_context = new LMainWindowContentContext(this);
m_tabWidget = new QTabWidget(this);
m_tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
m_tabWidget->setDocumentMode(true);
setCentralWidget(m_tabWidget);
// menu
auto menuBar = new QMenuBar(this);
setMenuBar(menuBar);
// tooolbar
m_mainToolBar = new QToolBar(this);
addToolBar(Qt::TopToolBarArea, m_mainToolBar);
// statusbar
auto statusBar = new QStatusBar(this);
setStatusBar(statusBar);
m_fileMenu = new QMenu("File", this);
createActions();
m_mainToolBar->addAction(m_closeAction);
connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, &LMainWindow::tabWidget_tabCloseRequested);
connect(m_tabWidget, &QTabWidget::currentChanged, this, &LMainWindow::tabWidget_currentChanged);
}
LMainWindow::~LMainWindow()
{
delete m_context;
}
void LMainWindow::initModuleMenus()
{
menuBar()->addMenu(m_fileMenu);
addModuleMenuActions();
}
void LMainWindow::addModuleMenuActions()
{
auto reg = PluginRegister::getInstance();
auto mods = reg->modules();
for (auto && mod : mods) {
auto items = mod.second->menuActions();
for (auto && item : items) {
addMenuAction(item);
}
}
}
void LMainWindow::createActions()
{
{
auto action = m_closeAction = new QAction(this);
QIcon icon;
icon.addFile(QString::fromUtf8(":/icons/page_white_delete.png"), QSize(), QIcon::Normal, QIcon::On);
action->setIcon(icon);
connect(m_closeAction, &QAction::triggered, this, &LMainWindow::actionClose_triggered);
}
}
void LMainWindow::addMenuAction(const MenuAction &ma)
{
qDebug() << "add action " << ma.text();
//auto ac =
m_fileMenu->addAction(ma.icon(), ma.text(),
[ma, this] ()
{
ma.perform(m_context);
},
ma.shortCut());
// auto ac = new QAction(this);
// ac->
}
void LMainWindow::actionClose_triggered()
{
m_tabWidget->tabCloseRequested(m_tabWidget->currentIndex());
}
void LMainWindow::addPage(PluginContentWidget* page, QString caption)
{
m_tabWidget->addTab(page, caption);
m_tabWidget->setCurrentWidget(page);
}
void LMainWindow::setTabCaptionForWidget(QWidget *widget, const QString &caption, const QString &hint)
{
auto index = m_tabWidget->indexOf(widget);
m_tabWidget->setTabText(index, caption);
m_tabWidget->setTabToolTip(index, hint);
}
void LMainWindow::setTabIcon(QWidget *widget, const QString &iconname)
{
auto index = m_tabWidget->indexOf(widget);
auto n = ":/icons/16x16/" + iconname;
m_tabWidget->setTabIcon(index, QIcon(n));
}
IPluginContentWidgetContext* LMainWindow::context()
{
return m_context;
}
void LMainWindow::tabWidget_tabCloseRequested(int index)
{
QWidget *widget = m_tabWidget->widget(index);
PluginContentWidget *plg_page = dynamic_cast<PluginContentWidget*>(widget);
if (plg_page) {
if (plg_page->canClose()) {
m_tabWidget->removeTab(index);
delete plg_page;
}
}
else {
// old behaviour shouldn't be needed any more when all pages have been migrated
// to PlgPage
m_tabWidget->removeTab(index);
delete widget;
}
}
void LMainWindow::tabWidget_currentChanged(int index)
{
// remove buttons of old page
if (m_previousPage) {
removeToolBarButtonsForPage(m_previousPage);
}
// add buttons of new page
PluginContentWidget * page = nullptr;
if (index >= 0) {
QWidget *widget = m_tabWidget->widget(index);
page = dynamic_cast<PluginContentWidget*>(widget);
if (page) {
addToolBarButtonsForPage(page);
}
}
m_previousPage = page;
}
void LMainWindow::addToolBarButtonsForPage(PluginContentWidget *page)
{
std::vector<QAction*> actions = page->getToolbarActions();
QList<QAction*> list;
for (auto act : actions) {
list.append(act);
}
m_mainToolBar->addActions(list);
}
void LMainWindow::removeToolBarButtonsForPage(PluginContentWidget *page)
{
std::vector<QAction*> actions = page->getToolbarActions();
for (auto act : actions) {
m_mainToolBar->removeAction(act);
}
}

View file

@ -0,0 +1,58 @@
#ifndef LMAINWINDOW_H
#define LMAINWINDOW_H
#include <QMainWindow>
class IPluginContentWidgetContext;
class MenuAction;
class PluginContentWidget;
namespace LMainWindow_details {
class LMainWindowContentContext;
}
class LMainWindow : public QMainWindow {
Q_OBJECT
public:
LMainWindow(QWidget *parent = nullptr);
~LMainWindow();
void initModuleMenus();
void setTabCaptionForWidget(QWidget *widget, const QString &caption, const QString &hint);
void setTabIcon(QWidget *widget, const QString &iconname);
/// Called when a newly created page is added to the QTabWidget
void addPage(PluginContentWidget* page, QString caption);
IPluginContentWidgetContext* context();
protected:
QTabWidget *m_tabWidget = nullptr;
QToolBar *m_mainToolBar = nullptr;
// Standard menu's
QMenu *m_fileMenu = nullptr;
// Standard actions
QAction *m_closeAction = nullptr;
void addModuleMenuActions();
void addToolBarButtonsForPage(PluginContentWidget *page);
void removeToolBarButtonsForPage(PluginContentWidget *page);
private:
LMainWindow_details::LMainWindowContentContext *m_context;
PluginContentWidget *m_previousPage = nullptr; ///< tracks which pages buttons were previously being displayed
void createActions();
void addMenuAction(const MenuAction &ma);
private slots:
void actionClose_triggered();
void tabWidget_tabCloseRequested(int index);
void tabWidget_currentChanged(int index);
};
#endif // LMAINWINDOW_H