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 string const & blp = buffer().params().listings_params;
325 size_t start = blp.find("language=");
326 if (start != string::npos) {
327 start += strlen("language=");
328 size_t len = blp.find(",", start);
329 if (len != string::npos)
331 par.addParam("language", blp.substr(start, len));
333 par.addParam("language", "TeX");
335 par.addParam("language", language);
336 } else if (language != "no language" && !contains(extra, "language=")) {
338 par.addParam("language", language);
340 par.addParam("language", "{[" + dialect + "]" + language + "}");
342 // this dialog uses float=placement instead of float,floatplacement=placement
343 // because float accepts *tbph and floatplacement accepts bph.
344 // our placement textedit is actually for the float parameter
346 par.addParam("float", placement);
347 if (numberSide != "none")
348 par.addParam("numbers", numberSide);
349 if (numberfontsize != "default" && numberSide != "none" && !use_minted)
350 par.addParam("numberstyle", "\\" + numberfontsize);
351 if (!stepnumber.empty() && numberSide != "none")
352 par.addParam("stepnumber", stepnumber);
353 if (!firstline.empty())
354 par.addParam("firstline", firstline);
355 if (!lastline.empty())
356 par.addParam("lastline", lastline);
357 if (!basicstyle.empty())
358 par.addParam(use_minted ? "fontfamily" : "basicstyle", basicstyle);
359 if (!mintedsize.empty())
360 par.addParam("fontsize", mintedsize);
362 par.addParam("breaklines", "true");
364 par.addParam("showspaces", "true");
365 if (!spaceInString && !use_minted)
366 par.addParam("showstringspaces", "false");
368 par.addParam("tabsize", convert<string>(tabsize));
369 if (extendedchars && !use_minted)
370 par.addParam("extendedchars", "true");
371 par.addParams(extra);
376 docstring GuiListings::validate_listings_params()
378 if (bypassCB->isChecked())
380 return InsetListingsParams(construct_params()).validate();
384 void GuiListings::setListingsMsg()
387 static bool isOK = true;
388 docstring msg = validate_listings_params();
393 listingsTB->setPlainText(
394 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
397 listingsTB->setPlainText(toqstr(msg));
402 void GuiListings::on_floatCB_stateChanged(int state)
404 if (state == Qt::Checked) {
405 inlineCB->setChecked(false);
406 placementLE->setEnabled(true);
408 placementLE->setEnabled(false);
412 void GuiListings::on_inlineCB_stateChanged(int state)
414 if (state == Qt::Checked) {
415 floatCB->setChecked(false);
416 placementLE->setEnabled(false);
421 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
423 numberStepLE->setEnabled(index > 0);
424 numberFontSizeCO->setEnabled(index > 0);
428 void GuiListings::on_languageCO_currentIndexChanged(int index)
432 int default_dialect = 0;
433 dialectCO->addItem(qt_("No dialect"));
434 string const language = languages_supported[index];
436 for (size_t i = 0; i != nr_dialects; ++i) {
437 if (language == dialects[i].language) {
438 dialectCO->addItem(qt_(dialects[i].gui));
439 if (dialects[i].is_default)
441 dialectCO->findText(qt_(dialects[i].gui));
444 dialectCO->setCurrentIndex(default_dialect);
445 dialectCO->setEnabled(dialectCO->count() > 1
446 && !buffer().params().use_minted);
450 void GuiListings::applyView()
452 params_.setMinted(buffer().params().use_minted);
453 params_.setInline(inlineCB->isChecked());
454 params_.setParams(construct_params());
458 static string plainParam(string const & par)
460 // remove enclosing braces
461 if (prefixIs(par, "{") && suffixIs(par, "}"))
462 return par.substr(1, par.size() - 2);
467 void GuiListings::updateContents()
469 bool const use_minted = buffer().params().use_minted;
470 // set default values
471 listingsTB->setPlainText(
472 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
473 languageCO->setCurrentIndex(findToken(languages_supported, "no language"));
474 dialectCO->setCurrentIndex(0);
475 floatCB->setChecked(false);
476 placementLE->clear();
477 numberSideCO->setCurrentIndex(0);
478 numberStepLE->clear();
479 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
480 firstlineLE->clear();
482 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
483 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
484 breaklinesCB->setChecked(false);
485 spaceCB->setChecked(false);
486 spaceInStringCB->setChecked(true);
487 tabsizeSB->setValue(8);
488 extendedcharsCB->setChecked(false);
490 // set values from param string
491 inlineCB->setChecked(params_.isInline());
492 if (params_.isInline()) {
493 floatCB->setChecked(false);
494 placementLE->setEnabled(false);
496 // break other parameters and set values
497 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
498 // process each of them
499 for (vector<string>::iterator it = pars.begin();
500 it != pars.end(); ++it) {
501 if (prefixIs(*it, "language=")) {
502 string arg = plainParam(it->substr(9));
507 if (prefixIs(arg, "[") && contains(arg, "]")) {
508 size_t end_dialect = arg.find("]");
509 dialect = arg.substr(1, end_dialect - 1);
510 language = arg.substr(end_dialect + 1);
514 int n = findToken(languages_supported, language);
516 languageCO->setCurrentIndex(n);
519 // on_languageCO_currentIndexChanged should have set dialects
520 if (!dialect.empty()) {
522 for (size_t i = 0; i != nr_dialects; ++i) {
523 if (dialect == dialects[i].dialect
524 && dialects[i].language == language) {
525 dialect_gui = dialects[i].gui;
529 n = dialectCO->findText(qt_(dialect_gui));
531 dialectCO->setCurrentIndex(n);
537 languageCO->setEnabled(in_gui);
538 dialectCO->setEnabled(!use_minted &&
539 in_gui && dialectCO->count() > 1);
540 } else if (prefixIs(*it, "float")) {
541 floatCB->setChecked(true);
542 inlineCB->setChecked(false);
543 placementLE->setEnabled(true);
544 if (prefixIs(*it, "float="))
545 placementLE->setText(
546 toqstr(plainParam(it->substr(6))));
548 } else if (prefixIs(*it, "numbers=")) {
549 string s = plainParam(it->substr(8));
553 else if (s == "right")
555 numberSideCO->setCurrentIndex(n);
557 } else if (prefixIs(*it, "stepnumber=")) {
558 numberStepLE->setText(
559 toqstr(plainParam(it->substr(11))));
561 } else if (prefixIs(*it, "numberstyle=")) {
562 string par = plainParam(it->substr(12));
563 int n = findToken(font_sizes, par.substr(1));
565 numberFontSizeCO->setCurrentIndex(n);
567 } else if (prefixIs(*it, "firstline=")) {
568 firstlineLE->setText(
569 toqstr(plainParam(it->substr(10))));
571 } else if (prefixIs(*it, "lastline=")) {
573 toqstr(plainParam(it->substr(9))));
575 } else if (prefixIs(*it, "basicstyle=")) {
578 for (int n = 0; font_styles[n][0]; ++n) {
579 string const s = font_styles[n];
580 if (contains(*it, "\\" + s)) {
585 for (int n = 0; font_sizes[n][0]; ++n) {
586 string const s = font_sizes[n];
587 if (contains(*it, "\\" + s)) {
592 if (plainParam(it->substr(11)) == style + size
593 || plainParam(it->substr(11)) == size + style) {
594 if (!style.empty()) {
595 int n = findToken(font_styles, style.substr(1));
597 fontstyleCO->setCurrentIndex(n);
600 int n = findToken(font_sizes, size.substr(1));
602 fontsizeCO->setCurrentIndex(n);
606 } else if (prefixIs(*it, "fontsize=")) {
608 for (int n = 0; font_sizes[n][0]; ++n) {
609 string const s = font_sizes[n];
610 if (contains(*it, "\\" + s)) {
616 int n = findToken(font_sizes, size.substr(1));
618 fontsizeCO->setCurrentIndex(n);
621 } else if (prefixIs(*it, "fontfamily=")) {
623 for (int n = 0; font_styles[n][0]; ++n) {
624 string const s = font_styles[n];
625 if (contains(*it, "=" + s.substr(0,2))) {
630 if (!style.empty()) {
631 int n = findToken(font_styles, style.substr(1));
633 fontstyleCO->setCurrentIndex(n);
636 } else if (prefixIs(*it, "breaklines=")) {
637 breaklinesCB->setChecked(contains(*it, "true"));
639 } else if (prefixIs(*it, "showspaces=")) {
640 spaceCB->setChecked(contains(*it, "true"));
642 } else if (prefixIs(*it, "showstringspaces=")) {
643 spaceInStringCB->setChecked(contains(*it, "true"));
645 } else if (prefixIs(*it, "tabsize=")) {
646 tabsizeSB->setValue(convert<int>(plainParam(it->substr(8))));
648 } else if (prefixIs(*it, "extendedchars=")) {
649 extendedcharsCB->setChecked(contains(*it, "true"));
654 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
655 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0
657 spaceInStringCB->setEnabled(!use_minted);
658 extendedcharsCB->setEnabled(!use_minted);
659 // parameters that can be handled by widgets are cleared
660 // the rest is put to the extra edit box.
661 string extra = getStringFromVector(pars);
662 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
663 params_.setMinted(use_minted);
667 bool GuiListings::isValid()
669 return validate_listings_params().empty();
673 bool GuiListings::initialiseParams(string const & data)
675 InsetListings::string2params(data, params_);
680 void GuiListings::clearParams()
683 params_.setMinted(buffer().params().use_minted);
687 void GuiListings::dispatchParams()
689 string const lfun = InsetListings::params2string(params_);
690 dispatch(FuncRequest(getLfun(), lfun));
694 void GuiListings::setParams(InsetListingsParams const & params)
697 params_.setMinted(buffer().params().use_minted);
701 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
704 } // namespace frontend
708 #include "moc_GuiListings.cpp"