]> git.lyx.org Git - features.git/blob - src/frontends/qt3/QLPopupMenu.C
This commit transfers the singletons defined in the Application class to the private...
[features.git] / src / frontends / qt3 / 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  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 // Qt defines a macro 'signals' that clashes with a boost namespace.
14 // All is well if the namespace is visible first.
15 #include "QtView.h"
16
17 #include "QLPopupMenu.h"
18 #include "QLMenubar.h"
19 #include "qt_helpers.h"
20
21 #include "MenuBackend.h"
22
23 #include "frontends/Application.h"
24
25 #include "support/lstrings.h"
26
27 #ifdef Q_WS_MACX
28 #include "kbmap.h"
29 #include "QLyXKeySym.h"
30 #endif
31
32 #include <qapplication.h>
33
34 using std::distance;
35 using std::make_pair;
36 using std::string;
37 using std::pair;
38
39 namespace lyx {
40
41 using support::subst;
42
43 namespace frontend {
44
45 namespace {
46
47 docstring const getLabel(MenuItem const & mi)
48 {
49         docstring const shortcut = mi.shortcut();
50         docstring label = subst(mi.label(),
51                                 lyx::from_ascii("&"),
52                                 lyx::from_ascii("&&"));
53
54         if (!shortcut.empty()) {
55                 docstring::size_type pos = label.find(shortcut);
56                 if (pos != docstring::npos)
57                         label.insert(pos, 1, char_type('&'));
58         }
59
60         return label;
61 }
62
63 #ifdef Q_WS_MACX
64 // The offset added to the special Mac menu entries
65 const int indexOffset = 5000;
66 #endif
67
68 } // namespace anon
69
70
71 pair<int, QLPopupMenu *>
72 createMenu(QMenuData * parent, MenuItem const * item, QLMenubar * owner,
73            bool is_toplevel)
74 {
75         QLPopupMenu * pm = new QLPopupMenu(owner, item->submenuname(), is_toplevel);
76         int const id = parent->insertItem(toqstr(getLabel(*item)), pm);
77         return make_pair(id, pm);
78 }
79
80
81 QLPopupMenu::QLPopupMenu(QLMenubar * owner,
82                          docstring const & name, bool toplevel)
83         : owner_(owner), name_(name)
84 {
85         if (toplevel)
86                 connect(this, SIGNAL(aboutToShow()), this, SLOT(showing()));
87         connect(this, SIGNAL(activated(int)),
88                 this, SLOT(fire(int)));
89 }
90
91
92 void QLPopupMenu::fire(int index)
93 {
94         // make sure the interface is repainted correctly (in case the
95         // action needs a long time, like File>Open).
96         theApp->syncEvents();
97 #ifdef Q_WS_MACX
98         if (index >= indexOffset) {
99                 MenuItem mi = owner_->backend().getMenu("LyX")[index - indexOffset];
100                 owner_->view()->activated(mi.func());
101         } else
102 #endif
103                 owner_->view()->activated(funcs_[index]);
104 }
105
106
107 void QLPopupMenu::populate(Menu * menu)
108 {
109         funcs_.clear();
110
111         Menu::const_iterator m = menu->begin();
112         Menu::const_iterator end = menu->end();
113         for (; m != end; ++m) {
114                 if (m->kind() == MenuItem::Separator) {
115                         insertSeparator();
116                 } else if (m->kind() == MenuItem::Submenu) {
117                         pair<int, QLPopupMenu *> res = createMenu(this, &(*m), owner_);
118                         setItemEnabled(res.first, m->status().enabled());
119                         res.second->populate(m->submenu());
120                 } else { // we have a MenuItem::Command
121                         FuncStatus status = m->status();
122
123                         Funcs::iterator fit =
124                                 funcs_.insert(funcs_.end(), m->func());
125                         int const index = distance(funcs_.begin(), fit);
126
127                         QString label = toqstr(getLabel(*m));
128 #ifdef Q_WS_MACX
129                         /* There are two constraints on Qt/Mac: (1)
130                            the bindings require a unicode string to be
131                            represented meaningfully and std::string
132                            does not work (2) only 1-key bindings can
133                            be represented in menus.
134
135                            This is why the unpleasant hack bellow is
136                            needed (JMarc)
137                         */
138                         pair<LyXKeySym const *, key_modifier::state>
139                                 binding = theTopLevelKeymap().find1keybinding(m->func());
140                         if (binding.first) {
141                                 QLyXKeySym const *key = static_cast<QLyXKeySym const *>(binding.first);
142                                 label += '\t' + key->qprint(binding.second);
143                         }
144 #else
145                         docstring const binding(m->binding());
146                         if (!binding.empty()) {
147                                 label += '\t' + toqstr(binding);
148                         }
149 #endif
150
151                         // Actually insert the menu item
152                         insertItem(label, index);
153                         setItemEnabled(index, status.enabled());
154                         setItemChecked(index, status.onoff(true));
155                 }
156         }
157 }
158
159
160 void QLPopupMenu::showing()
161 {
162         clear();
163         Menu tomenu;
164         Menu const frommenu = owner_->backend().getMenu(name_);
165         owner_->backend().expand(frommenu, tomenu, owner_->view()->buffer());
166         populate(&tomenu);
167 #ifdef Q_WS_MACX
168         /* The qt/mac menu code has a very silly hack that
169            moves some menu entries that it recognizes by name
170            (e.g. "Preferences...") to the "LyX" menu. This
171            feature can only work if the menu entries are
172            always available. Since we build menus on demand,
173            we add some dummy contents to one of the menus (JMarc)
174         */
175         static QLPopupMenu * themenu = this;
176         if (themenu == this && owner_->backend().hasMenu("LyX")) {
177                 Menu special = owner_->backend().getMenu("LyX");
178                 Menu::const_iterator end = special.end();
179                 Menu::size_type i = 0;
180                 for (Menu::const_iterator cit = special.begin();
181                      cit != end ; ++cit, ++i)
182                         insertItem(toqstr(cit->label()), indexOffset + i);
183         }
184 #endif
185 }
186
187 } // namespace frontend
188 } // namespace lyx
189
190 #include "QLPopupMenu_moc.cpp"