]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QLPopupMenu.C
rename LFUN enum values according to their command (as used in th minibuffer/bind...
[lyx.git] / src / frontends / qt4 / QLPopupMenu.C
1 /**
2  * \file QLPopupMenu.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Abdelrazak Younes
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include <boost/current_function.hpp>
15
16 // Qt defines a macro 'signals' that clashes with a boost namespace.
17 // All is well if the namespace is visible first.
18 #include "QtView.h"
19
20 #include "QLAction.h"
21 #include "QLPopupMenu.h"
22 #include "QLMenubar.h"
23 #include "qt_helpers.h"
24 #include "MenuBackend.h"
25
26 #include "frontends/lyx_gui.h"
27 #include "support/lstrings.h"
28 #include "debug.h"
29
30
31 #ifdef Q_WS_MACX
32 #include "kbmap.h"
33 #include "QLyXKeySym.h"
34 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
35 #endif
36
37 using std::make_pair;
38 using std::string;
39 using std::pair;
40 using std::endl;
41
42 namespace {
43
44 } // namespace anon
45
46 namespace lyx {
47
48 namespace frontend {
49
50
51 // MacOSX specific stuff is at the end.
52
53 QLPopupMenu::QLPopupMenu(QLMenubar * owner,
54                                                  MenuItem const & mi, bool topLevelMenu)
55         : owner_(owner)
56 {
57         name_ = mi.submenuname();
58
59         setTitle(toqstr(getLabel(mi)));
60
61         if (topLevelMenu)
62                 connect(this, SIGNAL(aboutToShow()), this, SLOT(update()));
63 }
64
65
66
67 void QLPopupMenu::update()
68 {
69         lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION << endl;
70         lyxerr[Debug::GUI] << "\tTriggered menu: " << name_ << endl;
71
72         clear();
73
74         if (name_.empty())
75                 return;
76
77         Menu const & fromLyxMenu = owner_->backend().getMenu(name_);
78         owner_->backend().expand(fromLyxMenu, topLevelMenu_, owner_->view());
79
80         if (!owner_->backend().hasMenu(topLevelMenu_.name())) {
81                 lyxerr[Debug::GUI] << "\tWARNING: menu seems empty" << topLevelMenu_.name() << endl;
82         }
83         populate(this, &topLevelMenu_);
84
85         specialMacXmenuHack();
86 }
87
88 void QLPopupMenu::populate(QMenu* qMenu, Menu * menu)
89 {
90         lyxerr[Debug::GUI] << "populating menu " << menu->name() ;
91         if (menu->size() == 0) {
92                 lyxerr[Debug::GUI] << "\tERROR: empty menu " << menu->name() << endl;
93                 return;
94         }
95         else {
96                 lyxerr[Debug::GUI] << " *****  menu entries " << menu->size() << endl;
97         }
98
99         Menu::const_iterator m = menu->begin();
100         Menu::const_iterator end = menu->end();
101
102         for (; m != end; ++m) {
103
104                 if (m->kind() == MenuItem::Separator) {
105
106                         qMenu->addSeparator();
107                         lyxerr[Debug::GUI] << "adding Menubar Separator" << endl;
108
109                 } else if (m->kind() == MenuItem::Submenu) {
110
111                         lyxerr[Debug::GUI] << "** creating New Sub-Menu " << getLabel(*m) << endl;
112                         QMenu * subMenu = qMenu->addMenu(toqstr(getLabel(*m)));
113                         populate(subMenu, m->submenu());
114
115                 } else { // we have a MenuItem::Command
116
117                         FuncStatus status = m->status();
118                         lyxerr[Debug::GUI] << "creating Menu Item " << m->label() << endl;
119
120                         string label = getLabel(*m);
121                         addBinding(label, *m);
122
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);
128                 }
129         }
130 }
131
132 string const QLPopupMenu::getLabel(MenuItem const & mi)
133 {
134         string const shortcut = mi.shortcut();
135         string label = support::subst(mi.label(), "&", "&&");
136
137         if (!shortcut.empty()) {
138                 string::size_type pos = label.find(shortcut);
139                 if (pos != string::npos)
140                         label.insert(pos, 1, '&');
141         }
142
143         return label;
144 }
145
146 /// \todo Mac specific binding handling.
147 void QLPopupMenu::addBinding(string & label, MenuItem const & mi)
148 {
149 #ifndef Q_WS_MACX
150
151                 string const binding(mi.binding());
152                 if (!binding.empty()) {
153                         label += '\t' + binding;
154                 }
155
156 #else
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.
162
163                            This is why the unpleasant hack bellow is
164                            needed (JMarc)
165                         */
166 /*                      pair<LyXKeySym const *, key_modifier::state>
167                                 binding = toplevel_keymap->find1keybinding(mi.func());
168                         if (binding.first) {
169                                 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
170                                 label += '\t' + key->qprint(binding.second);
171                         }
172 */
173 #endif
174 }
175
176 /// \todo Fix Mac specific menu hack
177 void QLPopupMenu::specialMacXmenuHack()
178 {
179 #ifdef Q_WS_MACX
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)
186         */
187 /*
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);
196         }
197 */
198 #endif
199 }
200
201 } // namespace frontend
202 } // namespace lyx