3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
13 // Qt defines a macro 'signals' that clashes with a boost namespace.
14 // All is well if the namespace is visible first.
17 #include "QLPopupMenu.h"
18 #include "QLMenubar.h"
19 #include "qt_helpers.h"
21 #include "MenuBackend.h"
23 #include "frontends/lyx_gui.h"
25 #include "support/lstrings.h"
29 #include "QLyXKeySym.h"
30 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
33 #include <qapplication.h>
48 string const getLabel(MenuItem const & mi)
50 string const shortcut = mi.shortcut();
51 string label = subst(mi.label(), "&", "&&");
53 if (!shortcut.empty()) {
54 string::size_type pos = label.find(shortcut);
55 if (pos != string::npos)
56 label.insert(pos, 1, '&');
63 // The offset added to the special Mac menu entries
64 const int indexOffset = 5000;
70 pair<int, QLPopupMenu *>
71 createMenu(QMenuData * parent, MenuItem const * item, QLMenubar * owner,
74 QLPopupMenu * pm = new QLPopupMenu(owner, item->submenuname(), is_toplevel);
75 int const id = parent->insertItem(toqstr(getLabel(*item)), pm);
76 return make_pair(id, pm);
80 QLPopupMenu::QLPopupMenu(QLMenubar * owner,
81 string const & name, bool toplevel)
82 : owner_(owner), name_(name)
85 connect(this, SIGNAL(aboutToShow()), this, SLOT(showing()));
86 connect(this, SIGNAL(activated(int)),
87 this, SLOT(fire(int)));
91 void QLPopupMenu::fire(int index)
93 // make sure the interface is repainted correctly (in case the
94 // action needs a long time, like File>Open).
95 lyx_gui::sync_events();
97 if (index >= indexOffset) {
98 MenuItem mi = owner_->backend().getMenu("LyX")[index - indexOffset];
99 owner_->view()->activated(mi.func());
102 owner_->view()->activated(funcs_[index]);
106 void QLPopupMenu::populate(Menu * menu)
110 Menu::const_iterator m = menu->begin();
111 Menu::const_iterator end = menu->end();
112 for (; m != end; ++m) {
113 if (m->kind() == MenuItem::Separator) {
115 } else if (m->kind() == MenuItem::Submenu) {
116 pair<int, QLPopupMenu *> res = createMenu(this, &(*m), owner_);
117 setItemEnabled(res.first, m->status().enabled());
118 res.second->populate(m->submenu());
119 } else { // we have a MenuItem::Command
120 FuncStatus status = m->status();
122 Funcs::iterator fit =
123 funcs_.insert(funcs_.end(), m->func());
124 int const index = distance(funcs_.begin(), fit);
126 QString label = toqstr(getLabel(*m));
128 /* There are two constraints on Qt/Mac: (1)
129 the bindings require a unicode string to be
130 represented meaningfully and std::string
131 does not work (2) only 1-key bindings can
132 be represented in menus.
134 This is why the unpleasant hack bellow is
137 pair<LyXKeySym const *, key_modifier::state>
138 binding = toplevel_keymap->find1keybinding(m->func());
140 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
141 label += '\t' + key->qprint(binding.second);
144 string const binding(m->binding());
145 if (!binding.empty()) {
146 label += '\t' + toqstr(binding);
150 // Actually insert the menu item
151 insertItem(label, index);
152 setItemEnabled(index, status.enabled());
153 setItemChecked(index, status.onoff(true));
159 void QLPopupMenu::showing()
163 Menu const frommenu = owner_->backend().getMenu(name_);
164 owner_->backend().expand(frommenu, tomenu, owner_->view());
167 /* The qt/mac menu code has a very silly hack that
168 moves some menu entries that it recognizes by name
169 (e.g. "Preferences...") to the "LyX" menu. This
170 feature can only work if the menu entries are
171 always available. Since we build menus on demand,
172 we add some dummy contents to one of the menus (JMarc)
174 static QLPopupMenu * themenu = this;
175 if (themenu == this && owner_->backend().hasMenu("LyX")) {
176 Menu special = owner_->backend().getMenu("LyX");
177 Menu::const_iterator end = special.end();
178 Menu::size_type i = 0;
179 for (Menu::const_iterator cit = special.begin();
180 cit != end ; ++cit, ++i)
181 insertItem(toqstr(cit->label()), indexOffset + i);
186 } // namespace frontend