]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/Toolbars.cpp
Fix crash when the Gui Name of a toolbar is not plain ascii. This
[lyx.git] / src / frontends / qt4 / Toolbars.cpp
1 /**
2  * \file Toolbars.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jean-Marc Lasgouttes
7  * \author John Levon
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "Toolbars.h"
15 #include "FuncRequest.h"
16 #include "Lexer.h"
17 #include "LyXAction.h"
18 #include "qt_helpers.h"
19
20 #include "support/debug.h"
21 #include "support/gettext.h"
22 #include "support/lstrings.h"
23
24 #include <boost/bind.hpp>
25
26 #include <algorithm>
27
28 using namespace std;
29 using namespace lyx::support;
30
31 namespace lyx {
32 namespace frontend {
33
34 namespace {
35
36 } // namespace anon
37
38
39 /////////////////////////////////////////////////////////////////////////
40 //
41 // ToolbarItem
42 //
43 /////////////////////////////////////////////////////////////////////////
44
45 ToolbarItem::ToolbarItem(Type type, FuncRequest const & func, docstring const & label)
46         : type_(type), func_(func), label_(label)
47 {
48 }
49
50
51 ToolbarItem::ToolbarItem(Type type, string const & name, docstring const & label)
52         : type_(type), label_(label), name_(name)
53 {
54 }
55
56
57 void ToolbarInfo::add(ToolbarItem const & item)
58 {
59         items.push_back(item);
60         items.back().func_.origin = FuncRequest::TOOLBAR;
61 }
62
63
64 ToolbarInfo & ToolbarInfo::read(Lexer & lex)
65 {
66         enum {
67                 TO_COMMAND = 1,
68                 TO_ENDTOOLBAR,
69                 TO_SEPARATOR,
70                 TO_LAYOUTS,
71                 TO_MINIBUFFER,
72                 TO_TABLEINSERT,
73                 TO_POPUPMENU,
74                 TO_ICONPALETTE,
75         };
76
77         struct LexerKeyword toolTags[] = {
78                 { "end", TO_ENDTOOLBAR },
79                 { "iconpalette", TO_ICONPALETTE },
80                 { "item", TO_COMMAND },
81                 { "layouts", TO_LAYOUTS },
82                 { "minibuffer", TO_MINIBUFFER },
83                 { "popupmenu", TO_POPUPMENU },
84                 { "separator", TO_SEPARATOR },
85                 { "tableinsert", TO_TABLEINSERT }
86         };
87
88         //consistency check
89         if (compare_ascii_no_case(lex.getString(), "toolbar")) {
90                 LYXERR0("ToolbarInfo::read: ERROR wrong token:`"
91                        << lex.getString() << '\'');
92         }
93
94         lex.next(true);
95         name = lex.getString();
96
97         lex.next(true);
98         gui_name = _(lex.getString());
99
100         // FIXME what to do here?
101         if (!lex) {
102                 LYXERR0("ToolbarInfo::read: Malformed toolbar "
103                         "description " <<  lex.getString());
104                 return *this;
105         }
106
107         bool quit = false;
108
109         lex.pushTable(toolTags);
110
111         if (lyxerr.debugging(Debug::PARSER))
112                 lex.printTable(lyxerr);
113
114         while (lex.isOK() && !quit) {
115                 switch (lex.lex()) {
116                 case TO_COMMAND:
117                         if (lex.next(true)) {
118                                 docstring const tooltip = translateIfPossible(lex.getDocString());
119                                 lex.next(true);
120                                 string const func_arg = lex.getString();
121                                 LYXERR(Debug::PARSER, "ToolbarInfo::read TO_COMMAND func: `"
122                                         << func_arg << '\'');
123
124                                 FuncRequest func =
125                                         lyxaction.lookupFunc(func_arg);
126                                 add(ToolbarItem(ToolbarItem::COMMAND, func, tooltip));
127                         }
128                         break;
129
130                 case TO_MINIBUFFER:
131                         add(ToolbarItem(ToolbarItem::MINIBUFFER,
132                                 FuncRequest(FuncCode(ToolbarItem::MINIBUFFER))));
133                         break;
134
135                 case TO_SEPARATOR:
136                         add(ToolbarItem(ToolbarItem::SEPARATOR,
137                                 FuncRequest(FuncCode(ToolbarItem::SEPARATOR))));
138                         break;
139
140                 case TO_POPUPMENU:
141                         if (lex.next(true)) {
142                                 string const name = lex.getString();
143                                 lex.next(true);
144                                 docstring const label = lex.getDocString();
145                                 add(ToolbarItem(ToolbarItem::POPUPMENU, name, label));
146                         }
147                         break;
148
149                 case TO_ICONPALETTE:
150                         if (lex.next(true)) {
151                                 string const name = lex.getString();
152                                 lex.next(true);
153                                 docstring const label = lex.getDocString();
154                                 add(ToolbarItem(ToolbarItem::ICONPALETTE, name, label));
155                         }
156                         break;
157
158                 case TO_LAYOUTS:
159                         add(ToolbarItem(ToolbarItem::LAYOUTS,
160                                 FuncRequest(FuncCode(ToolbarItem::LAYOUTS))));
161                         break;
162
163                 case TO_TABLEINSERT:
164                         if (lex.next(true)) {
165                                 docstring const tooltip = lex.getDocString();
166                                 add(ToolbarItem(ToolbarItem::TABLEINSERT,
167                                         FuncRequest(FuncCode(ToolbarItem::TABLEINSERT)), tooltip));
168                         }
169                         break;
170
171                 case TO_ENDTOOLBAR:
172                         quit = true;
173                         break;
174
175                 default:
176                         lex.printError("ToolbarInfo::read: "
177                                        "Unknown toolbar tag: `$$Token'");
178                         break;
179                 }
180         }
181
182         lex.popTable();
183         return *this;
184 }
185
186
187
188 /////////////////////////////////////////////////////////////////////////
189 //
190 // Toolbars
191 //
192 /////////////////////////////////////////////////////////////////////////
193
194 void Toolbars::reset()
195 {
196         toolbar_info_.clear();
197         toolbar_visibility_.clear();
198 }
199
200
201 void Toolbars::readToolbars(Lexer & lex)
202 {
203         enum {
204                 TO_TOOLBAR = 1,
205                 TO_ENDTOOLBARSET,
206         };
207
208         struct LexerKeyword toolTags[] = {
209                 { "end", TO_ENDTOOLBARSET },
210                 { "toolbar", TO_TOOLBAR }
211         };
212
213         //consistency check
214         if (compare_ascii_no_case(lex.getString(), "toolbarset")) {
215                 LYXERR0("Toolbars::readToolbars: ERROR wrong token:`"
216                        << lex.getString() << '\'');
217         }
218
219         lex.pushTable(toolTags);
220
221         if (lyxerr.debugging(Debug::PARSER))
222                 lex.printTable(lyxerr);
223
224         bool quit = false;
225         while (lex.isOK() && !quit) {
226                 switch (lex.lex()) {
227                 case TO_TOOLBAR: {
228                         ToolbarInfo tbinfo;
229                         tbinfo.read(lex);
230                         toolbar_info_.push_back(tbinfo);
231                         break;
232                         }
233                 case TO_ENDTOOLBARSET:
234                         quit = true;
235                         break;
236                 default:
237                         lex.printError("Toolbars::readToolbars: "
238                                        "Unknown toolbar tag: `$$Token'");
239                         break;
240                 }
241         }
242
243         lex.popTable();
244 }
245
246
247 void Toolbars::readToolbarSettings(Lexer & lex)
248 {
249         //consistency check
250         if (compare_ascii_no_case(lex.getString(), "toolbars")) {
251                 LYXERR0("Toolbars::readToolbarSettings: ERROR wrong token:`"
252                        << lex.getString() << '\'');
253         }
254
255         lex.next(true);
256
257         while (lex.isOK()) {
258                 string name = lex.getString();
259                 lex.next(true);
260
261                 if (!compare_ascii_no_case(name, "end"))
262                         return;
263
264                 int visibility = 0;
265                 string flagstr = lex.getString();
266                 lex.next(true);
267                 vector<string> flags = getVectorFromString(flagstr);
268
269                 vector<string>::const_iterator cit = flags.begin();
270                 vector<string>::const_iterator end = flags.end();
271
272                 for (; cit != end; ++cit) {
273                         Visibility flag = ON;
274                         if (!compare_ascii_no_case(*cit, "off"))
275                                 flag = OFF;
276                         else if (!compare_ascii_no_case(*cit, "on"))
277                                 flag = ON;
278                         else if (!compare_ascii_no_case(*cit, "math"))
279                                 flag = MATH;
280                         else if (!compare_ascii_no_case(*cit, "table"))
281                                 flag = TABLE;
282                         else if (!compare_ascii_no_case(*cit, "mathmacrotemplate"))
283                                 flag = MATHMACROTEMPLATE;
284                         else if (!compare_ascii_no_case(*cit, "review"))
285                                 flag = REVIEW;
286                         else if (!compare_ascii_no_case(*cit, "top"))
287                                 flag = TOP;
288                         else if (!compare_ascii_no_case(*cit, "bottom"))
289                                 flag = BOTTOM;
290                         else if (!compare_ascii_no_case(*cit, "left"))
291                                 flag = LEFT;
292                         else if (!compare_ascii_no_case(*cit, "right"))
293                                 flag = RIGHT;
294                         else if (!compare_ascii_no_case(*cit, "auto"))
295                                 flag = AUTO;
296                         else {
297                                 LYXERR(Debug::ANY,
298                                         "Toolbars::readToolbarSettings: unrecognised token:`"
299                                         << *cit << '\'');
300                                 continue;
301                         }
302                         visibility |= flag;
303                 }
304                 toolbar_visibility_[name] = visibility;
305
306                 if (visibility >= MATH) {
307                         if (ToolbarInfo const * ti = info(name))
308                                 const_cast<ToolbarInfo *>(ti)->gui_name +=
309                                         " (" + _("auto") + ")";
310                 }
311         }
312 }
313
314
315 ToolbarInfo const * Toolbars::info(std::string const & name) const
316 {
317         Infos::const_iterator end = toolbar_info_.end();
318         for (Infos::const_iterator it = toolbar_info_.begin(); it != end; ++it)
319                 if (it->name == name)
320                         return &(*it);
321         return 0;
322 }
323
324
325 int Toolbars::defaultVisibility(std::string const & name) const
326 {
327         map<string, int>::const_iterator it = toolbar_visibility_.find(name);
328         if (it != toolbar_visibility_.end())
329                 return it->second;
330         return OFF | BOTTOM;
331 }
332
333
334 bool Toolbars::isMainToolbar(std::string const & name) const
335 {
336         return toolbar_visibility_.find(name) != toolbar_visibility_.end();
337 }
338
339
340 } // namespace frontend
341 } // namespace lyx