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"
17 #include "FuncRequest.h"
18 #include "insets/InsetListings.h"
19 #include "insets/InsetListingsParams.h"
20 #include "support/debug.h"
22 #include "support/gettext.h"
23 #include "support/lstrings.h"
26 #include <QCloseEvent>
27 #include <QPushButton>
29 #include <QRegExpValidator>
32 using namespace lyx::support;
38 /////////////////////////////////////////////////////////////////////
42 /////////////////////////////////////////////////////////////////////
45 char const * languages[] =
46 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
47 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
48 "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
49 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
50 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
51 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
52 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
53 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
54 "VRML", "XML", "XSLT", "" };
57 char const * languages_gui[] =
58 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
59 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
60 "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
61 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
62 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
63 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
64 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
65 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
66 "VRML", "XML", "XSLT", "" };
72 /// the associated language
73 char const * language;
74 /// representation of the dialect in the gui
76 /// is this the default dialect?
81 dialect_info const dialects[] = {
82 { "R/2 4.3", "ABAP", "R/2 4.3", false },
83 { "R/2 5.0", "ABAP", "R/2 5.0", false },
84 { "R/3 3.1", "ABAP", "R/3 3.1", false },
85 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
86 { "R/3 6.10", "ABAP", "R/3 6.10", true },
87 { "2005", "Ada", "2005", true },
88 { "83", "Ada", "83", false },
89 { "95", "Ada", "95", false },
90 { "60", "Algol", "60", false },
91 { "68", "Algol", "68", true },
92 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
93 { "x86masm", "Assembler", "x86 (MASM)", false },
94 { "gnu", "Awk", "gnu", true },
95 { "POSIX", "Awk", "POSIX", false },
96 { "Visual", "Basic", "Visual", false },
97 { "ANSI", "C", "ANSI", true },
98 { "Handel", "C", "Handel", false },
99 { "Objective", "C", "Objective", false },
100 { "Sharp", "C", "Sharp", false },
101 { "ANSI", "C++", "ANSI", false },
102 { "GNU", "C++", "GNU", false },
103 { "ISO", "C++", "ISO", true },
104 { "Visual", "C++", "Visual", false },
105 { "light", "Caml", "light", true },
106 { "Objective", "Caml", "Objective", false },
107 { "1974", "Cobol", "1974", false },
108 { "1985", "Cobol", "1985", true },
109 { "ibm", "Cobol", "IBM", false },
110 { "WinXP", "command.com", "Windows XP", true },
111 { "77", "Fortran", "77", false },
112 { "90", "Fortran", "90", false },
113 { "95", "Fortran", "95", true },
114 { "CORBA", "IDL", "CORBA", false },
115 { "AspectJ", "Java", "Aspect J", false },
116 { "Auto", "Lisp", "Auto", false },
117 { "gnu", "make", "gnu", false },
118 { "1.0", "Mathematica", "1.0", false },
119 { "3.0", "Mathematica", "3.0", false },
120 { "5.2", "Mathematica", "5.2", true },
121 { "decorative", "OCL", "decorative", false },
122 { "OMG", "OCL", "OMG", true },
123 { "Borland6", "Pascal", "Borland 6", false },
124 { "Standard", "Pascal", "Standard", true },
125 { "XSC", "Pascal", "XSC", false },
126 { "PLUS", "S", "PLUS", false },
127 { "67", "Simula", "67", true },
128 { "CII", "Simula", "CII", false },
129 { "DEC", "Simula", "DEC", false },
130 { "IBM", "Simula", "IBM", false },
131 { "tk", "tcl", "tk", false },
132 { "AlLaTeX", "TeX", "AlLaTeX", false },
133 { "common", "TeX", "common", false },
134 { "LaTeX", "TeX", "LaTeX", false },
135 { "plain", "TeX", "plain", true },
136 { "primitive", "TeX", "primitive", false },
137 { "AMS", "VHDL", "AMS", false },
138 { "97", "VRML", "97", true }
142 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
145 char const * font_sizes[] =
146 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
149 char const * font_sizes_gui[] =
150 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
151 N_("Large"), N_("Larger"), "" };
153 char const * font_styles[] =
154 { "default", "rmfamily", "ttfamily", "sffamily", "" };
156 char const * font_styles_gui[] =
157 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
161 GuiListings::GuiListings(GuiView & lv)
162 : GuiDialog(lv, "listings", qt_("Program Listing Settings"))
166 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
167 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
168 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
170 connect(languageCO, SIGNAL(currentIndexChanged(int)),
171 this, SLOT(change_adaptor()));
172 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
173 this, SLOT(change_adaptor()));
174 connect(inlineCB, SIGNAL(clicked()),
175 this, SLOT(change_adaptor()));
176 connect(floatCB, SIGNAL(clicked()),
177 this, SLOT(change_adaptor()));
178 connect(placementLE, SIGNAL(textChanged(QString)),
179 this, SLOT(change_adaptor()));
180 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
181 this, SLOT(change_adaptor()));
182 connect(numberStepLE, SIGNAL(textChanged(QString)),
183 this, SLOT(change_adaptor()));
184 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
185 this, SLOT(change_adaptor()));
186 connect(firstlineLE, SIGNAL(textChanged(QString)),
187 this, SLOT(change_adaptor()));
188 connect(lastlineLE, SIGNAL(textChanged(QString)),
189 this, SLOT(change_adaptor()));
190 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
191 this, SLOT(change_adaptor()));
192 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
193 this, SLOT(change_adaptor()));
194 connect(breaklinesCB, SIGNAL(clicked()),
195 this, SLOT(change_adaptor()));
196 connect(spaceCB, SIGNAL(clicked()),
197 this, SLOT(change_adaptor()));
198 connect(spaceInStringCB, SIGNAL(clicked()),
199 this, SLOT(change_adaptor()));
200 connect(extendedcharsCB, SIGNAL(clicked()),
201 this, SLOT(change_adaptor()));
203 connect(listingsED, SIGNAL(textChanged()),
204 this, SLOT(change_adaptor()));
205 connect(listingsED, SIGNAL(textChanged()),
206 this, SLOT(set_listings_msg()));
207 connect(bypassCB, SIGNAL(clicked()),
208 this, SLOT(change_adaptor()));
209 connect(bypassCB, SIGNAL(clicked()),
210 this, SLOT(set_listings_msg()));
212 for (int n = 0; languages[n][0]; ++n)
213 languageCO->addItem(qt_(languages_gui[n]));
215 for (int n = 0; font_styles[n][0]; ++n)
216 fontstyleCO->addItem(qt_(font_styles_gui[n]));
218 for (int n = 0; font_sizes[n][0]; ++n) {
219 QString font = qt_(font_sizes_gui[n]);
220 fontsizeCO->addItem(font);
221 numberFontSizeCO->addItem(font);
225 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
226 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
227 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
228 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
231 bc().setApply(applyPB);
232 bc().setCancel(closePB);
233 listingsTB->setPlainText(
234 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
241 void GuiListings::change_adaptor()
247 string GuiListings::construct_params()
249 string language = languages[languageCO->currentIndex()];
251 string const dialect_gui = fromqstr(dialectCO->currentText());
252 if (dialectCO->currentIndex() > 0) {
253 for (size_t i = 0; i != nr_dialects; ++i) {
254 if (dialect_gui == dialects[i].gui
255 && dialects[i].language == language
256 && !dialects[i].is_default) {
257 dialect = dialects[i].dialect;
263 bool float_ = floatCB->isChecked();
265 if (placementLE->isEnabled())
266 placement = fromqstr(placementLE->text());
269 switch (numberSideCO->currentIndex()) {
277 numberSide = "right";
283 string stepnumber = fromqstr(numberStepLE->text());
284 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
285 string firstline = fromqstr(firstlineLE->text());
286 string lastline = fromqstr(lastlineLE->text());
288 string fontsize = font_sizes[fontsizeCO->currentIndex()];
289 string fontstyle = font_styles[fontstyleCO->currentIndex()];
291 if (fontsize != "default")
292 basicstyle = "\\" + fontsize;
293 if (fontstyle != "default")
294 basicstyle += "\\" + fontstyle;
295 bool breakline = breaklinesCB->isChecked();
296 bool space = spaceCB->isChecked();
297 bool spaceInString = spaceInStringCB->isChecked();
298 bool extendedchars = extendedcharsCB->isChecked();
299 string extra = fromqstr(listingsED->toPlainText());
302 InsetListingsParams par;
303 if (language != "no language" && !contains(extra, "language=")) {
305 par.addParam("language", language);
307 par.addParam("language", "{[" + dialect + "]" + language + "}");
309 // this dialog uses float=placement instead of float,floatplacement=placement
310 // because float accepts *tbph and floatplacement accepts bph.
311 // our placement textedit is actually for the float parameter
313 par.addParam("float", placement);
314 if (numberSide != "none")
315 par.addParam("numbers", numberSide);
316 if (numberfontsize != "default" && numberSide != "none")
317 par.addParam("numberstyle", "\\" + numberfontsize);
318 if (!stepnumber.empty() && numberSide != "none")
319 par.addParam("stepnumber", stepnumber);
320 if (!firstline.empty())
321 par.addParam("firstline", firstline);
322 if (!lastline.empty())
323 par.addParam("lastline", lastline);
324 if (!basicstyle.empty())
325 par.addParam("basicstyle", basicstyle);
327 par.addParam("breaklines", "true");
329 par.addParam("showspaces", "true");
331 par.addParam("showstringspaces", "false");
333 par.addParam("extendedchars", "true");
334 par.addParams(extra);
339 docstring GuiListings::validate_listings_params()
341 // use a cache here to avoid repeated validation
342 // of the same parameters
343 static string param_cache;
344 static docstring msg_cache;
346 if (bypassCB->isChecked())
349 string params = construct_params();
350 if (params != param_cache) {
351 param_cache = params;
352 msg_cache = InsetListingsParams(params).validate();
358 void GuiListings::set_listings_msg()
360 static bool isOK = true;
361 docstring msg = validate_listings_params();
366 listingsTB->setPlainText(
367 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
370 listingsTB->setPlainText(toqstr(msg));
375 void GuiListings::on_floatCB_stateChanged(int state)
377 if (state == Qt::Checked) {
378 inlineCB->setChecked(false);
379 placementLE->setEnabled(true);
381 placementLE->setEnabled(false);
385 void GuiListings::on_inlineCB_stateChanged(int state)
387 if (state == Qt::Checked) {
388 floatCB->setChecked(false);
389 placementLE->setEnabled(false);
394 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
396 numberStepLE->setEnabled(index > 0);
397 numberFontSizeCO->setEnabled(index > 0);
401 void GuiListings::on_languageCO_currentIndexChanged(int index)
405 int default_dialect = 0;
406 dialectCO->addItem(qt_("No dialect"));
407 string const language = languages[index];
409 for (size_t i = 0; i != nr_dialects; ++i) {
410 if (language == dialects[i].language) {
411 dialectCO->addItem(qt_(dialects[i].gui));
412 if (dialects[i].is_default)
414 dialectCO->findText(qt_(dialects[i].gui));
417 dialectCO->setCurrentIndex(default_dialect);
418 dialectCO->setEnabled(dialectCO->count() > 1);
422 void GuiListings::applyView()
424 params_.setInline(inlineCB->isChecked());
425 params_.setParams(construct_params());
429 static string plainParam(string const & par)
431 // remove enclosing braces
432 if (prefixIs(par, "{") && suffixIs(par, "}"))
433 return par.substr(1, par.size() - 2);
438 void GuiListings::updateContents()
440 // set default values
441 listingsTB->setPlainText(
442 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
443 languageCO->setCurrentIndex(findToken(languages, "no language"));
444 dialectCO->setCurrentIndex(0);
445 floatCB->setChecked(false);
446 placementLE->clear();
447 numberSideCO->setCurrentIndex(0);
448 numberStepLE->clear();
449 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
450 firstlineLE->clear();
452 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
453 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
454 breaklinesCB->setChecked(false);
455 spaceCB->setChecked(false);
456 spaceInStringCB->setChecked(true);
457 extendedcharsCB->setChecked(false);
459 // set values from param string
460 inlineCB->setChecked(params_.isInline());
461 if (params_.isInline()) {
462 floatCB->setChecked(false);
463 placementLE->setEnabled(false);
465 // break other parameters and set values
466 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
467 // process each of them
468 for (vector<string>::iterator it = pars.begin();
469 it != pars.end(); ++it) {
470 if (prefixIs(*it, "language=")) {
471 string arg = plainParam(it->substr(9));
476 if (prefixIs(arg, "[") && contains(arg, "]")) {
477 size_t end_dialect = arg.find("]");
478 dialect = arg.substr(1, end_dialect - 1);
479 language = arg.substr(end_dialect + 1);
483 int n = findToken(languages, language);
485 languageCO->setCurrentIndex(n);
488 // on_languageCO_currentIndexChanged should have set dialects
489 if (!dialect.empty()) {
491 for (size_t i = 0; i != nr_dialects; ++i) {
492 if (dialect == dialects[i].dialect
493 && dialects[i].language == language) {
494 dialect_gui = dialects[i].gui;
498 n = dialectCO->findText(qt_(dialect_gui));
500 dialectCO->setCurrentIndex(n);
506 languageCO->setEnabled(in_gui);
507 dialectCO->setEnabled(
508 in_gui && dialectCO->count() > 1);
509 } else if (prefixIs(*it, "float")) {
510 floatCB->setChecked(true);
511 inlineCB->setChecked(false);
512 placementLE->setEnabled(true);
513 if (prefixIs(*it, "float="))
514 placementLE->setText(
515 toqstr(plainParam(it->substr(6))));
517 } else if (prefixIs(*it, "numbers=")) {
518 string s = plainParam(it->substr(8));
522 else if (s == "right")
524 numberSideCO->setCurrentIndex(n);
526 } else if (prefixIs(*it, "stepnumber=")) {
527 numberStepLE->setText(
528 toqstr(plainParam(it->substr(11))));
530 } else if (prefixIs(*it, "numberstyle=")) {
531 string par = plainParam(it->substr(12));
532 int n = findToken(font_sizes, par.substr(1));
534 numberFontSizeCO->setCurrentIndex(n);
536 } else if (prefixIs(*it, "firstline=")) {
537 firstlineLE->setText(
538 toqstr(plainParam(it->substr(10))));
540 } else if (prefixIs(*it, "lastline=")) {
542 toqstr(plainParam(it->substr(9))));
544 } else if (prefixIs(*it, "basicstyle=")) {
547 for (int n = 0; font_styles[n][0]; ++n) {
548 string const s = font_styles[n];
549 if (contains(*it, "\\" + s)) {
554 for (int n = 0; font_sizes[n][0]; ++n) {
555 string const s = font_sizes[n];
556 if (contains(*it, "\\" + s)) {
561 if (plainParam(it->substr(11)) == style + size
562 || plainParam(it->substr(11)) == size + style) {
563 if (!style.empty()) {
564 int n = findToken(font_styles, style.substr(1));
566 fontstyleCO->setCurrentIndex(n);
569 int n = findToken(font_sizes, size.substr(1));
571 fontsizeCO->setCurrentIndex(n);
575 } else if (prefixIs(*it, "breaklines=")) {
576 breaklinesCB->setChecked(contains(*it, "true"));
578 } else if (prefixIs(*it, "showspaces=")) {
579 spaceCB->setChecked(contains(*it, "true"));
581 } else if (prefixIs(*it, "showstringspaces=")) {
582 spaceInStringCB->setChecked(contains(*it, "true"));
584 } else if (prefixIs(*it, "extendedchars=")) {
585 extendedcharsCB->setChecked(contains(*it, "true"));
590 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
591 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
592 // parameters that can be handled by widgets are cleared
593 // the rest is put to the extra edit box.
594 string extra = getStringFromVector(pars);
595 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
599 bool GuiListings::isValid()
601 return validate_listings_params().empty();
605 bool GuiListings::initialiseParams(string const & data)
607 InsetListingsMailer::string2params(data, params_);
612 void GuiListings::clearParams()
618 void GuiListings::dispatchParams()
620 string const lfun = InsetListingsMailer::params2string(params_);
621 dispatch(FuncRequest(getLfun(), lfun));
625 void GuiListings::setParams(InsetListingsParams const & params)
631 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
634 } // namespace frontend
638 #include "GuiListings_moc.cpp"