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)
91 qApp->processEvents();
93 if (index >= indexOffset) {
94 MenuItem mi = owner_->backend().getMenu("LyX")[index - indexOffset];
95 owner_->view()->activated(mi.func());
98 owner_->view()->activated(funcs_[index]);
102 void QLPopupMenu::populate(Menu * menu)
106 Menu::const_iterator m = menu->begin();
107 Menu::const_iterator end = menu->end();
108 for (; m != end; ++m) {
109 if (m->kind() == MenuItem::Separator) {
111 } else if (m->kind() == MenuItem::Submenu) {
112 pair<int, QLPopupMenu *> res = createMenu(this, &(*m), owner_);
113 setItemEnabled(res.first, m->status().enabled());
114 res.second->populate(m->submenu());
115 } else { // we have a MenuItem::Command
116 FuncStatus status = m->status();
118 Funcs::iterator fit =
119 funcs_.insert(funcs_.end(), m->func());
120 int const index = distance(funcs_.begin(), fit);
122 QString label = toqstr(getLabel(*m));
124 /* There are two constraints on Qt/Mac: (1)
125 the bindings require a unicode string to be
126 represented meaningfully and std::string
127 does not work (2) only 1-key bindings can
128 be represented in menus.
130 This is why the unpleasant hack bellow is
133 pair<LyXKeySym const *, key_modifier::state>
134 binding = toplevel_keymap->find1keybinding(m->func());
136 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
137 label += '\t' + key->qprint(binding.second);
140 string const binding(m->binding());
141 if (!binding.empty()) {
142 label += '\t' + toqstr(binding);
146 // Actually insert the menu item
147 insertItem(label, index);
148 setItemEnabled(index, status.enabled());
149 setItemChecked(index, status.onoff(true));
155 void QLPopupMenu::showing()
159 Menu const frommenu = owner_->backend().getMenu(name_);
160 owner_->backend().expand(frommenu, tomenu, owner_->view());
163 /* The qt/mac menu code has a very silly hack that
164 moves some menu entries that it recognizes by name
165 (e.g. "Preferences...") to the "LyX" menu. This
166 feature can only work if the menu entries are
167 always available. Since we build menus on demand,
168 we add some dummy contents to one of the menus (JMarc)
170 static QLPopupMenu * themenu = this;
171 if (themenu == this && owner_->backend().hasMenu("LyX")) {
172 Menu special = owner_->backend().getMenu("LyX");
173 Menu::const_iterator end = special.end();
174 Menu::size_type i = 0;
175 for (Menu::const_iterator cit = special.begin();
176 cit != end ; ++cit, ++i)
177 insertItem(toqstr(cit->label()), indexOffset + i);
182 } // namespace frontend