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