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(buttonBox, SIGNAL(clicked(QAbstractButton *)),
171 this, SLOT(slotButtonBox(QAbstractButton *)));
173 connect(languageCO, SIGNAL(currentIndexChanged(int)),
174 this, SLOT(change_adaptor()));
175 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
176 this, SLOT(change_adaptor()));
177 connect(inlineCB, SIGNAL(clicked()),
178 this, SLOT(change_adaptor()));
179 connect(floatCB, SIGNAL(clicked()),
180 this, SLOT(change_adaptor()));
181 connect(placementLE, SIGNAL(textChanged(QString)),
182 this, SLOT(change_adaptor()));
183 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
184 this, SLOT(change_adaptor()));
185 connect(numberStepLE, SIGNAL(textChanged(QString)),
186 this, SLOT(change_adaptor()));
187 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
188 this, SLOT(change_adaptor()));
189 connect(firstlineLE, SIGNAL(textChanged(QString)),
190 this, SLOT(change_adaptor()));
191 connect(lastlineLE, SIGNAL(textChanged(QString)),
192 this, SLOT(change_adaptor()));
193 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
194 this, SLOT(change_adaptor()));
195 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
196 this, SLOT(change_adaptor()));
197 connect(breaklinesCB, SIGNAL(clicked()),
198 this, SLOT(change_adaptor()));
199 connect(spaceCB, SIGNAL(clicked()),
200 this, SLOT(change_adaptor()));
201 connect(spaceInStringCB, SIGNAL(clicked()),
202 this, SLOT(change_adaptor()));
203 connect(tabsizeSB, SIGNAL(valueChanged(int)),
204 this, SLOT(change_adaptor()));
205 connect(extendedcharsCB, SIGNAL(clicked()),
206 this, SLOT(change_adaptor()));
208 connect(listingsED, SIGNAL(textChanged()),
209 this, SLOT(change_adaptor()));
210 connect(listingsED, SIGNAL(textChanged()),
211 this, SLOT(setListingsMsg()));
212 connect(bypassCB, SIGNAL(clicked()),
213 this, SLOT(change_adaptor()));
214 connect(bypassCB, SIGNAL(clicked()),
215 this, SLOT(setListingsMsg()));
217 for (int n = 0; languages_supported[n][0]; ++n)
218 languageCO->addItem(qt_(languages_gui[n]));
220 for (int n = 0; font_styles[n][0]; ++n)
221 fontstyleCO->addItem(qt_(font_styles_gui[n]));
223 for (int n = 0; font_sizes[n][0]; ++n) {
224 QString font = qt_(font_sizes_gui[n]);
225 fontsizeCO->addItem(font);
226 numberFontSizeCO->addItem(font);
230 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
231 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
232 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
233 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
235 bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
236 bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
237 bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
238 bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
239 listingsTB->setPlainText(
240 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
247 void GuiListings::change_adaptor()
253 string GuiListings::construct_params()
255 string language = languages_supported[qMax(0, languageCO->currentIndex())];
257 string const dialect_gui = fromqstr(dialectCO->currentText());
258 if (dialectCO->currentIndex() > 0) {
259 for (size_t i = 0; i != nr_dialects; ++i) {
260 if (dialect_gui == dialects[i].gui
261 && dialects[i].language == language
262 && !dialects[i].is_default) {
263 dialect = dialects[i].dialect;
269 bool float_ = floatCB->isChecked();
271 if (placementLE->isEnabled())
272 placement = fromqstr(placementLE->text());
275 switch (qMax(0, numberSideCO->currentIndex())) {
283 numberSide = "right";
289 string stepnumber = fromqstr(numberStepLE->text());
290 string numberfontsize = font_sizes[qMax(0, numberFontSizeCO->currentIndex())];
291 string firstline = fromqstr(firstlineLE->text());
292 string lastline = fromqstr(lastlineLE->text());
294 string fontsize = font_sizes[qMax(0, fontsizeCO->currentIndex())];
295 string fontstyle = font_styles[qMax(0, fontstyleCO->currentIndex())];
298 bool const use_minted = buffer().params().use_minted;
299 if (fontsize != "default") {
301 mintedsize = "\\" + fontsize;
303 basicstyle = "\\" + fontsize;
305 if (fontstyle != "default") {
307 basicstyle = fontstyle.substr(0, 2);
309 basicstyle += "\\" + fontstyle;
311 bool breakline = breaklinesCB->isChecked();
312 bool space = spaceCB->isChecked();
313 int tabsize = tabsizeSB->value();
314 bool spaceInString = spaceInStringCB->isChecked();
315 bool extendedchars = extendedcharsCB->isChecked();
316 string extra = fromqstr(listingsED->toPlainText());
319 InsetListingsParams par;
320 par.setMinted(use_minted);
322 if (language == "no language" && !contains(extra, "language="))
323 par.addParam("language", "TeX");
325 par.addParam("language", language);
326 } else if (language != "no language" && !contains(extra, "language=")) {
328 par.addParam("language", language);
330 par.addParam("language", "{[" + dialect + "]" + language + "}");
332 // this dialog uses float=placement instead of float,floatplacement=placement
333 // because float accepts *tbph and floatplacement accepts bph.
334 // our placement textedit is actually for the float parameter
336 par.addParam("float", placement);
337 if (numberSide != "none")
338 par.addParam("numbers", numberSide);
339 if (numberfontsize != "default" && numberSide != "none" && !use_minted)
340 par.addParam("numberstyle", "\\" + numberfontsize);
341 if (!stepnumber.empty() && numberSide != "none")
342 par.addParam("stepnumber", stepnumber);
343 if (!firstline.empty())
344 par.addParam("firstline", firstline);
345 if (!lastline.empty())
346 par.addParam("lastline", lastline);
347 if (!basicstyle.empty())
348 par.addParam(use_minted ? "fontfamily" : "basicstyle", basicstyle);
349 if (!mintedsize.empty())
350 par.addParam("fontsize", mintedsize);
352 par.addParam("breaklines", "true");
354 par.addParam("showspaces", "true");
355 if (!spaceInString && !use_minted)
356 par.addParam("showstringspaces", "false");
358 par.addParam("tabsize", convert<string>(tabsize));
359 if (extendedchars && !use_minted)
360 par.addParam("extendedchars", "true");
361 par.addParams(extra);
366 docstring GuiListings::validate_listings_params()
368 if (bypassCB->isChecked())
370 return InsetListingsParams(construct_params()).validate();
374 void GuiListings::setListingsMsg()
377 static bool isOK = true;
378 docstring msg = validate_listings_params();
383 listingsTB->setPlainText(
384 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
387 listingsTB->setPlainText(toqstr(msg));
392 void GuiListings::on_floatCB_stateChanged(int state)
394 if (state == Qt::Checked) {
395 inlineCB->setChecked(false);
396 placementLE->setEnabled(true);
398 placementLE->setEnabled(false);
402 void GuiListings::on_inlineCB_stateChanged(int state)
404 if (state == Qt::Checked) {
405 floatCB->setChecked(false);
406 placementLE->setEnabled(false);
411 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
413 numberStepLE->setEnabled(index > 0);
414 numberFontSizeCO->setEnabled(index > 0);
418 void GuiListings::on_languageCO_currentIndexChanged(int index)
422 int default_dialect = 0;
423 dialectCO->addItem(qt_("No dialect"));
424 string const language = languages_supported[index];
426 for (size_t i = 0; i != nr_dialects; ++i) {
427 if (language == dialects[i].language) {
428 dialectCO->addItem(qt_(dialects[i].gui));
429 if (dialects[i].is_default)
431 dialectCO->findText(qt_(dialects[i].gui));
434 dialectCO->setCurrentIndex(default_dialect);
435 dialectCO->setEnabled(dialectCO->count() > 1
436 && !buffer().params().use_minted);
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 & sdata)
665 InsetListings::string2params(sdata, 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"