WIP: not quite further ...

This commit is contained in:
Matthias Koefferlein 2020-02-04 23:54:29 +01:00
parent 22b3a5face
commit b2e6085ba1
8 changed files with 147 additions and 46 deletions

View File

@ -590,7 +590,7 @@ Action::no_shortcut ()
Action::Action (const std::string &title) Action::Action (const std::string &title)
{ {
mp_handle = AbstractMenu::create_action (title); mp_handle = AbstractMenu::create_action (title, 0);
gtf::action_connect (mp_handle->ptr (), SIGNAL (triggered ()), this, SLOT (triggered_slot ())); gtf::action_connect (mp_handle->ptr (), SIGNAL (triggered ()), this, SLOT (triggered_slot ()));
mp_handle->add_ref (); mp_handle->add_ref ();
} }
@ -1008,9 +1008,12 @@ ConfigureAction::configure (const std::string &value)
// AbstractMenu implementation // AbstractMenu implementation
ActionHandle * ActionHandle *
AbstractMenu::create_action (const std::string &s) AbstractMenu::create_action (const std::string &s, AbstractMenuProvider *provider)
{ {
tl_assert (lay::AbstractMenuProvider::instance () != 0); if (! provider) {
provider = lay::AbstractMenuProvider::instance ();
}
tl_assert (provider != 0);
std::string title; std::string title;
std::string shortcut; std::string shortcut;
@ -1019,7 +1022,7 @@ AbstractMenu::create_action (const std::string &s)
parse_menu_title (s, title, shortcut, res, tool_tip); parse_menu_title (s, title, shortcut, res, tool_tip);
ActionHandle *ah = new ActionHandle (lay::AbstractMenuProvider::instance ()->menu_parent_widget ()); ActionHandle *ah = new ActionHandle (provider->menu_parent_widget ());
ah->ptr ()->setText (tl::to_qstring (title)); ah->ptr ()->setText (tl::to_qstring (title));
if (! tool_tip.empty ()) { if (! tool_tip.empty ()) {
@ -1129,15 +1132,17 @@ AbstractMenu::build_detached (const std::string &name, QFrame *mbar)
void void
AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar) AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
{ {
tl_assert (mp_provider != 0);
m_helper_menu_items.clear (); m_helper_menu_items.clear ();
tbar->clear (); if (tbar) {
tbar->clear ();
}
std::set<std::pair<size_t, QAction *> > present_actions; std::set<std::pair<size_t, QAction *> > present_actions;
QList<QAction *> a = mbar->actions (); if (mbar) {
for (QList<QAction *>::const_iterator i = a.begin (); i != a.end (); ++i) { QList<QAction *> a = mbar->actions ();
present_actions.insert (std::make_pair (id_from_action (*i), *i)); for (QList<QAction *>::const_iterator i = a.begin (); i != a.end (); ++i) {
present_actions.insert (std::make_pair (id_from_action (*i), *i));
}
} }
for (std::list<AbstractMenuItem>::iterator c = m_root.children.begin (); c != m_root.children.end (); ++c) { for (std::list<AbstractMenuItem>::iterator c = m_root.children.begin (); c != m_root.children.end (); ++c) {
@ -1146,7 +1151,9 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
if (c->name () == "@toolbar") { if (c->name () == "@toolbar") {
build (tbar, c->children); if (tbar) {
build (tbar, c->children);
}
} else if (c->name ().find ("@@") == 0) { } else if (c->name ().find ("@@") == 0) {
@ -1160,14 +1167,16 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
// Otherwise, the keyboard shortcuts do not work for menu items inside such a // Otherwise, the keyboard shortcuts do not work for menu items inside such a
// popup menu. It seems not to have a negative effect to add the menu to the // popup menu. It seems not to have a negative effect to add the menu to the
// main widget. // main widget.
mp_provider->menu_parent_widget ()->addAction (menu->menuAction ()); if (mp_provider) {
mp_provider->menu_parent_widget ()->addAction (menu->menuAction ());
}
c->set_action (Action (new ActionHandle (menu)), true); c->set_action (Action (new ActionHandle (menu)), true);
} }
// prepare a detached menu which can be used as context menues // prepare a detached menu which can be used as context menues
build (c->menu (), c->children); build (c->menu (), c->children);
} else { } else if (mbar) {
if (c->menu () == 0) { if (c->menu () == 0) {
QMenu *menu = new QMenu (); QMenu *menu = new QMenu ();
@ -1192,7 +1201,7 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
} }
} else { } else if (mbar) {
// Move the action to the end if present in the menu already // Move the action to the end if present in the menu already
std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.find (std::make_pair (id_from_action (c->action ().qaction ()), c->action ().qaction ())); std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.find (std::make_pair (id_from_action (c->action ().qaction ()), c->action ().qaction ()));
if (a != present_actions.end ()) { if (a != present_actions.end ()) {
@ -1209,8 +1218,10 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
} }
// Remove all actions that have vanished // Remove all actions that have vanished
for (std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.begin (); a != present_actions.end (); ++a) { if (mbar) {
mbar->removeAction (a->second); for (std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.begin (); a != present_actions.end (); ++a) {
mbar->removeAction (a->second);
}
} }
} }
@ -1399,8 +1410,6 @@ AbstractMenu::insert_item (const std::string &p, const std::string &name, const
void void
AbstractMenu::insert_separator (const std::string &p, const std::string &name) AbstractMenu::insert_separator (const std::string &p, const std::string &name)
{ {
tl_assert (mp_provider != 0); // required to get the parent for the new QAction (via ActionHandle)
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type; typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
path_type path = find_item (p); path_type path = find_item (p);
if (! path.empty ()) { if (! path.empty ()) {
@ -1410,7 +1419,7 @@ AbstractMenu::insert_separator (const std::string &p, const std::string &name)
parent->children.insert (iter, AbstractMenuItem ()); parent->children.insert (iter, AbstractMenuItem ());
--iter; --iter;
Action action (new ActionHandle (mp_provider->menu_parent_widget ())); Action action (new ActionHandle (mp_provider ? mp_provider->menu_parent_widget () : 0));
action.set_separator (true); action.set_separator (true);
iter->setup_item (parent->name (), name, action); iter->setup_item (parent->name (), name, action);
@ -1452,7 +1461,7 @@ AbstractMenu::insert_menu (const std::string &p, const std::string &name, const
void void
AbstractMenu::insert_menu (const std::string &path, const std::string &name, const std::string &title) AbstractMenu::insert_menu (const std::string &path, const std::string &name, const std::string &title)
{ {
insert_menu (path, name, create_action (title)); insert_menu (path, name, create_action (title, mp_provider));
} }
void void
@ -1715,8 +1724,6 @@ AbstractMenu::find_item (const std::string &p)
void void
AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item) AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
{ {
tl_assert (mp_provider != 0);
while (layout->name) { while (layout->name) {
item.children.push_back (AbstractMenuItem ()); item.children.push_back (AbstractMenuItem ());
@ -1724,7 +1731,9 @@ AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
lay::Action a; lay::Action a;
if (layout->slot) { if (! mp_provider) {
a = lay::Action (new ActionHandle ((QWidget *) 0));
} else if (layout->slot) {
// reuse any actions already registered for this slot // reuse any actions already registered for this slot
a = mp_provider->action_for_slot (layout->slot); a = mp_provider->action_for_slot (layout->slot);
} else if (! layout->kv_pair.first.empty ()) { } else if (! layout->kv_pair.first.empty ()) {

View File

@ -887,10 +887,10 @@ private:
* The format of the string is: <text>["("shortcut")"]["<"icon-resource">"] * 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 s The title, key and icon resource string in the format given above
* @param parent The widget to which to attach the QAction object * @param provider The abstract menu provider (the global one will be used if this instance is 0)
* @return The ActionHandle object created * @return The ActionHandle object created
*/ */
static ActionHandle *create_action (const std::string &s); static ActionHandle *create_action (const std::string &s, lay::AbstractMenuProvider *provider);
AbstractMenuProvider *mp_provider; AbstractMenuProvider *mp_provider;
AbstractMenuItem m_root; AbstractMenuItem m_root;

View File

@ -28,9 +28,9 @@ namespace lay
static AbstractMenuProvider *ms_instance = 0; static AbstractMenuProvider *ms_instance = 0;
AbstractMenuProvider::AbstractMenuProvider () AbstractMenuProvider::AbstractMenuProvider (bool reg_inst)
{ {
if (! ms_instance) { if (reg_inst && ! ms_instance) {
ms_instance = this; ms_instance = this;
} }
} }

View File

@ -45,8 +45,9 @@ class LAYBASIC_PUBLIC AbstractMenuProvider
public: public:
/** /**
* @brief Constructor * @brief Constructor
* If "reg_inst" is true, this instance will become the global instance
*/ */
AbstractMenuProvider (); AbstractMenuProvider (bool reg_inst = true);
/** /**
* @brief Destructor * @brief Destructor
@ -71,14 +72,14 @@ public:
/** /**
* @brief Create a configuration action with the given title, parameter name and value * @brief Create a configuration action with the given title, parameter name and value
* *
* The action will be owned by the main window but can be deleted to remove the action from the main window. * The action will be owned by the abstract menu provider but can be deleted to remove it from there.
*/ */
virtual lay::Action *create_config_action (const std::string &title, const std::string &cname, const std::string &cvalue) = 0; virtual lay::Action *create_config_action (const std::string &title, const std::string &cname, const std::string &cvalue) = 0;
/** /**
* @brief Create a configuration action with the given parameter name and value * @brief Create a configuration action with the given parameter name and value
* *
* The action will be owned by the main window but can be deleted to remove the action from the main window. * The action will be owned by the abstract menu provider but can be deleted to remove it from there.
* This version is provided for applications, where the title is set later. * This version is provided for applications, where the title is set later.
*/ */
virtual lay::Action *create_config_action (const std::string &cname, const std::string &cvalue) = 0; virtual lay::Action *create_config_action (const std::string &cname, const std::string &cvalue) = 0;

View File

@ -256,23 +256,29 @@ static LayoutView *ms_current = 0;
LayoutView::LayoutView (db::Manager *manager, bool editable, lay::Plugin *plugin_parent, QWidget *parent, const char *name, unsigned int options) LayoutView::LayoutView (db::Manager *manager, bool editable, lay::Plugin *plugin_parent, QWidget *parent, const char *name, unsigned int options)
: QFrame (parent), : QFrame (parent),
lay::Plugin (plugin_parent), lay::Plugin (plugin_parent),
m_menu (0), lay::AbstractMenuProvider (false /* don't register as global instance */),
m_menu (this),
m_editable (editable), m_editable (editable),
m_options (options), m_options (options),
m_annotation_shapes (manager), m_annotation_shapes (manager),
dm_prop_changed (this, &LayoutView::do_prop_changed) dm_prop_changed (this, &LayoutView::do_prop_changed)
{ {
if (! plugin_root_maybe_null ()) {
mp_plugin_root.reset (new lay::PluginRoot (true, false));
}
// ensures the deferred method scheduler is present // ensures the deferred method scheduler is present
tl::DeferredMethodScheduler::instance (); tl::DeferredMethodScheduler::instance ();
setObjectName (QString::fromUtf8 (name)); setObjectName (QString::fromUtf8 (name));
init (manager, plugin_root_maybe_null (), parent); init (manager, plugin_root_maybe_null () ? plugin_root_maybe_null () : mp_plugin_root.get (), parent);
} }
LayoutView::LayoutView (lay::LayoutView *source, db::Manager *manager, bool editable, lay::PluginRoot *root, QWidget *parent, const char *name, unsigned int options) LayoutView::LayoutView (lay::LayoutView *source, db::Manager *manager, bool editable, lay::PluginRoot *root, QWidget *parent, const char *name, unsigned int options)
: QFrame (parent), : QFrame (parent),
lay::Plugin (root), lay::Plugin (root),
m_menu (0), lay::AbstractMenuProvider (false /* don't register as global instance */),
m_menu (this),
m_editable (editable), m_editable (editable),
m_options (options), m_options (options),
m_annotation_shapes (manager), m_annotation_shapes (manager),
@ -353,6 +359,8 @@ LayoutView::init (db::Manager *mgr, lay::PluginRoot *root, QWidget * /*parent*/)
if (! lay::AbstractMenuProvider::instance () || ! lay::AbstractMenuProvider::instance ()->menu ()) { if (! lay::AbstractMenuProvider::instance () || ! lay::AbstractMenuProvider::instance ()->menu ()) {
init_menu (m_menu); init_menu (m_menu);
// build the context menus, nothing else so far.
m_menu.build (0, 0);
} }
m_annotation_shapes.manager (mgr); m_annotation_shapes.manager (mgr);
@ -691,6 +699,67 @@ LayoutView::~LayoutView ()
mp_bookmarks_view = 0; mp_bookmarks_view = 0;
} }
QWidget *LayoutView::menu_parent_widget ()
{
return this;
}
lay::Action &
LayoutView::action_for_slot (const char *slot)
{
std::map<std::string, lay::Action>::iterator a = m_actions_for_slot.find (std::string (slot));
if (a != m_actions_for_slot.end ()) {
return a->second;
} else {
Action a = Action::create_free_action (this);
gtf::action_connect (a.qaction (), SIGNAL (triggered ()), this, slot);
return m_actions_for_slot.insert (std::make_pair (std::string (slot), a)).first->second;
}
}
lay::Action *
LayoutView::create_config_action (const std::string &title, const std::string &cname, const std::string &cvalue)
{
lay::ConfigureAction *ca = new lay::ConfigureAction(plugin_root (), title, cname, cvalue);
m_ca_collection.push_back (ca);
return ca;
}
lay::Action *
LayoutView::create_config_action (const std::string &cname, const std::string &cvalue)
{
lay::ConfigureAction *ca = new lay::ConfigureAction(plugin_root (), std::string (), cname, cvalue);
m_ca_collection.push_back (ca);
return ca;
}
void
LayoutView::register_config_action (const std::string &name, lay::ConfigureAction *action)
{
std::map<std::string, std::vector<lay::ConfigureAction *> >::iterator ca = m_configuration_actions.insert (std::make_pair (name, std::vector<lay::ConfigureAction *> ())).first;
for (std::vector<lay::ConfigureAction *>::iterator a = ca->second.begin (); a != ca->second.end (); ++a) {
if (*a == action) {
return; // already registered
}
}
ca->second.push_back (action);
}
void
LayoutView::unregister_config_action (const std::string &name, lay::ConfigureAction *action)
{
std::map<std::string, std::vector<lay::ConfigureAction *> >::iterator ca = m_configuration_actions.find (name);
if (ca != m_configuration_actions.end ()) {
for (std::vector<lay::ConfigureAction *>::iterator a = ca->second.begin (); a != ca->second.end (); ++a) {
if (*a == action) {
ca->second.erase (a);
return;
}
}
}
}
void LayoutView::side_panel_destroyed () void LayoutView::side_panel_destroyed ()
{ {
if (sender () == mp_control_frame) { if (sender () == mp_control_frame) {

View File

@ -31,12 +31,14 @@
#include <set> #include <set>
#include <list> #include <list>
#include <string> #include <string>
#include <memory>
#include <QFrame> #include <QFrame>
#include <QImage> #include <QImage>
#include "layLayerProperties.h" #include "layLayerProperties.h"
#include "layAbstractMenu.h" #include "layAbstractMenu.h"
#include "layAbstractMenuProvider.h"
#include "layAnnotationShapes.h" #include "layAnnotationShapes.h"
#include "layLayoutCanvas.h" #include "layLayoutCanvas.h"
#include "layColorPalette.h" #include "layColorPalette.h"
@ -79,6 +81,8 @@ class SelectionService;
class MoveService; class MoveService;
class Browser; class Browser;
class ColorButton; class ColorButton;
class PluginRoot;
class ConfigureAction;
/** /**
* @brief Stores a layer reference to create layers which have been added by some action * @brief Stores a layer reference to create layers which have been added by some action
@ -155,7 +159,8 @@ struct LAYBASIC_PUBLIC LayerDisplayProperties
class LAYBASIC_PUBLIC LayoutView class LAYBASIC_PUBLIC LayoutView
: public QFrame, : public QFrame,
public lay::Editables, public lay::Editables,
public lay::Plugin public lay::Plugin,
public lay::AbstractMenuProvider
{ {
Q_OBJECT Q_OBJECT
@ -217,6 +222,12 @@ public:
*/ */
static LayoutView *current (); static LayoutView *current ();
/**
* @brief Gets the abstract menu object for this view
* This is either the global menu object or the local one.
*/
AbstractMenu *menu ();
/** /**
* @brief Determine if there is something to copy * @brief Determine if there is something to copy
* *
@ -1667,12 +1678,6 @@ public:
*/ */
static void update_menu (lay::LayoutView *view, lay::AbstractMenu &menu); static void update_menu (lay::LayoutView *view, lay::AbstractMenu &menu);
/**
* @brief Get the menu abstraction object
* This is either the global abstract menu or a view-local one if the view is not embedded into a main window.
*/
AbstractMenu *menu ();
/** /**
* @brief Query the default mode * @brief Query the default mode
*/ */
@ -2758,6 +2763,10 @@ protected:
private: private:
lay::AbstractMenu m_menu; lay::AbstractMenu m_menu;
std::auto_ptr<lay::PluginRoot> mp_plugin_root;
std::map<std::string, lay::Action> m_actions_for_slot;
std::map<std::string, std::vector<lay::ConfigureAction *> > m_configuration_actions;
tl::shared_collection<lay::ConfigureAction> m_ca_collection;
bool m_editable; bool m_editable;
int m_disabled_edits; int m_disabled_edits;
@ -2939,6 +2948,14 @@ private:
std::list<lay::CellView>::iterator cellview_iter (int cv_index); std::list<lay::CellView>::iterator cellview_iter (int cv_index);
std::list<lay::CellView>::const_iterator cellview_iter (int cv_index) const; std::list<lay::CellView>::const_iterator cellview_iter (int cv_index) const;
// implementation of AbstractMenuProvider
virtual QWidget *menu_parent_widget ();
virtual lay::Action &action_for_slot (const char *slot);
virtual lay::Action *create_config_action (const std::string &title, const std::string &cname, const std::string &cvalue);
virtual lay::Action *create_config_action (const std::string &cname, const std::string &cvalue);
virtual void register_config_action (const std::string &name, lay::ConfigureAction *action);
virtual void unregister_config_action (const std::string &name, lay::ConfigureAction *action);
}; };
} }

View File

@ -368,9 +368,12 @@ Plugin::get_config_names (std::vector<std::string> &names) const
PluginRoot * PluginRoot *
Plugin::plugin_root () Plugin::plugin_root ()
{ {
PluginRoot *pr = plugin_root_maybe_null (); Plugin *p = this;
tl_assert (pr != 0); while (p->mp_parent) {
return pr; p = p->mp_parent;
}
return dynamic_cast<PluginRoot *> (p);
} }
PluginRoot * PluginRoot *
@ -436,10 +439,12 @@ Plugin::do_config_set (const std::string &name, const std::string &value, bool f
static PluginRoot *ms_root_instance = 0; static PluginRoot *ms_root_instance = 0;
PluginRoot::PluginRoot (bool standalone) PluginRoot::PluginRoot (bool standalone, bool reg_inst)
: Plugin (0, standalone) : Plugin (0, standalone)
{ {
ms_root_instance = this; if (reg_inst) {
ms_root_instance = this;
}
} }
PluginRoot::~PluginRoot () PluginRoot::~PluginRoot ()

View File

@ -805,7 +805,7 @@ public:
/** /**
* @brief The constructor * @brief The constructor
*/ */
PluginRoot (bool standalone = false); PluginRoot (bool standalone = false, bool reg_inst = true);
/** /**
* @brief Destructor * @brief Destructor