Merge pull request #24 from klayoutmatthias/menu_issue

Menu issue
This commit is contained in:
Kazunari Sekigawa 2018-02-10 06:48:58 +09:00 committed by GitHub
commit c162fa81d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 147 additions and 101 deletions

View File

@ -1380,6 +1380,17 @@ GuiApplication::notify (QObject *receiver, QEvent *e)
return ret; return ret;
} }
void
GuiApplication::force_update_app_menu ()
{
#if defined(__APPLE__)
// This is a workaround for a bug in the MacOS native menu integration:
// this signal forces the menu to become updated. Without this, any
// new menu items stay disabled.
emit focusWindowChanged (focusWindow ());
#endif
}
int int
GuiApplication::exec () GuiApplication::exec ()
{ {

View File

@ -432,6 +432,12 @@ public:
return mp_mw; return mp_mw;
} }
/**
* @brief Forces update of the application menu
* This function is used for work around a MacOS issue.
*/
void force_update_app_menu ();
protected: protected:
virtual void setup (); virtual void setup ();
virtual void shutdown (); virtual void shutdown ();

View File

@ -1195,10 +1195,6 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
pydoc = pya::PythonInterpreter::instance ()->python_doc (i->second.first); pydoc = pya::PythonInterpreter::instance ()->python_doc (i->second.first);
} }
os << "<a name=\"method" << n << "\"/>"
<< "<a name=\"m_" << escape_xml (i->first) << "\"/>"
<< "<keyword title=\"" << tl::to_string (QObject::tr ("API reference - Class")) << " " << escape_xml (cls) << ", " << tl::to_string (QObject::tr ("Method")) << " " << escape_xml (i->first) << "\" name=\"" << escape_xml (cls) << "#" << escape_xml (i->first) << "\"/>" << std::endl;
os << "<tr>"; os << "<tr>";
if (i->first != prev_title) { if (i->first != prev_title) {
int rows = 0; int rows = 0;
@ -1212,6 +1208,10 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
} }
os << "<td style=\"padding-bottom: 16px\">"; os << "<td style=\"padding-bottom: 16px\">";
os << "<a name=\"method" << n << "\"/>"
<< "<a name=\"m_" << escape_xml (i->first) << "\"/>"
<< "<keyword title=\"" << tl::to_string (QObject::tr ("API reference - Class")) << " " << escape_xml (cls) << ", " << tl::to_string (QObject::tr ("Method")) << " " << escape_xml (i->first) << "\" name=\"" << escape_xml (cls) << "#" << escape_xml (i->first) << "\"/>" << std::endl;
os << "<p><b>" << tl::to_string (QObject::tr ("Signature")) << "</b>: "; os << "<p><b>" << tl::to_string (QObject::tr ("Signature")) << "</b>: ";
std::string attr = method_attributes (i->second.first, method_doc); std::string attr = method_attributes (i->second.first, method_doc);
if (! attr.empty ()) { if (! attr.empty ()) {

View File

@ -450,6 +450,7 @@ MainWindow::MainWindow (QApplication *app, const char *name)
m_disable_tab_selected (false), m_disable_tab_selected (false),
m_exited (false), m_exited (false),
dm_do_update_menu (this, &MainWindow::do_update_menu), dm_do_update_menu (this, &MainWindow::do_update_menu),
dm_do_update_file_menu (this, &MainWindow::do_update_file_menu),
dm_exit (this, &MainWindow::exit), dm_exit (this, &MainWindow::exit),
m_grid_micron (0.001), m_grid_micron (0.001),
m_default_grids_updated (true), m_default_grids_updated (true),
@ -613,10 +614,6 @@ MainWindow::MainWindow (QApplication *app, const char *name)
tl_assert (bookmark_menu != 0); tl_assert (bookmark_menu != 0);
connect (bookmark_menu, SIGNAL (aboutToShow ()), this, SLOT (bookmark_menu_show ())); connect (bookmark_menu, SIGNAL (aboutToShow ()), this, SLOT (bookmark_menu_show ()));
QMenu *file_menu = mp_menu->menu ("file_menu");
tl_assert (file_menu != 0);
connect (file_menu, SIGNAL (aboutToShow ()), this, SLOT (file_menu_show ()));
// select the default mode // select the default mode
select_mode (lay::LayoutView::default_mode ()); select_mode (lay::LayoutView::default_mode ());
@ -1595,6 +1592,8 @@ MainWindow::configure (const std::string &name, const std::string &value)
} }
} }
dm_do_update_file_menu ();
return true; return true;
} else if (name == cfg_micron_digits) { } else if (name == cfg_micron_digits) {
@ -4173,30 +4172,31 @@ MainWindow::add_mru (const std::string &fn_rel, const std::string &tech)
} }
void void
MainWindow::file_menu_show () MainWindow::do_update_file_menu ()
{ {
if (mp_menu->is_valid ("file_menu.open_recent_menu")) { std::string mru_menu = "file_menu.open_recent_menu";
Action open_recent_action = mp_menu->action ("file_menu.open_recent_menu"); if (mp_menu->is_valid (mru_menu)) {
Action open_recent_action = mp_menu->action (mru_menu);
open_recent_action.set_enabled (true);
if (m_mru.size () > 0 && edits_enabled ()) { if (m_mru.size () > 0 && edits_enabled ()) {
open_recent_action.set_enabled (true); // rebuild MRU menu
std::vector<std::string> items = mp_menu->items (mru_menu);
QMenu *open_recent_menu = open_recent_action.qaction ()->menu (); for (std::vector<std::string>::const_iterator i = items.begin (); i != items.end (); ++i) {
if (open_recent_menu) { mp_menu->delete_item (mru_menu + "." + *i);
}
open_recent_menu->clear ();
for (std::vector<std::pair<std::string, std::string> >::iterator mru = m_mru.end (); mru != m_mru.begin (); ) {
--mru;
unsigned int i = std::distance (m_mru.begin (), mru);
QAction *action = open_recent_menu->addAction (tl::to_qstring (mru->first));
action->setObjectName (tl::to_qstring (tl::sprintf ("open_recent_%d", i + 1)));
gtf::action_connect (action, SIGNAL (triggered ()), this, SLOT (open_recent ()));
action->setData (QVariant (int (i)));
}
for (std::vector<std::pair<std::string, std::string> >::iterator mru = m_mru.end (); mru != m_mru.begin (); ) {
--mru;
unsigned int i = std::distance (m_mru.begin (), mru);
Action action;
gtf::action_connect (action.qaction (), SIGNAL (triggered ()), this, SLOT (open_recent ()));
action.set_title (mru->first);
action.qaction ()->setData (QVariant (int (i)));
mp_menu->insert_item (mru_menu + ".end", tl::sprintf ("open_recent_%d", i + 1), action);
} }
} else { } else {
@ -5016,6 +5016,10 @@ void
MainWindow::do_update_menu () MainWindow::do_update_menu ()
{ {
mp_menu->build (menuBar (), mp_tool_bar); mp_menu->build (menuBar (), mp_tool_bar);
lay::GuiApplication *app = dynamic_cast<lay::GuiApplication *> (qApp);
if (app) {
app->force_update_app_menu ();
}
} }
void void

View File

@ -859,7 +859,6 @@ protected slots:
void menu_changed (); void menu_changed ();
void message_timer (); void message_timer ();
void bookmark_menu_show (); void bookmark_menu_show ();
void file_menu_show ();
void edits_enabled_changed (); void edits_enabled_changed ();
void file_changed_timer (); void file_changed_timer ();
void file_changed (const QString &path); void file_changed (const QString &path);
@ -868,6 +867,7 @@ protected slots:
protected: protected:
void update_content (); void update_content ();
void do_update_menu (); void do_update_menu ();
void do_update_file_menu ();
private: private:
TextProgressDelegate m_text_progress; TextProgressDelegate m_text_progress;
@ -911,6 +911,7 @@ private:
bool m_disable_tab_selected; bool m_disable_tab_selected;
bool m_exited; bool m_exited;
tl::DeferredMethod<MainWindow> dm_do_update_menu; tl::DeferredMethod<MainWindow> dm_do_update_menu;
tl::DeferredMethod<MainWindow> dm_do_update_file_menu;
tl::DeferredMethod<MainWindow> dm_exit; tl::DeferredMethod<MainWindow> dm_exit;
QTimer m_message_timer; QTimer m_message_timer;
QTimer m_file_changed_timer; QTimer m_file_changed_timer;

View File

@ -66,7 +66,7 @@ static const bool s_can_move_menu = true;
#endif #endif
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Helper function to parse a title with potential shortcut and // Helper function to parse a title with potential shortcut and
// icon specification // icon specification
static void static void
@ -122,19 +122,19 @@ parse_menu_title (const std::string &s, std::string &title, std::string &shortcu
// --------------------------------------------------------------- // ---------------------------------------------------------------
// AbstractMenuItem implementation // AbstractMenuItem implementation
AbstractMenuItem::AbstractMenuItem () AbstractMenuItem::AbstractMenuItem ()
: m_has_submenu (false), m_remove_on_empty (false) : m_has_submenu (false), m_remove_on_empty (false)
{ {
// ... nothing yet .. // ... nothing yet ..
} }
AbstractMenuItem::AbstractMenuItem (const AbstractMenuItem &) AbstractMenuItem::AbstractMenuItem (const AbstractMenuItem &)
: m_has_submenu (false), m_remove_on_empty (false) : m_has_submenu (false), m_remove_on_empty (false)
{ {
// ... nothing yet .. // ... nothing yet ..
} }
void void
AbstractMenuItem::setup_item (const std::string &pn, const std::string &s, const Action &a) AbstractMenuItem::setup_item (const std::string &pn, const std::string &s, const Action &a)
{ {
m_basename.clear (); m_basename.clear ();
@ -162,7 +162,7 @@ AbstractMenuItem::setup_item (const std::string &pn, const std::string &s, const
set_action (a, false); set_action (a, false);
} }
void void
AbstractMenuItem::set_action (const Action &a, bool copy_properties) AbstractMenuItem::set_action (const Action &a, bool copy_properties)
{ {
Action acopy = a; Action acopy = a;
@ -187,13 +187,13 @@ AbstractMenuItem::set_action (const Action &a, bool copy_properties)
} }
} }
void void
AbstractMenuItem::set_action_title (const std::string &s) AbstractMenuItem::set_action_title (const std::string &s)
{ {
m_action.set_title (s); m_action.set_title (s);
} }
void void
AbstractMenuItem::set_has_submenu () AbstractMenuItem::set_has_submenu ()
{ {
m_has_submenu = true; m_has_submenu = true;
@ -214,10 +214,20 @@ static std::set<ActionHandle *> *sp_actionHandles = 0;
* @brief A specialization that provides a way to catch ambiguous key shortcuts * @brief A specialization that provides a way to catch ambiguous key shortcuts
*/ */
class ActionObject class ActionObject
: public QAction : public QAction
{ {
public: public:
ActionObject (QObject *parent) : QAction (parent) { } ActionObject (QObject *parent)
: QAction (parent)
{
static size_t s_id = 0;
m_id = ++s_id;
}
size_t id () const
{
return m_id;
}
bool event(QEvent *e) bool event(QEvent *e)
{ {
@ -251,8 +261,18 @@ public:
return QAction::event(e); return QAction::event(e);
} }
private:
size_t m_id;
}; };
static size_t
id_from_action (QAction *action)
{
ActionObject *ao = dynamic_cast<ActionObject *> (action);
return ao ? ao->id () : 0;
}
ActionHandle::ActionHandle (QWidget *parent) ActionHandle::ActionHandle (QWidget *parent)
: mp_menu (0), : mp_menu (0),
mp_action (new ActionObject (parent)), mp_action (new ActionObject (parent)),
@ -260,7 +280,7 @@ ActionHandle::ActionHandle (QWidget *parent)
m_owned (true), m_owned (true),
m_visible (true), m_visible (true),
m_hidden (false) m_hidden (false)
{ {
if (! sp_actionHandles) { if (! sp_actionHandles) {
sp_actionHandles = new std::set<ActionHandle *> (); sp_actionHandles = new std::set<ActionHandle *> ();
} }
@ -273,11 +293,11 @@ ActionHandle::ActionHandle (QWidget *parent)
ActionHandle::ActionHandle (QAction *action, bool owned) ActionHandle::ActionHandle (QAction *action, bool owned)
: mp_menu (0), : mp_menu (0),
mp_action (action), mp_action (action),
m_ref_count (0), m_ref_count (0),
m_owned (owned), m_owned (owned),
m_visible (true), m_visible (true),
m_hidden (false) m_hidden (false)
{ {
if (! sp_actionHandles) { if (! sp_actionHandles) {
sp_actionHandles = new std::set<ActionHandle *> (); sp_actionHandles = new std::set<ActionHandle *> ();
} }
@ -330,13 +350,13 @@ ActionHandle::~ActionHandle ()
} }
} }
void void
ActionHandle::add_ref () ActionHandle::add_ref ()
{ {
++m_ref_count; ++m_ref_count;
} }
void void
ActionHandle::remove_ref () ActionHandle::remove_ref ()
{ {
if (--m_ref_count == 0) { if (--m_ref_count == 0) {
@ -356,7 +376,7 @@ ActionHandle::menu () const
return mp_menu; return mp_menu;
} }
void void
ActionHandle::destroyed (QObject * /*obj*/) ActionHandle::destroyed (QObject * /*obj*/)
{ {
mp_action = 0; mp_action = 0;
@ -548,7 +568,7 @@ Action::triggered_slot ()
END_PROTECTED END_PROTECTED
} }
void void
Action::set_title (const std::string &t) Action::set_title (const std::string &t)
{ {
if (qaction ()) { if (qaction ()) {
@ -556,7 +576,7 @@ Action::set_title (const std::string &t)
} }
} }
std::string std::string
Action::get_title () const Action::get_title () const
{ {
if (qaction ()) { if (qaction ()) {
@ -566,7 +586,7 @@ Action::get_title () const
} }
} }
void void
Action::set_shortcut (const QKeySequence &s) Action::set_shortcut (const QKeySequence &s)
{ {
if (mp_handle) { if (mp_handle) {
@ -732,7 +752,7 @@ Action::set_separator (bool s)
} }
} }
void void
Action::set_icon (const std::string &filename) Action::set_icon (const std::string &filename)
{ {
if (qaction ()) { if (qaction ()) {
@ -744,7 +764,7 @@ Action::set_icon (const std::string &filename)
} }
} }
std::string std::string
Action::get_tool_tip () const Action::get_tool_tip () const
{ {
if (qaction ()) { if (qaction ()) {
@ -754,7 +774,7 @@ Action::get_tool_tip () const
} }
} }
void void
Action::set_tool_tip (const std::string &text) Action::set_tool_tip (const std::string &text)
{ {
if (qaction ()) { if (qaction ()) {
@ -766,7 +786,7 @@ Action::set_tool_tip (const std::string &text)
} }
} }
std::string std::string
Action::get_icon_text () const Action::get_icon_text () const
{ {
if (qaction ()) { if (qaction ()) {
@ -776,7 +796,7 @@ Action::get_icon_text () const
} }
} }
void void
Action::set_icon_text (const std::string &icon_text) Action::set_icon_text (const std::string &icon_text)
{ {
if (qaction ()) { if (qaction ()) {
@ -788,7 +808,7 @@ Action::set_icon_text (const std::string &icon_text)
} }
} }
void void
Action::set_object_name (const std::string &name) Action::set_object_name (const std::string &name)
{ {
if (qaction ()) { if (qaction ()) {
@ -814,7 +834,7 @@ ConfigureAction::ConfigureAction (lay::PluginRoot *pr, const std::string &cname,
} }
reg (); reg ();
} }
ConfigureAction::ConfigureAction (lay::PluginRoot *pr, const std::string &title, const std::string &cname, const std::string &cvalue) ConfigureAction::ConfigureAction (lay::PluginRoot *pr, const std::string &title, const std::string &cname, const std::string &cvalue)
: Action (title), m_pr (pr), m_cname (cname), m_cvalue (cvalue), m_type (ConfigureAction::setter_type) : Action (title), m_pr (pr), m_cname (cname), m_cvalue (cvalue), m_type (ConfigureAction::setter_type)
@ -831,19 +851,19 @@ ConfigureAction::ConfigureAction (lay::PluginRoot *pr, const std::string &title,
} }
reg (); reg ();
} }
ConfigureAction::~ConfigureAction () ConfigureAction::~ConfigureAction ()
{ {
unreg (); unreg ();
} }
void void
ConfigureAction::triggered () ConfigureAction::triggered ()
{ {
if (m_type == boolean_type) { if (m_type == boolean_type) {
m_cvalue = tl::to_string (is_checked ()); m_cvalue = tl::to_string (is_checked ());
} }
m_pr->config_set (m_cname, m_cvalue); m_pr->config_set (m_cname, m_cvalue);
} }
@ -880,7 +900,7 @@ ConfigureAction::configure (const std::string &value)
set_checkable (true); set_checkable (true);
set_checked (m_cvalue == value); set_checked (m_cvalue == value);
} }
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------
@ -897,7 +917,7 @@ AbstractMenu::create_action (const std::string &s)
std::string tool_tip; std::string tool_tip;
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 (lay::AbstractMenuProvider::instance ()->menu_parent_widget ());
ah->ptr ()->setText (tl::to_qstring (title)); ah->ptr ()->setText (tl::to_qstring (title));
@ -927,7 +947,7 @@ AbstractMenu::~AbstractMenu ()
// .. nothing yet .. // .. nothing yet ..
} }
void void
AbstractMenu::init (const MenuLayoutEntry *layout) AbstractMenu::init (const MenuLayoutEntry *layout)
{ {
m_root.set_has_submenu (); m_root.set_has_submenu ();
@ -943,12 +963,12 @@ AbstractMenu::make_exclusive_group (const std::string &name)
QActionGroup *ag = new QActionGroup (this); QActionGroup *ag = new QActionGroup (this);
ag->setExclusive (true); ag->setExclusive (true);
a = m_action_groups.insert (std::make_pair (name, ag)).first; a = m_action_groups.insert (std::make_pair (name, ag)).first;
} }
return a->second; return a->second;
} }
void void
AbstractMenu::build_detached (const std::string &name, QFrame *mbar) AbstractMenu::build_detached (const std::string &name, QFrame *mbar)
{ {
// Clean up the menu bar before rebuilding // Clean up the menu bar before rebuilding
@ -1005,7 +1025,7 @@ AbstractMenu::build_detached (const std::string &name, QFrame *mbar)
menu_layout->addStretch (1); menu_layout->addStretch (1);
} }
void void
AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar) AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
{ {
tl_assert (mp_provider != 0); tl_assert (mp_provider != 0);
@ -1013,9 +1033,11 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
m_helper_menu_items.clear (); m_helper_menu_items.clear ();
tbar->clear (); tbar->clear ();
std::set<QAction *> present_actions; std::set<std::pair<size_t, QAction *> > present_actions;
QList<QAction *> a = mbar->actions (); QList<QAction *> a = mbar->actions ();
present_actions.insert (a.begin (), a.end ()); 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) {
@ -1027,7 +1049,7 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
} else if (c->name ().find ("@@") == 0) { } else if (c->name ().find ("@@") == 0) {
// nothing: let build_detached build the menu // nothing: let build_detached build the menu
} else if (c->name ().find ("@") == 0) { } else if (c->name ().find ("@") == 0) {
@ -1035,9 +1057,9 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
QMenu *menu = new QMenu (tl::to_qstring (c->action ().get_title ())); QMenu *menu = new QMenu (tl::to_qstring (c->action ().get_title ()));
// HINT: it is necessary to add the menu action to a widget below the main window. // HINT: it is necessary to add the menu action to a widget below the main window.
// 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 ()); mp_provider->menu_parent_widget ()->addAction (menu->menuAction ());
c->set_action (Action (new ActionHandle (menu)), true); c->set_action (Action (new ActionHandle (menu)), true);
} }
@ -1053,10 +1075,10 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
c->set_action (Action (new ActionHandle (menu)), true); c->set_action (Action (new ActionHandle (menu)), true);
} else { } else {
// 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<QAction *>::iterator a = present_actions.find (c->menu ()->menuAction ()); std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.find (std::make_pair (id_from_action (c->menu ()->menuAction ()), c->menu ()->menuAction ()));
if (a != present_actions.end ()) { if (a != present_actions.end ()) {
if (s_can_move_menu) { if (s_can_move_menu) {
mbar->removeAction (*a); mbar->removeAction (a->second);
mbar->addMenu (c->menu ()); mbar->addMenu (c->menu ());
} }
present_actions.erase (*a); present_actions.erase (*a);
@ -1071,10 +1093,10 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
} else { } else {
// 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<QAction *>::iterator a = present_actions.find (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 ()) {
if (s_can_move_menu) { if (s_can_move_menu) {
mbar->removeAction (*a); mbar->removeAction (a->second);
mbar->addAction (c->action ().qaction ()); mbar->addAction (c->action ().qaction ());
} }
present_actions.erase (*a); present_actions.erase (*a);
@ -1086,17 +1108,19 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
} }
// Remove all actions that have vanished // Remove all actions that have vanished
for (std::set<QAction *>::iterator a = present_actions.begin (); a != present_actions.end (); ++a) { for (std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.begin (); a != present_actions.end (); ++a) {
mbar->removeAction (*a); mbar->removeAction (a->second);
} }
} }
void void
AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items) AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items)
{ {
std::set<QAction *> present_actions; std::set<std::pair<size_t, QAction *> > present_actions;
QList<QAction *> a = m->actions (); QList<QAction *> a = m->actions ();
present_actions.insert (a.begin (), a.end ()); 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 = items.begin (); c != items.end (); ++c) { for (std::list<AbstractMenuItem>::iterator c = items.begin (); c != items.end (); ++c) {
@ -1111,10 +1135,10 @@ AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items)
c->set_action (Action (new ActionHandle (menu)), true); c->set_action (Action (new ActionHandle (menu)), true);
} else { } else {
// 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<QAction *>::iterator a = present_actions.find (c->menu ()->menuAction ()); std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.find (std::make_pair (id_from_action (c->menu ()->menuAction ()), c->menu ()->menuAction ()));
if (a != present_actions.end ()) { if (a != present_actions.end ()) {
if (s_can_move_menu) { if (s_can_move_menu) {
m->removeAction (*a); m->removeAction (a->second);
m->addMenu (c->menu ()); m->addMenu (c->menu ());
} }
present_actions.erase (*a); present_actions.erase (*a);
@ -1128,10 +1152,10 @@ AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items)
} else { } else {
// 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<QAction *>::iterator a = present_actions.find (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 ()) {
if (s_can_move_menu) { if (s_can_move_menu) {
m->removeAction (*a); m->removeAction (a->second);
m->addAction (c->action ().qaction ()); m->addAction (c->action ().qaction ());
} }
present_actions.erase (*a); present_actions.erase (*a);
@ -1143,26 +1167,26 @@ AbstractMenu::build (QMenu *m, std::list<AbstractMenuItem> &items)
} }
// Remove all actions that have vanished // Remove all actions that have vanished
for (std::set<QAction *>::iterator a = present_actions.begin (); a != present_actions.end (); ++a) { for (std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.begin (); a != present_actions.end (); ++a) {
m->removeAction (*a); m->removeAction (a->second);
} }
} }
void void
AbstractMenu::build (QToolBar *t, std::list<AbstractMenuItem> &items) AbstractMenu::build (QToolBar *t, std::list<AbstractMenuItem> &items)
{ {
for (std::list<AbstractMenuItem>::iterator c = items.begin (); c != items.end (); ++c) { for (std::list<AbstractMenuItem>::iterator c = items.begin (); c != items.end (); ++c) {
if (! c->children.empty ()) { if (! c->children.empty ()) {
// To support tool buttons with menu we have to attach a helper menu // To support tool buttons with menu we have to attach a helper menu
// item to the QAction object. // item to the QAction object.
// TODO: this hurts if we use this QAction otherwise. In this case, this // TODO: this hurts if we use this QAction otherwise. In this case, this
// QAction would get a menu too. However, hopefully this usage is constrained // QAction would get a menu too. However, hopefully this usage is constrained
// to special toolbar buttons only. // to special toolbar buttons only.
// In order to be able to manage the QMenu ourselves, we must not give it a parent. // In order to be able to manage the QMenu ourselves, we must not give it a parent.
QMenu *menu = new QMenu (0); QMenu *menu = new QMenu (0);
m_helper_menu_items.push_back (menu); // will be owned by the stable vector m_helper_menu_items.push_back (menu); // will be owned by the stable vector
c->action ().qaction ()->setMenu (menu); c->action ().qaction ()->setMenu (menu);
t->addAction (c->action ().qaction ()); t->addAction (c->action ().qaction ());
build (menu, c->children); build (menu, c->children);
@ -1183,7 +1207,7 @@ AbstractMenu::detached_menu (const std::string &name)
} }
QMenu * QMenu *
AbstractMenu::menu (const std::string &path) AbstractMenu::menu (const std::string &path)
{ {
AbstractMenuItem *item = find_item_exact (path); AbstractMenuItem *item = find_item_exact (path);
if (item) { if (item) {
@ -1214,7 +1238,7 @@ AbstractMenu::is_separator (const std::string &path) const
return item != 0 && item->action ().is_separator (); return item != 0 && item->action ().is_separator ();
} }
Action Action
AbstractMenu::action (const std::string &path) const AbstractMenu::action (const std::string &path) const
{ {
const AbstractMenuItem *item = find_item_exact (path); const AbstractMenuItem *item = find_item_exact (path);
@ -1224,7 +1248,7 @@ AbstractMenu::action (const std::string &path) const
return item->action (); return item->action ();
} }
std::vector<std::string> std::vector<std::string>
AbstractMenu::items (const std::string &path) const AbstractMenu::items (const std::string &path) const
{ {
std::vector<std::string> res; std::vector<std::string> res;
@ -1240,7 +1264,7 @@ AbstractMenu::items (const std::string &path) const
return res; return res;
} }
void void
AbstractMenu::insert_item (const std::string &p, const std::string &name, const Action &action) AbstractMenu::insert_item (const std::string &p, const std::string &name, const Action &action)
{ {
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type; typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
@ -1271,7 +1295,7 @@ AbstractMenu::insert_item (const std::string &p, const std::string &name, const
emit changed (); emit changed ();
} }
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) tl_assert (mp_provider != 0); // required to get the parent for the new QAction (via ActionHandle)
@ -1294,7 +1318,7 @@ AbstractMenu::insert_separator (const std::string &p, const std::string &name)
emit changed (); emit changed ();
} }
void void
AbstractMenu::insert_menu (const std::string &p, const std::string &name, const Action &action) AbstractMenu::insert_menu (const std::string &p, const std::string &name, const Action &action)
{ {
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type; typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
@ -1324,13 +1348,13 @@ AbstractMenu::insert_menu (const std::string &p, const std::string &name, const
emit changed (); emit changed ();
} }
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));
} }
void void
AbstractMenu::delete_item (const std::string &p) AbstractMenu::delete_item (const std::string &p)
{ {
typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type; typedef std::vector<std::pair<AbstractMenuItem *, std::list<AbstractMenuItem>::iterator > > path_type;
@ -1387,7 +1411,7 @@ AbstractMenu::find_item_exact (const std::string &path) const
} }
AbstractMenuItem * AbstractMenuItem *
AbstractMenu::find_item_exact (const std::string &path) AbstractMenu::find_item_exact (const std::string &path)
{ {
tl::Extractor extr (path.c_str ()); tl::Extractor extr (path.c_str ());
AbstractMenuItem *item = &m_root; AbstractMenuItem *item = &m_root;
@ -1406,7 +1430,7 @@ AbstractMenu::find_item_exact (const std::string &path)
} }
if (n > 0) { if (n > 0) {
return 0; return 0;
} }
item = &*c; item = &*c;
@ -1576,7 +1600,7 @@ AbstractMenu::find_item (const std::string &p)
return path; return path;
} }
void void
AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item) AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
{ {
tl_assert (mp_provider != 0); tl_assert (mp_provider != 0);
@ -1609,7 +1633,7 @@ AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
std::string tool_tip; std::string tool_tip;
parse_menu_title (layout->title, title, shortcut, res, tool_tip); parse_menu_title (layout->title, title, shortcut, res, tool_tip);
a.set_separator (false); a.set_separator (false);
a.set_title (title); a.set_title (title);
@ -1641,7 +1665,7 @@ AbstractMenu::transfer (const MenuLayoutEntry *layout, AbstractMenuItem &item)
} }
} }
std::vector<std::string> std::vector<std::string>
AbstractMenu::group (const std::string &name) const AbstractMenu::group (const std::string &name) const
{ {
std::vector<std::string> grp; std::vector<std::string> grp;
@ -1649,7 +1673,7 @@ AbstractMenu::group (const std::string &name) const
return grp; return grp;
} }
void void
AbstractMenu::collect_group (std::vector<std::string> &grp, const std::string &name, const AbstractMenuItem &item) const AbstractMenu::collect_group (std::vector<std::string> &grp, const std::string &name, const AbstractMenuItem &item) const
{ {
for (std::list<AbstractMenuItem>::const_iterator c = item.children.begin (); c != item.children.end (); ++c) { for (std::list<AbstractMenuItem>::const_iterator c = item.children.begin (); c != item.children.end (); ++c) {