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"
18 #include "FuncRequest.h"
20 #include "insets/InsetListings.h"
21 #include "insets/InsetListingsParams.h"
23 #include "support/debug.h"
24 #include "support/gettext.h"
25 #include "support/lstrings.h"
28 #include <QPushButton>
30 #include <QRegExpValidator>
33 using namespace lyx::support;
39 /////////////////////////////////////////////////////////////////////
43 /////////////////////////////////////////////////////////////////////
46 char const * languages[] =
47 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
48 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
49 "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
50 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
51 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
52 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
53 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
54 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
55 "VRML", "XML", "XSLT", "" };
58 char const * languages_gui[] =
59 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
60 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
61 "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
62 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
63 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
64 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
65 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
66 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
67 "VRML", "XML", "XSLT", "" };
73 /// the associated language
74 char const * language;
75 /// representation of the dialect in the gui
77 /// is this the default dialect?
82 dialect_info const dialects[] = {
83 { "R/2 4.3", "ABAP", "R/2 4.3", false },
84 { "R/2 5.0", "ABAP", "R/2 5.0", false },
85 { "R/3 3.1", "ABAP", "R/3 3.1", false },
86 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
87 { "R/3 6.10", "ABAP", "R/3 6.10", true },
88 { "2005", "Ada", "2005", true },
89 { "83", "Ada", "83", false },
90 { "95", "Ada", "95", false },
91 { "60", "Algol", "60", false },
92 { "68", "Algol", "68", true },
93 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
94 { "x86masm", "Assembler", "x86 (MASM)", false },
95 { "gnu", "Awk", "gnu", true },
96 { "POSIX", "Awk", "POSIX", false },
97 { "Visual", "Basic", "Visual", false },
98 { "ANSI", "C", "ANSI", true },
99 { "Handel", "C", "Handel", false },
100 { "Objective", "C", "Objective", false },
101 { "Sharp", "C", "Sharp", false },
102 { "ANSI", "C++", "ANSI", false },
103 { "GNU", "C++", "GNU", false },
104 { "ISO", "C++", "ISO", true },
105 { "Visual", "C++", "Visual", false },
106 { "light", "Caml", "light", true },
107 { "Objective", "Caml", "Objective", false },
108 { "1974", "Cobol", "1974", false },
109 { "1985", "Cobol", "1985", true },
110 { "ibm", "Cobol", "IBM", false },
111 { "WinXP", "command.com", "Windows XP", true },
112 { "77", "Fortran", "77", false },
113 { "90", "Fortran", "90", false },
114 { "95", "Fortran", "95", true },
115 { "CORBA", "IDL", "CORBA", false },
116 { "AspectJ", "Java", "Aspect J", false },
117 { "Auto", "Lisp", "Auto", false },
118 { "gnu", "make", "gnu", false },
119 { "1.0", "Mathematica", "1.0", false },
120 { "3.0", "Mathematica", "3.0", false },
121 { "5.2", "Mathematica", "5.2", true },
122 { "decorative", "OCL", "decorative", false },
123 { "OMG", "OCL", "OMG", true },
124 { "Borland6", "Pascal", "Borland 6", false },
125 { "Standard", "Pascal", "Standard", true },
126 { "XSC", "Pascal", "XSC", false },
127 { "PLUS", "S", "PLUS", false },
128 { "67", "Simula", "67", true },
129 { "CII", "Simula", "CII", false },
130 { "DEC", "Simula", "DEC", false },
131 { "IBM", "Simula", "IBM", false },
132 { "tk", "tcl", "tk", false },
133 { "AlLaTeX", "TeX", "AlLaTeX", false },
134 { "common", "TeX", "common", false },
135 { "LaTeX", "TeX", "LaTeX", false },
136 { "plain", "TeX", "plain", true },
137 { "primitive", "TeX", "primitive", false },
138 { "AMS", "VHDL", "AMS", false },
139 { "97", "VRML", "97", true }
143 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
146 char const * font_sizes[] =
147 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
150 char const * font_sizes_gui[] =
151 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
152 N_("Large"), N_("Larger"), "" };
154 char const * font_styles[] =
155 { "default", "rmfamily", "ttfamily", "sffamily", "" };
157 char const * font_styles_gui[] =
158 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
162 GuiListings::GuiListings(GuiView & lv)
163 : GuiDialog(lv, "listings", qt_("Program Listing Settings"))
167 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
168 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
169 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
171 connect(languageCO, SIGNAL(currentIndexChanged(int)),
172 this, SLOT(change_adaptor()));
173 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
174 this, SLOT(change_adaptor()));
175 connect(inlineCB, SIGNAL(clicked()),
176 this, SLOT(change_adaptor()));
177 connect(floatCB, SIGNAL(clicked()),
178 this, SLOT(change_adaptor()));
179 connect(placementLE, SIGNAL(textChanged(QString)),
180 this, SLOT(change_adaptor()));
181 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
182 this, SLOT(change_adaptor()));
183 connect(numberStepLE, SIGNAL(textChanged(QString)),
184 this, SLOT(change_adaptor()));
185 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
186 this, SLOT(change_adaptor()));
187 connect(firstlineLE, SIGNAL(textChanged(QString)),
188 this, SLOT(change_adaptor()));
189 connect(lastlineLE, SIGNAL(textChanged(QString)),
190 this, SLOT(change_adaptor()));
191 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
192 this, SLOT(change_adaptor()));
193 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
194 this, SLOT(change_adaptor()));
195 connect(breaklinesCB, SIGNAL(clicked()),
196 this, SLOT(change_adaptor()));
197 connect(spaceCB, SIGNAL(clicked()),
198 this, SLOT(change_adaptor()));
199 connect(spaceInStringCB, SIGNAL(clicked()),
200 this, SLOT(change_adaptor()));
201 connect(extendedcharsCB, SIGNAL(clicked()),
202 this, SLOT(change_adaptor()));
204 connect(listingsED, SIGNAL(textChanged()),
205 this, SLOT(change_adaptor()));
206 connect(listingsED, SIGNAL(textChanged()),
207 this, SLOT(set_listings_msg()));
208 connect(bypassCB, SIGNAL(clicked()),
209 this, SLOT(change_adaptor()));
210 connect(bypassCB, SIGNAL(clicked()),
211 this, SLOT(set_listings_msg()));
213 for (int n = 0; languages[n][0]; ++n)
214 languageCO->addItem(qt_(languages_gui[n]));
216 for (int n = 0; font_styles[n][0]; ++n)
217 fontstyleCO->addItem(qt_(font_styles_gui[n]));
219 for (int n = 0; font_sizes[n][0]; ++n) {
220 QString font = qt_(font_sizes_gui[n]);
221 fontsizeCO->addItem(font);
222 numberFontSizeCO->addItem(font);
226 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
227 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
228 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
229 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
231 bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
233 bc().setApply(applyPB);
234 bc().setCancel(closePB);
235 listingsTB->setPlainText(
236 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
243 void GuiListings::change_adaptor()
249 string GuiListings::construct_params()
251 string language = languages[qMax(0, languageCO->currentIndex())];
253 string const dialect_gui = fromqstr(dialectCO->currentText());
254 if (dialectCO->currentIndex() > 0) {
255 for (size_t i = 0; i != nr_dialects; ++i) {
256 if (dialect_gui == dialects[i].gui
257 && dialects[i].language == language
258 && !dialects[i].is_default) {
259 dialect = dialects[i].dialect;
265 bool float_ = floatCB->isChecked();
267 if (placementLE->isEnabled())
268 placement = fromqstr(placementLE->text());
271 switch (qMax(0, numberSideCO->currentIndex())) {
279 numberSide = "right";
285 string stepnumber = fromqstr(numberStepLE->text());
286 string numberfontsize = font_sizes[qMax(0, numberFontSizeCO->currentIndex())];
287 string firstline = fromqstr(firstlineLE->text());
288 string lastline = fromqstr(lastlineLE->text());
290 string fontsize = font_sizes[qMax(0, fontsizeCO->currentIndex())];
291 string fontstyle = font_styles[qMax(0, fontstyleCO->currentIndex())];
293 if (fontsize != "default")
294 basicstyle = "\\" + fontsize;
295 if (fontstyle != "default")
296 basicstyle += "\\" + fontstyle;
297 bool breakline = breaklinesCB->isChecked();
298 bool space = spaceCB->isChecked();
299 bool spaceInString = spaceInStringCB->isChecked();
300 bool extendedchars = extendedcharsCB->isChecked();
301 string extra = fromqstr(listingsED->toPlainText());
304 InsetListingsParams par;
305 if (language != "no language" && !contains(extra, "language=")) {
307 par.addParam("language", language);
309 par.addParam("language", "{[" + dialect + "]" + language + "}");
311 // this dialog uses float=placement instead of float,floatplacement=placement
312 // because float accepts *tbph and floatplacement accepts bph.
313 // our placement textedit is actually for the float parameter
315 par.addParam("float", placement);
316 if (numberSide != "none")
317 par.addParam("numbers", numberSide);
318 if (numberfontsize != "default" && numberSide != "none")
319 par.addParam("numberstyle", "\\" + numberfontsize);
320 if (!stepnumber.empty() && numberSide != "none")
321 par.addParam("stepnumber", stepnumber);
322 if (!firstline.empty())
323 par.addParam("firstline", firstline);
324 if (!lastline.empty())
325 par.addParam("lastline", lastline);
326 if (!basicstyle.empty())
327 par.addParam("basicstyle", basicstyle);
329 par.addParam("breaklines", "true");
331 par.addParam("showspaces", "true");
333 par.addParam("showstringspaces", "false");
335 par.addParam("extendedchars", "true");
336 par.addParams(extra);
341 docstring GuiListings::validate_listings_params()
343 // use a cache here to avoid repeated validation
344 // of the same parameters
345 static string param_cache;
346 static docstring msg_cache;
348 if (bypassCB->isChecked())
351 string params = construct_params();
352 if (params != param_cache) {
353 param_cache = params;
354 msg_cache = InsetListingsParams(params).validate();
360 void GuiListings::set_listings_msg()
362 static bool isOK = true;
363 docstring msg = validate_listings_params();
368 listingsTB->setPlainText(
369 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
372 listingsTB->setPlainText(toqstr(msg));
377 void GuiListings::on_floatCB_stateChanged(int state)
379 if (state == Qt::Checked) {
380 inlineCB->setChecked(false);
381 placementLE->setEnabled(true);
383 placementLE->setEnabled(false);
387 void GuiListings::on_inlineCB_stateChanged(int state)
389 if (state == Qt::Checked) {
390 floatCB->setChecked(false);
391 placementLE->setEnabled(false);
396 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
398 numberStepLE->setEnabled(index > 0);
399 numberFontSizeCO->setEnabled(index > 0);
403 void GuiListings::on_languageCO_currentIndexChanged(int index)
407 int default_dialect = 0;
408 dialectCO->addItem(qt_("No dialect"));
409 string const language = languages[index];
411 for (size_t i = 0; i != nr_dialects; ++i) {
412 if (language == dialects[i].language) {
413 dialectCO->addItem(qt_(dialects[i].gui));
414 if (dialects[i].is_default)
416 dialectCO->findText(qt_(dialects[i].gui));
419 dialectCO->setCurrentIndex(default_dialect);
420 dialectCO->setEnabled(dialectCO->count() > 1);
424 void GuiListings::applyView()
426 params_.setInline(inlineCB->isChecked());
427 params_.setParams(construct_params());
431 static string plainParam(string const & par)
433 // remove enclosing braces
434 if (prefixIs(par, "{") && suffixIs(par, "}"))
435 return par.substr(1, par.size() - 2);
440 void GuiListings::updateContents()
442 // set default values
443 listingsTB->setPlainText(
444 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
445 languageCO->setCurrentIndex(findToken(languages, "no language"));
446 dialectCO->setCurrentIndex(0);
447 floatCB->setChecked(false);
448 placementLE->clear();
449 numberSideCO->setCurrentIndex(0);
450 numberStepLE->clear();
451 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
452 firstlineLE->clear();
454 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
455 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
456 breaklinesCB->setChecked(false);
457 spaceCB->setChecked(false);
458 spaceInStringCB->setChecked(true);
459 extendedcharsCB->setChecked(false);
461 // set values from param string
462 inlineCB->setChecked(params_.isInline());
463 if (params_.isInline()) {
464 floatCB->setChecked(false);
465 placementLE->setEnabled(false);
467 // break other parameters and set values
468 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
469 // process each of them
470 for (vector<string>::iterator it = pars.begin();
471 it != pars.end(); ++it) {
472 if (prefixIs(*it, "language=")) {
473 string arg = plainParam(it->substr(9));
478 if (prefixIs(arg, "[") && contains(arg, "]")) {
479 size_t end_dialect = arg.find("]");
480 dialect = arg.substr(1, end_dialect - 1);
481 language = arg.substr(end_dialect + 1);
485 int n = findToken(languages, language);
487 languageCO->setCurrentIndex(n);
490 // on_languageCO_currentIndexChanged should have set dialects
491 if (!dialect.empty()) {
493 for (size_t i = 0; i != nr_dialects; ++i) {
494 if (dialect == dialects[i].dialect
495 && dialects[i].language == language) {
496 dialect_gui = dialects[i].gui;
500 n = dialectCO->findText(qt_(dialect_gui));
502 dialectCO->setCurrentIndex(n);
508 languageCO->setEnabled(in_gui);
509 dialectCO->setEnabled(
510 in_gui && dialectCO->count() > 1);
511 } else if (prefixIs(*it, "float")) {
512 floatCB->setChecked(true);
513 inlineCB->setChecked(false);
514 placementLE->setEnabled(true);
515 if (prefixIs(*it, "float="))
516 placementLE->setText(
517 toqstr(plainParam(it->substr(6))));
519 } else if (prefixIs(*it, "numbers=")) {
520 string s = plainParam(it->substr(8));
524 else if (s == "right")
526 numberSideCO->setCurrentIndex(n);
528 } else if (prefixIs(*it, "stepnumber=")) {
529 numberStepLE->setText(
530 toqstr(plainParam(it->substr(11))));
532 } else if (prefixIs(*it, "numberstyle=")) {
533 string par = plainParam(it->substr(12));
534 int n = findToken(font_sizes, par.substr(1));
536 numberFontSizeCO->setCurrentIndex(n);
538 } else if (prefixIs(*it, "firstline=")) {
539 firstlineLE->setText(
540 toqstr(plainParam(it->substr(10))));
542 } else if (prefixIs(*it, "lastline=")) {
544 toqstr(plainParam(it->substr(9))));
546 } else if (prefixIs(*it, "basicstyle=")) {
549 for (int n = 0; font_styles[n][0]; ++n) {
550 string const s = font_styles[n];
551 if (contains(*it, "\\" + s)) {
556 for (int n = 0; font_sizes[n][0]; ++n) {
557 string const s = font_sizes[n];
558 if (contains(*it, "\\" + s)) {
563 if (plainParam(it->substr(11)) == style + size
564 || plainParam(it->substr(11)) == size + style) {
565 if (!style.empty()) {
566 int n = findToken(font_styles, style.substr(1));
568 fontstyleCO->setCurrentIndex(n);
571 int n = findToken(font_sizes, size.substr(1));
573 fontsizeCO->setCurrentIndex(n);
577 } else if (prefixIs(*it, "breaklines=")) {
578 breaklinesCB->setChecked(contains(*it, "true"));
580 } else if (prefixIs(*it, "showspaces=")) {
581 spaceCB->setChecked(contains(*it, "true"));
583 } else if (prefixIs(*it, "showstringspaces=")) {
584 spaceInStringCB->setChecked(contains(*it, "true"));
586 } else if (prefixIs(*it, "extendedchars=")) {
587 extendedcharsCB->setChecked(contains(*it, "true"));
592 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
593 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
594 // parameters that can be handled by widgets are cleared
595 // the rest is put to the extra edit box.
596 string extra = getStringFromVector(pars);
597 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
601 bool GuiListings::isValid()
603 return validate_listings_params().empty();
607 bool GuiListings::initialiseParams(string const & data)
609 InsetListings::string2params(data, params_);
614 void GuiListings::clearParams()
620 void GuiListings::dispatchParams()
622 string const lfun = InsetListings::params2string(params_);
623 dispatch(FuncRequest(getLfun(), lfun));
627 void GuiListings::setParams(InsetListingsParams const & params)
633 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
636 } // namespace frontend
640 #include "GuiListings_moc.cpp"