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"
19 #include "BufferParams.h"
20 #include "FuncRequest.h"
22 #include "insets/InsetListings.h"
23 #include "insets/InsetListingsParams.h"
25 #include "support/convert.h"
26 #include "support/debug.h"
27 #include "support/gettext.h"
28 #include "support/lstrings.h"
31 #include <QPushButton>
33 #include <QRegExpValidator>
36 using namespace lyx::support;
42 /////////////////////////////////////////////////////////////////////
46 /////////////////////////////////////////////////////////////////////
49 char const * languages_supported[] =
50 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
51 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
52 "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
53 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
54 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
55 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
56 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
57 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
58 "VRML", "XML", "XSLT", "" };
61 char const * languages_gui[] =
62 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
63 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
64 "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
65 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
66 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
67 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
68 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
69 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
70 "VRML", "XML", "XSLT", "" };
76 /// the associated language
77 char const * language;
78 /// representation of the dialect in the gui
80 /// is this the default dialect?
85 dialect_info const dialects[] = {
86 { "R/2 4.3", "ABAP", "R/2 4.3", false },
87 { "R/2 5.0", "ABAP", "R/2 5.0", false },
88 { "R/3 3.1", "ABAP", "R/3 3.1", false },
89 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
90 { "R/3 6.10", "ABAP", "R/3 6.10", true },
91 { "2005", "Ada", "2005", true },
92 { "83", "Ada", "83", false },
93 { "95", "Ada", "95", false },
94 { "60", "Algol", "60", false },
95 { "68", "Algol", "68", true },
96 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
97 { "x86masm", "Assembler", "x86 (MASM)", false },
98 { "gnu", "Awk", "gnu", true },
99 { "POSIX", "Awk", "POSIX", false },
100 { "Visual", "Basic", "Visual", false },
101 { "ANSI", "C", "ANSI", true },
102 { "Handel", "C", "Handel", false },
103 { "Objective", "C", "Objective", false },
104 { "Sharp", "C", "Sharp", false },
105 { "ANSI", "C++", "ANSI", false },
106 { "GNU", "C++", "GNU", false },
107 { "ISO", "C++", "ISO", true },
108 { "Visual", "C++", "Visual", false },
109 { "light", "Caml", "light", true },
110 { "Objective", "Caml", "Objective", false },
111 { "1974", "Cobol", "1974", false },
112 { "1985", "Cobol", "1985", true },
113 { "ibm", "Cobol", "IBM", false },
114 { "WinXP", "command.com", "Windows XP", true },
115 { "77", "Fortran", "77", false },
116 { "90", "Fortran", "90", false },
117 { "95", "Fortran", "95", true },
118 { "CORBA", "IDL", "CORBA", false },
119 { "AspectJ", "Java", "Aspect J", false },
120 { "Auto", "Lisp", "Auto", false },
121 { "gnu", "make", "gnu", false },
122 { "1.0", "Mathematica", "1.0", false },
123 { "3.0", "Mathematica", "3.0", false },
124 { "5.2", "Mathematica", "5.2", true },
125 { "decorative", "OCL", "decorative", false },
126 { "OMG", "OCL", "OMG", true },
127 { "Borland6", "Pascal", "Borland 6", false },
128 { "Standard", "Pascal", "Standard", true },
129 { "XSC", "Pascal", "XSC", false },
130 { "PLUS", "S", "PLUS", false },
131 { "67", "Simula", "67", true },
132 { "CII", "Simula", "CII", false },
133 { "DEC", "Simula", "DEC", false },
134 { "IBM", "Simula", "IBM", false },
135 { "tk", "tcl", "tk", false },
136 { "AlLaTeX", "TeX", "AlLaTeX", false },
137 { "common", "TeX", "common", false },
138 { "LaTeX", "TeX", "LaTeX", false },
139 { "plain", "TeX", "plain", true },
140 { "primitive", "TeX", "primitive", false },
141 { "AMS", "VHDL", "AMS", false },
142 { "97", "VRML", "97", true }
146 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
149 char const * font_sizes[] =
150 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
153 char const * font_sizes_gui[] =
154 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
155 N_("Large"), N_("Larger"), "" };
157 char const * font_styles[] =
158 { "default", "rmfamily", "ttfamily", "sffamily", "" };
160 char const * font_styles_gui[] =
161 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
165 GuiListings::GuiListings(GuiView & lv)
166 : GuiDialog(lv, "listings", qt_("Program Listing Settings"))
170 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
171 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
172 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
174 connect(languageCO, SIGNAL(currentIndexChanged(int)),
175 this, SLOT(change_adaptor()));
176 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
177 this, SLOT(change_adaptor()));
178 connect(inlineCB, SIGNAL(clicked()),
179 this, SLOT(change_adaptor()));
180 connect(floatCB, SIGNAL(clicked()),
181 this, SLOT(change_adaptor()));
182 connect(placementLE, SIGNAL(textChanged(QString)),
183 this, SLOT(change_adaptor()));
184 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
185 this, SLOT(change_adaptor()));
186 connect(numberStepLE, SIGNAL(textChanged(QString)),
187 this, SLOT(change_adaptor()));
188 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
189 this, SLOT(change_adaptor()));
190 connect(firstlineLE, SIGNAL(textChanged(QString)),
191 this, SLOT(change_adaptor()));
192 connect(lastlineLE, SIGNAL(textChanged(QString)),
193 this, SLOT(change_adaptor()));
194 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
195 this, SLOT(change_adaptor()));
196 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
197 this, SLOT(change_adaptor()));
198 connect(breaklinesCB, SIGNAL(clicked()),
199 this, SLOT(change_adaptor()));
200 connect(spaceCB, SIGNAL(clicked()),
201 this, SLOT(change_adaptor()));
202 connect(spaceInStringCB, SIGNAL(clicked()),
203 this, SLOT(change_adaptor()));
204 connect(tabsizeSB, SIGNAL(valueChanged(int)),
205 this, SLOT(change_adaptor()));
206 connect(extendedcharsCB, SIGNAL(clicked()),
207 this, SLOT(change_adaptor()));
209 connect(listingsED, SIGNAL(textChanged()),
210 this, SLOT(change_adaptor()));
211 connect(listingsED, SIGNAL(textChanged()),
212 this, SLOT(setListingsMsg()));
213 connect(bypassCB, SIGNAL(clicked()),
214 this, SLOT(change_adaptor()));
215 connect(bypassCB, SIGNAL(clicked()),
216 this, SLOT(setListingsMsg()));
218 for (int n = 0; languages_supported[n][0]; ++n)
219 languageCO->addItem(qt_(languages_gui[n]));
221 for (int n = 0; font_styles[n][0]; ++n)
222 fontstyleCO->addItem(qt_(font_styles_gui[n]));
224 for (int n = 0; font_sizes[n][0]; ++n) {
225 QString font = qt_(font_sizes_gui[n]);
226 fontsizeCO->addItem(font);
227 numberFontSizeCO->addItem(font);
231 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
232 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
233 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
234 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
236 bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
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::change_adaptor()
254 string GuiListings::construct_params()
256 string language = languages_supported[qMax(0, languageCO->currentIndex())];
258 string const dialect_gui = fromqstr(dialectCO->currentText());
259 if (dialectCO->currentIndex() > 0) {
260 for (size_t i = 0; i != nr_dialects; ++i) {
261 if (dialect_gui == dialects[i].gui
262 && dialects[i].language == language
263 && !dialects[i].is_default) {
264 dialect = dialects[i].dialect;
270 bool float_ = floatCB->isChecked();
272 if (placementLE->isEnabled())
273 placement = fromqstr(placementLE->text());
276 switch (qMax(0, numberSideCO->currentIndex())) {
284 numberSide = "right";
290 string stepnumber = fromqstr(numberStepLE->text());
291 string numberfontsize = font_sizes[qMax(0, numberFontSizeCO->currentIndex())];
292 string firstline = fromqstr(firstlineLE->text());
293 string lastline = fromqstr(lastlineLE->text());
295 string fontsize = font_sizes[qMax(0, fontsizeCO->currentIndex())];
296 string fontstyle = font_styles[qMax(0, fontstyleCO->currentIndex())];
299 bool const use_minted = buffer().params().use_minted;
300 if (fontsize != "default") {
302 mintedsize = "\\" + fontsize;
304 basicstyle = "\\" + fontsize;
306 if (fontstyle != "default") {
308 basicstyle = fontstyle.substr(0, 2);
310 basicstyle += "\\" + fontstyle;
312 bool breakline = breaklinesCB->isChecked();
313 bool space = spaceCB->isChecked();
314 int tabsize = tabsizeSB->value();
315 bool spaceInString = spaceInStringCB->isChecked();
316 bool extendedchars = extendedcharsCB->isChecked();
317 string extra = fromqstr(listingsED->toPlainText());
320 InsetListingsParams par;
321 par.setMinted(use_minted);
323 if (language == "no language" && !contains(extra, "language="))
324 par.addParam("language", "TeX");
326 par.addParam("language", language);
327 } else if (language != "no language" && !contains(extra, "language=")) {
329 par.addParam("language", language);
331 par.addParam("language", "{[" + dialect + "]" + language + "}");
333 // this dialog uses float=placement instead of float,floatplacement=placement
334 // because float accepts *tbph and floatplacement accepts bph.
335 // our placement textedit is actually for the float parameter
337 par.addParam("float", placement);
338 if (numberSide != "none")
339 par.addParam("numbers", numberSide);
340 if (numberfontsize != "default" && numberSide != "none" && !use_minted)
341 par.addParam("numberstyle", "\\" + numberfontsize);
342 if (!stepnumber.empty() && numberSide != "none")
343 par.addParam("stepnumber", stepnumber);
344 if (!firstline.empty())
345 par.addParam("firstline", firstline);
346 if (!lastline.empty())
347 par.addParam("lastline", lastline);
348 if (!basicstyle.empty())
349 par.addParam(use_minted ? "fontfamily" : "basicstyle", basicstyle);
350 if (!mintedsize.empty())
351 par.addParam("fontsize", mintedsize);
353 par.addParam("breaklines", "true");
355 par.addParam("showspaces", "true");
356 if (!spaceInString && !use_minted)
357 par.addParam("showstringspaces", "false");
359 par.addParam("tabsize", convert<string>(tabsize));
360 if (extendedchars && !use_minted)
361 par.addParam("extendedchars", "true");
362 par.addParams(extra);
367 docstring GuiListings::validate_listings_params()
369 if (bypassCB->isChecked())
371 return InsetListingsParams(construct_params()).validate();
375 void GuiListings::setListingsMsg()
378 static bool isOK = true;
379 docstring msg = validate_listings_params();
384 listingsTB->setPlainText(
385 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
388 listingsTB->setPlainText(toqstr(msg));
393 void GuiListings::on_floatCB_stateChanged(int state)
395 if (state == Qt::Checked) {
396 inlineCB->setChecked(false);
397 placementLE->setEnabled(true);
399 placementLE->setEnabled(false);
403 void GuiListings::on_inlineCB_stateChanged(int state)
405 if (state == Qt::Checked) {
406 floatCB->setChecked(false);
407 placementLE->setEnabled(false);
412 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
414 numberStepLE->setEnabled(index > 0);
415 numberFontSizeCO->setEnabled(index > 0);
419 void GuiListings::on_languageCO_currentIndexChanged(int index)
423 int default_dialect = 0;
424 dialectCO->addItem(qt_("No dialect"));
425 string const language = languages_supported[index];
427 for (size_t i = 0; i != nr_dialects; ++i) {
428 if (language == dialects[i].language) {
429 dialectCO->addItem(qt_(dialects[i].gui));
430 if (dialects[i].is_default)
432 dialectCO->findText(qt_(dialects[i].gui));
435 dialectCO->setCurrentIndex(default_dialect);
436 dialectCO->setEnabled(dialectCO->count() > 1);
440 void GuiListings::applyView()
442 params_.setMinted(buffer().params().use_minted);
443 params_.setInline(inlineCB->isChecked());
444 params_.setParams(construct_params());
448 static string plainParam(string const & par)
450 // remove enclosing braces
451 if (prefixIs(par, "{") && suffixIs(par, "}"))
452 return par.substr(1, par.size() - 2);
457 void GuiListings::updateContents()
459 bool const use_minted = buffer().params().use_minted;
460 // set default values
461 listingsTB->setPlainText(
462 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
463 languageCO->setCurrentIndex(findToken(languages_supported, "no language"));
464 dialectCO->setCurrentIndex(0);
465 floatCB->setChecked(false);
466 placementLE->clear();
467 numberSideCO->setCurrentIndex(0);
468 numberStepLE->clear();
469 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
470 firstlineLE->clear();
472 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
473 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
474 breaklinesCB->setChecked(false);
475 spaceCB->setChecked(false);
476 spaceInStringCB->setChecked(true);
477 tabsizeSB->setValue(8);
478 extendedcharsCB->setChecked(false);
480 // set values from param string
481 inlineCB->setChecked(params_.isInline());
482 if (params_.isInline()) {
483 floatCB->setChecked(false);
484 placementLE->setEnabled(false);
486 // break other parameters and set values
487 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
488 // process each of them
489 for (vector<string>::iterator it = pars.begin();
490 it != pars.end(); ++it) {
491 if (prefixIs(*it, "language=")) {
492 string arg = plainParam(it->substr(9));
497 if (prefixIs(arg, "[") && contains(arg, "]")) {
498 size_t end_dialect = arg.find("]");
499 dialect = arg.substr(1, end_dialect - 1);
500 language = arg.substr(end_dialect + 1);
504 int n = findToken(languages_supported, language);
506 languageCO->setCurrentIndex(n);
509 // on_languageCO_currentIndexChanged should have set dialects
510 if (!dialect.empty()) {
512 for (size_t i = 0; i != nr_dialects; ++i) {
513 if (dialect == dialects[i].dialect
514 && dialects[i].language == language) {
515 dialect_gui = dialects[i].gui;
519 n = dialectCO->findText(qt_(dialect_gui));
521 dialectCO->setCurrentIndex(n);
527 languageCO->setEnabled(in_gui);
528 dialectCO->setEnabled(!use_minted &&
529 in_gui && dialectCO->count() > 1);
530 } else if (prefixIs(*it, "float")) {
531 floatCB->setChecked(true);
532 inlineCB->setChecked(false);
533 placementLE->setEnabled(true);
534 if (prefixIs(*it, "float="))
535 placementLE->setText(
536 toqstr(plainParam(it->substr(6))));
538 } else if (prefixIs(*it, "numbers=")) {
539 string s = plainParam(it->substr(8));
543 else if (s == "right")
545 numberSideCO->setCurrentIndex(n);
547 } else if (prefixIs(*it, "stepnumber=")) {
548 numberStepLE->setText(
549 toqstr(plainParam(it->substr(11))));
551 } else if (prefixIs(*it, "numberstyle=")) {
552 string par = plainParam(it->substr(12));
553 int n = findToken(font_sizes, par.substr(1));
555 numberFontSizeCO->setCurrentIndex(n);
557 } else if (prefixIs(*it, "firstline=")) {
558 firstlineLE->setText(
559 toqstr(plainParam(it->substr(10))));
561 } else if (prefixIs(*it, "lastline=")) {
563 toqstr(plainParam(it->substr(9))));
565 } else if (prefixIs(*it, "basicstyle=")) {
568 for (int n = 0; font_styles[n][0]; ++n) {
569 string const s = font_styles[n];
570 if (contains(*it, "\\" + s)) {
575 for (int n = 0; font_sizes[n][0]; ++n) {
576 string const s = font_sizes[n];
577 if (contains(*it, "\\" + s)) {
582 if (plainParam(it->substr(11)) == style + size
583 || plainParam(it->substr(11)) == size + style) {
584 if (!style.empty()) {
585 int n = findToken(font_styles, style.substr(1));
587 fontstyleCO->setCurrentIndex(n);
590 int n = findToken(font_sizes, size.substr(1));
592 fontsizeCO->setCurrentIndex(n);
596 } else if (prefixIs(*it, "fontsize=")) {
598 for (int n = 0; font_sizes[n][0]; ++n) {
599 string const s = font_sizes[n];
600 if (contains(*it, "\\" + s)) {
606 int n = findToken(font_sizes, size.substr(1));
608 fontsizeCO->setCurrentIndex(n);
611 } else if (prefixIs(*it, "fontfamily=")) {
613 for (int n = 0; font_styles[n][0]; ++n) {
614 string const s = font_styles[n];
615 if (contains(*it, "=" + s.substr(0,2))) {
620 if (!style.empty()) {
621 int n = findToken(font_styles, style.substr(1));
623 fontstyleCO->setCurrentIndex(n);
626 } else if (prefixIs(*it, "breaklines=")) {
627 breaklinesCB->setChecked(contains(*it, "true"));
629 } else if (prefixIs(*it, "showspaces=")) {
630 spaceCB->setChecked(contains(*it, "true"));
632 } else if (prefixIs(*it, "showstringspaces=")) {
633 spaceInStringCB->setChecked(contains(*it, "true"));
635 } else if (prefixIs(*it, "tabsize=")) {
636 tabsizeSB->setValue(convert<int>(plainParam(it->substr(8))));
638 } else if (prefixIs(*it, "extendedchars=")) {
639 extendedcharsCB->setChecked(contains(*it, "true"));
644 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
645 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0
647 spaceInStringCB->setEnabled(!use_minted);
648 extendedcharsCB->setEnabled(!use_minted);
649 // parameters that can be handled by widgets are cleared
650 // the rest is put to the extra edit box.
651 string extra = getStringFromVector(pars);
652 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
653 params_.setMinted(use_minted);
657 bool GuiListings::isValid()
659 return validate_listings_params().empty();
663 bool GuiListings::initialiseParams(string const & data)
665 InsetListings::string2params(data, params_);
670 void GuiListings::clearParams()
673 params_.setMinted(buffer().params().use_minted);
677 void GuiListings::dispatchParams()
679 string const lfun = InsetListings::params2string(params_);
680 dispatch(FuncRequest(getLfun(), lfun));
684 void GuiListings::setParams(InsetListingsParams const & params)
687 params_.setMinted(buffer().params().use_minted);
691 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
694 } // namespace frontend
698 #include "moc_GuiListings.cpp"