Am Mittwoch, dem 03.04.2024 um 11:41 +0200 schrieb Jürgen Spitzmüller:
> What could be a more clever (?) option, I think, is the possibility
> to assign shortcut alternatives, as in "Text actions|Txct", and LyX
> checks the characters in turn until one is free.

As in the attached.

-- 
Jürgen
diff --git a/src/frontends/qt/Menus.cpp b/src/frontends/qt/Menus.cpp
index 4a09a1b4a7..3704051288 100644
--- a/src/frontends/qt/Menus.cpp
+++ b/src/frontends/qt/Menus.cpp
@@ -233,10 +233,17 @@ public:
 	}
 
 	/// The keyboard shortcut (usually underlined in the entry)
-	QString shortcut() const
+	QString shortcut(bool first = false) const
 	{
 		int const index = label_.lastIndexOf('|');
-		return index == -1 ? QString() : label_.mid(index + 1);
+		if (index == -1)
+			return QString();
+		QString accelerators = label_.mid(index + 1);
+		if (accelerators.size() == 1)
+			return accelerators;
+		if (first)
+			return accelerators.left(1);
+		return accelerators;
 	}
 	/// The complete label, with label and shortcut separated by a '|'
 	QString fulllabel() const { return label_; }
@@ -349,8 +356,12 @@ public:
 	/// Checks the associated FuncRequest status before adding the
 	/// menu item.
 	void addWithStatusCheck(MenuItem const &);
-	// Check whether the menu shortcuts are unique
-	void checkShortcuts() const;
+	/// Check whether the menu shortcuts are unique
+	void checkShortcutUnique(QString const sc) const;
+	/// Check a given menu shortcuts is unique
+	bool checkShortcut(QString const sc) const;
+	/// Try to find a unique shortcut from a string of alternatives
+	QString getBestShortcut(MenuItem const & mi) const;
 	///
 	void expandLastfiles();
 	void expandDocuments();
@@ -760,13 +771,33 @@ void MenuDefinition::cat(MenuDefinition const & other)
 }
 
 
-void MenuDefinition::checkShortcuts() const
+QString MenuDefinition::getBestShortcut(MenuItem const & mi) const
+{
+	QString accelerators = mi.shortcut();
+	if (accelerators.size() <= 1) {
+		checkShortcutUnique(accelerators);
+		return accelerators;
+	}
+	for (int i = 0; i < accelerators.length(); i++)
+	{
+		QString const sc = accelerators.at(i);
+		if (checkShortcut(sc))
+			return sc;
+	}
+	LYXERR0("Menu warning: All accelerators of menu entry "
+	       << '"' << mi.fulllabel()
+	       << "\" are already taken. Omitting shortcut.");
+	return QString();
+}
+
+
+void MenuDefinition::checkShortcutUnique(QString const sc) const
 {
 	// This is a quadratic algorithm, but we do not care because
 	// menus are short enough
 	for (const_iterator it1 = begin(); it1 != end(); ++it1) {
-		QString shortcut = it1->shortcut();
-		if (shortcut.isEmpty())
+		QString shortcut = it1->shortcut(true);
+		if (shortcut != sc)
 			continue;
 		if (!it1->label().contains(shortcut))
 			LYXERR0("Menu warning: menu entry \""
@@ -785,6 +816,19 @@ void MenuDefinition::checkShortcuts() const
 }
 
 
+bool MenuDefinition::checkShortcut(QString const shortcut) const
+{
+	if (shortcut.isEmpty())
+		return true;
+	for (const_iterator it = begin(); it != end(); ++it) {
+		if (it->shortcut(true).compare(shortcut, Qt::CaseInsensitive) == 0) {
+			return false;
+		}
+	}
+	return true;
+}
+
+
 bool MenuDefinition::searchMenu(FuncRequest const & func, docstring_list & names) const
 {
 	const_iterator m = begin();
@@ -2116,12 +2160,12 @@ struct Menu::Impl
 
 
 /// Get a MenuDefinition item label from the menu backend
-static QString label(MenuItem const & mi)
+static QString label(MenuItem const & mi, MenuDefinition const & menu)
 {
 	QString label = mi.label();
 	label.replace("&", "&&");
 
-	QString shortcut = mi.shortcut();
+	QString shortcut = menu.getBestShortcut(mi);
 	if (!shortcut.isEmpty()) {
 		int pos = label.indexOf(shortcut);
 		if (pos != -1)
@@ -2158,7 +2202,7 @@ void Menu::Impl::populate(QMenu * qMenu, MenuDefinition const & menu)
 			qMenu->addSeparator();
 			break;
 		case MenuItem::Submenu: {
-			QMenu * subMenu = qMenu->addMenu(label(m));
+			QMenu * subMenu = qMenu->addMenu(label(m, menu));
 			populate(subMenu, m.submenu());
 			subMenu->setEnabled(!subMenu->isEmpty());
 			break;
@@ -2168,7 +2212,7 @@ void Menu::Impl::populate(QMenu * qMenu, MenuDefinition const & menu)
 			// FIXME: A previous comment assured that MenuItem::Command was the
 			// only possible case in practice, but this is wrong.  It would be
 			// good to document which cases are actually treated here.
-			qMenu->addAction(new Action(m.func(), QIcon(), label(m),
+			qMenu->addAction(new Action(m.func(), QIcon(), label(m, menu),
 			                            m.tooltip(), qMenu));
 			break;
 		}
@@ -2529,9 +2573,6 @@ void Menus::Impl::expand(MenuDefinition const & frommenu,
 	// we do not want the menu to end with a separator
 	if (!tomenu.empty() && tomenu.items_.back().kind() == MenuItem::Separator)
 		tomenu.items_.pop_back();
-
-	// Check whether the shortcuts are unique
-	tomenu.checkShortcuts();
 }
 
 
@@ -2700,7 +2741,7 @@ void Menus::fillMenuBar(QMenuBar * qmb, GuiView * view, bool initial)
 		}
 
 		Menu * menuptr = new Menu(view, m.submenuname(), true);
-		menuptr->setTitle(label(m));
+		menuptr->setTitle(label(m, menu));
 
 #if defined(Q_OS_MAC)
 		// On Mac OS with Qt/Cocoa, the menu is not displayed if there is no action
-- 
lyx-devel mailing list
lyx-devel@lists.lyx.org
http://lists.lyx.org/mailman/listinfo/lyx-devel

Reply via email to