WIP: further refactoring.

This commit is contained in:
Matthias Koefferlein 2020-02-10 00:07:41 +01:00
parent e8a875ccb5
commit 45b6a72bee
6 changed files with 124 additions and 89 deletions

1
TODO
View File

@ -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

View File

@ -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 <lay::LayoutView *>::iterator vp = mp_views.begin (); vp != mp_views.end (); ++vp) {

View File

@ -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<AbstractMenuItem>::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<AbstractMenuItem>::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<AbstractMenuItem>::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 ();

View File

@ -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: <text>["("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 <AbstractMenuItem> 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<std::string> m_groups;
@ -831,10 +859,9 @@ private:
* The format of the string is: <text>["("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

View File

@ -100,18 +100,17 @@ PluginDeclaration::generic_menu ()
{
BEGIN_PROTECTED
QAction *action = dynamic_cast <QAction *> (sender ());
tl_assert (action);
std::string symbol = tl::to_string (action->data ().toString ());
ActionHandle *action_handle = dynamic_cast <ActionHandle *> (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<QAction *> (sender ());
if (action) {
ActionHandle *action_handle = dynamic_cast<ActionHandle *> (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 <lay::Action>::iterator a = m_menu_actions.begin (); a != m_menu_actions.end (); ++a) {

View File

@ -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