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/convert.h"
22 #include "support/lstrings.h"
25 #include <QCloseEvent>
26 #include <QPushButton>
28 #include <QRegExpValidator>
33 using lyx::support::findToken;
34 using lyx::support::getVectorFromString;
35 using lyx::support::getStringFromVector;
36 using lyx::support::prefixIs;
37 using lyx::support::suffixIs;
38 using lyx::support::contains;
43 /////////////////////////////////////////////////////////////////////
47 /////////////////////////////////////////////////////////////////////
50 char const * languages[] =
51 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
52 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
53 "Eiffel", "Elan", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
54 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
55 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
56 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
57 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
58 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
59 "VRML", "XML", "XSLT", "" };
62 char const * languages_gui[] =
63 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
64 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
65 "Eiffel", "Elan", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
66 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
67 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
68 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
69 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
70 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
71 "VRML", "XML", "XSLT", "" };
77 /// the associated language
78 char const * language;
79 /// representation of the dialect in the gui
81 /// is this the default dialect?
86 dialect_info const dialects[] = {
87 { "R/2 4.3", "ABAP", "R/2 4.3", false },
88 { "R/2 5.0", "ABAP", "R/2 5.0", false },
89 { "R/3 3.1", "ABAP", "R/3 3.1", false },
90 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
91 { "R/3 6.10", "ABAP", "R/3 6.10", true },
92 { "2005", "Ada", "2005", true },
93 { "83", "Ada", "83", false },
94 { "95", "Ada", "95", false },
95 { "60", "Algol", "60", false },
96 { "68", "Algol", "68", true },
97 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
98 { "x86masm", "Assembler", "x86 (MASM)", false },
99 { "gnu", "Awk", "gnu", true },
100 { "POSIX", "Awk", "POSIX", false },
101 { "Visual", "Basic", "Visual", false },
102 { "ANSI", "C", "ANSI", true },
103 { "Handel", "C", "Handel", false },
104 { "Objective", "C", "Objective", false },
105 { "Sharp", "C", "Sharp", false },
106 { "ANSI", "C++", "ANSI", false },
107 { "GNU", "C++", "GNU", false },
108 { "ISO", "C++", "ISO", true },
109 { "Visual", "C++", "Visual", false },
110 { "light", "Caml", "light", true },
111 { "Objective", "Caml", "Objective", false },
112 { "1974", "Cobol", "1974", false },
113 { "1985", "Cobol", "1985", true },
114 { "ibm", "Cobol", "IBM", false },
115 { "WinXP", "command.com", "Windows XP", true },
116 { "77", "Fortran", "77", false },
117 { "90", "Fortran", "90", false },
118 { "95", "Fortran", "95", true },
119 { "CORBA", "IDL", "CORBA", false },
120 { "AspectJ", "Java", "Aspect J", false },
121 { "Auto", "Lisp", "Auto", false },
122 { "gnu", "make", "gnu", false },
123 { "1.0", "Mathematica", "1.0", false },
124 { "3.0", "Mathematica", "3.0", false },
125 { "5.2", "Mathematica", "5.2", true },
126 { "decorative", "OCL", "decorative", false },
127 { "OMG", "OCL", "OMG", true },
128 { "Borland6", "Pascal", "Borland 6", false },
129 { "Standard", "Pascal", "Standard", true },
130 { "XSC", "Pascal", "XSC", false },
131 { "PLUS", "S", "PLUS", false },
132 { "67", "Simula", "67", true },
133 { "CII", "Simula", "CII", false },
134 { "DEC", "Simula", "DEC", false },
135 { "IBM", "Simula", "IBM", false },
136 { "tk", "tcl", "tk", false },
137 { "AlLaTeX", "TeX", "AlLaTeX", false },
138 { "common", "TeX", "common", false },
139 { "LaTeX", "TeX", "LaTeX", false },
140 { "plain", "TeX", "plain", true },
141 { "primitive", "TeX", "primitive", false },
142 { "AMS", "VHDL", "AMS", false },
143 { "97", "VRML", "97", true }
147 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
150 char const * font_sizes[] =
151 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
154 char const * font_sizes_gui[] =
155 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
156 N_("Large"), N_("Larger"), "" };
158 char const * font_styles[] =
159 { "default", "rmfamily", "ttfamily", "sffamily", "" };
161 char const * font_styles_gui[] =
162 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
166 GuiListingsDialog::GuiListingsDialog(LyXView & lv)
167 : GuiDialog(lv, "listings")
170 setViewTitle(_("Program Listing Settings"));
171 setController(new ControlListings(*this));
173 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
174 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
175 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
177 connect(languageCO, SIGNAL(currentIndexChanged(int)),
178 this, SLOT(change_adaptor()));
179 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
180 this, SLOT(change_adaptor()));
181 connect(inlineCB, SIGNAL(clicked()),
182 this, SLOT(change_adaptor()));
183 connect(floatCB, SIGNAL(clicked()),
184 this, SLOT(change_adaptor()));
185 connect(placementLE, SIGNAL(textChanged(const QString&)),
186 this, SLOT(change_adaptor()));
187 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
188 this, SLOT(change_adaptor()));
189 connect(numberStepLE, SIGNAL(textChanged(const QString&)),
190 this, SLOT(change_adaptor()));
191 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
192 this, SLOT(change_adaptor()));
193 connect(firstlineLE, SIGNAL(textChanged(const QString&)),
194 this, SLOT(change_adaptor()));
195 connect(lastlineLE, SIGNAL(textChanged(const QString&)),
196 this, SLOT(change_adaptor()));
197 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
198 this, SLOT(change_adaptor()));
199 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
200 this, SLOT(change_adaptor()));
201 connect(breaklinesCB, SIGNAL(clicked()),
202 this, SLOT(change_adaptor()));
203 connect(spaceCB, SIGNAL(clicked()),
204 this, SLOT(change_adaptor()));
205 connect(spaceInStringCB, SIGNAL(clicked()),
206 this, SLOT(change_adaptor()));
207 connect(extendedcharsCB, SIGNAL(clicked()),
208 this, SLOT(change_adaptor()));
210 connect(listingsED, SIGNAL(textChanged()),
211 this, SLOT(change_adaptor()));
212 connect(listingsED, SIGNAL(textChanged()),
213 this, SLOT(set_listings_msg()));
214 connect(bypassCB, SIGNAL(clicked()),
215 this, SLOT(change_adaptor()));
216 connect(bypassCB, SIGNAL(clicked()),
217 this, SLOT(set_listings_msg()));
219 for (int n = 0; languages[n][0]; ++n)
220 languageCO->addItem(qt_(languages_gui[n]));
222 for (int n = 0; font_styles[n][0]; ++n)
223 fontstyleCO->addItem(qt_(font_styles_gui[n]));
225 for (int n = 0; font_sizes[n][0]; ++n) {
226 QString font = qt_(font_sizes_gui[n]);
227 fontsizeCO->addItem(font);
228 numberFontSizeCO->addItem(font);
232 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
233 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
234 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
235 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
238 bc().setApply(applyPB);
239 bc().setCancel(closePB);
240 listingsTB->setPlainText(
241 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
248 ControlListings & GuiListingsDialog::controller() const
250 return static_cast<ControlListings &>(Dialog::controller());
254 void GuiListingsDialog::closeEvent(QCloseEvent * e)
261 void GuiListingsDialog::change_adaptor()
267 string GuiListingsDialog::construct_params()
269 string language = languages[languageCO->currentIndex()];
271 string const dialect_gui = fromqstr(dialectCO->currentText());
272 if (dialectCO->currentIndex() > 0) {
273 for (size_t i = 0; i < nr_dialects; ++i) {
274 if (dialect_gui == dialects[i].gui
275 && dialects[i].language == language
276 && !dialects[i].is_default) {
277 dialect = dialects[i].dialect;
283 bool float_ = floatCB->isChecked();
285 if (placementLE->isEnabled())
286 placement = fromqstr(placementLE->text());
289 switch (numberSideCO->currentIndex()) {
297 numberSide = "right";
303 string stepnumber = fromqstr(numberStepLE->text());
304 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
305 string firstline = fromqstr(firstlineLE->text());
306 string lastline = fromqstr(lastlineLE->text());
308 string fontsize = font_sizes[fontsizeCO->currentIndex()];
309 string fontstyle = font_styles[fontstyleCO->currentIndex()];
311 if (fontsize != "default")
312 basicstyle = "\\" + fontsize;
313 if (fontstyle != "default")
314 basicstyle += "\\" + fontstyle;
315 bool breakline = breaklinesCB->isChecked();
316 bool space = spaceCB->isChecked();
317 bool spaceInString = spaceInStringCB->isChecked();
318 bool extendedchars = extendedcharsCB->isChecked();
319 string extra = fromqstr(listingsED->toPlainText());
322 InsetListingsParams par;
323 if (language != "no language" && !contains(extra, "language=")) {
325 par.addParam("language", language);
327 par.addParam("language", "{[" + dialect + "]" + language + "}");
329 // this dialog uses float=placement instead of float,floatplacement=placement
330 // because float accepts *tbph and floatplacement accepts bph.
331 // our placement textedit is actually for the float parameter
333 par.addParam("float", placement);
334 if (numberSide != "none")
335 par.addParam("numbers", numberSide);
336 if (numberfontsize != "default" && numberSide != "none")
337 par.addParam("numberstyle", "\\" + numberfontsize);
338 if (!stepnumber.empty() && numberSide != "none")
339 par.addParam("stepnumber", stepnumber);
340 if (!firstline.empty())
341 par.addParam("firstline", firstline);
342 if (!lastline.empty())
343 par.addParam("lastline", lastline);
344 if (!basicstyle.empty())
345 par.addParam("basicstyle", basicstyle);
347 par.addParam("breaklines", "true");
349 par.addParam("showspaces", "true");
351 par.addParam("showstringspaces", "false");
353 par.addParam("extendedchars", "true");
354 par.addParams(extra);
359 docstring GuiListingsDialog::validate_listings_params()
361 // use a cache here to avoid repeated validation
362 // of the same parameters
363 static string param_cache = string();
364 static docstring msg_cache = docstring();
366 if (bypassCB->isChecked())
369 string params = construct_params();
370 if (params != param_cache) {
371 param_cache = params;
372 msg_cache = InsetListingsParams(params).validate();
378 void GuiListingsDialog::set_listings_msg()
380 static bool isOK = true;
381 docstring msg = validate_listings_params();
386 listingsTB->setPlainText(
387 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
390 listingsTB->setPlainText(toqstr(msg));
395 void GuiListingsDialog::on_floatCB_stateChanged(int state)
397 if (state == Qt::Checked) {
398 inlineCB->setChecked(false);
399 placementLE->setEnabled(true);
401 placementLE->setEnabled(false);
405 void GuiListingsDialog::on_inlineCB_stateChanged(int state)
407 if (state == Qt::Checked) {
408 floatCB->setChecked(false);
409 placementLE->setEnabled(false);
414 void GuiListingsDialog::on_numberSideCO_currentIndexChanged(int index)
416 numberStepLE->setEnabled(index > 0);
417 numberFontSizeCO->setEnabled(index > 0);
421 void GuiListingsDialog::on_languageCO_currentIndexChanged(int index)
425 int default_dialect = 0;
426 dialectCO->addItem(qt_("No dialect"));
427 string const language = languages[index];
429 for (size_t i = 0; i < nr_dialects; ++i) {
430 if (language == dialects[i].language) {
431 dialectCO->addItem(qt_(dialects[i].gui));
432 if (dialects[i].is_default)
434 dialectCO->findText(qt_(dialects[i].gui));
437 dialectCO->setCurrentIndex(default_dialect);
438 dialectCO->setEnabled(dialectCO->count() > 1);
442 void GuiListingsDialog::applyView()
444 InsetListingsParams & params = controller().params();
445 params.setInline(inlineCB->isChecked());
446 params.setParams(construct_params());
447 controller().setParams(params);
451 static string plainParam(std::string const & par)
453 // remove enclosing braces
454 if (prefixIs(par, "{") && suffixIs(par, "}"))
455 return par.substr(1, par.size() - 2);
460 void GuiListingsDialog::update_contents()
462 // set default values
463 listingsTB->setPlainText(
464 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
465 languageCO->setCurrentIndex(findToken(languages, "no language"));
466 dialectCO->setCurrentIndex(0);
467 floatCB->setChecked(false);
468 placementLE->clear();
469 numberSideCO->setCurrentIndex(0);
470 numberStepLE->clear();
471 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
472 firstlineLE->clear();
474 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
475 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
476 breaklinesCB->setChecked(false);
477 spaceCB->setChecked(false);
478 spaceInStringCB->setChecked(true);
479 extendedcharsCB->setChecked(false);
481 // set values from param string
482 InsetListingsParams & params = controller().params();
483 inlineCB->setChecked(params.isInline());
484 if (params.isInline()) {
485 floatCB->setChecked(false);
486 placementLE->setEnabled(false);
488 // break other parameters and set values
489 vector<string> pars = getVectorFromString(params.separatedParams(), "\n");
490 // process each of them
491 for (vector<string>::iterator it = pars.begin();
492 it != pars.end(); ++it) {
493 if (prefixIs(*it, "language=")) {
494 string arg = plainParam(it->substr(9));
499 if (prefixIs(arg, "[") && contains(arg, "]")) {
500 string::size_type end_dialect = arg.find("]");
501 dialect = arg.substr(1, end_dialect - 1);
502 language = arg.substr(end_dialect + 1);
505 int n = findToken(languages, language);
507 languageCO->setCurrentIndex(n);
510 // on_languageCO_currentIndexChanged should have set dialects
511 if (!dialect.empty()) {
513 for (size_t i = 0; i < nr_dialects; ++i) {
514 if (dialect == dialects[i].dialect
515 && dialects[i].language == language) {
516 dialect_gui = dialects[i].gui;
520 n = dialectCO->findText(qt_(dialect_gui));
522 dialectCO->setCurrentIndex(n);
528 languageCO->setEnabled(in_gui);
529 dialectCO->setEnabled(
530 in_gui && dialectCO->count() > 1);
531 } else if (prefixIs(*it, "float")) {
532 floatCB->setChecked(true);
533 inlineCB->setChecked(false);
534 placementLE->setEnabled(true);
535 if (prefixIs(*it, "float="))
536 placementLE->setText(
537 toqstr(plainParam(it->substr(6))));
539 } else if (prefixIs(*it, "numbers=")) {
540 string s = plainParam(it->substr(8));
544 else if (s == "right")
546 numberSideCO->setCurrentIndex(n);
548 } else if (prefixIs(*it, "stepnumber=")) {
549 numberStepLE->setText(
550 toqstr(plainParam(it->substr(11))));
552 } else if (prefixIs(*it, "numberstyle=")) {
553 string par = plainParam(it->substr(12));
554 int n = findToken(font_sizes, par.substr(1));
556 numberFontSizeCO->setCurrentIndex(n);
558 } else if (prefixIs(*it, "firstline=")) {
559 firstlineLE->setText(
560 toqstr(plainParam(it->substr(10))));
562 } else if (prefixIs(*it, "lastline=")) {
564 toqstr(plainParam(it->substr(9))));
566 } else if (prefixIs(*it, "basicstyle=")) {
569 for (int n = 0; font_styles[n][0]; ++n) {
570 string const s = font_styles[n];
571 if (contains(*it, "\\" + s)) {
576 for (int n = 0; font_sizes[n][0]; ++n) {
577 string const s = font_sizes[n];
578 if (contains(*it, "\\" + s)) {
583 if (plainParam(it->substr(11)) == style + size
584 || plainParam(it->substr(11)) == size + style) {
585 if (!style.empty()) {
586 int n = findToken(font_styles, style.substr(1));
588 fontstyleCO->setCurrentIndex(n);
591 int n = findToken(font_sizes, size.substr(1));
593 fontsizeCO->setCurrentIndex(n);
597 } else if (prefixIs(*it, "breaklines=")) {
598 breaklinesCB->setChecked(contains(*it, "true"));
600 } else if (prefixIs(*it, "showspaces=")) {
601 spaceCB->setChecked(contains(*it, "true"));
603 } else if (prefixIs(*it, "showstringspaces=")) {
604 spaceInStringCB->setChecked(contains(*it, "true"));
606 } else if (prefixIs(*it, "extendedchars=")) {
607 extendedcharsCB->setChecked(contains(*it, "true"));
612 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
613 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
614 // parameters that can be handled by widgets are cleared
615 // the rest is put to the extra edit box.
616 string extra = getStringFromVector(pars);
617 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
621 bool GuiListingsDialog::isValid()
623 return validate_listings_params().empty();
627 } // namespace frontend
631 #include "GuiListings_moc.cpp"