From 45b6a72beef05707700d3a52b945c239b4550434 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 10 Feb 2020 00:07:41 +0100 Subject: [PATCH] WIP: further refactoring. --- TODO | 1 + src/lay/lay/layMainWindow.cc | 2 +- src/laybasic/laybasic/layAbstractMenu.cc | 95 ++++++++++++++---------- src/laybasic/laybasic/layAbstractMenu.h | 68 +++++++++++------ src/laybasic/laybasic/layPlugin.cc | 45 +++++------ src/laybasic/laybasic/layPlugin.h | 2 +- 6 files changed, 124 insertions(+), 89 deletions(-) diff --git a/TODO b/TODO index 874152466..f53481150 100644 --- a/TODO +++ b/TODO @@ -39,4 +39,5 @@ Tests: - changing of macro title, move macro to different place - funktionieren die check marks vor den menus? (Mode, selection modes, ruler template) - check whether there is a replacement for the "cm_..." methods and tests them (at least one) + - check if changing the default grid works diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 0ede5654d..b80164781 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -4056,7 +4056,7 @@ MainWindow::plugin_registered (lay::PluginDeclaration *cls) void MainWindow::plugin_removed (lay::PluginDeclaration *cls) { - cls->remove_menu_items (); + cls->remove_menu_items (this); // recreate all plugins except the one that got removed for (std::vector ::iterator vp = mp_views.begin (); vp != mp_views.end (); ++vp) { diff --git a/src/laybasic/laybasic/layAbstractMenu.cc b/src/laybasic/laybasic/layAbstractMenu.cc index 87f4e29d5..acb8d169f 100644 --- a/src/laybasic/laybasic/layAbstractMenu.cc +++ b/src/laybasic/laybasic/layAbstractMenu.cc @@ -195,14 +195,14 @@ parse_menu_title (const std::string &s, std::string &title, std::string &shortcu // --------------------------------------------------------------- // AbstractMenuItem implementation -AbstractMenuItem::AbstractMenuItem () - : m_has_submenu (false), m_remove_on_empty (false) +AbstractMenuItem::AbstractMenuItem (Dispatcher *dispatcher) + : m_action (), mp_dispatcher (dispatcher), m_has_submenu (false), m_remove_on_empty (false) { // ... nothing yet .. } -AbstractMenuItem::AbstractMenuItem (const AbstractMenuItem &) - : m_has_submenu (false), m_remove_on_empty (false) +AbstractMenuItem::AbstractMenuItem (const AbstractMenuItem &item) + : m_action (), mp_dispatcher (item.dispatcher ()), m_has_submenu (false), m_remove_on_empty (false) { // ... nothing yet .. } @@ -249,9 +249,11 @@ AbstractMenuItem::set_action (const Action &a, bool copy_properties) bool enabled = m_action.is_enabled (); bool visible = m_action.is_visible (); + m_action.handle ()->set_dispatcher (0); m_action = acopy; m_action.set_enabled (enabled); m_action.set_visible (visible); + m_action.handle ()->set_dispatcher (mp_dispatcher); m_action.set_object_name (m_basename); @@ -346,9 +348,10 @@ id_from_action (QAction *action) return ao ? ao->id () : 0; } -ActionHandle::ActionHandle (QWidget *parent) +ActionHandle::ActionHandle () : mp_menu (0), - mp_action (new ActionObject (parent)), + mp_action (new ActionObject (0)), + mp_dispatcher (0), m_ref_count (0), m_owned (true), m_visible (true), @@ -362,11 +365,13 @@ ActionHandle::ActionHandle (QWidget *parent) // catch the destroyed signal to tell if the QAction object is deleted. connect (mp_action, SIGNAL (destroyed (QObject *)), this, SLOT (destroyed (QObject *))); + connect (mp_action, SIGNAL (triggered ()), this, SLOT (qaction_triggered ())); } ActionHandle::ActionHandle (QAction *action, bool owned) : mp_menu (0), mp_action (action), + mp_dispatcher (0), m_ref_count (0), m_owned (owned), m_visible (true), @@ -380,11 +385,13 @@ ActionHandle::ActionHandle (QAction *action, bool owned) // catch the destroyed signal to tell if the QAction object is deleted. connect (mp_action, SIGNAL (destroyed (QObject *)), this, SLOT (destroyed (QObject *))); + connect (mp_action, SIGNAL (triggered ()), this, SLOT (qaction_triggered ())); } ActionHandle::ActionHandle (QMenu *menu, bool owned) : mp_menu (menu), mp_action (menu->menuAction ()), + mp_dispatcher (0), m_ref_count (0), m_owned (owned), m_visible (true), @@ -398,6 +405,7 @@ ActionHandle::ActionHandle (QMenu *menu, bool owned) // catch the destroyed signal to tell if the QAction object is deleted. connect (mp_menu, SIGNAL (destroyed (QObject *)), this, SLOT (destroyed (QObject *))); + connect (mp_action, SIGNAL (triggered ()), this, SLOT (qaction_triggered ())); } ActionHandle::~ActionHandle () @@ -426,6 +434,23 @@ ActionHandle::~ActionHandle () } } +void +ActionHandle::set_dispatcher (Dispatcher *dispatcher) +{ + if (mp_dispatcher != dispatcher) { + if (mp_action && m_owned) { + mp_action->setParent (dispatcher ? dispatcher->menu_parent_widget () : 0); + } + mp_dispatcher = dispatcher; + } +} + +void +ActionHandle::qaction_triggered () +{ + emit triggered (); +} + void ActionHandle::add_ref () { @@ -580,11 +605,9 @@ ActionHandle::get_key_sequence_for (const std::string &sc) const Action::Action () : mp_handle (0) { - if (lay::Dispatcher::instance ()) { - mp_handle = new ActionHandle (lay::Dispatcher::instance ()->menu_parent_widget ()); - gtf::action_connect (mp_handle->ptr (), SIGNAL (triggered ()), this, SLOT (triggered_slot ())); - mp_handle->add_ref (); - } + mp_handle = new ActionHandle (); + connect (mp_handle, SIGNAL (triggered ()), this, SLOT (triggered_slot ())); + mp_handle->add_ref (); } const std::string & @@ -596,30 +619,24 @@ Action::no_shortcut () Action::Action (const std::string &title) { - mp_handle = AbstractMenu::create_action (title, 0); - gtf::action_connect (mp_handle->ptr (), SIGNAL (triggered ()), this, SLOT (triggered_slot ())); + mp_handle = AbstractMenu::create_action (title); + connect (mp_handle, SIGNAL (triggered ()), this, SLOT (triggered_slot ())); mp_handle->add_ref (); } Action::Action (ActionHandle *handle) { mp_handle = handle; - gtf::action_connect (mp_handle->ptr (), SIGNAL (triggered ()), this, SLOT (triggered_slot ())); + connect (mp_handle, SIGNAL (triggered ()), this, SLOT (triggered_slot ())); mp_handle->add_ref (); } -Action -Action::create_free_action (QWidget *parent) -{ - return Action (new ActionHandle (parent)); -} - Action::Action (const Action &action) : QObject () { mp_handle = action.mp_handle; if (mp_handle) { - gtf::action_connect (mp_handle->ptr (), SIGNAL (triggered ()), this, SLOT (triggered_slot ())); + connect (mp_handle, SIGNAL (triggered ()), this, SLOT (triggered_slot ())); mp_handle->add_ref (); } } @@ -630,14 +647,14 @@ Action::operator= (const Action &action) if (this != &action) { if (mp_handle) { if (mp_handle->ptr ()) { - gtf::action_disconnect (mp_handle->ptr (), SIGNAL (triggered ()), this, SLOT (triggered_slot ())); + connect (mp_handle, SIGNAL (triggered ()), this, SLOT (triggered_slot ())); } mp_handle->remove_ref (); mp_handle = 0; } mp_handle = action.mp_handle; if (mp_handle) { - gtf::action_connect (mp_handle->ptr (), SIGNAL (triggered ()), this, SLOT (triggered_slot ())); + connect (mp_handle, SIGNAL (triggered ()), this, SLOT (triggered_slot ())); mp_handle->add_ref (); } } @@ -648,7 +665,7 @@ Action::~Action () { if (mp_handle) { if (mp_handle->ptr ()) { - gtf::action_disconnect (mp_handle->ptr (), SIGNAL (triggered ()), this, SLOT (triggered_slot ())); + connect (mp_handle, SIGNAL (triggered ()), this, SLOT (triggered_slot ())); } mp_handle->remove_ref (); mp_handle = 0; @@ -927,13 +944,13 @@ Action::set_object_name (const std::string &name) // ConfigureAction implementation ConfigureAction::ConfigureAction (lay::Dispatcher *dispatcher) - : Action (), m_dispatcher (dispatcher), m_type (ConfigureAction::setter_type) + : Action (), mp_dispatcher (dispatcher), m_type (ConfigureAction::setter_type) { // .. nothing yet .. } ConfigureAction::ConfigureAction (lay::Dispatcher *dispatcher, const std::string &cname, const std::string &cvalue) - : Action (), m_dispatcher (dispatcher), m_cname (cname), m_cvalue (cvalue), m_type (ConfigureAction::setter_type) + : Action (), mp_dispatcher (dispatcher), m_cname (cname), m_cvalue (cvalue), m_type (ConfigureAction::setter_type) { if (cvalue == "?") { m_type = boolean_type; @@ -944,7 +961,7 @@ ConfigureAction::ConfigureAction (lay::Dispatcher *dispatcher, const std::string } ConfigureAction::ConfigureAction (lay::Dispatcher *dispatcher, const std::string &title, const std::string &cname, const std::string &cvalue) - : Action (title), m_dispatcher (dispatcher), m_cname (cname), m_cvalue (cvalue), m_type (ConfigureAction::setter_type) + : Action (title), mp_dispatcher (dispatcher), m_cname (cname), m_cvalue (cvalue), m_type (ConfigureAction::setter_type) { if (cvalue == "?") { // A "?" notation indicates a boolean toogle entry @@ -972,19 +989,19 @@ ConfigureAction::triggered () m_cvalue = tl::to_string (is_checked ()); } - m_dispatcher->config_set (m_cname, m_cvalue); + mp_dispatcher->config_set (m_cname, m_cvalue); } void ConfigureAction::reg () { - m_dispatcher->register_config_action (m_cname, this); + mp_dispatcher->register_config_action (m_cname, this); } void ConfigureAction::unreg () { - m_dispatcher->unregister_config_action (m_cname, this); + mp_dispatcher->unregister_config_action (m_cname, this); } void @@ -1010,7 +1027,7 @@ ConfigureAction::configure (const std::string &value) // AbstractMenu implementation ActionHandle * -AbstractMenu::create_action (const std::string &s, lay::Dispatcher *dispatcher) +AbstractMenu::create_action (const std::string &s) { std::string title; std::string shortcut; @@ -1019,7 +1036,7 @@ AbstractMenu::create_action (const std::string &s, lay::Dispatcher *dispatcher) parse_menu_title (s, title, shortcut, res, tool_tip); - ActionHandle *ah = new ActionHandle (dispatcher ? dispatcher->menu_parent_widget () : 0); + ActionHandle *ah = new ActionHandle (); ah->ptr ()->setText (tl::to_qstring (title)); if (! tool_tip.empty ()) { @@ -1038,7 +1055,7 @@ AbstractMenu::create_action (const std::string &s, lay::Dispatcher *dispatcher) } AbstractMenu::AbstractMenu (Dispatcher *dispatcher) - : mp_dispatcher (dispatcher) + : mp_dispatcher (dispatcher), m_root (dispatcher) { // .. nothing yet .. } @@ -1380,7 +1397,7 @@ AbstractMenu::insert_item (const std::string &p, const std::string &name, const std::list::iterator iter = path.back ().second; // insert the new item - parent->children.insert (iter, AbstractMenuItem ()); + parent->children.insert (iter, AbstractMenuItem (mp_dispatcher)); --iter; iter->setup_item (parent->name (), name, action); @@ -1413,9 +1430,9 @@ AbstractMenu::insert_separator (const std::string &p, const std::string &name) AbstractMenuItem *parent = path.back ().first; std::list::iterator iter = path.back ().second; - parent->children.insert (iter, AbstractMenuItem ()); + parent->children.insert (iter, AbstractMenuItem (mp_dispatcher)); --iter; - Action action (new ActionHandle (mp_dispatcher->menu_parent_widget ())); + Action action (new ActionHandle ()); action.set_separator (true); iter->setup_item (parent->name (), name, action); @@ -1435,7 +1452,7 @@ AbstractMenu::insert_menu (const std::string &p, const std::string &name, const AbstractMenuItem *parent = path.back ().first; std::list::iterator iter = path.back ().second; - parent->children.insert (iter, AbstractMenuItem ()); + parent->children.insert (iter, AbstractMenuItem (mp_dispatcher)); --iter; iter->setup_item (parent->name (), name, action); iter->set_has_submenu (); @@ -1458,7 +1475,7 @@ AbstractMenu::insert_menu (const std::string &p, const std::string &name, const void AbstractMenu::insert_menu (const std::string &path, const std::string &name, const std::string &title) { - insert_menu (path, name, create_action (title, mp_dispatcher)); + insert_menu (path, name, create_action (title)); } void @@ -1694,7 +1711,7 @@ AbstractMenu::find_item (tl::Extractor &extr) } if (parent) { - parent->children.insert (iter, AbstractMenuItem ()); + parent->children.insert (iter, AbstractMenuItem (mp_dispatcher)); --iter; iter->setup_item (parent->name (), n, Action ()); iter->set_has_submenu (); diff --git a/src/laybasic/laybasic/layAbstractMenu.h b/src/laybasic/laybasic/layAbstractMenu.h index 1f9768660..4d8e11fee 100644 --- a/src/laybasic/laybasic/layAbstractMenu.h +++ b/src/laybasic/laybasic/layAbstractMenu.h @@ -83,7 +83,7 @@ class ActionHandle Q_OBJECT public: - ActionHandle (QWidget *parent); + ActionHandle (); ActionHandle (QAction *action, bool owned = true); ActionHandle (QMenu *menu, bool owned = true); ~ActionHandle (); @@ -91,6 +91,10 @@ public: void remove_ref (); QAction *ptr () const; QMenu *menu () const; + Dispatcher *dispatcher () { return mp_dispatcher; } + + void set_symbol (const std::string &s) { m_symbol = s; } + const std::string &symbol () const { return m_symbol; } void set_visible (bool v); void set_hidden (bool h); @@ -105,12 +109,19 @@ public: QKeySequence get_key_sequence () const; QKeySequence get_key_sequence_for (const std::string &sc) const; +signals: + void triggered (); + protected slots: void destroyed (QObject *obj); + void qaction_triggered (); private: + friend struct AbstractMenuItem; + QMenu *mp_menu; QAction *mp_action; + lay::Dispatcher *mp_dispatcher; int m_ref_count; bool m_owned; bool m_visible; @@ -118,9 +129,12 @@ private: std::string m_default_shortcut; QKeySequence m_default_key_sequence; std::string m_shortcut; + std::string m_symbol; QKeySequence m_key_sequence; bool m_no_key_sequence; + void set_dispatcher (Dispatcher *dispatcher); + // no copying ActionHandle (const ActionHandle &); ActionHandle &operator= (const ActionHandle &); @@ -147,11 +161,11 @@ Q_OBJECT public: /** - * @brief The default constructor + * @brief The main constructor * * This constructor creates an QAction object internally which is owned by the Action object. */ - Action (); + Action (); /** * @brief The copy constructor @@ -161,20 +175,13 @@ public: Action (const Action &action); /** - * @brief Create an action with the given title (icon, keyboard shortcut) + * @brief Creates an action with the given title (icon, keyboard shortcut) * * The format of the title string is: ["("shortcut")"]["<"icon-resource">"] * * @param title The title string encoding icon and keyboard shortcut if applicable. */ - Action (const std::string &title); - - /** - * @brief Creates a new free action - * This constructor wil create a new action with it's own QAction object - * under the given parent. - */ - static Action create_free_action (QWidget *parent); + Action (const std::string &title); /** * @brief Assignement @@ -375,6 +382,24 @@ public: */ QMenu *menu () const; + /** + * @brief Gets the handle + * The handle is the representative of the menu entry which is shared + * by all Action copies. + */ + ActionHandle *handle () + { + return mp_handle; + } + + /** + * @brief Gets the dispatcher object this action is connected to + */ + Dispatcher *dispatcher () const + { + return mp_handle->dispatcher (); + } + /** * @brief Compares two action objects * @@ -418,15 +443,12 @@ public: /** * @brief The default constructor - * - * @param dispatcher The reference to the dispatcher object which receives the configure request */ ConfigureAction (lay::Dispatcher *dispatcher); /** * @brief Create an configure action with the given name and value * - * @param dispatcher The reference to the dispatcher object which receives the configure request * @param cname The name of the configuration parameter to set * @param cvalue The value to set "cname" to * @@ -504,7 +526,7 @@ private: ConfigureAction (const ConfigureAction &action); ConfigureAction &operator= (const ConfigureAction &action); - lay::Dispatcher *m_dispatcher; + lay::Dispatcher *mp_dispatcher; std::string m_cname, m_cvalue; type m_type; }; @@ -514,7 +536,7 @@ private: */ struct LAYBASIC_PUBLIC AbstractMenuItem { - AbstractMenuItem (); + AbstractMenuItem (lay::Dispatcher *dispatcher); // No copy constructor semantics because we don't need it (we use list's) and Action does not provide one. AbstractMenuItem (const AbstractMenuItem &); @@ -524,6 +546,11 @@ struct LAYBASIC_PUBLIC AbstractMenuItem */ void setup_item (const std::string &pn, const std::string &n, const Action &a); + Dispatcher *dispatcher () const + { + return mp_dispatcher; + } + const std::string &name () const { return m_name; @@ -565,9 +592,10 @@ struct LAYBASIC_PUBLIC AbstractMenuItem std::list children; private: + Action m_action; + Dispatcher *mp_dispatcher; bool m_has_submenu; bool m_remove_on_empty; - Action m_action; std::string m_name; std::string m_basename; std::set m_groups; @@ -831,10 +859,9 @@ private: * The format of the string is: ["("shortcut")"]["<"icon-resource">"] * * @param s The title, key and icon resource string in the format given above - * @param provider The abstract menu provider (the global one will be used if this instance is 0) * @return The ActionHandle object created */ - static ActionHandle *create_action (const std::string &s, lay::Dispatcher *dispatcher); + static ActionHandle *create_action (const std::string &s); Dispatcher *mp_dispatcher; AbstractMenuItem m_root; @@ -850,7 +877,6 @@ namespace tl typedef tl::false_tag has_copy_constructor; typedef tl::false_tag has_default_constructor; }; - } #endif diff --git a/src/laybasic/laybasic/layPlugin.cc b/src/laybasic/laybasic/layPlugin.cc index bb34af587..538493994 100644 --- a/src/laybasic/laybasic/layPlugin.cc +++ b/src/laybasic/laybasic/layPlugin.cc @@ -100,18 +100,17 @@ PluginDeclaration::generic_menu () { BEGIN_PROTECTED - QAction *action = dynamic_cast (sender ()); - tl_assert (action); - - std::string symbol = tl::to_string (action->data ().toString ()); + ActionHandle *action_handle = dynamic_cast (sender ()); + tl_assert (action_handle); + tl_assert (action_handle->dispatcher () != 0); // Global handler: give the declaration a chance to handle the menu request globally - if (menu_activated (symbol)) { + if (menu_activated (action_handle->symbol ())) { return; } // Forward the request to the plugin root which will propagate it down to the plugins - lay::Dispatcher::instance ()->menu_activated (symbol); + action_handle->dispatcher ()->menu_activated (action_handle->symbol ()); END_PROTECTED } @@ -121,18 +120,15 @@ PluginDeclaration::mode_triggered () { BEGIN_PROTECTED - QAction *action = dynamic_cast (sender ()); - if (action) { + ActionHandle *action_handle = dynamic_cast (sender ()); + tl_assert (action_handle != 0); + tl_assert (action_handle->dispatcher () != 0); - int mode = action->data ().toInt (); + int mode = 0; + tl::from_string (action_handle->symbol (), mode); - if (lay::Dispatcher::instance ()) { - lay::Dispatcher::instance ()->select_mode (mode); - } - - action->setChecked (true); - - } + action_handle->dispatcher ()->select_mode (mode); + action_handle->ptr ()->setChecked (true); END_PROTECTED } @@ -172,7 +168,6 @@ PluginDeclaration::init_menu (lay::Dispatcher *dispatcher) m_editable_mode_action = Action (title); gtf::action_connect (m_editable_mode_action.qaction (), SIGNAL (triggered ()), this, SLOT (toggle_editable_enabled ())); - m_editable_mode_action.qaction ()->setData (id ()); m_editable_mode_action.set_checkable (true); m_editable_mode_action.set_checked (m_editable_enabled); @@ -209,8 +204,8 @@ PluginDeclaration::init_menu (lay::Dispatcher *dispatcher) } else { action = new Action (m->title); - action->qaction ()->setData (QVariant (tl::to_qstring (m->symbol))); - gtf::action_connect (action->qaction (), SIGNAL (triggered ()), this, SLOT (generic_menu ())); + action->handle ()->set_symbol (m->symbol); + connect (action->handle (), SIGNAL (triggered ()), this, SLOT (generic_menu ())); m_our_menu_actions.push_back (action); } @@ -262,23 +257,19 @@ PluginDeclaration::init_menu (lay::Dispatcher *dispatcher) m_mouse_mode_action = Action (title); m_mouse_mode_action.add_to_exclusive_group (&menu, "mouse_mode_exclusive_group"); m_mouse_mode_action.set_checkable (true); - m_mouse_mode_action.qaction ()->setData (QVariant (m->second.second)); + m_mouse_mode_action.handle ()->set_symbol (tl::to_string (m->second.second)); menu.insert_item (m->second.first, name + ":mode_group", m_mouse_mode_action); - gtf::action_connect (m_mouse_mode_action.qaction (), SIGNAL (triggered ()), this, SLOT (mode_triggered ())); + connect (m_mouse_mode_action.handle (), SIGNAL (triggered ()), this, SLOT (mode_triggered ())); } } void -PluginDeclaration::remove_menu_items () +PluginDeclaration::remove_menu_items (Dispatcher *dispatcher) { - if (! lay::Dispatcher::instance () || ! lay::Dispatcher::instance ()->menu ()) { - return; - } - - lay::AbstractMenu *menu = lay::Dispatcher::instance ()->menu (); + lay::AbstractMenu *menu = dispatcher->menu (); menu->delete_items (m_editable_mode_action); menu->delete_items (m_mouse_mode_action); for (tl::weak_collection ::iterator a = m_menu_actions.begin (); a != m_menu_actions.end (); ++a) { diff --git a/src/laybasic/laybasic/layPlugin.h b/src/laybasic/laybasic/layPlugin.h index f9ac69b19..59860887b 100644 --- a/src/laybasic/laybasic/layPlugin.h +++ b/src/laybasic/laybasic/layPlugin.h @@ -421,7 +421,7 @@ public: /** * @brief Removes the menu resources associated with this plugin */ - void remove_menu_items (); + void remove_menu_items (lay::Dispatcher *dispatcher); /** * @brief Enables this editable part of the plugin