]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QLPopupMenu.C
This commit saves the need to check for lyx::use_gui in a number of places.
[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 "GuiView.h"
19
20 #include "Action.h"
21 #include "QLPopupMenu.h"
22 #include "QLMenubar.h"
23 #include "qt_helpers.h"
24 #include "MenuBackend.h"
25
26 #include "support/lstrings.h"
27 #include "debug.h"
28
29
30 #ifdef Q_WS_MACX
31 #include "kbmap.h"
32 #include "QLyXKeySym.h"
33 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
34 #endif
35
36 using std::make_pair;
37 using std::string;
38 using std::pair;
39 using std::endl;
40
41 namespace {
42
43 } // namespace anon
44
45 namespace lyx {
46
47 namespace frontend {
48
49
50 // MacOSX specific stuff is at the end.
51
52 QLPopupMenu::QLPopupMenu(QLMenubar * owner,
53                                                  MenuItem const & mi, bool topLevelMenu)
54         : owner_(owner)
55 {
56         name_ = mi.submenuname();
57
58         setTitle(toqstr(getLabel(mi)));
59
60         if (topLevelMenu)
61                 connect(this, SIGNAL(aboutToShow()), this, SLOT(update()));
62 }
63
64
65
66 void QLPopupMenu::update()
67 {
68         lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION << endl;
69         lyxerr[Debug::GUI] << "\tTriggered menu: " << lyx::to_utf8(name_) << endl;
70
71         clear();
72
73         if (name_.empty())
74                 return;
75
76         Menu const & fromLyxMenu = owner_->backend().getMenu(name_);
77         owner_->backend().expand(fromLyxMenu, topLevelMenu_, owner_->view()->buffer());
78
79         if (!owner_->backend().hasMenu(topLevelMenu_.name())) {
80                 lyxerr[Debug::GUI] << "\tWARNING: menu seems empty" << lyx::to_utf8(topLevelMenu_.name()) << endl;
81         }
82         populate(this, &topLevelMenu_);
83
84         specialMacXmenuHack();
85 }
86
87 void QLPopupMenu::populate(QMenu* qMenu, Menu * menu)
88 {
89         lyxerr[Debug::GUI] << "populating menu " << lyx::to_utf8(menu->name()) ;
90         if (menu->size() == 0) {
91                 lyxerr[Debug::GUI] << "\tERROR: empty menu " << lyx::to_utf8(menu->name()) << endl;
92                 return;
93         }
94         else {
95                 lyxerr[Debug::GUI] << " *****  menu entries " << menu->size() << endl;
96         }
97
98         Menu::const_iterator m = menu->begin();
99         Menu::const_iterator end = menu->end();
100
101         for (; m != end; ++m) {
102
103                 if (m->kind() == MenuItem::Separator) {
104
105                         qMenu->addSeparator();
106                         lyxerr[Debug::GUI] << "adding Menubar Separator" << endl;
107
108                 } else if (m->kind() == MenuItem::Submenu) {
109
110                         lyxerr[Debug::GUI] << "** creating New Sub-Menu " << lyx::to_utf8(getLabel(*m)) << endl;
111                         QMenu * subMenu = qMenu->addMenu(toqstr(getLabel(*m)));
112                         populate(subMenu, m->submenu());
113
114                 } else { // we have a MenuItem::Command
115
116                         lyxerr[Debug::GUI] << "creating Menu Item " << lyx::to_utf8(m->label()) << endl;
117
118                         docstring label = getLabel(*m);
119                         addBinding(label, *m);
120
121                         Action * action = new Action(*(owner_->view()),
122                                                      label, m->func());
123                         qMenu->addAction(action);
124                 }
125         }
126 }
127
128 docstring const QLPopupMenu::getLabel(MenuItem const & mi)
129 {
130         docstring const shortcut = mi.shortcut();
131         docstring label = support::subst(mi.label(),
132                                       lyx::from_ascii("&"),
133                                       lyx::from_ascii("&&"));
134
135         if (!shortcut.empty()) {
136                 docstring::size_type pos = label.find(shortcut);
137                 if (pos != docstring::npos)
138                         label.insert(pos, 1, char_type('&'));
139         }
140
141         return label;
142 }
143
144 /// \todo Mac specific binding handling.
145 void QLPopupMenu::addBinding(docstring & label, MenuItem const & mi)
146 {
147 #ifndef Q_WS_MACX
148
149                 docstring const binding(mi.binding());
150                 if (!binding.empty()) {
151                         label += char_type('\t') + binding;
152                 }
153
154 #else
155                         /* There are two constraints on Qt/Mac: (1)
156                            the bindings require a unicode string to be
157                            represented meaningfully and std::string
158                            does not work (2) only 1-key bindings can
159                            be represented in menus.
160
161                            This is why the unpleasant hack bellow is
162                            needed (JMarc)
163                         */
164 /*                      pair<LyXKeySym const *, key_modifier::state>
165                                 binding = toplevel_keymap->find1keybinding(mi.func());
166                         if (binding.first) {
167                                 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
168                                 label += '\t' + key->qprint(binding.second);
169                         }
170 */
171 #endif
172 }
173
174 /// \todo Fix Mac specific menu hack
175 void QLPopupMenu::specialMacXmenuHack()
176 {
177 #ifdef Q_WS_MACX
178         /* The qt/mac menu code has a very silly hack that
179            moves some menu entries that it recognizes by name
180            (e.g. "Preferences...") to the "LyX" menu. This
181            feature can only work if the menu entries are
182            always available. Since we build menus on demand,
183            we add some dummy contents to one of the menus (JMarc)
184         */
185 /*
186         static QLPopupMenu * themenu = this;
187         if (themenu == this && owner_->backend().hasMenu("LyX")) {
188                 Menu special = owner_->backend().getMenu("LyX");
189                 Menu::const_iterator end = special.end();
190                 Menu::size_type i = 0;
191                 for (Menu::const_iterator cit = special.begin();
192                      cit != end ; ++cit, ++i)
193                         insertItem(toqstr(cit->label()), indexOffset + i);
194         }
195 */
196 #endif
197 }
198
199 } // namespace frontend
200 } // namespace lyx
201
202 #include "QLPopupMenu_moc.cpp"