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)
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;
77 Menu const & fromLyxMenu = owner_->backend().getMenu(name_);
78 owner_->backend().expand(fromLyxMenu, topLevelMenu_, owner_->view());
80 if (!owner_->backend().hasMenu(topLevelMenu_.name())) {
81 lyxerr[Debug::GUI] << "\tWARNING: menu seems empty" << topLevelMenu_.name() << endl;
83 populate(this, &topLevelMenu_);
85 specialMacXmenuHack();
88 void QLPopupMenu::populate(QMenu* qMenu, Menu * menu)
90 lyxerr[Debug::GUI] << "populating menu " << menu->name() ;
91 if (menu->size() == 0) {
92 lyxerr[Debug::GUI] << "\tERROR: empty menu " << menu->name() << endl;
96 lyxerr[Debug::GUI] << " ***** menu entries " << menu->size() << endl;
99 Menu::const_iterator m = menu->begin();
100 Menu::const_iterator end = menu->end();
102 for (; m != end; ++m) {
104 if (m->kind() == MenuItem::Separator) {
106 qMenu->addSeparator();
107 lyxerr[Debug::GUI] << "adding Menubar Separator" << endl;
109 } else if (m->kind() == MenuItem::Submenu) {
111 lyxerr[Debug::GUI] << "** creating New Sub-Menu " << getLabel(*m) << endl;
112 QMenu * subMenu = qMenu->addMenu(toqstr(getLabel(*m)));
113 populate(subMenu, m->submenu());
115 } else { // we have a MenuItem::Command
117 FuncStatus status = m->status();
118 lyxerr[Debug::GUI] << "creating Menu Item " << m->label() << endl;
120 string label = getLabel(*m);
121 addBinding(label, *m);
123 QLAction * action = new QLAction(*(owner_->view()), label, m->func());
124 action->setEnabled(m->status().enabled());
125 action->setChecked(m->status().onoff(true));
126 // Actually insert the menu item
127 qMenu->addAction(action);
132 string const QLPopupMenu::getLabel(MenuItem const & mi)
134 string const shortcut = mi.shortcut();
135 string label = support::subst(mi.label(), "&", "&&");
137 if (!shortcut.empty()) {
138 string::size_type pos = label.find(shortcut);
139 if (pos != string::npos)
140 label.insert(pos, 1, '&');
146 /// \todo Mac specific binding handling.
147 void QLPopupMenu::addBinding(string & label, MenuItem const & mi)
151 string const binding(mi.binding());
152 if (!binding.empty()) {
153 label += '\t' + binding;
157 /* There are two constraints on Qt/Mac: (1)
158 the bindings require a unicode string to be
159 represented meaningfully and std::string
160 does not work (2) only 1-key bindings can
161 be represented in menus.
163 This is why the unpleasant hack bellow is
166 /* pair<LyXKeySym const *, key_modifier::state>
167 binding = toplevel_keymap->find1keybinding(mi.func());
169 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
170 label += '\t' + key->qprint(binding.second);
176 /// \todo Fix Mac specific menu hack
177 void QLPopupMenu::specialMacXmenuHack()
180 /* The qt/mac menu code has a very silly hack that
181 moves some menu entries that it recognizes by name
182 (e.g. "Preferences...") to the "LyX" menu. This
183 feature can only work if the menu entries are
184 always available. Since we build menus on demand,
185 we add some dummy contents to one of the menus (JMarc)
188 static QLPopupMenu * themenu = this;
189 if (themenu == this && owner_->backend().hasMenu("LyX")) {
190 Menu special = owner_->backend().getMenu("LyX");
191 Menu::const_iterator end = special.end();
192 Menu::size_type i = 0;
193 for (Menu::const_iterator cit = special.begin();
194 cit != end ; ++cit, ++i)
195 insertItem(toqstr(cit->label()), indexOffset + i);
201 } // namespace frontend