3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
7 * \author Abdelrazak Younes
9 * Full author contact details are available in file CREDITS.
14 #include <boost/current_function.hpp>
16 // Qt defines a macro 'signals' that clashes with a boost namespace.
17 // All is well if the namespace is visible first.
21 #include "QLPopupMenu.h"
22 #include "QLMenubar.h"
23 #include "qt_helpers.h"
24 #include "MenuBackend.h"
26 #include "frontends/lyx_gui.h"
27 #include "support/lstrings.h"
33 #include "QLyXKeySym.h"
34 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
51 // MacOSX specific stuff is at the end.
53 QLPopupMenu::QLPopupMenu(QLMenubar * owner,
54 MenuItem const & mi, bool topLevelMenu)
55 : owner_(owner), topLevelMenu_(topLevelMenu)
57 name_ = mi.submenuname();
59 setTitle(toqstr(getLabel(mi)));
62 connect(this, SIGNAL(aboutToShow()), this, SLOT(update()));
67 void QLPopupMenu::update()
69 lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION << endl;
70 lyxerr[Debug::GUI] << "\tTriggered menu: " << name_ << endl;
78 Menu const & fromLyxMenu = owner_->backend().getMenu(name_);
79 owner_->backend().expand(fromLyxMenu, topLevelMenu, owner_->view());
81 if (!owner_->backend().hasMenu(topLevelMenu.name())) {
82 lyxerr[Debug::GUI] << "\tWARNING: menu seems empty" << topLevelMenu.name() << endl;
84 populate(this, &topLevelMenu);
86 specialMacXmenuHack();
89 void QLPopupMenu::populate(QMenu* qMenu, Menu * menu)
91 lyxerr[Debug::GUI] << "populating menu " << menu->name() ;
92 if (menu->size() == 0) {
93 lyxerr[Debug::GUI] << "\tERROR: empty menu " << menu->name() << endl;
97 lyxerr[Debug::GUI] << " ***** menu entries " << menu->size() << endl;
100 Menu::const_iterator m = menu->begin();
101 Menu::const_iterator end = menu->end();
103 for (; m != end; ++m) {
105 if (m->kind() == MenuItem::Separator) {
107 qMenu->addSeparator();
108 lyxerr[Debug::GUI] << "adding Menubar Separator" << endl;
110 } else if (m->kind() == MenuItem::Submenu) {
112 lyxerr[Debug::GUI] << "** creating New Sub-Menu " << getLabel(*m) << endl;
113 QMenu * subMenu = qMenu->addMenu(toqstr(getLabel(*m)));
114 populate(subMenu, m->submenu());
116 } else { // we have a MenuItem::Command
118 FuncStatus status = m->status();
119 lyxerr[Debug::GUI] << "creating Menu Item " << m->label() << endl;
121 string label = getLabel(*m);
122 addBinding(label, *m);
124 QLAction * action = new QLAction(*(owner_->view()), label, m->func());
125 action->setEnabled(m->status().enabled());
126 action->setChecked(m->status().onoff(true));
127 // Actually insert the menu item
128 qMenu->addAction(action);
133 string const QLPopupMenu::getLabel(MenuItem const & mi)
135 string const shortcut = mi.shortcut();
136 string label = support::subst(mi.label(), "&", "&&");
138 if (!shortcut.empty()) {
139 string::size_type pos = label.find(shortcut);
140 if (pos != string::npos)
141 label.insert(pos, 1, '&');
147 /// \todo Mac specific binding handling.
148 void QLPopupMenu::addBinding(string & label, MenuItem const & mi)
152 string const binding(mi.binding());
153 if (!binding.empty()) {
154 label += '\t' + binding;
158 /* There are two constraints on Qt/Mac: (1)
159 the bindings require a unicode string to be
160 represented meaningfully and std::string
161 does not work (2) only 1-key bindings can
162 be represented in menus.
164 This is why the unpleasant hack bellow is
167 /* pair<LyXKeySym const *, key_modifier::state>
168 binding = toplevel_keymap->find1keybinding(mi.func());
170 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
171 label += '\t' + key->qprint(binding.second);
177 /// \todo Fix Mac specific menu hack
178 void QLPopupMenu::specialMacXmenuHack()
181 /* The qt/mac menu code has a very silly hack that
182 moves some menu entries that it recognizes by name
183 (e.g. "Preferences...") to the "LyX" menu. This
184 feature can only work if the menu entries are
185 always available. Since we build menus on demand,
186 we add some dummy contents to one of the menus (JMarc)
189 static QLPopupMenu * themenu = this;
190 if (themenu == this && owner_->backend().hasMenu("LyX")) {
191 Menu special = owner_->backend().getMenu("LyX");
192 Menu::const_iterator end = special.end();
193 Menu::size_type i = 0;
194 for (Menu::const_iterator cit = special.begin();
195 cit != end ; ++cit, ++i)
196 insertItem(toqstr(cit->label()), indexOffset + i);
202 } // namespace frontend