From 601d071d0f9b1b9d15efa9bd5f9aaaa2092af221 Mon Sep 17 00:00:00 2001 From: eelke Date: Wed, 14 Aug 2019 09:06:48 +0200 Subject: [PATCH] Proof of concept for having the context actions statically defined in the module. Needs work for correctly placing the items in menu and on toolbar. Old system still needs to be removed left in place to keep app useable. --- pglab/CatalogInspector.cpp | 8 +- pglab/CatalogInspector.h | 3 +- pglab/CodeGenerator.cpp | 4 +- pglab/CodeGenerator.h | 2 +- pglab/CrudTab.cpp | 8 +- pglab/CrudTab.h | 3 +- pglab/DatabaseWindow.cpp | 9 +- pglab/PgLabItemDelegate.cpp | 5 +- pglab/QueryTool.cpp | 6 +- pglab/QueryTool.h | 2 +- pglab/QueryToolModule.cpp | 43 ++++++++- .../IPluginContentWidgetContext.h | 2 +- pglab/plugin_support/LMainWindow.cpp | 6 +- pglab/plugin_support/PluginContentWidget.cpp | 13 ++- pglab/plugin_support/PluginContentWidget.h | 10 +- .../PluginContentWidgetContextBase.cpp | 52 ++++++++++- .../PluginContentWidgetContextBase.h | 19 +++- pglab/plugin_support/PluginModule.cpp | 29 +++++- pglab/plugin_support/PluginModule.h | 20 ++++ pglab/plugin_support/StaticAction.cpp | 36 ++++--- pglab/plugin_support/StaticAction.h | 93 +++++++++++++++++-- 21 files changed, 303 insertions(+), 70 deletions(-) diff --git a/pglab/CatalogInspector.cpp b/pglab/CatalogInspector.cpp index fd23765..7f63070 100644 --- a/pglab/CatalogInspector.cpp +++ b/pglab/CatalogInspector.cpp @@ -12,8 +12,8 @@ #include #include -CatalogInspector::CatalogInspector(IPluginContentWidgetContext *context_, QWidget *parent) - : PluginContentWidget(context_, parent) +CatalogInspector::CatalogInspector(IPluginContentWidgetContext *context_, PluginModule *module, QWidget *parent) + : PluginContentWidget(context_, module, parent) { m_tabWidget = new QTabWidget(this); m_tablesPage = new CatalogTablesPage(this); @@ -93,8 +93,8 @@ void CatalogInspectorModule::moduleAction_open( const ModuleActionParameters ¶ms ) { - auto ct = new CatalogInspector(context, nullptr); - context->addContentWidget(this, ct); + auto ct = new CatalogInspector(context, this); + context->addContentWidget(ct); auto nsf = params.at("namespace-filter").toString(); NamespaceFilter filter = NamespaceFilter::User; if (nsf == "pg_catalog") filter = NamespaceFilter::PgCatalog; diff --git a/pglab/CatalogInspector.h b/pglab/CatalogInspector.h index dfe50cb..cfa141a 100644 --- a/pglab/CatalogInspector.h +++ b/pglab/CatalogInspector.h @@ -16,7 +16,8 @@ class QTabWidget; class CatalogInspector : public PluginContentWidget { Q_OBJECT public: - explicit CatalogInspector(IPluginContentWidgetContext *context, QWidget *parent = nullptr); + explicit CatalogInspector(IPluginContentWidgetContext *context, PluginModule *module, + QWidget *parent = nullptr); ~CatalogInspector(); void setCatalog(std::shared_ptr cat); diff --git a/pglab/CodeGenerator.cpp b/pglab/CodeGenerator.cpp index 3c2841e..2fa9752 100644 --- a/pglab/CodeGenerator.cpp +++ b/pglab/CodeGenerator.cpp @@ -5,8 +5,8 @@ #include "UserConfiguration.h" #include -CodeGenerator::CodeGenerator(IPluginContentWidgetContext *context, QWidget *parent) : - PluginContentWidget(context, parent), +CodeGenerator::CodeGenerator(IPluginContentWidgetContext *context, PluginModule *module, QWidget *parent) : + PluginContentWidget(context, module, parent), ui(new Ui::CodeGenerator) { ui->setupUi(this); diff --git a/pglab/CodeGenerator.h b/pglab/CodeGenerator.h index 63ac868..ecd01dd 100644 --- a/pglab/CodeGenerator.h +++ b/pglab/CodeGenerator.h @@ -16,7 +16,7 @@ class CodeGenerator : public PluginContentWidget Q_OBJECT public: - CodeGenerator(IPluginContentWidgetContext *context, QWidget *parent = nullptr); + CodeGenerator(IPluginContentWidgetContext *context, PluginModule *module, QWidget *parent = nullptr); ~CodeGenerator(); void Init(std::shared_ptr catalog, QString query, std::shared_ptr dbres); diff --git a/pglab/CrudTab.cpp b/pglab/CrudTab.cpp index d94a712..ceb2f94 100644 --- a/pglab/CrudTab.cpp +++ b/pglab/CrudTab.cpp @@ -16,8 +16,8 @@ #include "plugin_support/IPluginContentWidgetContext.h" -CrudTab::CrudTab(IPluginContentWidgetContext *context, QWidget *parent) - : PluginContentWidget(context, parent) +CrudTab::CrudTab(IPluginContentWidgetContext *context, PluginModule *module, QWidget *parent) + : PluginContentWidget(context, module, parent) , ui(new Ui::CrudTab) { ui->setupUi(this); @@ -140,8 +140,8 @@ void CrudPageModule::moduleAction_open( { // create new widget for specified table // hand widget to context for display - CrudTab *ct = new CrudTab(context, nullptr); - context->addContentWidget(this, ct); // maybe CrudTab should do this + CrudTab *ct = new CrudTab(context, this); + context->addContentWidget(ct); // maybe CrudTab should do this ct->setConfig(params.at("oid").toUInt()); } diff --git a/pglab/CrudTab.h b/pglab/CrudTab.h index fd623a2..b75dbb5 100644 --- a/pglab/CrudTab.h +++ b/pglab/CrudTab.h @@ -20,7 +20,8 @@ class CrudTab : public PluginContentWidget Q_OBJECT public: - explicit CrudTab(IPluginContentWidgetContext *context, QWidget *parent = nullptr); + explicit CrudTab(IPluginContentWidgetContext *context, PluginModule *module, + QWidget *parent = nullptr); ~CrudTab() override; void setConfig(Oid oid); diff --git a/pglab/DatabaseWindow.cpp b/pglab/DatabaseWindow.cpp index b111c1e..e4b730d 100644 --- a/pglab/DatabaseWindow.cpp +++ b/pglab/DatabaseWindow.cpp @@ -38,9 +38,12 @@ void DatabaseWindow::newCreateTablePage() void DatabaseWindow::newCodeGenPage(QString query, std::shared_ptr dbres) { - auto cgtab = new CodeGenerator(context(), this); - cgtab->Init(m_database->catalog(), query, dbres); - addPage(cgtab, "Codegen"); + // TODO should this call be this direct or should it go through module system + // yes it should otherwise context cannot properly setup toolbar and menu!!! +// auto cgtab = new CodeGenerator(context(), pluginModule(), this); +// cgtab->Init(m_database->catalog(), query, dbres); +// addPage(cgtab, "Codegen"); +// } void DatabaseWindow::setConfig(const ConnectionConfig &config) diff --git a/pglab/PgLabItemDelegate.cpp b/pglab/PgLabItemDelegate.cpp index c489321..40b1a88 100644 --- a/pglab/PgLabItemDelegate.cpp +++ b/pglab/PgLabItemDelegate.cpp @@ -104,8 +104,9 @@ void PgLabItemDelegate::initStyleOption(QStyleOptionViewItem *option, else { auto str = value.toString(); auto s = str.leftRef(100); - auto f = s.indexOf('\n'); - option->text = ((f > 0) ? s.left(f) : s).toString(); +// auto f = s.indexOf('\n'); +// option->text = ((f > 0) ? s.left(f) : s).toString(); + option->text = s.toString(); } } else { diff --git a/pglab/QueryTool.cpp b/pglab/QueryTool.cpp index d6874df..17bc833 100644 --- a/pglab/QueryTool.cpp +++ b/pglab/QueryTool.cpp @@ -22,8 +22,8 @@ #include "plugin_support/IPluginContentWidgetContext.h" -QueryTool::QueryTool(IPluginContentWidgetContext *context_, QWidget *parent) - : PluginContentWidget(context_, parent) +QueryTool::QueryTool(IPluginContentWidgetContext *context_, PluginModule *module, QWidget *parent) + : PluginContentWidget(context_, module, parent) , ui(new Ui::QueryTab) , m_dbConnection(*getGlobalAsioIoService()) { @@ -632,8 +632,6 @@ void QueryTool::exportData() void QueryTool::initActions() { - - { auto ac = new QAction(QIcon(":/icons/script_save.png"), tr("Save SQL"), this); ac->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); diff --git a/pglab/QueryTool.h b/pglab/QueryTool.h index 9515ae6..edfee19 100644 --- a/pglab/QueryTool.h +++ b/pglab/QueryTool.h @@ -34,7 +34,7 @@ class PgDatabaseCatalog; class QueryTool : public PluginContentWidget { Q_OBJECT public: - QueryTool(IPluginContentWidgetContext *context, QWidget *parent = nullptr); + QueryTool(IPluginContentWidgetContext *context, PluginModule *module, QWidget *parent = nullptr); ~QueryTool() override; void newdoc(); diff --git a/pglab/QueryToolModule.cpp b/pglab/QueryToolModule.cpp index 766d7d0..a18abc9 100644 --- a/pglab/QueryToolModule.cpp +++ b/pglab/QueryToolModule.cpp @@ -26,12 +26,43 @@ void QueryToolModule::init() ma.setIcon(QIcon(":/icons/folder.png")); registerStaticAction(ma); } + + { + auto ca = makeContextAction(tr("Save SQL"), &QueryTool::save); + ca->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); +// ca->setMenuLocation(MenuPath("File/Save")); +// ca->setToolbarLocation(ToolbarLocation("main", "save")); + // how we tell the system we want this to become a menu button with this as it's default action + registerContextAction(ca); + } +// { +// auto ca = makeContextAction(tr("Save SQL as"), &QueryTool::saveAs); +// ca->setMenuLocation(MenuPath("File/Save")); +// ca->setToolbarLocation(ToolbarLocation("main", "save")); +// // how we tell the system we want this to become a secondary action for the previous button? +// registerContextAction(ca); +// } +// { +// auto ca = makeContextAction(tr("Save copy of SQL as"), &QueryTool::saveCopyAs); +// ca->setMenuLocation(MenuPath("File/Save")); +// ca->setToolbarLocation(ToolbarLocation("main", "save")); +// // how we tell the system we want this to become a secondary action for the previous button? +// registerContextAction(ca); +// } + } void QueryToolModule::staticAction_new(IPluginContentWidgetContext* context) { - auto *ct = new QueryTool(context, nullptr); - context->addContentWidget(this, ct); + auto *ct = new QueryTool(context, this); + + // Should we let constructor of PluginContentWidget do this? + // Saves a line but what if we don't want it. + context->addContentWidget(ct); + + // should content widget now to which module it belongs? + // That way the context would not need to keep track of this. + ct->newdoc(); } @@ -41,9 +72,11 @@ void QueryToolModule::staticAction_open(IPluginContentWidgetContext* context) 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 QueryTool(context, nullptr); - context->addContentWidget(this, ct); - ct->load(file_name); + auto *ct = new QueryTool(context, this); + context->addContentWidget(ct); + if (!ct->load(file_name)) { + // TODO load has failed remove widget or never add it? + } } } diff --git a/pglab/plugin_support/IPluginContentWidgetContext.h b/pglab/plugin_support/IPluginContentWidgetContext.h index c976ce9..5c531c0 100644 --- a/pglab/plugin_support/IPluginContentWidgetContext.h +++ b/pglab/plugin_support/IPluginContentWidgetContext.h @@ -47,7 +47,7 @@ public: const ModuleActionParameters &action_params ) = 0; - virtual void addContentWidget(PluginModule *module, PluginContentWidget *widget) = 0; + virtual void addContentWidget(PluginContentWidget *widget) = 0; virtual void removeContentWidget(PluginContentWidget *widget) = 0; /** Return a widget you can use as a parent diff --git a/pglab/plugin_support/LMainWindow.cpp b/pglab/plugin_support/LMainWindow.cpp index b3e2277..2a21feb 100644 --- a/pglab/plugin_support/LMainWindow.cpp +++ b/pglab/plugin_support/LMainWindow.cpp @@ -32,9 +32,9 @@ namespace LMainWindow_details { m_window->statusBar()->showMessage(msg); } - void addContentWidget(PluginModule *module, PluginContentWidget *widget) override + void addContentWidget(PluginContentWidget *widget) override { - PluginContentWidgetContextBase::addContentWidget(module, widget); + PluginContentWidgetContextBase::addContentWidget(widget); m_window->addPage(widget, ""); } @@ -207,9 +207,11 @@ void LMainWindow::tabWidget_currentChanged(int index) void LMainWindow::addModuleWidgetActionsForPage(PluginContentWidget *page) { m_context->addWidgetActionsToToolbar(page, m_mainToolBar); + m_context->addContextActionsToMenu(page, menuBar()); } void LMainWindow::removeModuleWidgetActionsForPage(PluginContentWidget *page) { + m_context->removeContextActionsFromMenu(page, menuBar()); m_context->removeWidgetActionsFromToolbar(page, m_mainToolBar); } diff --git a/pglab/plugin_support/PluginContentWidget.cpp b/pglab/plugin_support/PluginContentWidget.cpp index 39ff62d..83b9782 100644 --- a/pglab/plugin_support/PluginContentWidget.cpp +++ b/pglab/plugin_support/PluginContentWidget.cpp @@ -1,11 +1,22 @@ #include "PluginContentWidget.h" -PluginContentWidget::PluginContentWidget(IPluginContentWidgetContext *context, QWidget* parent) +PluginContentWidget::PluginContentWidget(IPluginContentWidgetContext *context, + PluginModule *module, QWidget* parent) : QWidget(parent) , m_context(context) + , m_pluginModule(module) {} bool PluginContentWidget::canClose() { return true; } + +QList PluginContentWidget::actions() +{ return QList(); } + +PluginModule *PluginContentWidget::pluginModule() +{ return m_pluginModule; } + +IPluginContentWidgetContext *PluginContentWidget::context() +{ return m_context; } diff --git a/pglab/plugin_support/PluginContentWidget.h b/pglab/plugin_support/PluginContentWidget.h index 64018d2..ee79c3e 100644 --- a/pglab/plugin_support/PluginContentWidget.h +++ b/pglab/plugin_support/PluginContentWidget.h @@ -20,17 +20,19 @@ class PluginModule; /// class PluginContentWidget: public QWidget{ public: - PluginContentWidget(IPluginContentWidgetContext *context, QWidget* parent = nullptr); + PluginContentWidget(IPluginContentWidgetContext *context, PluginModule *module, QWidget* parent = nullptr); /// Returns the toolbar buttons for this page virtual bool canClose(); - virtual QList actions() { return QList(); } + virtual QList actions(); + PluginModule *pluginModule(); + IPluginContentWidgetContext *context(); protected: - IPluginContentWidgetContext *context() { return m_context; } private: - IPluginContentWidgetContext *m_context; + IPluginContentWidgetContext *m_context = nullptr; + PluginModule *m_pluginModule = nullptr; }; #endif // PGLPAGE_H diff --git a/pglab/plugin_support/PluginContentWidgetContextBase.cpp b/pglab/plugin_support/PluginContentWidgetContextBase.cpp index 1749e61..f97e577 100644 --- a/pglab/plugin_support/PluginContentWidgetContextBase.cpp +++ b/pglab/plugin_support/PluginContentWidgetContextBase.cpp @@ -4,19 +4,43 @@ #include "PluginRegister.h" #include #include +#include #include #include -LWidgetData::LWidgetData(PluginModule *module) +LWidgetData::LWidgetData(PluginModule *module, PluginContentWidget *widget) : m_module(module) + , m_widget(widget) {} -void LWidgetData::init(PluginContentWidget *widget) +void LWidgetData::init() { } +void LWidgetData::addToMenu(QMenuBar *menubar) +{ + auto&& menu = menubar->actions().first()->menu(); + + auto ti = std::type_index(typeid(*m_widget)); + auto&& actions = m_module->actionsForContext(ti); + m_menuActions.reserve(actions.size()); + for (auto&& actiondef : actions) { + auto ac = actiondef->createAction(m_widget); + menu->addAction(ac); + m_menuActions.push_back(ac); + } +} + +void LWidgetData::removeFromMenu(QMenuBar *menubar) +{ + for (auto&& action : m_menuActions) { + delete action; + } + m_menuActions.clear(); +} + PluginContentWidgetContextBase::PluginContentWidgetContextBase() = default; @@ -41,13 +65,13 @@ void PluginContentWidgetContextBase::moduleAction( qWarning() << QString("module not found %1").arg(module_identifier); } -void PluginContentWidgetContextBase::addContentWidget(PluginModule *module, PluginContentWidget *widget) +void PluginContentWidgetContextBase::addContentWidget(PluginContentWidget *widget) { - auto res = m_widgetLst.emplace(widget, module); + auto res = m_widgetLst.emplace(widget, LWidgetData{widget->pluginModule(), widget}); if (!res.second) throw std::runtime_error("Unexpected conflicting key on insertiong PluginContentWidgetContextBase::addContentWidget"); - res.first->second.init(widget); + res.first->second.init(); } void PluginContentWidgetContextBase::removeContentWidget(PluginContentWidget *widget) @@ -64,6 +88,7 @@ void PluginContentWidgetContextBase::addWidgetActionsToToolbar(PluginContentWidg { auto && actions = widget->actions(); toolbar->addActions(actions); + } void PluginContentWidgetContextBase::removeWidgetActionsFromToolbar(PluginContentWidget *widget, QToolBar *toolbar) @@ -73,3 +98,20 @@ void PluginContentWidgetContextBase::removeWidgetActionsFromToolbar(PluginConten toolbar->removeAction(ac); } + +void PluginContentWidgetContextBase::addContextActionsToMenu(PluginContentWidget *widget, QMenuBar *menubar) +{ + auto res = m_widgetLst.find(widget); + if (res == m_widgetLst.end()) + return; + res->second.addToMenu(menubar); +} + +void PluginContentWidgetContextBase::removeContextActionsFromMenu(PluginContentWidget *widget, QMenuBar *menubar) +{ + auto res = m_widgetLst.find(widget); + if (res == m_widgetLst.end()) + return; + res->second.removeFromMenu(menubar); +} + diff --git a/pglab/plugin_support/PluginContentWidgetContextBase.h b/pglab/plugin_support/PluginContentWidgetContextBase.h index 0fa35e8..aeaa40c 100644 --- a/pglab/plugin_support/PluginContentWidgetContextBase.h +++ b/pglab/plugin_support/PluginContentWidgetContextBase.h @@ -3,10 +3,12 @@ #include "plugin_support/IPluginContentWidgetContext.h" #include +#include class LContextAction; class QToolBar; class QAction; +class QMenuBar; /// Maintains the list of actions added to a toolbar for a specific widget /// it facilitates the removal of all those actions. @@ -32,13 +34,19 @@ private: class LWidgetData { public: - LWidgetData(PluginModule *module); + LWidgetData(PluginModule *module, PluginContentWidget *widget); PluginModule* module() { return m_module; } - void init(PluginContentWidget *widget); + PluginContentWidget *widget() { return m_widget; } + void init(); + void addToMenu(QMenuBar* menubar); + void removeFromMenu(QMenuBar* menubar); private: PluginModule *m_module; + PluginContentWidget *m_widget; WidgetToolbarManager m_toolbarManager; + + std::vector m_menuActions; ///< List of actions we put in the menu }; /// Provides base implementation of IPluginContentWidgetContext @@ -53,16 +61,19 @@ public: const ModuleActionParameters &action_params ) override; - void addContentWidget(PluginModule *module, PluginContentWidget *widget) override; + void addContentWidget(PluginContentWidget *widget) override; void removeContentWidget(PluginContentWidget *widget) override; void addWidgetActionsToToolbar(PluginContentWidget *widget, QToolBar *toolbar); void removeWidgetActionsFromToolbar(PluginContentWidget *widget, QToolBar *toolbar); + + void addContextActionsToMenu(PluginContentWidget *widget, QMenuBar *menubar); + void removeContextActionsFromMenu(PluginContentWidget *widget, QMenuBar *menubar); private: using WidgetLst = std::map; - WidgetLst m_widgetLst; + WidgetLst m_widgetLst; /// Keeps track of which widget belongs to which module }; #endif // PLUGINCONTENTWIDGETCONTEXTBASE_H diff --git a/pglab/plugin_support/PluginModule.cpp b/pglab/plugin_support/PluginModule.cpp index 17ad3af..1074b25 100644 --- a/pglab/plugin_support/PluginModule.cpp +++ b/pglab/plugin_support/PluginModule.cpp @@ -1,5 +1,8 @@ #include "plugin_support/PluginModule.h" +#include "PluginContentWidget.h" #include +#include +#include PluginModule::PluginModule(QString name, QString ident) : m_name(std::move(name)) @@ -14,7 +17,6 @@ void PluginModule::setDisplayCategory(QString category) void PluginModule::registerStaticAction(StaticAction action) { - qDebug() << "registerMenuAction " << action.text(); m_menuActions.emplace_back(std::move(action)); } @@ -39,3 +41,28 @@ const PluginModule::ModuleAction* PluginModule::findModuleAction(const QString & return &res->second; } +void PluginModule::registerContextAction(std::shared_ptr action) +{ + auto find_result_iter = m_contextMap.find(action->contextTypeIndex()); + if (find_result_iter != m_contextMap.end()) + find_result_iter->second.push_back(action); + else + m_contextMap.emplace(action->contextTypeIndex(), ContextActionContainer({ action })); +} + +const PluginModule::ContextActionContainer &PluginModule::actionsForContext(std::type_index ti) +{ + static const ContextActionContainer empty_result; + + auto find_result_iter = m_contextMap.find(ti); + if (find_result_iter != m_contextMap.end()) + return find_result_iter->second; + + return empty_result; +} + +const PluginModule::ContextActionContainer& PluginModule::actionsForContext(PluginContentWidget *widget) +{ + return actionsForContext(std::type_index(typeid(*widget))); +} + diff --git a/pglab/plugin_support/PluginModule.h b/pglab/plugin_support/PluginModule.h index 73ee685..f212fa5 100644 --- a/pglab/plugin_support/PluginModule.h +++ b/pglab/plugin_support/PluginModule.h @@ -7,11 +7,20 @@ #include #include #include +#include +#include #include +#include class QAction; class IPluginContentWidgetContext; +class PluginContentWidget; +/** Defines available actions for the application framework. + * + * There are static and context actions. + * There can be multiple contexts which are seperated by there typeid/type_index. + */ class PluginModule: public QObject { Q_OBJECT public: @@ -19,6 +28,8 @@ public: using ModuleAction = std::function; using ModuleActionMap = std::map; + using ContextActionContainer = std::vector>; + PluginModule(QString name, QString ident); virtual void init() {} @@ -41,7 +52,15 @@ public: /// When the action is not found nullptr is returned. const ModuleAction* findModuleAction(const QString &module_action) const; + void registerContextAction(std::shared_ptr action); + + std::set contextTypeIndexes(); + const ContextActionContainer& actionsForContext(std::type_index ti); + const ContextActionContainer& actionsForContext(PluginContentWidget *widget); + private: + using ContextMap = std::unordered_map; + /// Name shown to end users QString m_name; /// Unique identifier @@ -50,6 +69,7 @@ private: StaticActionList m_menuActions; ModuleActionMap m_moduleActions; + ContextMap m_contextMap; }; diff --git a/pglab/plugin_support/StaticAction.cpp b/pglab/plugin_support/StaticAction.cpp index 272c431..a537fb0 100644 --- a/pglab/plugin_support/StaticAction.cpp +++ b/pglab/plugin_support/StaticAction.cpp @@ -1,67 +1,75 @@ #include "StaticAction.h" -StaticAction::StaticAction(QString text, Func func) - : m_text(std::move(text)) - , m_func(std::move(func)) +BaseAction::BaseAction(const QString &text) + : m_text(text) {} -const QIcon& StaticAction::icon() const +const QIcon& BaseAction::icon() const { return m_icon; } -const MenuLocation& StaticAction::menuLocation() const +const MenuLocation& BaseAction::menuLocation() const { return m_menuLocation; } -void StaticAction::setIcon(QIcon icon) +void BaseAction::setIcon(QIcon icon) { m_icon = std::move(icon); } -void StaticAction::setMenuLocation(MenuLocation menu_location) +void BaseAction::setMenuLocation(MenuLocation menu_location) { m_menuLocation = std::move(menu_location); } -void StaticAction::setToolbarLocation(ToolbarLocation toolbar_location) +void BaseAction::setToolbarLocation(ToolbarLocation toolbar_location) { m_toolbarLocation = toolbar_location; } -void StaticAction::setShortcut(QKeySequence shortcut) +void BaseAction::setShortcut(QKeySequence shortcut) { m_shortcut = std::move(shortcut); } -void StaticAction::setText(QString text) +void BaseAction::setText(QString text) { m_text = std::move(text); } -void StaticAction::setToolTip(QString tooltip) +void BaseAction::setToolTip(QString tooltip) { m_toolTip = std::move(tooltip); } -const QKeySequence& StaticAction::shortcut() const +const QKeySequence& BaseAction::shortcut() const { return m_shortcut; } -const QString& StaticAction::text() const +const QString& BaseAction::text() const { return m_text; } -const QString& StaticAction::toolTip() const +const QString& BaseAction::toolTip() const { return m_toolTip; } +StaticAction::StaticAction(QString text, Func func) + : BaseAction(std::move(text)) + , m_func(std::move(func)) +{} + void StaticAction::perform(IPluginContentWidgetContext *context) const { if (m_func) m_func(context); } + + +ContextBaseAction::~ContextBaseAction() +{} diff --git a/pglab/plugin_support/StaticAction.h b/pglab/plugin_support/StaticAction.h index 16559b5..f342dbe 100644 --- a/pglab/plugin_support/StaticAction.h +++ b/pglab/plugin_support/StaticAction.h @@ -3,24 +3,20 @@ #include "MenuLocation.h" #include "ToolbarLocation.h" +#include "plugin_support/PluginContentWidget.h" +#include #include #include #include #include +#include class IPluginContentWidgetContext; -/** An action for in a menu or toolbar that does not pertain to a specific - * widget. It often will create a widget for instance a New or Open action. - * It does need a context. - * - */ -class StaticAction { +class BaseAction { public: - using Func = std::function; - - StaticAction(QString text, Func func); + explicit BaseAction(const QString &text); const QIcon& icon() const; const MenuLocation& menuLocation() const; @@ -34,7 +30,6 @@ public: const QString& text() const; const QString& toolTip() const; - void perform(IPluginContentWidgetContext *context) const; private: QString m_text; QString m_toolTip; @@ -43,7 +38,85 @@ private: MenuLocation m_menuLocation; ToolbarLocation m_toolbarLocation; +}; +/** An action for in a menu or toolbar that does not pertain to a specific + * widget. It often will create a widget for instance a New or Open action. + * It does need a context. + * + */ +class StaticAction: public BaseAction { +public: + using Func = std::function; + + StaticAction(QString text, Func func); + + + void perform(IPluginContentWidgetContext *context) const; +private: + Func m_func; }; + +class ContextBaseAction: public BaseAction { +public: + using BaseAction::BaseAction; + virtual ~ContextBaseAction(); + + virtual std::type_index contextTypeIndex() const = 0; + + virtual QAction* createAction(PluginContentWidget *widget) + { + auto action = new QAction(widget); + action->setText(text()); + setupConnectionForAction(action, widget); + return action; + } + + virtual void setupConnectionForAction(QAction *action, PluginContentWidget *context) = 0; +}; + +class QAction; + +/** Defines an action that can be performed within a certain context. + * For instance the save action for a query can only be called when a query is loaded. + * + * Note Func should be something that QAction::triggered can connect to. If not you + * could get quite a vague error. + */ +template +class ContextAction: public ContextBaseAction { +public: + //using Func = void (Context::*)(bool); + + ContextAction(QString text, Func func) + : ContextBaseAction(text) + , m_func(func) + {} + + std::type_index contextTypeIndex() const override + { + return std::type_index(typeid(Context)); + } + + // Mostly a helper for the code that creates the QAction + // without the helper that would need template code to. + virtual void setupConnectionForAction(QAction *action, PluginContentWidget *context) override + { + QObject::connect(action, &QAction::triggered, dynamic_cast(context), m_func); + } + +private: + Func m_func; +}; + +template +auto makeContextAction(QString text, Func func) +{ + return std::make_shared>(text, func); +} + + + + #endif // MENUACTION_H