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/gettext.h"
23 #include "support/lstrings.h"
26 #include <QPushButton>
28 #include <QRegExpValidator>
31 using namespace lyx::support;
37 /////////////////////////////////////////////////////////////////////
41 /////////////////////////////////////////////////////////////////////
44 char const * languages[] =
45 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
46 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
47 "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
48 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
49 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
50 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
51 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
52 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
53 "VRML", "XML", "XSLT", "" };
56 char const * languages_gui[] =
57 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
58 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
59 "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
60 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
61 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
62 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
63 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
64 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
65 "VRML", "XML", "XSLT", "" };
71 /// the associated language
72 char const * language;
73 /// representation of the dialect in the gui
75 /// is this the default dialect?
80 dialect_info const dialects[] = {
81 { "R/2 4.3", "ABAP", "R/2 4.3", false },
82 { "R/2 5.0", "ABAP", "R/2 5.0", false },
83 { "R/3 3.1", "ABAP", "R/3 3.1", false },
84 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
85 { "R/3 6.10", "ABAP", "R/3 6.10", true },
86 { "2005", "Ada", "2005", true },
87 { "83", "Ada", "83", false },
88 { "95", "Ada", "95", false },
89 { "60", "Algol", "60", false },
90 { "68", "Algol", "68", true },
91 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
92 { "x86masm", "Assembler", "x86 (MASM)", false },
93 { "gnu", "Awk", "gnu", true },
94 { "POSIX", "Awk", "POSIX", false },
95 { "Visual", "Basic", "Visual", false },
96 { "ANSI", "C", "ANSI", true },
97 { "Handel", "C", "Handel", false },
98 { "Objective", "C", "Objective", false },
99 { "Sharp", "C", "Sharp", false },
100 { "ANSI", "C++", "ANSI", false },
101 { "GNU", "C++", "GNU", false },
102 { "ISO", "C++", "ISO", true },
103 { "Visual", "C++", "Visual", false },
104 { "light", "Caml", "light", true },
105 { "Objective", "Caml", "Objective", false },
106 { "1974", "Cobol", "1974", false },
107 { "1985", "Cobol", "1985", true },
108 { "ibm", "Cobol", "IBM", false },
109 { "WinXP", "command.com", "Windows XP", true },
110 { "77", "Fortran", "77", false },
111 { "90", "Fortran", "90", false },
112 { "95", "Fortran", "95", true },
113 { "CORBA", "IDL", "CORBA", false },
114 { "AspectJ", "Java", "Aspect J", false },
115 { "Auto", "Lisp", "Auto", false },
116 { "gnu", "make", "gnu", false },
117 { "1.0", "Mathematica", "1.0", false },
118 { "3.0", "Mathematica", "3.0", false },
119 { "5.2", "Mathematica", "5.2", true },
120 { "decorative", "OCL", "decorative", false },
121 { "OMG", "OCL", "OMG", true },
122 { "Borland6", "Pascal", "Borland 6", false },
123 { "Standard", "Pascal", "Standard", true },
124 { "XSC", "Pascal", "XSC", false },
125 { "PLUS", "S", "PLUS", false },
126 { "67", "Simula", "67", true },
127 { "CII", "Simula", "CII", false },
128 { "DEC", "Simula", "DEC", false },
129 { "IBM", "Simula", "IBM", false },
130 { "tk", "tcl", "tk", false },
131 { "AlLaTeX", "TeX", "AlLaTeX", false },
132 { "common", "TeX", "common", false },
133 { "LaTeX", "TeX", "LaTeX", false },
134 { "plain", "TeX", "plain", true },
135 { "primitive", "TeX", "primitive", false },
136 { "AMS", "VHDL", "AMS", false },
137 { "97", "VRML", "97", true }
141 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
144 char const * font_sizes[] =
145 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
148 char const * font_sizes_gui[] =
149 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
150 N_("Large"), N_("Larger"), "" };
152 char const * font_styles[] =
153 { "default", "rmfamily", "ttfamily", "sffamily", "" };
155 char const * font_styles_gui[] =
156 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
160 GuiListings::GuiListings(GuiView & lv)
161 : GuiDialog(lv, "listings", qt_("Program Listing Settings"))
165 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
166 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
167 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
169 connect(languageCO, SIGNAL(currentIndexChanged(int)),
170 this, SLOT(change_adaptor()));
171 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
172 this, SLOT(change_adaptor()));
173 connect(inlineCB, SIGNAL(clicked()),
174 this, SLOT(change_adaptor()));
175 connect(floatCB, SIGNAL(clicked()),
176 this, SLOT(change_adaptor()));
177 connect(placementLE, SIGNAL(textChanged(QString)),
178 this, SLOT(change_adaptor()));
179 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
180 this, SLOT(change_adaptor()));
181 connect(numberStepLE, SIGNAL(textChanged(QString)),
182 this, SLOT(change_adaptor()));
183 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
184 this, SLOT(change_adaptor()));
185 connect(firstlineLE, SIGNAL(textChanged(QString)),
186 this, SLOT(change_adaptor()));
187 connect(lastlineLE, SIGNAL(textChanged(QString)),
188 this, SLOT(change_adaptor()));
189 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
190 this, SLOT(change_adaptor()));
191 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
192 this, SLOT(change_adaptor()));
193 connect(breaklinesCB, SIGNAL(clicked()),
194 this, SLOT(change_adaptor()));
195 connect(spaceCB, SIGNAL(clicked()),
196 this, SLOT(change_adaptor()));
197 connect(spaceInStringCB, SIGNAL(clicked()),
198 this, SLOT(change_adaptor()));
199 connect(extendedcharsCB, SIGNAL(clicked()),
200 this, SLOT(change_adaptor()));
202 connect(listingsED, SIGNAL(textChanged()),
203 this, SLOT(change_adaptor()));
204 connect(listingsED, SIGNAL(textChanged()),
205 this, SLOT(set_listings_msg()));
206 connect(bypassCB, SIGNAL(clicked()),
207 this, SLOT(change_adaptor()));
208 connect(bypassCB, SIGNAL(clicked()),
209 this, SLOT(set_listings_msg()));
211 for (int n = 0; languages[n][0]; ++n)
212 languageCO->addItem(qt_(languages_gui[n]));
214 for (int n = 0; font_styles[n][0]; ++n)
215 fontstyleCO->addItem(qt_(font_styles_gui[n]));
217 for (int n = 0; font_sizes[n][0]; ++n) {
218 QString font = qt_(font_sizes_gui[n]);
219 fontsizeCO->addItem(font);
220 numberFontSizeCO->addItem(font);
224 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
225 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
226 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
227 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
230 bc().setApply(applyPB);
231 bc().setCancel(closePB);
232 listingsTB->setPlainText(
233 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
240 void GuiListings::change_adaptor()
246 string GuiListings::construct_params()
248 string language = languages[languageCO->currentIndex()];
250 string const dialect_gui = fromqstr(dialectCO->currentText());
251 if (dialectCO->currentIndex() > 0) {
252 for (size_t i = 0; i != nr_dialects; ++i) {
253 if (dialect_gui == dialects[i].gui
254 && dialects[i].language == language
255 && !dialects[i].is_default) {
256 dialect = dialects[i].dialect;
262 bool float_ = floatCB->isChecked();
264 if (placementLE->isEnabled())
265 placement = fromqstr(placementLE->text());
268 switch (numberSideCO->currentIndex()) {
276 numberSide = "right";
282 string stepnumber = fromqstr(numberStepLE->text());
283 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
284 string firstline = fromqstr(firstlineLE->text());
285 string lastline = fromqstr(lastlineLE->text());
287 string fontsize = font_sizes[fontsizeCO->currentIndex()];
288 string fontstyle = font_styles[fontstyleCO->currentIndex()];
290 if (fontsize != "default")
291 basicstyle = "\\" + fontsize;
292 if (fontstyle != "default")
293 basicstyle += "\\" + fontstyle;
294 bool breakline = breaklinesCB->isChecked();
295 bool space = spaceCB->isChecked();
296 bool spaceInString = spaceInStringCB->isChecked();
297 bool extendedchars = extendedcharsCB->isChecked();
298 string extra = fromqstr(listingsED->toPlainText());
301 InsetListingsParams par;
302 if (language != "no language" && !contains(extra, "language=")) {
304 par.addParam("language", language);
306 par.addParam("language", "{[" + dialect + "]" + language + "}");
308 // this dialog uses float=placement instead of float,floatplacement=placement
309 // because float accepts *tbph and floatplacement accepts bph.
310 // our placement textedit is actually for the float parameter
312 par.addParam("float", placement);
313 if (numberSide != "none")
314 par.addParam("numbers", numberSide);
315 if (numberfontsize != "default" && numberSide != "none")
316 par.addParam("numberstyle", "\\" + numberfontsize);
317 if (!stepnumber.empty() && numberSide != "none")
318 par.addParam("stepnumber", stepnumber);
319 if (!firstline.empty())
320 par.addParam("firstline", firstline);
321 if (!lastline.empty())
322 par.addParam("lastline", lastline);
323 if (!basicstyle.empty())
324 par.addParam("basicstyle", basicstyle);
326 par.addParam("breaklines", "true");
328 par.addParam("showspaces", "true");
330 par.addParam("showstringspaces", "false");
332 par.addParam("extendedchars", "true");
333 par.addParams(extra);
338 docstring GuiListings::validate_listings_params()
340 // use a cache here to avoid repeated validation
341 // of the same parameters
342 static string param_cache;
343 static docstring msg_cache;
345 if (bypassCB->isChecked())
348 string params = construct_params();
349 if (params != param_cache) {
350 param_cache = params;
351 msg_cache = InsetListingsParams(params).validate();
357 void GuiListings::set_listings_msg()
359 static bool isOK = true;
360 docstring msg = validate_listings_params();
365 listingsTB->setPlainText(
366 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
369 listingsTB->setPlainText(toqstr(msg));
374 void GuiListings::on_floatCB_stateChanged(int state)
376 if (state == Qt::Checked) {
377 inlineCB->setChecked(false);
378 placementLE->setEnabled(true);
380 placementLE->setEnabled(false);
384 void GuiListings::on_inlineCB_stateChanged(int state)
386 if (state == Qt::Checked) {
387 floatCB->setChecked(false);
388 placementLE->setEnabled(false);
393 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
395 numberStepLE->setEnabled(index > 0);
396 numberFontSizeCO->setEnabled(index > 0);
400 void GuiListings::on_languageCO_currentIndexChanged(int index)
404 int default_dialect = 0;
405 dialectCO->addItem(qt_("No dialect"));
406 string const language = languages[index];
408 for (size_t i = 0; i != nr_dialects; ++i) {
409 if (language == dialects[i].language) {
410 dialectCO->addItem(qt_(dialects[i].gui));
411 if (dialects[i].is_default)
413 dialectCO->findText(qt_(dialects[i].gui));
416 dialectCO->setCurrentIndex(default_dialect);
417 dialectCO->setEnabled(dialectCO->count() > 1);
421 void GuiListings::applyView()
423 params_.setInline(inlineCB->isChecked());
424 params_.setParams(construct_params());
428 static string plainParam(string const & par)
430 // remove enclosing braces
431 if (prefixIs(par, "{") && suffixIs(par, "}"))
432 return par.substr(1, par.size() - 2);
437 void GuiListings::updateContents()
439 // set default values
440 listingsTB->setPlainText(
441 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
442 languageCO->setCurrentIndex(findToken(languages, "no language"));
443 dialectCO->setCurrentIndex(0);
444 floatCB->setChecked(false);
445 placementLE->clear();
446 numberSideCO->setCurrentIndex(0);
447 numberStepLE->clear();
448 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
449 firstlineLE->clear();
451 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
452 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
453 breaklinesCB->setChecked(false);
454 spaceCB->setChecked(false);
455 spaceInStringCB->setChecked(true);
456 extendedcharsCB->setChecked(false);
458 // set values from param string
459 inlineCB->setChecked(params_.isInline());
460 if (params_.isInline()) {
461 floatCB->setChecked(false);
462 placementLE->setEnabled(false);
464 // break other parameters and set values
465 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
466 // process each of them
467 for (vector<string>::iterator it = pars.begin();
468 it != pars.end(); ++it) {
469 if (prefixIs(*it, "language=")) {
470 string arg = plainParam(it->substr(9));
475 if (prefixIs(arg, "[") && contains(arg, "]")) {
476 size_t end_dialect = arg.find("]");
477 dialect = arg.substr(1, end_dialect - 1);
478 language = arg.substr(end_dialect + 1);
482 int n = findToken(languages, language);
484 languageCO->setCurrentIndex(n);
487 // on_languageCO_currentIndexChanged should have set dialects
488 if (!dialect.empty()) {
490 for (size_t i = 0; i != nr_dialects; ++i) {
491 if (dialect == dialects[i].dialect
492 && dialects[i].language == language) {
493 dialect_gui = dialects[i].gui;
497 n = dialectCO->findText(qt_(dialect_gui));
499 dialectCO->setCurrentIndex(n);
505 languageCO->setEnabled(in_gui);
506 dialectCO->setEnabled(
507 in_gui && dialectCO->count() > 1);
508 } else if (prefixIs(*it, "float")) {
509 floatCB->setChecked(true);
510 inlineCB->setChecked(false);
511 placementLE->setEnabled(true);
512 if (prefixIs(*it, "float="))
513 placementLE->setText(
514 toqstr(plainParam(it->substr(6))));
516 } else if (prefixIs(*it, "numbers=")) {
517 string s = plainParam(it->substr(8));
521 else if (s == "right")
523 numberSideCO->setCurrentIndex(n);
525 } else if (prefixIs(*it, "stepnumber=")) {
526 numberStepLE->setText(
527 toqstr(plainParam(it->substr(11))));
529 } else if (prefixIs(*it, "numberstyle=")) {
530 string par = plainParam(it->substr(12));
531 int n = findToken(font_sizes, par.substr(1));
533 numberFontSizeCO->setCurrentIndex(n);
535 } else if (prefixIs(*it, "firstline=")) {
536 firstlineLE->setText(
537 toqstr(plainParam(it->substr(10))));
539 } else if (prefixIs(*it, "lastline=")) {
541 toqstr(plainParam(it->substr(9))));
543 } else if (prefixIs(*it, "basicstyle=")) {
546 for (int n = 0; font_styles[n][0]; ++n) {
547 string const s = font_styles[n];
548 if (contains(*it, "\\" + s)) {
553 for (int n = 0; font_sizes[n][0]; ++n) {
554 string const s = font_sizes[n];
555 if (contains(*it, "\\" + s)) {
560 if (plainParam(it->substr(11)) == style + size
561 || plainParam(it->substr(11)) == size + style) {
562 if (!style.empty()) {
563 int n = findToken(font_styles, style.substr(1));
565 fontstyleCO->setCurrentIndex(n);
568 int n = findToken(font_sizes, size.substr(1));
570 fontsizeCO->setCurrentIndex(n);
574 } else if (prefixIs(*it, "breaklines=")) {
575 breaklinesCB->setChecked(contains(*it, "true"));
577 } else if (prefixIs(*it, "showspaces=")) {
578 spaceCB->setChecked(contains(*it, "true"));
580 } else if (prefixIs(*it, "showstringspaces=")) {
581 spaceInStringCB->setChecked(contains(*it, "true"));
583 } else if (prefixIs(*it, "extendedchars=")) {
584 extendedcharsCB->setChecked(contains(*it, "true"));
589 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
590 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
591 // parameters that can be handled by widgets are cleared
592 // the rest is put to the extra edit box.
593 string extra = getStringFromVector(pars);
594 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
598 bool GuiListings::isValid()
600 return validate_listings_params().empty();
604 bool GuiListings::initialiseParams(string const & data)
606 InsetListingsMailer::string2params(data, params_);
611 void GuiListings::clearParams()
617 void GuiListings::dispatchParams()
619 string const lfun = InsetListingsMailer::params2string(params_);
620 dispatch(FuncRequest(getLfun(), lfun));
624 void GuiListings::setParams(InsetListingsParams const & params)
630 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
633 } // namespace frontend
637 #include "GuiListings_moc.cpp"