]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiListings.cpp
Crash fix.
[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/lstrings.h"
23
24 #include <QLineEdit>
25 #include <QCloseEvent>
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")
162 {
163         setupUi(this);
164         setViewTitle(_("Program Listing Settings"));
165
166         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
167         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
168         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
169
170         connect(languageCO, SIGNAL(currentIndexChanged(int)),
171                 this, SLOT(change_adaptor()));
172         connect(dialectCO, SIGNAL(currentIndexChanged(int)),
173                 this, SLOT(change_adaptor()));
174         connect(inlineCB, SIGNAL(clicked()),
175                 this, SLOT(change_adaptor()));
176         connect(floatCB, SIGNAL(clicked()),
177                 this, SLOT(change_adaptor()));
178         connect(placementLE, SIGNAL(textChanged(QString)),
179                 this, SLOT(change_adaptor()));
180         connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
181                 this, SLOT(change_adaptor()));
182         connect(numberStepLE, SIGNAL(textChanged(QString)),
183                 this, SLOT(change_adaptor()));
184         connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
185                 this, SLOT(change_adaptor()));
186         connect(firstlineLE, SIGNAL(textChanged(QString)),
187                 this, SLOT(change_adaptor()));
188         connect(lastlineLE, SIGNAL(textChanged(QString)),
189                 this, SLOT(change_adaptor()));
190         connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
191                 this, SLOT(change_adaptor()));
192         connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
193                 this, SLOT(change_adaptor()));
194         connect(breaklinesCB, SIGNAL(clicked()),
195                 this, SLOT(change_adaptor()));
196         connect(spaceCB, SIGNAL(clicked()),
197                 this, SLOT(change_adaptor()));
198         connect(spaceInStringCB, SIGNAL(clicked()),
199                 this, SLOT(change_adaptor()));
200         connect(extendedcharsCB, SIGNAL(clicked()),
201                 this, SLOT(change_adaptor()));
202
203         connect(listingsED,  SIGNAL(textChanged()),
204                 this, SLOT(change_adaptor()));
205         connect(listingsED,  SIGNAL(textChanged()),
206                 this, SLOT(set_listings_msg()));
207         connect(bypassCB, SIGNAL(clicked()),
208                 this, SLOT(change_adaptor()));
209         connect(bypassCB, SIGNAL(clicked()),
210                 this, SLOT(set_listings_msg()));
211
212         for (int n = 0; languages[n][0]; ++n)
213                 languageCO->addItem(qt_(languages_gui[n]));
214
215         for (int n = 0; font_styles[n][0]; ++n)
216                 fontstyleCO->addItem(qt_(font_styles_gui[n]));
217
218         for (int n = 0; font_sizes[n][0]; ++n) {
219                 QString font = qt_(font_sizes_gui[n]);
220                 fontsizeCO->addItem(font);
221                 numberFontSizeCO->addItem(font);
222         }
223
224         // set validators
225         numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
226         firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
227         lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
228         placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
229
230         bc().setOK(okPB);
231         bc().setApply(applyPB);
232         bc().setCancel(closePB);
233         listingsTB->setPlainText(
234                 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
235
236         updateContents();
237
238 }
239
240
241 void GuiListings::closeEvent(QCloseEvent * e)
242 {
243         slotClose();
244         e->accept();
245 }
246
247
248 void GuiListings::change_adaptor()
249 {
250         changed();
251 }
252
253
254 string GuiListings::construct_params()
255 {
256         string language = languages[languageCO->currentIndex()];
257         string dialect;
258         string const dialect_gui = fromqstr(dialectCO->currentText());
259         if (dialectCO->currentIndex() > 0) {
260                 for (size_t i = 0; i != nr_dialects; ++i) {
261                         if (dialect_gui == dialects[i].gui
262                         && dialects[i].language == language
263                         && !dialects[i].is_default) {
264                                 dialect = dialects[i].dialect;
265                                 break;
266                         }
267                 }
268         }
269
270         bool float_ = floatCB->isChecked();
271         string placement;
272         if (placementLE->isEnabled())
273                 placement = fromqstr(placementLE->text());
274
275         string numberSide;
276         switch (numberSideCO->currentIndex()) {
277         case 0:
278                 numberSide = "none";
279                 break;
280         case 1:
281                 numberSide = "left";
282                 break;
283         case 2:
284                 numberSide = "right";
285                 break;
286         default:
287                 numberSide = "none";
288                 break;
289         }
290         string stepnumber = fromqstr(numberStepLE->text());
291         string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
292         string firstline = fromqstr(firstlineLE->text());
293         string lastline = fromqstr(lastlineLE->text());
294
295         string fontsize = font_sizes[fontsizeCO->currentIndex()];
296         string fontstyle = font_styles[fontstyleCO->currentIndex()];
297         string basicstyle;
298         if (fontsize != "default")
299                 basicstyle = "\\" + fontsize;
300         if (fontstyle != "default")
301                 basicstyle += "\\" + fontstyle;
302         bool breakline = breaklinesCB->isChecked();
303         bool space = spaceCB->isChecked();
304         bool spaceInString = spaceInStringCB->isChecked();
305         bool extendedchars = extendedcharsCB->isChecked();
306         string extra = fromqstr(listingsED->toPlainText());
307
308         // compose a string
309         InsetListingsParams par;
310         if (language != "no language" && !contains(extra, "language=")) {
311                 if (dialect.empty())
312                         par.addParam("language", language);
313                 else
314                         par.addParam("language", "{[" + dialect + "]" + language + "}");
315         }
316         // this dialog uses float=placement instead of float,floatplacement=placement
317         // because float accepts *tbph and floatplacement accepts bph.
318         // our placement textedit is actually for the float parameter
319         if (float_)
320                 par.addParam("float", placement);
321         if (numberSide != "none")
322                 par.addParam("numbers", numberSide);
323         if (numberfontsize != "default" && numberSide != "none")
324                 par.addParam("numberstyle", "\\" + numberfontsize);
325         if (!stepnumber.empty() && numberSide != "none")
326                 par.addParam("stepnumber", stepnumber);
327         if (!firstline.empty())
328                 par.addParam("firstline", firstline);
329         if (!lastline.empty())
330                 par.addParam("lastline", lastline);
331         if (!basicstyle.empty())
332                 par.addParam("basicstyle", basicstyle);
333         if (breakline)
334                 par.addParam("breaklines", "true");
335         if (space)
336                 par.addParam("showspaces", "true");
337         if (!spaceInString)
338                 par.addParam("showstringspaces", "false");
339         if (extendedchars)
340                 par.addParam("extendedchars", "true");
341         par.addParams(extra);
342         return par.params();
343 }
344
345
346 docstring GuiListings::validate_listings_params()
347 {
348         // use a cache here to avoid repeated validation
349         // of the same parameters
350         static string param_cache;
351         static docstring msg_cache;
352         
353         if (bypassCB->isChecked())
354                 return docstring();
355
356         string params = construct_params();
357         if (params != param_cache) {
358                 param_cache = params;
359                 msg_cache = InsetListingsParams(params).validate();
360         }
361         return msg_cache;
362 }
363
364
365 void GuiListings::set_listings_msg()
366 {
367         static bool isOK = true;
368         docstring msg = validate_listings_params();
369         if (msg.empty()) {
370                 if (isOK)
371                         return;
372                 isOK = true;
373                 listingsTB->setPlainText(
374                         qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
375         } else {
376                 isOK = false;
377                 listingsTB->setPlainText(toqstr(msg));
378         }
379 }
380
381
382 void GuiListings::on_floatCB_stateChanged(int state)
383 {
384         if (state == Qt::Checked) {
385                 inlineCB->setChecked(false);
386                 placementLE->setEnabled(true);
387         } else
388                 placementLE->setEnabled(false);
389 }
390
391
392 void GuiListings::on_inlineCB_stateChanged(int state)
393 {
394         if (state == Qt::Checked) {
395                 floatCB->setChecked(false);
396                 placementLE->setEnabled(false);
397         }
398 }
399
400
401 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
402 {
403         numberStepLE->setEnabled(index > 0);
404         numberFontSizeCO->setEnabled(index > 0);
405 }
406
407
408 void GuiListings::on_languageCO_currentIndexChanged(int index)
409 {
410         dialectCO->clear();
411         // 0 is "no dialect"
412         int default_dialect = 0;
413         dialectCO->addItem(qt_("No dialect"));
414         string const language = languages[index];
415
416         for (size_t i = 0; i != nr_dialects; ++i) {
417                 if (language == dialects[i].language) {
418                         dialectCO->addItem(qt_(dialects[i].gui));
419                         if (dialects[i].is_default)
420                                 default_dialect =
421                                         dialectCO->findText(qt_(dialects[i].gui));
422                 }
423         }
424         dialectCO->setCurrentIndex(default_dialect);
425         dialectCO->setEnabled(dialectCO->count() > 1);
426 }
427
428
429 void GuiListings::applyView()
430 {
431         params_.setInline(inlineCB->isChecked());
432         params_.setParams(construct_params());
433 }
434
435
436 static string plainParam(string const & par)
437 {
438         // remove enclosing braces
439         if (prefixIs(par, "{") && suffixIs(par, "}"))
440                 return par.substr(1, par.size() - 2);
441         return par;
442 }
443
444
445 void GuiListings::updateContents()
446 {
447         // set default values
448         listingsTB->setPlainText(
449                 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
450         languageCO->setCurrentIndex(findToken(languages, "no language"));
451         dialectCO->setCurrentIndex(0);
452         floatCB->setChecked(false);
453         placementLE->clear();
454         numberSideCO->setCurrentIndex(0);
455         numberStepLE->clear();
456         numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
457         firstlineLE->clear();
458         lastlineLE->clear();
459         fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
460         fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
461         breaklinesCB->setChecked(false);
462         spaceCB->setChecked(false);
463         spaceInStringCB->setChecked(true);
464         extendedcharsCB->setChecked(false);
465
466         // set values from param string
467         inlineCB->setChecked(params_.isInline());
468         if (params_.isInline()) {
469                 floatCB->setChecked(false);
470                 placementLE->setEnabled(false);
471         }
472         // break other parameters and set values
473         vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
474         // process each of them
475         for (vector<string>::iterator it = pars.begin();
476             it != pars.end(); ++it) {
477                 if (prefixIs(*it, "language=")) {
478                         string arg = plainParam(it->substr(9));
479                         // has dialect?
480                         string language;
481                         string dialect;
482                         bool in_gui = false;
483                         if (prefixIs(arg, "[") && contains(arg, "]")) {
484                                 size_t end_dialect = arg.find("]");
485                                 dialect = arg.substr(1, end_dialect - 1);
486                                 language = arg.substr(end_dialect + 1);
487                         } else {
488                                 language = arg;
489                         }
490                         int n = findToken(languages, language);
491                         if (n >= 0) {
492                                 languageCO->setCurrentIndex(n);
493                                 in_gui = true;
494                         }
495                         // on_languageCO_currentIndexChanged should have set dialects
496                         if (!dialect.empty()) {
497                                 string dialect_gui;
498                                 for (size_t i = 0; i != nr_dialects; ++i) {
499                                         if (dialect == dialects[i].dialect
500                                             && dialects[i].language == language) {
501                                                 dialect_gui = dialects[i].gui;
502                                                 break;
503                                         }
504                                 }
505                                 n = dialectCO->findText(qt_(dialect_gui));
506                                 if (n >= 0)
507                                         dialectCO->setCurrentIndex(n);
508                                 else
509                                         in_gui = false;
510                         }
511                         if (in_gui)
512                                 *it = "";
513                         languageCO->setEnabled(in_gui);
514                         dialectCO->setEnabled(
515                                 in_gui && dialectCO->count() > 1);
516                 } else if (prefixIs(*it, "float")) {
517                         floatCB->setChecked(true);
518                         inlineCB->setChecked(false);
519                         placementLE->setEnabled(true);
520                         if (prefixIs(*it, "float="))
521                                 placementLE->setText(
522                                         toqstr(plainParam(it->substr(6))));
523                         *it = "";
524                 } else if (prefixIs(*it, "numbers=")) {
525                         string s = plainParam(it->substr(8));
526                         int n = 0;
527                         if (s == "left")
528                                 n = 1;
529                         else if (s == "right")
530                                 n = 2;
531                         numberSideCO->setCurrentIndex(n);
532                         *it = "";
533                 } else if (prefixIs(*it, "stepnumber=")) {
534                         numberStepLE->setText(
535                                 toqstr(plainParam(it->substr(11))));
536                         *it = "";
537                 } else if (prefixIs(*it, "numberstyle=")) {
538                         string par = plainParam(it->substr(12));
539                         int n = findToken(font_sizes, par.substr(1));
540                         if (n >= 0)
541                                 numberFontSizeCO->setCurrentIndex(n);
542                         *it = "";
543                 } else if (prefixIs(*it, "firstline=")) {
544                         firstlineLE->setText(
545                                 toqstr(plainParam(it->substr(10))));
546                         *it = "";
547                 } else if (prefixIs(*it, "lastline=")) {
548                         lastlineLE->setText(
549                                 toqstr(plainParam(it->substr(9))));
550                         *it = "";
551                 } else if (prefixIs(*it, "basicstyle=")) {
552                         string style;
553                         string size;
554                         for (int n = 0; font_styles[n][0]; ++n) {
555                                 string const s = font_styles[n];
556                                 if (contains(*it, "\\" + s)) {
557                                         style = "\\" + s;
558                                         break;
559                                 }
560                         }
561                         for (int n = 0; font_sizes[n][0]; ++n) {
562                                 string const s = font_sizes[n];
563                                 if (contains(*it, "\\" + s)) {
564                                         size = "\\" + s;
565                                         break;
566                                 }
567                         }
568                         if (plainParam(it->substr(11)) == style + size
569                             || plainParam(it->substr(11)) == size + style) {
570                                 if (!style.empty()) {
571                                         int n = findToken(font_styles, style.substr(1));
572                                         if (n >= 0)
573                                                 fontstyleCO->setCurrentIndex(n);
574                                 }
575                                 if (!size.empty()) {
576                                         int n = findToken(font_sizes, size.substr(1));
577                                         if (n >= 0)
578                                                 fontsizeCO->setCurrentIndex(n);
579                                 }
580                                 *it = "";
581                         }
582                 } else if (prefixIs(*it, "breaklines=")) {
583                         breaklinesCB->setChecked(contains(*it, "true"));
584                         *it = "";
585                 } else if (prefixIs(*it, "showspaces=")) {
586                         spaceCB->setChecked(contains(*it, "true"));
587                         *it = "";
588                 } else if (prefixIs(*it, "showstringspaces=")) {
589                         spaceInStringCB->setChecked(contains(*it, "true"));
590                         *it = "";
591                 } else if (prefixIs(*it, "extendedchars=")) {
592                         extendedcharsCB->setChecked(contains(*it, "true"));
593                         *it = "";
594                 }
595         }
596
597         numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
598         numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
599         // parameters that can be handled by widgets are cleared
600         // the rest is put to the extra edit box.
601         string extra = getStringFromVector(pars);
602         listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
603 }
604
605
606 bool GuiListings::isValid()
607 {
608         return validate_listings_params().empty();
609 }
610
611
612 bool GuiListings::initialiseParams(string const & data)
613 {
614         InsetListingsMailer::string2params(data, params_);
615         return true;
616 }
617
618
619 void GuiListings::clearParams()
620 {
621         params_.clear();
622 }
623
624
625 void GuiListings::dispatchParams()
626 {
627         string const lfun = InsetListingsMailer::params2string(params_);
628         dispatch(FuncRequest(getLfun(), lfun));
629 }
630
631
632 void GuiListings::setParams(InsetListingsParams const & params)
633 {
634         params_ = params;
635 }
636
637
638 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
639
640
641 } // namespace frontend
642 } // namespace lyx
643
644
645 #include "GuiListings_moc.cpp"