]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiListings.cpp
52c03e9508ccb4c6f13f1ab859cbc772bfaffbac
[lyx.git] / src / frontends / qt4 / GuiListings.cpp
1 /**
2  * \file GuiListings.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Bo Peng
7  * \author Jürgen Spitzmüller
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiListings.h"
15
16 #include "qt_helpers.h"
17 #include "FuncRequest.h"
18 #include "insets/InsetListings.h"
19 #include "insets/InsetListingsParams.h"
20 #include "support/debug.h"
21
22 #include "support/gettext.h"
23 #include "support/lstrings.h"
24
25 #include <QLineEdit>
26 #include <QPushButton>
27 #include <QValidator>
28 #include <QRegExpValidator>
29
30 using namespace std;
31 using namespace lyx::support;
32
33 namespace lyx {
34 namespace frontend {
35
36
37 /////////////////////////////////////////////////////////////////////
38 //
39 // GuiListings
40 //
41 /////////////////////////////////////////////////////////////////////
42
43
44 char const * languages[] =
45 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
46   "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
47   "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
48   "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
49   "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
50   "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
51   "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
52   "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
53   "VRML", "XML", "XSLT", "" };
54
55
56 char const * languages_gui[] =
57 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
58   "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
59   "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
60   "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
61   "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
62   "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
63   "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
64   "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
65   "VRML", "XML", "XSLT", "" };
66
67
68 struct dialect_info {
69         /// the dialect
70         char const * dialect;
71         /// the associated language
72         char const * language;
73         /// representation of the dialect in the gui
74         char const * gui;
75         /// is this the default dialect?
76         bool is_default;
77 };
78
79
80 dialect_info const dialects[] = {
81         { "R/2 4.3", "ABAP", "R/2 4.3", false },
82         { "R/2 5.0", "ABAP", "R/2 5.0", false },
83         { "R/3 3.1", "ABAP", "R/3 3.1", false },
84         { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
85         { "R/3 6.10", "ABAP", "R/3 6.10", true },
86         { "2005", "Ada", "2005", true },
87         { "83", "Ada", "83", false },
88         { "95", "Ada", "95", false },
89         { "60", "Algol", "60", false },
90         { "68", "Algol", "68", true },
91         { "Motorola68k", "Assembler", "Motorola 68xxx", false },
92         { "x86masm", "Assembler", "x86 (MASM)", false },
93         { "gnu", "Awk", "gnu", true },
94         { "POSIX", "Awk", "POSIX", false },
95         { "Visual", "Basic", "Visual", false },
96         { "ANSI", "C", "ANSI", true },
97         { "Handel", "C", "Handel", false },
98         { "Objective", "C", "Objective", false },
99         { "Sharp", "C", "Sharp", false },
100         { "ANSI", "C++", "ANSI", false },
101         { "GNU", "C++", "GNU", false },
102         { "ISO", "C++", "ISO", true },
103         { "Visual", "C++", "Visual", false },
104         { "light", "Caml", "light", true },
105         { "Objective", "Caml", "Objective", false },
106         { "1974", "Cobol", "1974", false },
107         { "1985", "Cobol", "1985", true },
108         { "ibm", "Cobol", "IBM", false },
109         { "WinXP", "command.com", "Windows XP", true },
110         { "77", "Fortran", "77", false },
111         { "90", "Fortran", "90", false },
112         { "95", "Fortran", "95", true },
113         { "CORBA", "IDL", "CORBA", false },
114         { "AspectJ", "Java", "Aspect J", false },
115         { "Auto", "Lisp", "Auto", false },
116         { "gnu", "make", "gnu", false },
117         { "1.0", "Mathematica", "1.0", false },
118         { "3.0", "Mathematica", "3.0", false },
119         { "5.2", "Mathematica", "5.2", true },
120         { "decorative", "OCL", "decorative", false },
121         { "OMG", "OCL", "OMG", true },
122         { "Borland6", "Pascal", "Borland 6", false },
123         { "Standard", "Pascal", "Standard", true },
124         { "XSC", "Pascal", "XSC", false },
125         { "PLUS", "S", "PLUS", false },
126         { "67", "Simula", "67", true },
127         { "CII", "Simula", "CII", false },
128         { "DEC", "Simula", "DEC", false },
129         { "IBM", "Simula", "IBM", false },
130         { "tk", "tcl", "tk", false },
131         { "AlLaTeX", "TeX", "AlLaTeX", false },
132         { "common", "TeX", "common", false },
133         { "LaTeX", "TeX", "LaTeX", false },
134         { "plain", "TeX", "plain", true },
135         { "primitive", "TeX", "primitive", false },
136         { "AMS", "VHDL", "AMS", false },
137         { "97", "VRML", "97", true }
138 };
139
140
141 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
142
143
144 char const * font_sizes[] =
145 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
146   "Large", "" };
147
148 char const * font_sizes_gui[] =
149 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
150   N_("Large"), N_("Larger"), "" };
151
152 char const * font_styles[] =
153 { "default", "rmfamily", "ttfamily", "sffamily", "" };
154
155 char const * font_styles_gui[] =
156 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
157
158
159
160 GuiListings::GuiListings(GuiView & lv)
161         : GuiDialog(lv, "listings", qt_("Program Listing Settings"))
162 {
163         setupUi(this);
164
165         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
166         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
167         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
168
169         connect(languageCO, SIGNAL(currentIndexChanged(int)),
170                 this, SLOT(change_adaptor()));
171         connect(dialectCO, SIGNAL(currentIndexChanged(int)),
172                 this, SLOT(change_adaptor()));
173         connect(inlineCB, SIGNAL(clicked()),
174                 this, SLOT(change_adaptor()));
175         connect(floatCB, SIGNAL(clicked()),
176                 this, SLOT(change_adaptor()));
177         connect(placementLE, SIGNAL(textChanged(QString)),
178                 this, SLOT(change_adaptor()));
179         connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
180                 this, SLOT(change_adaptor()));
181         connect(numberStepLE, SIGNAL(textChanged(QString)),
182                 this, SLOT(change_adaptor()));
183         connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
184                 this, SLOT(change_adaptor()));
185         connect(firstlineLE, SIGNAL(textChanged(QString)),
186                 this, SLOT(change_adaptor()));
187         connect(lastlineLE, SIGNAL(textChanged(QString)),
188                 this, SLOT(change_adaptor()));
189         connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
190                 this, SLOT(change_adaptor()));
191         connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
192                 this, SLOT(change_adaptor()));
193         connect(breaklinesCB, SIGNAL(clicked()),
194                 this, SLOT(change_adaptor()));
195         connect(spaceCB, SIGNAL(clicked()),
196                 this, SLOT(change_adaptor()));
197         connect(spaceInStringCB, SIGNAL(clicked()),
198                 this, SLOT(change_adaptor()));
199         connect(extendedcharsCB, SIGNAL(clicked()),
200                 this, SLOT(change_adaptor()));
201
202         connect(listingsED,  SIGNAL(textChanged()),
203                 this, SLOT(change_adaptor()));
204         connect(listingsED,  SIGNAL(textChanged()),
205                 this, SLOT(set_listings_msg()));
206         connect(bypassCB, SIGNAL(clicked()),
207                 this, SLOT(change_adaptor()));
208         connect(bypassCB, SIGNAL(clicked()),
209                 this, SLOT(set_listings_msg()));
210
211         for (int n = 0; languages[n][0]; ++n)
212                 languageCO->addItem(qt_(languages_gui[n]));
213
214         for (int n = 0; font_styles[n][0]; ++n)
215                 fontstyleCO->addItem(qt_(font_styles_gui[n]));
216
217         for (int n = 0; font_sizes[n][0]; ++n) {
218                 QString font = qt_(font_sizes_gui[n]);
219                 fontsizeCO->addItem(font);
220                 numberFontSizeCO->addItem(font);
221         }
222
223         // set validators
224         numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
225         firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
226         lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
227         placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
228
229         bc().setOK(okPB);
230         bc().setApply(applyPB);
231         bc().setCancel(closePB);
232         listingsTB->setPlainText(
233                 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
234
235         updateContents();
236
237 }
238
239
240 void GuiListings::change_adaptor()
241 {
242         changed();
243 }
244
245
246 string GuiListings::construct_params()
247 {
248         string language = languages[languageCO->currentIndex()];
249         string dialect;
250         string const dialect_gui = fromqstr(dialectCO->currentText());
251         if (dialectCO->currentIndex() > 0) {
252                 for (size_t i = 0; i != nr_dialects; ++i) {
253                         if (dialect_gui == dialects[i].gui
254                         && dialects[i].language == language
255                         && !dialects[i].is_default) {
256                                 dialect = dialects[i].dialect;
257                                 break;
258                         }
259                 }
260         }
261
262         bool float_ = floatCB->isChecked();
263         string placement;
264         if (placementLE->isEnabled())
265                 placement = fromqstr(placementLE->text());
266
267         string numberSide;
268         switch (numberSideCO->currentIndex()) {
269         case 0:
270                 numberSide = "none";
271                 break;
272         case 1:
273                 numberSide = "left";
274                 break;
275         case 2:
276                 numberSide = "right";
277                 break;
278         default:
279                 numberSide = "none";
280                 break;
281         }
282         string stepnumber = fromqstr(numberStepLE->text());
283         string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
284         string firstline = fromqstr(firstlineLE->text());
285         string lastline = fromqstr(lastlineLE->text());
286
287         string fontsize = font_sizes[fontsizeCO->currentIndex()];
288         string fontstyle = font_styles[fontstyleCO->currentIndex()];
289         string basicstyle;
290         if (fontsize != "default")
291                 basicstyle = "\\" + fontsize;
292         if (fontstyle != "default")
293                 basicstyle += "\\" + fontstyle;
294         bool breakline = breaklinesCB->isChecked();
295         bool space = spaceCB->isChecked();
296         bool spaceInString = spaceInStringCB->isChecked();
297         bool extendedchars = extendedcharsCB->isChecked();
298         string extra = fromqstr(listingsED->toPlainText());
299
300         // compose a string
301         InsetListingsParams par;
302         if (language != "no language" && !contains(extra, "language=")) {
303                 if (dialect.empty())
304                         par.addParam("language", language);
305                 else
306                         par.addParam("language", "{[" + dialect + "]" + language + "}");
307         }
308         // this dialog uses float=placement instead of float,floatplacement=placement
309         // because float accepts *tbph and floatplacement accepts bph.
310         // our placement textedit is actually for the float parameter
311         if (float_)
312                 par.addParam("float", placement);
313         if (numberSide != "none")
314                 par.addParam("numbers", numberSide);
315         if (numberfontsize != "default" && numberSide != "none")
316                 par.addParam("numberstyle", "\\" + numberfontsize);
317         if (!stepnumber.empty() && numberSide != "none")
318                 par.addParam("stepnumber", stepnumber);
319         if (!firstline.empty())
320                 par.addParam("firstline", firstline);
321         if (!lastline.empty())
322                 par.addParam("lastline", lastline);
323         if (!basicstyle.empty())
324                 par.addParam("basicstyle", basicstyle);
325         if (breakline)
326                 par.addParam("breaklines", "true");
327         if (space)
328                 par.addParam("showspaces", "true");
329         if (!spaceInString)
330                 par.addParam("showstringspaces", "false");
331         if (extendedchars)
332                 par.addParam("extendedchars", "true");
333         par.addParams(extra);
334         return par.params();
335 }
336
337
338 docstring GuiListings::validate_listings_params()
339 {
340         // use a cache here to avoid repeated validation
341         // of the same parameters
342         static string param_cache;
343         static docstring msg_cache;
344         
345         if (bypassCB->isChecked())
346                 return docstring();
347
348         string params = construct_params();
349         if (params != param_cache) {
350                 param_cache = params;
351                 msg_cache = InsetListingsParams(params).validate();
352         }
353         return msg_cache;
354 }
355
356
357 void GuiListings::set_listings_msg()
358 {
359         static bool isOK = true;
360         docstring msg = validate_listings_params();
361         if (msg.empty()) {
362                 if (isOK)
363                         return;
364                 isOK = true;
365                 listingsTB->setPlainText(
366                         qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
367         } else {
368                 isOK = false;
369                 listingsTB->setPlainText(toqstr(msg));
370         }
371 }
372
373
374 void GuiListings::on_floatCB_stateChanged(int state)
375 {
376         if (state == Qt::Checked) {
377                 inlineCB->setChecked(false);
378                 placementLE->setEnabled(true);
379         } else
380                 placementLE->setEnabled(false);
381 }
382
383
384 void GuiListings::on_inlineCB_stateChanged(int state)
385 {
386         if (state == Qt::Checked) {
387                 floatCB->setChecked(false);
388                 placementLE->setEnabled(false);
389         }
390 }
391
392
393 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
394 {
395         numberStepLE->setEnabled(index > 0);
396         numberFontSizeCO->setEnabled(index > 0);
397 }
398
399
400 void GuiListings::on_languageCO_currentIndexChanged(int index)
401 {
402         dialectCO->clear();
403         // 0 is "no dialect"
404         int default_dialect = 0;
405         dialectCO->addItem(qt_("No dialect"));
406         string const language = languages[index];
407
408         for (size_t i = 0; i != nr_dialects; ++i) {
409                 if (language == dialects[i].language) {
410                         dialectCO->addItem(qt_(dialects[i].gui));
411                         if (dialects[i].is_default)
412                                 default_dialect =
413                                         dialectCO->findText(qt_(dialects[i].gui));
414                 }
415         }
416         dialectCO->setCurrentIndex(default_dialect);
417         dialectCO->setEnabled(dialectCO->count() > 1);
418 }
419
420
421 void GuiListings::applyView()
422 {
423         params_.setInline(inlineCB->isChecked());
424         params_.setParams(construct_params());
425 }
426
427
428 static string plainParam(string const & par)
429 {
430         // remove enclosing braces
431         if (prefixIs(par, "{") && suffixIs(par, "}"))
432                 return par.substr(1, par.size() - 2);
433         return par;
434 }
435
436
437 void GuiListings::updateContents()
438 {
439         // set default values
440         listingsTB->setPlainText(
441                 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
442         languageCO->setCurrentIndex(findToken(languages, "no language"));
443         dialectCO->setCurrentIndex(0);
444         floatCB->setChecked(false);
445         placementLE->clear();
446         numberSideCO->setCurrentIndex(0);
447         numberStepLE->clear();
448         numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
449         firstlineLE->clear();
450         lastlineLE->clear();
451         fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
452         fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
453         breaklinesCB->setChecked(false);
454         spaceCB->setChecked(false);
455         spaceInStringCB->setChecked(true);
456         extendedcharsCB->setChecked(false);
457
458         // set values from param string
459         inlineCB->setChecked(params_.isInline());
460         if (params_.isInline()) {
461                 floatCB->setChecked(false);
462                 placementLE->setEnabled(false);
463         }
464         // break other parameters and set values
465         vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
466         // process each of them
467         for (vector<string>::iterator it = pars.begin();
468             it != pars.end(); ++it) {
469                 if (prefixIs(*it, "language=")) {
470                         string arg = plainParam(it->substr(9));
471                         // has dialect?
472                         string language;
473                         string dialect;
474                         bool in_gui = false;
475                         if (prefixIs(arg, "[") && contains(arg, "]")) {
476                                 size_t end_dialect = arg.find("]");
477                                 dialect = arg.substr(1, end_dialect - 1);
478                                 language = arg.substr(end_dialect + 1);
479                         } else {
480                                 language = arg;
481                         }
482                         int n = findToken(languages, language);
483                         if (n >= 0) {
484                                 languageCO->setCurrentIndex(n);
485                                 in_gui = true;
486                         }
487                         // on_languageCO_currentIndexChanged should have set dialects
488                         if (!dialect.empty()) {
489                                 string dialect_gui;
490                                 for (size_t i = 0; i != nr_dialects; ++i) {
491                                         if (dialect == dialects[i].dialect
492                                             && dialects[i].language == language) {
493                                                 dialect_gui = dialects[i].gui;
494                                                 break;
495                                         }
496                                 }
497                                 n = dialectCO->findText(qt_(dialect_gui));
498                                 if (n >= 0)
499                                         dialectCO->setCurrentIndex(n);
500                                 else
501                                         in_gui = false;
502                         }
503                         if (in_gui)
504                                 *it = "";
505                         languageCO->setEnabled(in_gui);
506                         dialectCO->setEnabled(
507                                 in_gui && dialectCO->count() > 1);
508                 } else if (prefixIs(*it, "float")) {
509                         floatCB->setChecked(true);
510                         inlineCB->setChecked(false);
511                         placementLE->setEnabled(true);
512                         if (prefixIs(*it, "float="))
513                                 placementLE->setText(
514                                         toqstr(plainParam(it->substr(6))));
515                         *it = "";
516                 } else if (prefixIs(*it, "numbers=")) {
517                         string s = plainParam(it->substr(8));
518                         int n = 0;
519                         if (s == "left")
520                                 n = 1;
521                         else if (s == "right")
522                                 n = 2;
523                         numberSideCO->setCurrentIndex(n);
524                         *it = "";
525                 } else if (prefixIs(*it, "stepnumber=")) {
526                         numberStepLE->setText(
527                                 toqstr(plainParam(it->substr(11))));
528                         *it = "";
529                 } else if (prefixIs(*it, "numberstyle=")) {
530                         string par = plainParam(it->substr(12));
531                         int n = findToken(font_sizes, par.substr(1));
532                         if (n >= 0)
533                                 numberFontSizeCO->setCurrentIndex(n);
534                         *it = "";
535                 } else if (prefixIs(*it, "firstline=")) {
536                         firstlineLE->setText(
537                                 toqstr(plainParam(it->substr(10))));
538                         *it = "";
539                 } else if (prefixIs(*it, "lastline=")) {
540                         lastlineLE->setText(
541                                 toqstr(plainParam(it->substr(9))));
542                         *it = "";
543                 } else if (prefixIs(*it, "basicstyle=")) {
544                         string style;
545                         string size;
546                         for (int n = 0; font_styles[n][0]; ++n) {
547                                 string const s = font_styles[n];
548                                 if (contains(*it, "\\" + s)) {
549                                         style = "\\" + s;
550                                         break;
551                                 }
552                         }
553                         for (int n = 0; font_sizes[n][0]; ++n) {
554                                 string const s = font_sizes[n];
555                                 if (contains(*it, "\\" + s)) {
556                                         size = "\\" + s;
557                                         break;
558                                 }
559                         }
560                         if (plainParam(it->substr(11)) == style + size
561                             || plainParam(it->substr(11)) == size + style) {
562                                 if (!style.empty()) {
563                                         int n = findToken(font_styles, style.substr(1));
564                                         if (n >= 0)
565                                                 fontstyleCO->setCurrentIndex(n);
566                                 }
567                                 if (!size.empty()) {
568                                         int n = findToken(font_sizes, size.substr(1));
569                                         if (n >= 0)
570                                                 fontsizeCO->setCurrentIndex(n);
571                                 }
572                                 *it = "";
573                         }
574                 } else if (prefixIs(*it, "breaklines=")) {
575                         breaklinesCB->setChecked(contains(*it, "true"));
576                         *it = "";
577                 } else if (prefixIs(*it, "showspaces=")) {
578                         spaceCB->setChecked(contains(*it, "true"));
579                         *it = "";
580                 } else if (prefixIs(*it, "showstringspaces=")) {
581                         spaceInStringCB->setChecked(contains(*it, "true"));
582                         *it = "";
583                 } else if (prefixIs(*it, "extendedchars=")) {
584                         extendedcharsCB->setChecked(contains(*it, "true"));
585                         *it = "";
586                 }
587         }
588
589         numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
590         numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
591         // parameters that can be handled by widgets are cleared
592         // the rest is put to the extra edit box.
593         string extra = getStringFromVector(pars);
594         listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
595 }
596
597
598 bool GuiListings::isValid()
599 {
600         return validate_listings_params().empty();
601 }
602
603
604 bool GuiListings::initialiseParams(string const & data)
605 {
606         InsetListingsMailer::string2params(data, params_);
607         return true;
608 }
609
610
611 void GuiListings::clearParams()
612 {
613         params_.clear();
614 }
615
616
617 void GuiListings::dispatchParams()
618 {
619         string const lfun = InsetListingsMailer::params2string(params_);
620         dispatch(FuncRequest(getLfun(), lfun));
621 }
622
623
624 void GuiListings::setParams(InsetListingsParams const & params)
625 {
626         params_ = params;
627 }
628
629
630 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
631
632
633 } // namespace frontend
634 } // namespace lyx
635
636
637 #include "GuiListings_moc.cpp"