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