2 * \file GuiListings.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
7 * \author Jürgen Spitzmüller
9 * Full author contact details are available in file CREDITS.
14 #include "GuiListings.h"
16 #include "ControlListings.h"
17 #include "qt_helpers.h"
18 #include "insets/InsetListingsParams.h"
21 #include "support/lstrings.h"
24 #include <QCloseEvent>
25 #include <QPushButton>
27 #include <QRegExpValidator>
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;
42 /////////////////////////////////////////////////////////////////////
46 /////////////////////////////////////////////////////////////////////
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", "" };
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", "" };
76 /// the associated language
77 char const * language;
78 /// representation of the dialect in the gui
80 /// is this the default dialect?
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 }
146 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
149 char const * font_sizes[] =
150 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
153 char const * font_sizes_gui[] =
154 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
155 N_("Large"), N_("Larger"), "" };
157 char const * font_styles[] =
158 { "default", "rmfamily", "ttfamily", "sffamily", "" };
160 char const * font_styles_gui[] =
161 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
165 GuiListingsDialog::GuiListingsDialog(LyXView & lv)
166 : GuiDialog(lv, "listings")
169 setViewTitle(_("Program Listing Settings"));
170 setController(new ControlListings(*this));
172 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
173 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
174 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
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()));
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()));
218 for (int n = 0; languages[n][0]; ++n)
219 languageCO->addItem(qt_(languages_gui[n]));
221 for (int n = 0; font_styles[n][0]; ++n)
222 fontstyleCO->addItem(qt_(font_styles_gui[n]));
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);
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));
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."));
247 ControlListings & GuiListingsDialog::controller()
249 return static_cast<ControlListings &>(GuiDialog::controller());
253 void GuiListingsDialog::closeEvent(QCloseEvent * e)
260 void GuiListingsDialog::change_adaptor()
266 string GuiListingsDialog::construct_params()
268 string language = languages[languageCO->currentIndex()];
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;
282 bool float_ = floatCB->isChecked();
284 if (placementLE->isEnabled())
285 placement = fromqstr(placementLE->text());
288 switch (numberSideCO->currentIndex()) {
296 numberSide = "right";
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());
307 string fontsize = font_sizes[fontsizeCO->currentIndex()];
308 string fontstyle = font_styles[fontstyleCO->currentIndex()];
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());
321 InsetListingsParams par;
322 if (language != "no language" && !contains(extra, "language=")) {
324 par.addParam("language", language);
326 par.addParam("language", "{[" + dialect + "]" + language + "}");
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
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);
346 par.addParam("breaklines", "true");
348 par.addParam("showspaces", "true");
350 par.addParam("showstringspaces", "false");
352 par.addParam("extendedchars", "true");
353 par.addParams(extra);
358 docstring GuiListingsDialog::validate_listings_params()
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();
365 if (bypassCB->isChecked())
368 string params = construct_params();
369 if (params != param_cache) {
370 param_cache = params;
371 msg_cache = InsetListingsParams(params).validate();
377 void GuiListingsDialog::set_listings_msg()
379 static bool isOK = true;
380 docstring msg = validate_listings_params();
385 listingsTB->setPlainText(
386 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
389 listingsTB->setPlainText(toqstr(msg));
394 void GuiListingsDialog::on_floatCB_stateChanged(int state)
396 if (state == Qt::Checked) {
397 inlineCB->setChecked(false);
398 placementLE->setEnabled(true);
400 placementLE->setEnabled(false);
404 void GuiListingsDialog::on_inlineCB_stateChanged(int state)
406 if (state == Qt::Checked) {
407 floatCB->setChecked(false);
408 placementLE->setEnabled(false);
413 void GuiListingsDialog::on_numberSideCO_currentIndexChanged(int index)
415 numberStepLE->setEnabled(index > 0);
416 numberFontSizeCO->setEnabled(index > 0);
420 void GuiListingsDialog::on_languageCO_currentIndexChanged(int index)
424 int default_dialect = 0;
425 dialectCO->addItem(qt_("No dialect"));
426 string const language = languages[index];
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)
433 dialectCO->findText(qt_(dialects[i].gui));
436 dialectCO->setCurrentIndex(default_dialect);
437 dialectCO->setEnabled(dialectCO->count() > 1);
441 void GuiListingsDialog::applyView()
443 InsetListingsParams & params = controller().params();
444 params.setInline(inlineCB->isChecked());
445 params.setParams(construct_params());
446 controller().setParams(params);
450 static string plainParam(std::string const & par)
452 // remove enclosing braces
453 if (prefixIs(par, "{") && suffixIs(par, "}"))
454 return par.substr(1, par.size() - 2);
459 void GuiListingsDialog::updateContents()
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();
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);
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);
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));
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);
504 int n = findToken(languages, language);
506 languageCO->setCurrentIndex(n);
509 // on_languageCO_currentIndexChanged should have set dialects
510 if (!dialect.empty()) {
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;
519 n = dialectCO->findText(qt_(dialect_gui));
521 dialectCO->setCurrentIndex(n);
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))));
538 } else if (prefixIs(*it, "numbers=")) {
539 string s = plainParam(it->substr(8));
543 else if (s == "right")
545 numberSideCO->setCurrentIndex(n);
547 } else if (prefixIs(*it, "stepnumber=")) {
548 numberStepLE->setText(
549 toqstr(plainParam(it->substr(11))));
551 } else if (prefixIs(*it, "numberstyle=")) {
552 string par = plainParam(it->substr(12));
553 int n = findToken(font_sizes, par.substr(1));
555 numberFontSizeCO->setCurrentIndex(n);
557 } else if (prefixIs(*it, "firstline=")) {
558 firstlineLE->setText(
559 toqstr(plainParam(it->substr(10))));
561 } else if (prefixIs(*it, "lastline=")) {
563 toqstr(plainParam(it->substr(9))));
565 } else if (prefixIs(*it, "basicstyle=")) {
568 for (int n = 0; font_styles[n][0]; ++n) {
569 string const s = font_styles[n];
570 if (contains(*it, "\\" + s)) {
575 for (int n = 0; font_sizes[n][0]; ++n) {
576 string const s = font_sizes[n];
577 if (contains(*it, "\\" + s)) {
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));
587 fontstyleCO->setCurrentIndex(n);
590 int n = findToken(font_sizes, size.substr(1));
592 fontsizeCO->setCurrentIndex(n);
596 } else if (prefixIs(*it, "breaklines=")) {
597 breaklinesCB->setChecked(contains(*it, "true"));
599 } else if (prefixIs(*it, "showspaces=")) {
600 spaceCB->setChecked(contains(*it, "true"));
602 } else if (prefixIs(*it, "showstringspaces=")) {
603 spaceInStringCB->setChecked(contains(*it, "true"));
605 } else if (prefixIs(*it, "extendedchars=")) {
606 extendedcharsCB->setChecked(contains(*it, "true"));
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()));
620 bool GuiListingsDialog::isValid()
622 return validate_listings_params().empty();
626 } // namespace frontend
630 #include "GuiListings_moc.cpp"