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 // Qt defines a macro 'signals' that clashes with a boost namespace.
15 // All is well if the namespace is visible first.
19 #include "QLPopupMenu.h"
20 #include "QLMenubar.h"
21 #include "qt_helpers.h"
22 #include "MenuBackend.h"
24 #include "frontends/lyx_gui.h"
25 #include "support/lstrings.h"
31 #include "QLyXKeySym.h"
32 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
49 // MacOSX specific stuff is at the end.
51 QLPopupMenu::QLPopupMenu(QLMenubar * owner,
52 MenuItem const & mi, bool topLevelMenu)
53 : owner_(owner), topLevelMenu_(topLevelMenu)
55 name_ = mi.submenuname();
57 setTitle(toqstr(getLabel(mi)));
60 connect(this, SIGNAL(aboutToShow()), this, SLOT(update()));
65 void QLPopupMenu::update()
67 lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION << endl;
68 lyxerr[Debug::GUI] << "\tTriggered menu: " << name_ << endl;
76 Menu const & fromLyxMenu = owner_->backend().getMenu(name_);
77 owner_->backend().expand(fromLyxMenu, topLevelMenu, owner_->view());
79 if (!owner_->backend().hasMenu(topLevelMenu.name())) {
80 lyxerr[Debug::GUI] << "\tWARNING: menu seems empty" << topLevelMenu.name() << endl;
82 populate(this, &topLevelMenu);
84 specialMacXmenuHack();
87 void QLPopupMenu::populate(QMenu* qMenu, Menu * menu)
89 lyxerr[Debug::GUI] << "populating menu " << menu->name() ;
90 if (menu->size() == 0) {
91 lyxerr[Debug::GUI] << "\tERROR: empty menu " << menu->name() << endl;
95 lyxerr[Debug::GUI] << " ***** menu entries " << menu->size() << endl;
98 Menu::const_iterator m = menu->begin();
99 Menu::const_iterator end = menu->end();
101 for (; m != end; ++m) {
103 if (m->kind() == MenuItem::Separator) {
105 qMenu->addSeparator();
106 lyxerr[Debug::GUI] << "adding Menubar Separator" << endl;
108 } else if (m->kind() == MenuItem::Submenu) {
110 lyxerr[Debug::GUI] << "** creating New Sub-Menu " << getLabel(*m) << endl;
111 QMenu * subMenu = qMenu->addMenu(toqstr(getLabel(*m)));
112 populate(subMenu, m->submenu());
114 } else { // we have a MenuItem::Command
116 FuncStatus status = m->status();
117 lyxerr[Debug::GUI] << "creating Menu Item " << m->label() << endl;
119 string label = getLabel(*m);
120 addBinding(label, *m);
122 QLAction * action = new QLAction(*(owner_->view()), label, m->func());
123 action->setEnabled(m->status().enabled());
124 action->setChecked(m->status().onoff(true));
125 // Actually insert the menu item
126 qMenu->addAction(action);
131 string const QLPopupMenu::getLabel(MenuItem const & mi)
133 string const shortcut = mi.shortcut();
134 string label = support::subst(mi.label(), "&", "&&");
136 if (!shortcut.empty()) {
137 string::size_type pos = label.find(shortcut);
138 if (pos != string::npos)
139 label.insert(pos, 1, '&');
145 /// \todo Mac specific binding handling.
146 void QLPopupMenu::addBinding(string & label, MenuItem const & mi)
150 string const binding(mi.binding());
151 if (!binding.empty()) {
152 label += '\t' + binding;
156 /* There are two constraints on Qt/Mac: (1)
157 the bindings require a unicode string to be
158 represented meaningfully and std::string
159 does not work (2) only 1-key bindings can
160 be represented in menus.
162 This is why the unpleasant hack bellow is
165 /* pair<LyXKeySym const *, key_modifier::state>
166 binding = toplevel_keymap->find1keybinding(mi.func());
168 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
169 label += '\t' + key->qprint(binding.second);
175 /// \todo Fix Mac specific menu hack
176 void QLPopupMenu::specialMacXmenuHack()
179 /* The qt/mac menu code has a very silly hack that
180 moves some menu entries that it recognizes by name
181 (e.g. "Preferences...") to the "LyX" menu. This
182 feature can only work if the menu entries are
183 always available. Since we build menus on demand,
184 we add some dummy contents to one of the menus (JMarc)
187 static QLPopupMenu * themenu = this;
188 if (themenu == this && owner_->backend().hasMenu("LyX")) {
189 Menu special = owner_->backend().getMenu("LyX");
190 Menu::const_iterator end = special.end();
191 Menu::size_type i = 0;
192 for (Menu::const_iterator cit = special.begin();
193 cit != end ; ++cit, ++i)
194 insertItem(toqstr(cit->label()), indexOffset + i);
200 } // namespace frontend