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 "support/lstrings.h"
27 #include "QLyXKeySym.h"
28 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
31 #include <qapplication.h>
46 string const getLabel(MenuItem const & mi)
48 string const shortcut = mi.shortcut();
49 string label = subst(mi.label(), "&", "&&");
51 if (!shortcut.empty()) {
52 string::size_type pos = label.find(shortcut);
53 if (pos != string::npos)
54 label.insert(pos, 1, '&');
61 // The offset added to the special Mac menu entries
62 const int indexOffset = 5000;
68 pair<int, QLPopupMenu *>
69 createMenu(QMenuData * parent, MenuItem const * item, QLMenubar * owner,
72 QLPopupMenu * pm = new QLPopupMenu(owner, item->submenuname(), is_toplevel);
73 int const id = parent->insertItem(toqstr(getLabel(*item)), pm);
74 return make_pair(id, pm);
78 QLPopupMenu::QLPopupMenu(QLMenubar * owner,
79 string const & name, bool toplevel)
80 : owner_(owner), name_(name)
83 connect(this, SIGNAL(aboutToShow()), this, SLOT(showing()));
84 connect(this, SIGNAL(activated(int)),
85 this, SLOT(fire(int)));
89 void QLPopupMenu::fire(int index)
92 if (index >= indexOffset) {
93 MenuItem mi = owner_->backend().getMenu("LyX")[index - indexOffset];
94 owner_->view()->activated(mi.func());
97 owner_->view()->activated(funcs_[index]);
101 void QLPopupMenu::populate(Menu * menu)
105 Menu::const_iterator m = menu->begin();
106 Menu::const_iterator end = menu->end();
107 for (; m != end; ++m) {
108 if (m->kind() == MenuItem::Separator) {
110 } else if (m->kind() == MenuItem::Submenu) {
111 pair<int, QLPopupMenu *> res = createMenu(this, &(*m), owner_);
112 setItemEnabled(res.first, m->status().enabled());
113 res.second->populate(m->submenu());
114 } else { // we have a MenuItem::Command
115 FuncStatus status = m->status();
117 Funcs::iterator fit =
118 funcs_.insert(funcs_.end(), m->func());
119 int const index = distance(funcs_.begin(), fit);
121 QString label = toqstr(getLabel(*m));
123 /* There are two constraints on Qt/Mac: (1)
124 the bindings require a unicode string to be
125 represented meaningfully and std::string
126 does not work (2) only 1-key bindings can
127 be represented in menus.
129 This is why the unpleasant hack bellow is
132 pair<LyXKeySym const *, key_modifier::state>
133 binding = toplevel_keymap->find1keybinding(m->func());
135 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
136 label += '\t' + key->qprint(binding.second);
139 string const binding(m->binding());
140 if (!binding.empty()) {
141 label += '\t' + toqstr(binding);
145 // Actually insert the menu item
146 insertItem(label, index);
147 setItemEnabled(index, status.enabled());
148 setItemChecked(index, status.onoff(true));
154 void QLPopupMenu::showing()
158 Menu const frommenu = owner_->backend().getMenu(name_);
159 owner_->backend().expand(frommenu, tomenu, owner_->view());
162 /* The qt/mac menu code has a very silly hack that
163 moves some menu entries that it recognizes by name
164 (e.g. "Preferences...") to the "LyX" menu. This
165 feature can only work if the menu entries are
166 always available. Since we build menus on demand,
167 we add some dummy contents to one of the menus (JMarc)
169 static QLPopupMenu * themenu = this;
170 if (themenu == this && owner_->backend().hasMenu("LyX")) {
171 Menu special = owner_->backend().getMenu("LyX");
172 Menu::const_iterator end = special.end();
173 Menu::size_type i = 0;
174 for (Menu::const_iterator cit = special.begin();
175 cit != end ; ++cit, ++i)
176 insertItem(toqstr(cit->label()), indexOffset + i);
181 } // namespace frontend