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
437 && !buffer().params().use_minted);
441 void GuiListings::applyView()
443 params_.setMinted(buffer().params().use_minted);
444 params_.setInline(inlineCB->isChecked());
445 params_.setParams(construct_params());
449 static string plainParam(string const & par)
451 // remove enclosing braces
452 if (prefixIs(par, "{") && suffixIs(par, "}"))
453 return par.substr(1, par.size() - 2);
458 void GuiListings::updateContents()
460 bool const use_minted = buffer().params().use_minted;
461 // set default values
462 listingsTB->setPlainText(
463 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
464 languageCO->setCurrentIndex(findToken(languages_supported, "no language"));
465 dialectCO->setCurrentIndex(0);
466 floatCB->setChecked(false);
467 placementLE->clear();
468 numberSideCO->setCurrentIndex(0);
469 numberStepLE->clear();
470 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
471 firstlineLE->clear();
473 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
474 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
475 breaklinesCB->setChecked(false);
476 spaceCB->setChecked(false);
477 spaceInStringCB->setChecked(true);
478 tabsizeSB->setValue(8);
479 extendedcharsCB->setChecked(false);
481 // set values from param string
482 inlineCB->setChecked(params_.isInline());
483 if (params_.isInline()) {
484 floatCB->setChecked(false);
485 placementLE->setEnabled(false);
487 // break other parameters and set values
488 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
489 // process each of them
490 for (vector<string>::iterator it = pars.begin();
491 it != pars.end(); ++it) {
492 if (prefixIs(*it, "language=")) {
493 string arg = plainParam(it->substr(9));
498 if (prefixIs(arg, "[") && contains(arg, "]")) {
499 size_t end_dialect = arg.find("]");
500 dialect = arg.substr(1, end_dialect - 1);
501 language = arg.substr(end_dialect + 1);
505 int n = findToken(languages_supported, language);
507 languageCO->setCurrentIndex(n);
510 // on_languageCO_currentIndexChanged should have set dialects
511 if (!dialect.empty()) {
513 for (size_t i = 0; i != nr_dialects; ++i) {
514 if (dialect == dialects[i].dialect
515 && dialects[i].language == language) {
516 dialect_gui = dialects[i].gui;
520 n = dialectCO->findText(qt_(dialect_gui));
522 dialectCO->setCurrentIndex(n);
528 languageCO->setEnabled(in_gui);
529 dialectCO->setEnabled(!use_minted &&
530 in_gui && dialectCO->count() > 1);
531 } else if (prefixIs(*it, "float")) {
532 floatCB->setChecked(true);
533 inlineCB->setChecked(false);
534 placementLE->setEnabled(true);
535 if (prefixIs(*it, "float="))
536 placementLE->setText(
537 toqstr(plainParam(it->substr(6))));
539 } else if (prefixIs(*it, "numbers=")) {
540 string s = plainParam(it->substr(8));
544 else if (s == "right")
546 numberSideCO->setCurrentIndex(n);
548 } else if (prefixIs(*it, "stepnumber=")) {
549 numberStepLE->setText(
550 toqstr(plainParam(it->substr(11))));
552 } else if (prefixIs(*it, "numberstyle=")) {
553 string par = plainParam(it->substr(12));
554 int n = findToken(font_sizes, par.substr(1));
556 numberFontSizeCO->setCurrentIndex(n);
558 } else if (prefixIs(*it, "firstline=")) {
559 firstlineLE->setText(
560 toqstr(plainParam(it->substr(10))));
562 } else if (prefixIs(*it, "lastline=")) {
564 toqstr(plainParam(it->substr(9))));
566 } else if (prefixIs(*it, "basicstyle=")) {
569 for (int n = 0; font_styles[n][0]; ++n) {
570 string const s = font_styles[n];
571 if (contains(*it, "\\" + s)) {
576 for (int n = 0; font_sizes[n][0]; ++n) {
577 string const s = font_sizes[n];
578 if (contains(*it, "\\" + s)) {
583 if (plainParam(it->substr(11)) == style + size
584 || plainParam(it->substr(11)) == size + style) {
585 if (!style.empty()) {
586 int n = findToken(font_styles, style.substr(1));
588 fontstyleCO->setCurrentIndex(n);
591 int n = findToken(font_sizes, size.substr(1));
593 fontsizeCO->setCurrentIndex(n);
597 } else if (prefixIs(*it, "fontsize=")) {
599 for (int n = 0; font_sizes[n][0]; ++n) {
600 string const s = font_sizes[n];
601 if (contains(*it, "\\" + s)) {
607 int n = findToken(font_sizes, size.substr(1));
609 fontsizeCO->setCurrentIndex(n);
612 } else if (prefixIs(*it, "fontfamily=")) {
614 for (int n = 0; font_styles[n][0]; ++n) {
615 string const s = font_styles[n];
616 if (contains(*it, "=" + s.substr(0,2))) {
621 if (!style.empty()) {
622 int n = findToken(font_styles, style.substr(1));
624 fontstyleCO->setCurrentIndex(n);
627 } else if (prefixIs(*it, "breaklines=")) {
628 breaklinesCB->setChecked(contains(*it, "true"));
630 } else if (prefixIs(*it, "showspaces=")) {
631 spaceCB->setChecked(contains(*it, "true"));
633 } else if (prefixIs(*it, "showstringspaces=")) {
634 spaceInStringCB->setChecked(contains(*it, "true"));
636 } else if (prefixIs(*it, "tabsize=")) {
637 tabsizeSB->setValue(convert<int>(plainParam(it->substr(8))));
639 } else if (prefixIs(*it, "extendedchars=")) {
640 extendedcharsCB->setChecked(contains(*it, "true"));
645 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
646 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0
648 spaceInStringCB->setEnabled(!use_minted);
649 extendedcharsCB->setEnabled(!use_minted);
650 // parameters that can be handled by widgets are cleared
651 // the rest is put to the extra edit box.
652 string extra = getStringFromVector(pars);
653 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
654 params_.setMinted(use_minted);
658 bool GuiListings::isValid()
660 return validate_listings_params().empty();
664 bool GuiListings::initialiseParams(string const & data)
666 InsetListings::string2params(data, params_);
671 void GuiListings::clearParams()
674 params_.setMinted(buffer().params().use_minted);
678 void GuiListings::dispatchParams()
680 string const lfun = InsetListings::params2string(params_);
681 dispatch(FuncRequest(getLfun(), lfun));
685 void GuiListings::setParams(InsetListingsParams const & params)
688 params_.setMinted(buffer().params().use_minted);
692 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
695 } // namespace frontend
699 #include "moc_GuiListings.cpp"