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/convert.h"
24 #include "support/debug.h"
25 #include "support/gettext.h"
26 #include "support/lstrings.h"
29 #include <QPushButton>
31 #include <QRegExpValidator>
34 using namespace lyx::support;
40 /////////////////////////////////////////////////////////////////////
44 /////////////////////////////////////////////////////////////////////
47 char const * languages_supported[] =
48 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
49 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
50 "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
51 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
52 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
53 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
54 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
55 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
56 "VRML", "XML", "XSLT", "" };
59 char const * languages_gui[] =
60 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
61 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
62 "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
63 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
64 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
65 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
66 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
67 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
68 "VRML", "XML", "XSLT", "" };
74 /// the associated language
75 char const * language;
76 /// representation of the dialect in the gui
78 /// is this the default dialect?
83 dialect_info const dialects[] = {
84 { "R/2 4.3", "ABAP", "R/2 4.3", false },
85 { "R/2 5.0", "ABAP", "R/2 5.0", false },
86 { "R/3 3.1", "ABAP", "R/3 3.1", false },
87 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
88 { "R/3 6.10", "ABAP", "R/3 6.10", true },
89 { "2005", "Ada", "2005", true },
90 { "83", "Ada", "83", false },
91 { "95", "Ada", "95", false },
92 { "60", "Algol", "60", false },
93 { "68", "Algol", "68", true },
94 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
95 { "x86masm", "Assembler", "x86 (MASM)", false },
96 { "gnu", "Awk", "gnu", true },
97 { "POSIX", "Awk", "POSIX", false },
98 { "Visual", "Basic", "Visual", false },
99 { "ANSI", "C", "ANSI", true },
100 { "Handel", "C", "Handel", false },
101 { "Objective", "C", "Objective", false },
102 { "Sharp", "C", "Sharp", false },
103 { "ANSI", "C++", "ANSI", false },
104 { "GNU", "C++", "GNU", false },
105 { "ISO", "C++", "ISO", true },
106 { "Visual", "C++", "Visual", false },
107 { "light", "Caml", "light", true },
108 { "Objective", "Caml", "Objective", false },
109 { "1974", "Cobol", "1974", false },
110 { "1985", "Cobol", "1985", true },
111 { "ibm", "Cobol", "IBM", false },
112 { "WinXP", "command.com", "Windows XP", true },
113 { "77", "Fortran", "77", false },
114 { "90", "Fortran", "90", false },
115 { "95", "Fortran", "95", true },
116 { "CORBA", "IDL", "CORBA", false },
117 { "AspectJ", "Java", "Aspect J", false },
118 { "Auto", "Lisp", "Auto", false },
119 { "gnu", "make", "gnu", false },
120 { "1.0", "Mathematica", "1.0", false },
121 { "3.0", "Mathematica", "3.0", false },
122 { "5.2", "Mathematica", "5.2", true },
123 { "decorative", "OCL", "decorative", false },
124 { "OMG", "OCL", "OMG", true },
125 { "Borland6", "Pascal", "Borland 6", false },
126 { "Standard", "Pascal", "Standard", true },
127 { "XSC", "Pascal", "XSC", false },
128 { "PLUS", "S", "PLUS", false },
129 { "67", "Simula", "67", true },
130 { "CII", "Simula", "CII", false },
131 { "DEC", "Simula", "DEC", false },
132 { "IBM", "Simula", "IBM", false },
133 { "tk", "tcl", "tk", false },
134 { "AlLaTeX", "TeX", "AlLaTeX", false },
135 { "common", "TeX", "common", false },
136 { "LaTeX", "TeX", "LaTeX", false },
137 { "plain", "TeX", "plain", true },
138 { "primitive", "TeX", "primitive", false },
139 { "AMS", "VHDL", "AMS", false },
140 { "97", "VRML", "97", true }
144 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
147 char const * font_sizes[] =
148 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
151 char const * font_sizes_gui[] =
152 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
153 N_("Large"), N_("Larger"), "" };
155 char const * font_styles[] =
156 { "default", "rmfamily", "ttfamily", "sffamily", "" };
158 char const * font_styles_gui[] =
159 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
163 GuiListings::GuiListings(GuiView & lv)
164 : GuiDialog(lv, "listings", qt_("Program Listing Settings"))
168 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
169 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
170 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
172 connect(languageCO, SIGNAL(currentIndexChanged(int)),
173 this, SLOT(change_adaptor()));
174 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
175 this, SLOT(change_adaptor()));
176 connect(inlineCB, SIGNAL(clicked()),
177 this, SLOT(change_adaptor()));
178 connect(floatCB, SIGNAL(clicked()),
179 this, SLOT(change_adaptor()));
180 connect(placementLE, SIGNAL(textChanged(QString)),
181 this, SLOT(change_adaptor()));
182 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
183 this, SLOT(change_adaptor()));
184 connect(numberStepLE, SIGNAL(textChanged(QString)),
185 this, SLOT(change_adaptor()));
186 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
187 this, SLOT(change_adaptor()));
188 connect(firstlineLE, SIGNAL(textChanged(QString)),
189 this, SLOT(change_adaptor()));
190 connect(lastlineLE, SIGNAL(textChanged(QString)),
191 this, SLOT(change_adaptor()));
192 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
193 this, SLOT(change_adaptor()));
194 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
195 this, SLOT(change_adaptor()));
196 connect(breaklinesCB, SIGNAL(clicked()),
197 this, SLOT(change_adaptor()));
198 connect(spaceCB, SIGNAL(clicked()),
199 this, SLOT(change_adaptor()));
200 connect(spaceInStringCB, SIGNAL(clicked()),
201 this, SLOT(change_adaptor()));
202 connect(tabsizeSB, SIGNAL(valueChanged(int)),
203 this, SLOT(change_adaptor()));
204 connect(extendedcharsCB, SIGNAL(clicked()),
205 this, SLOT(change_adaptor()));
207 connect(listingsED, SIGNAL(textChanged()),
208 this, SLOT(change_adaptor()));
209 connect(listingsED, SIGNAL(textChanged()),
210 this, SLOT(setListingsMsg()));
211 connect(bypassCB, SIGNAL(clicked()),
212 this, SLOT(change_adaptor()));
213 connect(bypassCB, SIGNAL(clicked()),
214 this, SLOT(setListingsMsg()));
216 for (int n = 0; languages_supported[n][0]; ++n)
217 languageCO->addItem(qt_(languages_gui[n]));
219 for (int n = 0; font_styles[n][0]; ++n)
220 fontstyleCO->addItem(qt_(font_styles_gui[n]));
222 for (int n = 0; font_sizes[n][0]; ++n) {
223 QString font = qt_(font_sizes_gui[n]);
224 fontsizeCO->addItem(font);
225 numberFontSizeCO->addItem(font);
229 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
230 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
231 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
232 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
234 bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
236 bc().setApply(applyPB);
237 bc().setCancel(closePB);
238 listingsTB->setPlainText(
239 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
246 void GuiListings::change_adaptor()
252 string GuiListings::construct_params()
254 string language = languages_supported[qMax(0, languageCO->currentIndex())];
256 string const dialect_gui = fromqstr(dialectCO->currentText());
257 if (dialectCO->currentIndex() > 0) {
258 for (size_t i = 0; i != nr_dialects; ++i) {
259 if (dialect_gui == dialects[i].gui
260 && dialects[i].language == language
261 && !dialects[i].is_default) {
262 dialect = dialects[i].dialect;
268 bool float_ = floatCB->isChecked();
270 if (placementLE->isEnabled())
271 placement = fromqstr(placementLE->text());
274 switch (qMax(0, numberSideCO->currentIndex())) {
282 numberSide = "right";
288 string stepnumber = fromqstr(numberStepLE->text());
289 string numberfontsize = font_sizes[qMax(0, numberFontSizeCO->currentIndex())];
290 string firstline = fromqstr(firstlineLE->text());
291 string lastline = fromqstr(lastlineLE->text());
293 string fontsize = font_sizes[qMax(0, fontsizeCO->currentIndex())];
294 string fontstyle = font_styles[qMax(0, fontstyleCO->currentIndex())];
296 if (fontsize != "default")
297 basicstyle = "\\" + fontsize;
298 if (fontstyle != "default")
299 basicstyle += "\\" + fontstyle;
300 bool breakline = breaklinesCB->isChecked();
301 bool space = spaceCB->isChecked();
302 int tabsize = tabsizeSB->value();
303 bool spaceInString = spaceInStringCB->isChecked();
304 bool extendedchars = extendedcharsCB->isChecked();
305 string extra = fromqstr(listingsED->toPlainText());
308 InsetListingsParams par;
309 if (language != "no language" && !contains(extra, "language=")) {
311 par.addParam("language", language);
313 par.addParam("language", "{[" + dialect + "]" + language + "}");
315 // this dialog uses float=placement instead of float,floatplacement=placement
316 // because float accepts *tbph and floatplacement accepts bph.
317 // our placement textedit is actually for the float parameter
319 par.addParam("float", placement);
320 if (numberSide != "none")
321 par.addParam("numbers", numberSide);
322 if (numberfontsize != "default" && numberSide != "none")
323 par.addParam("numberstyle", "\\" + numberfontsize);
324 if (!stepnumber.empty() && numberSide != "none")
325 par.addParam("stepnumber", stepnumber);
326 if (!firstline.empty())
327 par.addParam("firstline", firstline);
328 if (!lastline.empty())
329 par.addParam("lastline", lastline);
330 if (!basicstyle.empty())
331 par.addParam("basicstyle", basicstyle);
333 par.addParam("breaklines", "true");
335 par.addParam("showspaces", "true");
337 par.addParam("showstringspaces", "false");
339 par.addParam("tabsize", convert<string>(tabsize));
341 par.addParam("extendedchars", "true");
342 par.addParams(extra);
347 docstring GuiListings::validate_listings_params()
349 if (bypassCB->isChecked())
351 return InsetListingsParams(construct_params()).validate();
355 void GuiListings::setListingsMsg()
358 static bool isOK = true;
359 docstring msg = validate_listings_params();
364 listingsTB->setPlainText(
365 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
368 listingsTB->setPlainText(toqstr(msg));
373 void GuiListings::on_floatCB_stateChanged(int state)
375 if (state == Qt::Checked) {
376 inlineCB->setChecked(false);
377 placementLE->setEnabled(true);
379 placementLE->setEnabled(false);
383 void GuiListings::on_inlineCB_stateChanged(int state)
385 if (state == Qt::Checked) {
386 floatCB->setChecked(false);
387 placementLE->setEnabled(false);
392 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
394 numberStepLE->setEnabled(index > 0);
395 numberFontSizeCO->setEnabled(index > 0);
399 void GuiListings::on_languageCO_currentIndexChanged(int index)
403 int default_dialect = 0;
404 dialectCO->addItem(qt_("No dialect"));
405 string const language = languages_supported[index];
407 for (size_t i = 0; i != nr_dialects; ++i) {
408 if (language == dialects[i].language) {
409 dialectCO->addItem(qt_(dialects[i].gui));
410 if (dialects[i].is_default)
412 dialectCO->findText(qt_(dialects[i].gui));
415 dialectCO->setCurrentIndex(default_dialect);
416 dialectCO->setEnabled(dialectCO->count() > 1);
420 void GuiListings::applyView()
422 params_.setInline(inlineCB->isChecked());
423 params_.setParams(construct_params());
427 static string plainParam(string const & par)
429 // remove enclosing braces
430 if (prefixIs(par, "{") && suffixIs(par, "}"))
431 return par.substr(1, par.size() - 2);
436 void GuiListings::updateContents()
438 // set default values
439 listingsTB->setPlainText(
440 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
441 languageCO->setCurrentIndex(findToken(languages_supported, "no language"));
442 dialectCO->setCurrentIndex(0);
443 floatCB->setChecked(false);
444 placementLE->clear();
445 numberSideCO->setCurrentIndex(0);
446 numberStepLE->clear();
447 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
448 firstlineLE->clear();
450 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
451 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
452 breaklinesCB->setChecked(false);
453 spaceCB->setChecked(false);
454 spaceInStringCB->setChecked(true);
455 tabsizeSB->setValue(8);
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_supported, 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, "tabsize=")) {
584 tabsizeSB->setValue(convert<int>(plainParam(it->substr(8))));
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 "moc_GuiListings.cpp"