Right, here's how I've handled this issue: -modify GLyXKeySym.C to produce nicer human-readable accelerators like Ctrl+N. Not functionally necessary, but better UI. -In GMenubar.C, load two labels (item name and accel string) into an hbox and load the hbox into a menuitem. It's not that concise, but it's not really a hack.
Attached patch should sort this issue: Add gtk+ style accelerator labels to menu items. Previous runtime warnings have of course vanished because we're not using Gtk accels any more, just plain old labels. Less important comments follow, for completeness's sake. On Wed, 2004-09-29 at 13:42, Jean-Marc Lasgouttes wrote: > John> produce gtk-style strings like "Ctrl+N" (in fact, this is also > John> the normal style for qt apps, so I don't know why the qt > John> frontend uses "C-n"). > > AFAIK it does not do so in 1.4.0cvs. Note that the qt frontend does > not use the Ctrl+n style on OSX, and I guess it uses local style on > windows too. Oh, I don't actually have a cvs-built qt frontend, only a 1.3.x one. Fair enough. > John> The problem is that I also use a string like "<control>n" to > John> create GTK+ AccelKey objects for the menus. Right now I'm > John> converting from "Ctrl+N" to "<control>N" by string substitution > John> at the time of creating the menu item. > > So gtk+ has two types of string representation for an accel, one being > the internal representation, and the other the user-visible one. > Right? I'm not sure I'd call it the internal representation: the string I pass it on construction is probably not stored (just parsed). > One can only create a AccelKey object from a "<string>n" type of > string. Right? Yes, or from non-string information about the key and modifier like so: AccelKey (guint accel_key, Gdk::ModifierType accel_mods, const Glib::ustring& accel_path="") > Note that we do not really want to create accelerators for the menus > (since LyX does call the function itself). We just want to _display_ > an accelerator in the menu, as a reminder to the user. I think that > getting access to Gtk::MenuItem::add_accel_label would be the right > solution. It might be that subclassing Gtk::MenuItem is the simplest > thing to do... Right, I've tried that. However, add_accel_label doesn't actually do what you'd expect. I've actually looked in the gtk source and I'm still not sure how it's meant to work. > - a given function can be bound to several kb_sequences (for example, > font-emph is either "C-e" or "M-c e".). For the menu, we select the > first such sequence. Thanks for the clarification. > - LyX supports multi-LyXKeysym keyboard sequences (think "C-x C-f" in > emacs bindings). Does Gtk+ AccelKey support that? I doubt it. However, the gtk frontend does seem to support the sequences somehow. I haven't looked into how that's handled. John
Index: GLyXKeySym.C =================================================================== RCS file: /cvs/lyx/lyx-devel/src/frontends/gtk/GLyXKeySym.C,v retrieving revision 1.5 diff -u -3 -p -r1.5 GLyXKeySym.C --- GLyXKeySym.C 2004/09/26 18:36:07 1.5 +++ GLyXKeySym.C 2004/09/29 14:14:12 @@ -16,6 +16,8 @@ #include <gtkmm.h> #include <gdk/gdkkeysyms.h> +#include "support/lstrings.h" + using std::string; @@ -94,9 +96,25 @@ char GLyXKeySym::getISOEncoded(string co } +//Produce a human readable version in the GTK+ style (eg Ctrl+N) string const GLyXKeySym::print(key_modifier::state mod) const { - return kb_keymap::printKeySym(*this, mod); + string buf; + string symname = getSymbolName(); + + if (mod & key_modifier::shift) + buf += "Shift+"; + if (mod & key_modifier::ctrl) + buf += "Ctrl+"; + if (mod & key_modifier::alt) + buf += "Alt+"; + + //Uppercase the first letter, for Ctrl+N rather than Ctrl+n, + //and for Ctrl+Greater rather than Ctrl+GREATER + *symname.begin() = lyx::support::uppercase(*symname.begin()); + buf += symname; + + return buf; } Index: GMenubar.C =================================================================== RCS file: /cvs/lyx/lyx-devel/src/frontends/gtk/GMenubar.C,v retrieving revision 1.14 diff -u -3 -p -r1.14 GMenubar.C --- GMenubar.C 2004/09/26 18:36:07 1.14 +++ GMenubar.C 2004/09/29 14:14:12 @@ -180,9 +180,6 @@ void GMenubar::onSubMenuActivate(MenuIte break; case MenuItem::Command: { -#ifdef WITH_WARNINGS -#warning Bindings are not inserted into the menu labels here. (Lgb) -#endif FuncStatus const flag = view_->getLyXFunc().getStatus(i->func()); bool on = flag.onoff(true); @@ -198,10 +195,21 @@ void GMenubar::onSubMenuActivate(MenuIte gmenu->items().back()); citem.set_active(on); } else { - gmenu->items().push_back( - Gtk::Menu_Helpers::MenuElem( - labelTrans(i->label(), - i->shortcut()))); + //This is necessary because add_accel_label is protected, + //and even if you subclass Gtk::MenuItem then add_accel_label + //doesn't do what you'd expect. + Gtk::MenuItem * item = Gtk::manage(new Gtk::MenuItem); + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox); + Gtk::Label * label1 = Gtk::manage(new Gtk::Label( + labelTrans(i->label(), i->shortcut()), true)); + Gtk::Label * label2 = Gtk::manage(new Gtk::Label( + " " + i->binding(), false)); + hbox->pack_start(*label1, false, false, 0); + hbox->pack_end(*label2, false, false, 0); + item->add(*hbox); + + gmenu->append(*item); + item->show_all(); } Gtk::MenuItem & item = gmenu->items().back(); item.signal_activate().connect(