]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QLPopupMenu.C
enable Font cache only for MacOSX and inline width() for other platform.
[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 "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: " << lyx::to_utf8(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()->buffer());
79
80         if (!owner_->backend().hasMenu(topLevelMenu_.name())) {
81                 lyxerr[Debug::GUI] << "\tWARNING: menu seems empty" << lyx::to_utf8(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 " << lyx::to_utf8(menu->name()) ;
91         if (menu->size() == 0) {
92                 lyxerr[Debug::GUI] << "\tERROR: empty menu " << lyx::to_utf8(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 " << lyx::to_utf8(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                         lyxerr[Debug::GUI] << "creating Menu Item " << lyx::to_utf8(m->label()) << endl;
118
119                         docstring label = getLabel(*m);
120                         addBinding(label, *m);
121
122                         Action * action = new Action(*(owner_->view()),
123                                                      lyx::to_utf8(label), m->func());
124                         qMenu->addAction(action);
125                 }
126         }
127 }
128
129 docstring const QLPopupMenu::getLabel(MenuItem const & mi)
130 {
131         docstring const shortcut = mi.shortcut();
132         docstring label = support::subst(mi.label(),
133                                       lyx::from_ascii("&"),
134                                       lyx::from_ascii("&&"));
135
136         if (!shortcut.empty()) {
137                 docstring::size_type pos = label.find(shortcut);
138                 if (pos != docstring::npos)
139                         label.insert(pos, 1, char_type('&'));
140         }
141
142         return label;
143 }
144
145 /// \todo Mac specific binding handling.
146 void QLPopupMenu::addBinding(docstring & label, MenuItem const & mi)
147 {
148 #ifndef Q_WS_MACX
149
150                 docstring const binding(mi.binding());
151                 if (!binding.empty()) {
152                         label += char_type('\t') + binding;
153                 }
154
155 #else
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.
161
162                            This is why the unpleasant hack bellow is
163                            needed (JMarc)
164                         */
165 /*                      pair<LyXKeySym const *, key_modifier::state>
166                                 binding = toplevel_keymap->find1keybinding(mi.func());
167                         if (binding.first) {
168                                 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
169                                 label += '\t' + key->qprint(binding.second);
170                         }
171 */
172 #endif
173 }
174
175 /// \todo Fix Mac specific menu hack
176 void QLPopupMenu::specialMacXmenuHack()
177 {
178 #ifdef Q_WS_MACX
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)
185         */
186 /*
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);
195         }
196 */
197 #endif
198 }
199
200 } // namespace frontend
201 } // namespace lyx
202
203 #include "QLPopupMenu_moc.cpp"