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 "qt_helpers.h"
17 #include "FuncRequest.h"
18 #include "insets/InsetListings.h"
19 #include "insets/InsetListingsParams.h"
20 #include "support/debug.h"
22 #include "support/lstrings.h"
25 #include <QCloseEvent>
26 #include <QPushButton>
28 #include <QRegExpValidator>
34 using support::findToken;
35 using support::getVectorFromString;
36 using support::getStringFromVector;
37 using support::prefixIs;
38 using support::suffixIs;
39 using support::contains;
44 /////////////////////////////////////////////////////////////////////
48 /////////////////////////////////////////////////////////////////////
51 char const * languages[] =
52 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
53 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
54 "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
55 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
56 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
57 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
58 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
59 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
60 "VRML", "XML", "XSLT", "" };
63 char const * languages_gui[] =
64 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
65 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
66 "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
67 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
68 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
69 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
70 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
71 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
72 "VRML", "XML", "XSLT", "" };
78 /// the associated language
79 char const * language;
80 /// representation of the dialect in the gui
82 /// is this the default dialect?
87 dialect_info const dialects[] = {
88 { "R/2 4.3", "ABAP", "R/2 4.3", false },
89 { "R/2 5.0", "ABAP", "R/2 5.0", false },
90 { "R/3 3.1", "ABAP", "R/3 3.1", false },
91 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
92 { "R/3 6.10", "ABAP", "R/3 6.10", true },
93 { "2005", "Ada", "2005", true },
94 { "83", "Ada", "83", false },
95 { "95", "Ada", "95", false },
96 { "60", "Algol", "60", false },
97 { "68", "Algol", "68", true },
98 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
99 { "x86masm", "Assembler", "x86 (MASM)", false },
100 { "gnu", "Awk", "gnu", true },
101 { "POSIX", "Awk", "POSIX", false },
102 { "Visual", "Basic", "Visual", false },
103 { "ANSI", "C", "ANSI", true },
104 { "Handel", "C", "Handel", false },
105 { "Objective", "C", "Objective", false },
106 { "Sharp", "C", "Sharp", false },
107 { "ANSI", "C++", "ANSI", false },
108 { "GNU", "C++", "GNU", false },
109 { "ISO", "C++", "ISO", true },
110 { "Visual", "C++", "Visual", false },
111 { "light", "Caml", "light", true },
112 { "Objective", "Caml", "Objective", false },
113 { "1974", "Cobol", "1974", false },
114 { "1985", "Cobol", "1985", true },
115 { "ibm", "Cobol", "IBM", false },
116 { "WinXP", "command.com", "Windows XP", true },
117 { "77", "Fortran", "77", false },
118 { "90", "Fortran", "90", false },
119 { "95", "Fortran", "95", true },
120 { "CORBA", "IDL", "CORBA", false },
121 { "AspectJ", "Java", "Aspect J", false },
122 { "Auto", "Lisp", "Auto", false },
123 { "gnu", "make", "gnu", false },
124 { "1.0", "Mathematica", "1.0", false },
125 { "3.0", "Mathematica", "3.0", false },
126 { "5.2", "Mathematica", "5.2", true },
127 { "decorative", "OCL", "decorative", false },
128 { "OMG", "OCL", "OMG", true },
129 { "Borland6", "Pascal", "Borland 6", false },
130 { "Standard", "Pascal", "Standard", true },
131 { "XSC", "Pascal", "XSC", false },
132 { "PLUS", "S", "PLUS", false },
133 { "67", "Simula", "67", true },
134 { "CII", "Simula", "CII", false },
135 { "DEC", "Simula", "DEC", false },
136 { "IBM", "Simula", "IBM", false },
137 { "tk", "tcl", "tk", false },
138 { "AlLaTeX", "TeX", "AlLaTeX", false },
139 { "common", "TeX", "common", false },
140 { "LaTeX", "TeX", "LaTeX", false },
141 { "plain", "TeX", "plain", true },
142 { "primitive", "TeX", "primitive", false },
143 { "AMS", "VHDL", "AMS", false },
144 { "97", "VRML", "97", true }
148 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
151 char const * font_sizes[] =
152 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
155 char const * font_sizes_gui[] =
156 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
157 N_("Large"), N_("Larger"), "" };
159 char const * font_styles[] =
160 { "default", "rmfamily", "ttfamily", "sffamily", "" };
162 char const * font_styles_gui[] =
163 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
167 GuiListings::GuiListings(GuiView & lv)
168 : GuiDialog(lv, "listings")
171 setViewTitle(_("Program Listing Settings"));
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(QString)),
186 this, SLOT(change_adaptor()));
187 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
188 this, SLOT(change_adaptor()));
189 connect(numberStepLE, SIGNAL(textChanged(QString)),
190 this, SLOT(change_adaptor()));
191 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
192 this, SLOT(change_adaptor()));
193 connect(firstlineLE, SIGNAL(textChanged(QString)),
194 this, SLOT(change_adaptor()));
195 connect(lastlineLE, SIGNAL(textChanged(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 void GuiListings::closeEvent(QCloseEvent * e)
255 void GuiListings::change_adaptor()
261 string GuiListings::construct_params()
263 string language = languages[languageCO->currentIndex()];
265 string const dialect_gui = fromqstr(dialectCO->currentText());
266 if (dialectCO->currentIndex() > 0) {
267 for (size_t i = 0; i != nr_dialects; ++i) {
268 if (dialect_gui == dialects[i].gui
269 && dialects[i].language == language
270 && !dialects[i].is_default) {
271 dialect = dialects[i].dialect;
277 bool float_ = floatCB->isChecked();
279 if (placementLE->isEnabled())
280 placement = fromqstr(placementLE->text());
283 switch (numberSideCO->currentIndex()) {
291 numberSide = "right";
297 string stepnumber = fromqstr(numberStepLE->text());
298 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
299 string firstline = fromqstr(firstlineLE->text());
300 string lastline = fromqstr(lastlineLE->text());
302 string fontsize = font_sizes[fontsizeCO->currentIndex()];
303 string fontstyle = font_styles[fontstyleCO->currentIndex()];
305 if (fontsize != "default")
306 basicstyle = "\\" + fontsize;
307 if (fontstyle != "default")
308 basicstyle += "\\" + fontstyle;
309 bool breakline = breaklinesCB->isChecked();
310 bool space = spaceCB->isChecked();
311 bool spaceInString = spaceInStringCB->isChecked();
312 bool extendedchars = extendedcharsCB->isChecked();
313 string extra = fromqstr(listingsED->toPlainText());
316 InsetListingsParams par;
317 if (language != "no language" && !contains(extra, "language=")) {
319 par.addParam("language", language);
321 par.addParam("language", "{[" + dialect + "]" + language + "}");
323 // this dialog uses float=placement instead of float,floatplacement=placement
324 // because float accepts *tbph and floatplacement accepts bph.
325 // our placement textedit is actually for the float parameter
327 par.addParam("float", placement);
328 if (numberSide != "none")
329 par.addParam("numbers", numberSide);
330 if (numberfontsize != "default" && numberSide != "none")
331 par.addParam("numberstyle", "\\" + numberfontsize);
332 if (!stepnumber.empty() && numberSide != "none")
333 par.addParam("stepnumber", stepnumber);
334 if (!firstline.empty())
335 par.addParam("firstline", firstline);
336 if (!lastline.empty())
337 par.addParam("lastline", lastline);
338 if (!basicstyle.empty())
339 par.addParam("basicstyle", basicstyle);
341 par.addParam("breaklines", "true");
343 par.addParam("showspaces", "true");
345 par.addParam("showstringspaces", "false");
347 par.addParam("extendedchars", "true");
348 par.addParams(extra);
353 docstring GuiListings::validate_listings_params()
355 // use a cache here to avoid repeated validation
356 // of the same parameters
357 static string param_cache;
358 static docstring msg_cache;
360 if (bypassCB->isChecked())
363 string params = construct_params();
364 if (params != param_cache) {
365 param_cache = params;
366 msg_cache = InsetListingsParams(params).validate();
372 void GuiListings::set_listings_msg()
374 static bool isOK = true;
375 docstring msg = validate_listings_params();
380 listingsTB->setPlainText(
381 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
384 listingsTB->setPlainText(toqstr(msg));
389 void GuiListings::on_floatCB_stateChanged(int state)
391 if (state == Qt::Checked) {
392 inlineCB->setChecked(false);
393 placementLE->setEnabled(true);
395 placementLE->setEnabled(false);
399 void GuiListings::on_inlineCB_stateChanged(int state)
401 if (state == Qt::Checked) {
402 floatCB->setChecked(false);
403 placementLE->setEnabled(false);
408 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
410 numberStepLE->setEnabled(index > 0);
411 numberFontSizeCO->setEnabled(index > 0);
415 void GuiListings::on_languageCO_currentIndexChanged(int index)
419 int default_dialect = 0;
420 dialectCO->addItem(qt_("No dialect"));
421 string const language = languages[index];
423 for (size_t i = 0; i != nr_dialects; ++i) {
424 if (language == dialects[i].language) {
425 dialectCO->addItem(qt_(dialects[i].gui));
426 if (dialects[i].is_default)
428 dialectCO->findText(qt_(dialects[i].gui));
431 dialectCO->setCurrentIndex(default_dialect);
432 dialectCO->setEnabled(dialectCO->count() > 1);
436 void GuiListings::applyView()
438 params_.setInline(inlineCB->isChecked());
439 params_.setParams(construct_params());
443 static string plainParam(std::string const & par)
445 // remove enclosing braces
446 if (prefixIs(par, "{") && suffixIs(par, "}"))
447 return par.substr(1, par.size() - 2);
452 void GuiListings::updateContents()
454 // set default values
455 listingsTB->setPlainText(
456 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
457 languageCO->setCurrentIndex(findToken(languages, "no language"));
458 dialectCO->setCurrentIndex(0);
459 floatCB->setChecked(false);
460 placementLE->clear();
461 numberSideCO->setCurrentIndex(0);
462 numberStepLE->clear();
463 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
464 firstlineLE->clear();
466 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
467 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
468 breaklinesCB->setChecked(false);
469 spaceCB->setChecked(false);
470 spaceInStringCB->setChecked(true);
471 extendedcharsCB->setChecked(false);
473 // set values from param string
474 inlineCB->setChecked(params_.isInline());
475 if (params_.isInline()) {
476 floatCB->setChecked(false);
477 placementLE->setEnabled(false);
479 // break other parameters and set values
480 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
481 // process each of them
482 for (vector<string>::iterator it = pars.begin();
483 it != pars.end(); ++it) {
484 if (prefixIs(*it, "language=")) {
485 string arg = plainParam(it->substr(9));
490 if (prefixIs(arg, "[") && contains(arg, "]")) {
491 size_t end_dialect = arg.find("]");
492 dialect = arg.substr(1, end_dialect - 1);
493 language = arg.substr(end_dialect + 1);
497 int n = findToken(languages, language);
499 languageCO->setCurrentIndex(n);
502 // on_languageCO_currentIndexChanged should have set dialects
503 if (!dialect.empty()) {
505 for (size_t i = 0; i != nr_dialects; ++i) {
506 if (dialect == dialects[i].dialect
507 && dialects[i].language == language) {
508 dialect_gui = dialects[i].gui;
512 n = dialectCO->findText(qt_(dialect_gui));
514 dialectCO->setCurrentIndex(n);
520 languageCO->setEnabled(in_gui);
521 dialectCO->setEnabled(
522 in_gui && dialectCO->count() > 1);
523 } else if (prefixIs(*it, "float")) {
524 floatCB->setChecked(true);
525 inlineCB->setChecked(false);
526 placementLE->setEnabled(true);
527 if (prefixIs(*it, "float="))
528 placementLE->setText(
529 toqstr(plainParam(it->substr(6))));
531 } else if (prefixIs(*it, "numbers=")) {
532 string s = plainParam(it->substr(8));
536 else if (s == "right")
538 numberSideCO->setCurrentIndex(n);
540 } else if (prefixIs(*it, "stepnumber=")) {
541 numberStepLE->setText(
542 toqstr(plainParam(it->substr(11))));
544 } else if (prefixIs(*it, "numberstyle=")) {
545 string par = plainParam(it->substr(12));
546 int n = findToken(font_sizes, par.substr(1));
548 numberFontSizeCO->setCurrentIndex(n);
550 } else if (prefixIs(*it, "firstline=")) {
551 firstlineLE->setText(
552 toqstr(plainParam(it->substr(10))));
554 } else if (prefixIs(*it, "lastline=")) {
556 toqstr(plainParam(it->substr(9))));
558 } else if (prefixIs(*it, "basicstyle=")) {
561 for (int n = 0; font_styles[n][0]; ++n) {
562 string const s = font_styles[n];
563 if (contains(*it, "\\" + s)) {
568 for (int n = 0; font_sizes[n][0]; ++n) {
569 string const s = font_sizes[n];
570 if (contains(*it, "\\" + s)) {
575 if (plainParam(it->substr(11)) == style + size
576 || plainParam(it->substr(11)) == size + style) {
577 if (!style.empty()) {
578 int n = findToken(font_styles, style.substr(1));
580 fontstyleCO->setCurrentIndex(n);
583 int n = findToken(font_sizes, size.substr(1));
585 fontsizeCO->setCurrentIndex(n);
589 } else if (prefixIs(*it, "breaklines=")) {
590 breaklinesCB->setChecked(contains(*it, "true"));
592 } else if (prefixIs(*it, "showspaces=")) {
593 spaceCB->setChecked(contains(*it, "true"));
595 } else if (prefixIs(*it, "showstringspaces=")) {
596 spaceInStringCB->setChecked(contains(*it, "true"));
598 } else if (prefixIs(*it, "extendedchars=")) {
599 extendedcharsCB->setChecked(contains(*it, "true"));
604 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
605 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
606 // parameters that can be handled by widgets are cleared
607 // the rest is put to the extra edit box.
608 string extra = getStringFromVector(pars);
609 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
613 bool GuiListings::isValid()
615 return validate_listings_params().empty();
619 bool GuiListings::initialiseParams(string const & data)
621 InsetListingsMailer::string2params(data, params_);
626 void GuiListings::clearParams()
632 void GuiListings::dispatchParams()
634 string const lfun = InsetListingsMailer::params2string(params_);
635 dispatch(FuncRequest(getLfun(), lfun));
639 void GuiListings::setParams(InsetListingsParams const & params)
645 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
648 } // namespace frontend
652 #include "GuiListings_moc.cpp"