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)
{
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 ()));
mp_handle->add_ref ();
}
@ -1008,9 +1008,12 @@ ConfigureAction::configure (const std::string &value)
// AbstractMenu implementation
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 shortcut;
@ -1019,7 +1022,7 @@ AbstractMenu::create_action (const std::string &s)
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));
if (! tool_tip.empty ()) {
@ -1129,15 +1132,17 @@ AbstractMenu::build_detached (const std::string &name, QFrame *mbar)
void
AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
{
tl_assert (mp_provider != 0);
m_helper_menu_items.clear ();
tbar->clear ();
if (tbar) {
tbar->clear ();
}
std::set<std::pair<size_t, QAction *> > present_actions;
QList<QAction *> a = mbar->actions ();
for (QList<QAction *>::const_iterator i = a.begin (); i != a.end (); ++i) {
present_actions.insert (std::make_pair (id_from_action (*i), *i));
if (mbar) {
QList<QAction *> a = mbar->actions ();
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) {
@ -1146,7 +1151,9 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
if (c->name () == "@toolbar") {
build (tbar, c->children);
if (tbar) {
build (tbar, c->children);
}
} 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
// popup menu. It seems not to have a negative effect to add the menu to the
// 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);
}
// prepare a detached menu which can be used as context menues
build (c->menu (), c->children);
} else {
} else if (mbar) {
if (c->menu () == 0) {
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
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 ()) {
@ -1209,8 +1218,10 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
}
// Remove all actions that have vanished
for (std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.begin (); a != present_actions.end (); ++a) {
mbar->removeAction (a->second);
if (mbar) {
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
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;
path_type path = find_item (p);
if (! path.empty ()) {
@ -1410,7 +1419,7 @@ AbstractMenu::insert_separator (const std::string &p, const std::string &name)
parent->children.insert (iter, AbstractMenuItem ());
--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);
iter->setup_item (parent->name (), name, action);
@ -1452,7 +1461,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));
insert_menu (path, name, create_action (title, mp_provider));
}
void
@ -1715,8 +1724,6 @@ AbstractMenu::find_item (const std::string &p)
void
AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
{
tl_assert (mp_provider != 0);
while (layout->name) {
item.children.push_back (AbstractMenuItem ());
@ -1724,7 +1731,9 @@ AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
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
a = mp_provider->action_for_slot (layout->slot);
} else if (! layout->kv_pair.first.empty ()) {

View File

@ -887,10 +887,10 @@ 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 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
*/
static ActionHandle *create_action (const std::string &s);
static ActionHandle *create_action (const std::string &s, lay::AbstractMenuProvider *provider);
AbstractMenuProvider *mp_provider;
AbstractMenuItem m_root;

View File

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

View File

@ -45,8 +45,9 @@ class LAYBASIC_PUBLIC AbstractMenuProvider
public:
/**
* @brief Constructor
* If "reg_inst" is true, this instance will become the global instance
*/
AbstractMenuProvider ();
AbstractMenuProvider (bool reg_inst = true);
/**
* @brief Destructor
@ -71,14 +72,14 @@ public:
/**
* @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;
/**
* @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.
*/
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)
: QFrame (parent),
lay::Plugin (plugin_parent),
m_menu (0),
lay::AbstractMenuProvider (false /* don't register as global instance */),
m_menu (this),
m_editable (editable),
m_options (options),
m_annotation_shapes (manager),
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
tl::DeferredMethodScheduler::instance ();
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)
: QFrame (parent),
lay::Plugin (root),
m_menu (0),
lay::AbstractMenuProvider (false /* don't register as global instance */),
m_menu (this),
m_editable (editable),
m_options (options),
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 ()) {
init_menu (m_menu);
// build the context menus, nothing else so far.
m_menu.build (0, 0);
}
m_annotation_shapes.manager (mgr);
@ -691,6 +699,67 @@ LayoutView::~LayoutView ()
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 ()
{
if (sender () == mp_control_frame) {

View File

@ -31,12 +31,14 @@
#include <set>
#include <list>
#include <string>
#include <memory>
#include <QFrame>
#include <QImage>
#include "layLayerProperties.h"
#include "layAbstractMenu.h"
#include "layAbstractMenuProvider.h"
#include "layAnnotationShapes.h"
#include "layLayoutCanvas.h"
#include "layColorPalette.h"
@ -79,6 +81,8 @@ class SelectionService;
class MoveService;
class Browser;
class ColorButton;
class PluginRoot;
class ConfigureAction;
/**
* @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
: public QFrame,
public lay::Editables,
public lay::Plugin
public lay::Plugin,
public lay::AbstractMenuProvider
{
Q_OBJECT
@ -217,6 +222,12 @@ public:
*/
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
*
@ -1667,12 +1678,6 @@ public:
*/
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
*/
@ -2758,6 +2763,10 @@ protected:
private:
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;
int m_disabled_edits;
@ -2939,6 +2948,14 @@ private:
std::list<lay::CellView>::iterator cellview_iter (int cv_index);
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 *
Plugin::plugin_root ()
{
PluginRoot *pr = plugin_root_maybe_null ();
tl_assert (pr != 0);
return pr;
Plugin *p = this;
while (p->mp_parent) {
p = p->mp_parent;
}
return dynamic_cast<PluginRoot *> (p);
}
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;
PluginRoot::PluginRoot (bool standalone)
PluginRoot::PluginRoot (bool standalone, bool reg_inst)
: Plugin (0, standalone)
{
ms_root_instance = this;
if (reg_inst) {
ms_root_instance = this;
}
}
PluginRoot::~PluginRoot ()

View File

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