Proposing a fix for issue #1722: add a '...' menu to hold the dynamic parts

This commit is contained in:
Matthias Koefferlein 2024-05-31 11:15:45 +02:00
parent 48b32733c2
commit c148f591b4
3 changed files with 89 additions and 2 deletions

View File

@ -4350,6 +4350,10 @@ public:
menu_entries.push_back (lay::submenu ("zoom_menu", at, tl::to_string (QObject::tr ("&Display"))));
menu_entries.push_back (lay::submenu ("tools_menu", at, tl::to_string (QObject::tr ("&Tools"))));
menu_entries.push_back (lay::submenu ("macros_menu", at, tl::to_string (QObject::tr ("&Macros"))));
if (lay::AbstractMenu::wants_extra_menu ()) {
// for MacOS
menu_entries.push_back (lay::submenu (lay::AbstractMenu::extra_menu_name (), at, "..."));
}
menu_entries.push_back (lay::separator ("help_group", at));
menu_entries.push_back (lay::submenu ("help_menu", at, tl::to_string (QObject::tr ("&Help"))));
menu_entries.push_back (lay::submenu ("@secrets", at, tl::to_string (QObject::tr ("Secret Features"))));

View File

@ -1225,6 +1225,36 @@ static QAction *insert_action_after (QWidget *widget, QAction *after, QAction *a
return action;
}
static const std::string s_extras_menu_name ("_extras_menu");
static QMenu *find_extras_menu (QMenuBar *mbar)
{
if (! mbar) {
return 0;
}
QList<QAction *> a = mbar->actions ();
for (QList<QAction *>::const_iterator i = a.begin (); i != a.end (); ++i) {
if (tl::to_string ((*i)->objectName ()) == s_extras_menu_name) {
return (*i)->menu ();
}
}
return 0;
}
bool
AbstractMenu::wants_extra_menu ()
{
return !s_can_move_menu;
}
const std::string &
AbstractMenu::extra_menu_name ()
{
return s_extras_menu_name;
}
void
AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
{
@ -1234,10 +1264,22 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
std::set<std::pair<size_t, QAction *> > present_actions;
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));
}
}
// NOTE: on MacOS, once the top level menu is created, we should not
// modify it and place menu items into the "Extras" menu instead.
bool menu_frozen = ! s_can_move_menu && ! present_actions.empty ();
// NOTE: the "extras" menu is relevant on MacOS only
QMenu *extras_menu = find_extras_menu (mbar);
if (extras_menu) {
extras_menu->clear ();
}
QAction *prev_action = 0;
@ -1277,11 +1319,25 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
} else if (mbar) {
if (c->menu () == 0) {
QMenu *menu = new QMenu (mp_dispatcher->menu_parent_widget ());
menu->setTitle (tl::to_qstring (c->action ()->get_title ()));
c->set_action (new Action (menu), true);
prev_action = insert_action_after (mbar, prev_action, menu->menuAction ());
// This case happens when we dynamically create menus.
// MacOS does not like generating top-level menus dynamically, so
// we put them into the "_extra" top level one.
if (menu_frozen) {
QMenu *extras_menu = find_extras_menu (mbar);
if (extras_menu) {
extras_menu->addMenu (menu);
}
} else {
prev_action = insert_action_after (mbar, prev_action, menu->menuAction ());
}
} else {
// 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->menu ()->menuAction ()), c->menu ()->menuAction ()));
if (a != present_actions.end ()) {
@ -1291,9 +1347,15 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
}
prev_action = a->second;
present_actions.erase (*a);
} else if (menu_frozen) {
QMenu *extras_menu = find_extras_menu (mbar);
if (extras_menu) {
extras_menu->addMenu (c->menu ());
}
} else {
prev_action = insert_action_after (mbar, prev_action, c->menu ()->menuAction ());
}
}
build (c->menu (), c->children);
@ -1311,6 +1373,11 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
}
prev_action = a->second;
present_actions.erase (*a);
} else if (menu_frozen) {
QMenu *extras_menu = find_extras_menu (mbar);
if (extras_menu) {
extras_menu->addAction (c->action ()->qaction ());
}
} else {
prev_action = insert_action_after (mbar, prev_action, c->action ()->qaction ());
}
@ -1319,8 +1386,14 @@ AbstractMenu::build (QMenuBar *mbar, QToolBar *tbar)
}
// Disable the (maybe new) "extras" menu if empty
extras_menu = find_extras_menu (mbar);
if (extras_menu) {
extras_menu->setEnabled (! extras_menu->isEmpty ());
}
// Remove all actions that have vanished
if (mbar) {
if (mbar && s_can_move_menu) {
for (std::set<std::pair<size_t, QAction *> >::iterator a = present_actions.begin (); a != present_actions.end (); ++a) {
mbar->removeAction (a->second);
}

View File

@ -692,6 +692,16 @@ public:
*/
~AbstractMenu ();
/**
* @brief Returns a value indicating that a special "extras" menu is needed
*/
static bool wants_extra_menu ();
/**
* @brief Returns the name of the special "extras" menu
*/
static const std::string &extra_menu_name ();
#if defined(HAVE_QT)
/**
* @brief Rebuild the QMenu's and refill the QMenuBar object