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));
232 bc().setApply(applyPB);
233 bc().setCancel(closePB);
234 listingsTB->setPlainText(
235 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
242 void GuiListings::change_adaptor()
248 string GuiListings::construct_params()
250 string language = languages[languageCO->currentIndex()];
252 string const dialect_gui = fromqstr(dialectCO->currentText());
253 if (dialectCO->currentIndex() > 0) {
254 for (size_t i = 0; i != nr_dialects; ++i) {
255 if (dialect_gui == dialects[i].gui
256 && dialects[i].language == language
257 && !dialects[i].is_default) {
258 dialect = dialects[i].dialect;
264 bool float_ = floatCB->isChecked();
266 if (placementLE->isEnabled())
267 placement = fromqstr(placementLE->text());
270 switch (numberSideCO->currentIndex()) {
278 numberSide = "right";
284 string stepnumber = fromqstr(numberStepLE->text());
285 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
286 string firstline = fromqstr(firstlineLE->text());
287 string lastline = fromqstr(lastlineLE->text());
289 string fontsize = font_sizes[fontsizeCO->currentIndex()];
290 string fontstyle = font_styles[fontstyleCO->currentIndex()];
292 if (fontsize != "default")
293 basicstyle = "\\" + fontsize;
294 if (fontstyle != "default")
295 basicstyle += "\\" + fontstyle;
296 bool breakline = breaklinesCB->isChecked();
297 bool space = spaceCB->isChecked();
298 bool spaceInString = spaceInStringCB->isChecked();
299 bool extendedchars = extendedcharsCB->isChecked();
300 string extra = fromqstr(listingsED->toPlainText());
303 InsetListingsParams par;
304 if (language != "no language" && !contains(extra, "language=")) {
306 par.addParam("language", language);
308 par.addParam("language", "{[" + dialect + "]" + language + "}");
310 // this dialog uses float=placement instead of float,floatplacement=placement
311 // because float accepts *tbph and floatplacement accepts bph.
312 // our placement textedit is actually for the float parameter
314 par.addParam("float", placement);
315 if (numberSide != "none")
316 par.addParam("numbers", numberSide);
317 if (numberfontsize != "default" && numberSide != "none")
318 par.addParam("numberstyle", "\\" + numberfontsize);
319 if (!stepnumber.empty() && numberSide != "none")
320 par.addParam("stepnumber", stepnumber);
321 if (!firstline.empty())
322 par.addParam("firstline", firstline);
323 if (!lastline.empty())
324 par.addParam("lastline", lastline);
325 if (!basicstyle.empty())
326 par.addParam("basicstyle", basicstyle);
328 par.addParam("breaklines", "true");
330 par.addParam("showspaces", "true");
332 par.addParam("showstringspaces", "false");
334 par.addParam("extendedchars", "true");
335 par.addParams(extra);
340 docstring GuiListings::validate_listings_params()
342 // use a cache here to avoid repeated validation
343 // of the same parameters
344 static string param_cache;
345 static docstring msg_cache;
347 if (bypassCB->isChecked())
350 string params = construct_params();
351 if (params != param_cache) {
352 param_cache = params;
353 msg_cache = InsetListingsParams(params).validate();
359 void GuiListings::set_listings_msg()
361 static bool isOK = true;
362 docstring msg = validate_listings_params();
367 listingsTB->setPlainText(
368 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
371 listingsTB->setPlainText(toqstr(msg));
376 void GuiListings::on_floatCB_stateChanged(int state)
378 if (state == Qt::Checked) {
379 inlineCB->setChecked(false);
380 placementLE->setEnabled(true);
382 placementLE->setEnabled(false);
386 void GuiListings::on_inlineCB_stateChanged(int state)
388 if (state == Qt::Checked) {
389 floatCB->setChecked(false);
390 placementLE->setEnabled(false);
395 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
397 numberStepLE->setEnabled(index > 0);
398 numberFontSizeCO->setEnabled(index > 0);
402 void GuiListings::on_languageCO_currentIndexChanged(int index)
406 int default_dialect = 0;
407 dialectCO->addItem(qt_("No dialect"));
408 string const language = languages[index];
410 for (size_t i = 0; i != nr_dialects; ++i) {
411 if (language == dialects[i].language) {
412 dialectCO->addItem(qt_(dialects[i].gui));
413 if (dialects[i].is_default)
415 dialectCO->findText(qt_(dialects[i].gui));
418 dialectCO->setCurrentIndex(default_dialect);
419 dialectCO->setEnabled(dialectCO->count() > 1);
423 void GuiListings::applyView()
425 params_.setInline(inlineCB->isChecked());
426 params_.setParams(construct_params());
430 static string plainParam(string const & par)
432 // remove enclosing braces
433 if (prefixIs(par, "{") && suffixIs(par, "}"))
434 return par.substr(1, par.size() - 2);
439 void GuiListings::updateContents()
441 // set default values
442 listingsTB->setPlainText(
443 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
444 languageCO->setCurrentIndex(findToken(languages, "no language"));
445 dialectCO->setCurrentIndex(0);
446 floatCB->setChecked(false);
447 placementLE->clear();
448 numberSideCO->setCurrentIndex(0);
449 numberStepLE->clear();
450 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
451 firstlineLE->clear();
453 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
454 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
455 breaklinesCB->setChecked(false);
456 spaceCB->setChecked(false);
457 spaceInStringCB->setChecked(true);
458 extendedcharsCB->setChecked(false);
460 // set values from param string
461 inlineCB->setChecked(params_.isInline());
462 if (params_.isInline()) {
463 floatCB->setChecked(false);
464 placementLE->setEnabled(false);
466 // break other parameters and set values
467 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
468 // process each of them
469 for (vector<string>::iterator it = pars.begin();
470 it != pars.end(); ++it) {
471 if (prefixIs(*it, "language=")) {
472 string arg = plainParam(it->substr(9));
477 if (prefixIs(arg, "[") && contains(arg, "]")) {
478 size_t end_dialect = arg.find("]");
479 dialect = arg.substr(1, end_dialect - 1);
480 language = arg.substr(end_dialect + 1);
484 int n = findToken(languages, language);
486 languageCO->setCurrentIndex(n);
489 // on_languageCO_currentIndexChanged should have set dialects
490 if (!dialect.empty()) {
492 for (size_t i = 0; i != nr_dialects; ++i) {
493 if (dialect == dialects[i].dialect
494 && dialects[i].language == language) {
495 dialect_gui = dialects[i].gui;
499 n = dialectCO->findText(qt_(dialect_gui));
501 dialectCO->setCurrentIndex(n);
507 languageCO->setEnabled(in_gui);
508 dialectCO->setEnabled(
509 in_gui && dialectCO->count() > 1);
510 } else if (prefixIs(*it, "float")) {
511 floatCB->setChecked(true);
512 inlineCB->setChecked(false);
513 placementLE->setEnabled(true);
514 if (prefixIs(*it, "float="))
515 placementLE->setText(
516 toqstr(plainParam(it->substr(6))));
518 } else if (prefixIs(*it, "numbers=")) {
519 string s = plainParam(it->substr(8));
523 else if (s == "right")
525 numberSideCO->setCurrentIndex(n);
527 } else if (prefixIs(*it, "stepnumber=")) {
528 numberStepLE->setText(
529 toqstr(plainParam(it->substr(11))));
531 } else if (prefixIs(*it, "numberstyle=")) {
532 string par = plainParam(it->substr(12));
533 int n = findToken(font_sizes, par.substr(1));
535 numberFontSizeCO->setCurrentIndex(n);
537 } else if (prefixIs(*it, "firstline=")) {
538 firstlineLE->setText(
539 toqstr(plainParam(it->substr(10))));
541 } else if (prefixIs(*it, "lastline=")) {
543 toqstr(plainParam(it->substr(9))));
545 } else if (prefixIs(*it, "basicstyle=")) {
548 for (int n = 0; font_styles[n][0]; ++n) {
549 string const s = font_styles[n];
550 if (contains(*it, "\\" + s)) {
555 for (int n = 0; font_sizes[n][0]; ++n) {
556 string const s = font_sizes[n];
557 if (contains(*it, "\\" + s)) {
562 if (plainParam(it->substr(11)) == style + size
563 || plainParam(it->substr(11)) == size + style) {
564 if (!style.empty()) {
565 int n = findToken(font_styles, style.substr(1));
567 fontstyleCO->setCurrentIndex(n);
570 int n = findToken(font_sizes, size.substr(1));
572 fontsizeCO->setCurrentIndex(n);
576 } else if (prefixIs(*it, "breaklines=")) {
577 breaklinesCB->setChecked(contains(*it, "true"));
579 } else if (prefixIs(*it, "showspaces=")) {
580 spaceCB->setChecked(contains(*it, "true"));
582 } else if (prefixIs(*it, "showstringspaces=")) {
583 spaceInStringCB->setChecked(contains(*it, "true"));
585 } else if (prefixIs(*it, "extendedchars=")) {
586 extendedcharsCB->setChecked(contains(*it, "true"));
591 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
592 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
593 // parameters that can be handled by widgets are cleared
594 // the rest is put to the extra edit box.
595 string extra = getStringFromVector(pars);
596 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
600 bool GuiListings::isValid()
602 return validate_listings_params().empty();
606 bool GuiListings::initialiseParams(string const & data)
608 InsetListingsMailer::string2params(data, params_);
613 void GuiListings::clearParams()
619 void GuiListings::dispatchParams()
621 string const lfun = InsetListingsMailer::params2string(params_);
622 dispatch(FuncRequest(getLfun(), lfun));
626 void GuiListings::setParams(InsetListingsParams const & params)
632 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
635 } // namespace frontend
639 #include "GuiListings_moc.cpp"