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/lstrings.h"
25 #include <QCloseEvent>
26 #include <QPushButton>
28 #include <QRegExpValidator>
33 using lyx::support::findToken;
34 using lyx::support::getVectorFromString;
35 using lyx::support::getStringFromVector;
36 using lyx::support::prefixIs;
37 using lyx::support::suffixIs;
38 using lyx::support::contains;
45 /////////////////////////////////////////////////////////////////////
49 /////////////////////////////////////////////////////////////////////
52 char const * languages[] =
53 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
54 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
55 "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
56 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
57 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
58 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
59 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
60 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
61 "VRML", "XML", "XSLT", "" };
64 char const * languages_gui[] =
65 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
66 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
67 "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
68 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
69 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
70 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
71 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
72 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
73 "VRML", "XML", "XSLT", "" };
79 /// the associated language
80 char const * language;
81 /// representation of the dialect in the gui
83 /// is this the default dialect?
88 dialect_info const dialects[] = {
89 { "R/2 4.3", "ABAP", "R/2 4.3", false },
90 { "R/2 5.0", "ABAP", "R/2 5.0", false },
91 { "R/3 3.1", "ABAP", "R/3 3.1", false },
92 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
93 { "R/3 6.10", "ABAP", "R/3 6.10", true },
94 { "2005", "Ada", "2005", true },
95 { "83", "Ada", "83", false },
96 { "95", "Ada", "95", false },
97 { "60", "Algol", "60", false },
98 { "68", "Algol", "68", true },
99 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
100 { "x86masm", "Assembler", "x86 (MASM)", false },
101 { "gnu", "Awk", "gnu", true },
102 { "POSIX", "Awk", "POSIX", false },
103 { "Visual", "Basic", "Visual", false },
104 { "ANSI", "C", "ANSI", true },
105 { "Handel", "C", "Handel", false },
106 { "Objective", "C", "Objective", false },
107 { "Sharp", "C", "Sharp", false },
108 { "ANSI", "C++", "ANSI", false },
109 { "GNU", "C++", "GNU", false },
110 { "ISO", "C++", "ISO", true },
111 { "Visual", "C++", "Visual", false },
112 { "light", "Caml", "light", true },
113 { "Objective", "Caml", "Objective", false },
114 { "1974", "Cobol", "1974", false },
115 { "1985", "Cobol", "1985", true },
116 { "ibm", "Cobol", "IBM", false },
117 { "WinXP", "command.com", "Windows XP", true },
118 { "77", "Fortran", "77", false },
119 { "90", "Fortran", "90", false },
120 { "95", "Fortran", "95", true },
121 { "CORBA", "IDL", "CORBA", false },
122 { "AspectJ", "Java", "Aspect J", false },
123 { "Auto", "Lisp", "Auto", false },
124 { "gnu", "make", "gnu", false },
125 { "1.0", "Mathematica", "1.0", false },
126 { "3.0", "Mathematica", "3.0", false },
127 { "5.2", "Mathematica", "5.2", true },
128 { "decorative", "OCL", "decorative", false },
129 { "OMG", "OCL", "OMG", true },
130 { "Borland6", "Pascal", "Borland 6", false },
131 { "Standard", "Pascal", "Standard", true },
132 { "XSC", "Pascal", "XSC", false },
133 { "PLUS", "S", "PLUS", false },
134 { "67", "Simula", "67", true },
135 { "CII", "Simula", "CII", false },
136 { "DEC", "Simula", "DEC", false },
137 { "IBM", "Simula", "IBM", false },
138 { "tk", "tcl", "tk", false },
139 { "AlLaTeX", "TeX", "AlLaTeX", false },
140 { "common", "TeX", "common", false },
141 { "LaTeX", "TeX", "LaTeX", false },
142 { "plain", "TeX", "plain", true },
143 { "primitive", "TeX", "primitive", false },
144 { "AMS", "VHDL", "AMS", false },
145 { "97", "VRML", "97", true }
149 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
152 char const * font_sizes[] =
153 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
156 char const * font_sizes_gui[] =
157 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
158 N_("Large"), N_("Larger"), "" };
160 char const * font_styles[] =
161 { "default", "rmfamily", "ttfamily", "sffamily", "" };
163 char const * font_styles_gui[] =
164 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
168 GuiListings::GuiListings(GuiView & lv)
169 : GuiDialog(lv, "listings")
172 setViewTitle(_("Program Listing Settings"));
174 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
175 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
176 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
178 connect(languageCO, SIGNAL(currentIndexChanged(int)),
179 this, SLOT(change_adaptor()));
180 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
181 this, SLOT(change_adaptor()));
182 connect(inlineCB, SIGNAL(clicked()),
183 this, SLOT(change_adaptor()));
184 connect(floatCB, SIGNAL(clicked()),
185 this, SLOT(change_adaptor()));
186 connect(placementLE, SIGNAL(textChanged(QString)),
187 this, SLOT(change_adaptor()));
188 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
189 this, SLOT(change_adaptor()));
190 connect(numberStepLE, SIGNAL(textChanged(QString)),
191 this, SLOT(change_adaptor()));
192 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
193 this, SLOT(change_adaptor()));
194 connect(firstlineLE, SIGNAL(textChanged(QString)),
195 this, SLOT(change_adaptor()));
196 connect(lastlineLE, SIGNAL(textChanged(QString)),
197 this, SLOT(change_adaptor()));
198 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
199 this, SLOT(change_adaptor()));
200 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
201 this, SLOT(change_adaptor()));
202 connect(breaklinesCB, SIGNAL(clicked()),
203 this, SLOT(change_adaptor()));
204 connect(spaceCB, SIGNAL(clicked()),
205 this, SLOT(change_adaptor()));
206 connect(spaceInStringCB, SIGNAL(clicked()),
207 this, SLOT(change_adaptor()));
208 connect(extendedcharsCB, SIGNAL(clicked()),
209 this, SLOT(change_adaptor()));
211 connect(listingsED, SIGNAL(textChanged()),
212 this, SLOT(change_adaptor()));
213 connect(listingsED, SIGNAL(textChanged()),
214 this, SLOT(set_listings_msg()));
215 connect(bypassCB, SIGNAL(clicked()),
216 this, SLOT(change_adaptor()));
217 connect(bypassCB, SIGNAL(clicked()),
218 this, SLOT(set_listings_msg()));
220 for (int n = 0; languages[n][0]; ++n)
221 languageCO->addItem(qt_(languages_gui[n]));
223 for (int n = 0; font_styles[n][0]; ++n)
224 fontstyleCO->addItem(qt_(font_styles_gui[n]));
226 for (int n = 0; font_sizes[n][0]; ++n) {
227 QString font = qt_(font_sizes_gui[n]);
228 fontsizeCO->addItem(font);
229 numberFontSizeCO->addItem(font);
233 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
234 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
235 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
236 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
239 bc().setApply(applyPB);
240 bc().setCancel(closePB);
241 listingsTB->setPlainText(
242 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
249 void GuiListings::closeEvent(QCloseEvent * e)
256 void GuiListings::change_adaptor()
262 string GuiListings::construct_params()
264 string language = languages[languageCO->currentIndex()];
266 string const dialect_gui = fromqstr(dialectCO->currentText());
267 if (dialectCO->currentIndex() > 0) {
268 for (size_t i = 0; i != nr_dialects; ++i) {
269 if (dialect_gui == dialects[i].gui
270 && dialects[i].language == language
271 && !dialects[i].is_default) {
272 dialect = dialects[i].dialect;
278 bool float_ = floatCB->isChecked();
280 if (placementLE->isEnabled())
281 placement = fromqstr(placementLE->text());
284 switch (numberSideCO->currentIndex()) {
292 numberSide = "right";
298 string stepnumber = fromqstr(numberStepLE->text());
299 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
300 string firstline = fromqstr(firstlineLE->text());
301 string lastline = fromqstr(lastlineLE->text());
303 string fontsize = font_sizes[fontsizeCO->currentIndex()];
304 string fontstyle = font_styles[fontstyleCO->currentIndex()];
306 if (fontsize != "default")
307 basicstyle = "\\" + fontsize;
308 if (fontstyle != "default")
309 basicstyle += "\\" + fontstyle;
310 bool breakline = breaklinesCB->isChecked();
311 bool space = spaceCB->isChecked();
312 bool spaceInString = spaceInStringCB->isChecked();
313 bool extendedchars = extendedcharsCB->isChecked();
314 string extra = fromqstr(listingsED->toPlainText());
317 InsetListingsParams par;
318 if (language != "no language" && !contains(extra, "language=")) {
320 par.addParam("language", language);
322 par.addParam("language", "{[" + dialect + "]" + language + "}");
324 // this dialog uses float=placement instead of float,floatplacement=placement
325 // because float accepts *tbph and floatplacement accepts bph.
326 // our placement textedit is actually for the float parameter
328 par.addParam("float", placement);
329 if (numberSide != "none")
330 par.addParam("numbers", numberSide);
331 if (numberfontsize != "default" && numberSide != "none")
332 par.addParam("numberstyle", "\\" + numberfontsize);
333 if (!stepnumber.empty() && numberSide != "none")
334 par.addParam("stepnumber", stepnumber);
335 if (!firstline.empty())
336 par.addParam("firstline", firstline);
337 if (!lastline.empty())
338 par.addParam("lastline", lastline);
339 if (!basicstyle.empty())
340 par.addParam("basicstyle", basicstyle);
342 par.addParam("breaklines", "true");
344 par.addParam("showspaces", "true");
346 par.addParam("showstringspaces", "false");
348 par.addParam("extendedchars", "true");
349 par.addParams(extra);
354 docstring GuiListings::validate_listings_params()
356 // use a cache here to avoid repeated validation
357 // of the same parameters
358 static string param_cache;
359 static docstring msg_cache;
361 if (bypassCB->isChecked())
364 string params = construct_params();
365 if (params != param_cache) {
366 param_cache = params;
367 msg_cache = InsetListingsParams(params).validate();
373 void GuiListings::set_listings_msg()
375 static bool isOK = true;
376 docstring msg = validate_listings_params();
381 listingsTB->setPlainText(
382 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
385 listingsTB->setPlainText(toqstr(msg));
390 void GuiListings::on_floatCB_stateChanged(int state)
392 if (state == Qt::Checked) {
393 inlineCB->setChecked(false);
394 placementLE->setEnabled(true);
396 placementLE->setEnabled(false);
400 void GuiListings::on_inlineCB_stateChanged(int state)
402 if (state == Qt::Checked) {
403 floatCB->setChecked(false);
404 placementLE->setEnabled(false);
409 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
411 numberStepLE->setEnabled(index > 0);
412 numberFontSizeCO->setEnabled(index > 0);
416 void GuiListings::on_languageCO_currentIndexChanged(int index)
420 int default_dialect = 0;
421 dialectCO->addItem(qt_("No dialect"));
422 string const language = languages[index];
424 for (size_t i = 0; i != nr_dialects; ++i) {
425 if (language == dialects[i].language) {
426 dialectCO->addItem(qt_(dialects[i].gui));
427 if (dialects[i].is_default)
429 dialectCO->findText(qt_(dialects[i].gui));
432 dialectCO->setCurrentIndex(default_dialect);
433 dialectCO->setEnabled(dialectCO->count() > 1);
437 void GuiListings::applyView()
439 params_.setInline(inlineCB->isChecked());
440 params_.setParams(construct_params());
444 static string plainParam(std::string const & par)
446 // remove enclosing braces
447 if (prefixIs(par, "{") && suffixIs(par, "}"))
448 return par.substr(1, par.size() - 2);
453 void GuiListings::updateContents()
455 // set default values
456 listingsTB->setPlainText(
457 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
458 languageCO->setCurrentIndex(findToken(languages, "no language"));
459 dialectCO->setCurrentIndex(0);
460 floatCB->setChecked(false);
461 placementLE->clear();
462 numberSideCO->setCurrentIndex(0);
463 numberStepLE->clear();
464 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
465 firstlineLE->clear();
467 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
468 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
469 breaklinesCB->setChecked(false);
470 spaceCB->setChecked(false);
471 spaceInStringCB->setChecked(true);
472 extendedcharsCB->setChecked(false);
474 // set values from param string
475 inlineCB->setChecked(params_.isInline());
476 if (params_.isInline()) {
477 floatCB->setChecked(false);
478 placementLE->setEnabled(false);
480 // break other parameters and set values
481 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
482 // process each of them
483 for (vector<string>::iterator it = pars.begin();
484 it != pars.end(); ++it) {
485 if (prefixIs(*it, "language=")) {
486 string arg = plainParam(it->substr(9));
491 if (prefixIs(arg, "[") && contains(arg, "]")) {
492 size_t end_dialect = arg.find("]");
493 dialect = arg.substr(1, end_dialect - 1);
494 language = arg.substr(end_dialect + 1);
498 int n = findToken(languages, language);
500 languageCO->setCurrentIndex(n);
503 // on_languageCO_currentIndexChanged should have set dialects
504 if (!dialect.empty()) {
506 for (size_t i = 0; i != nr_dialects; ++i) {
507 if (dialect == dialects[i].dialect
508 && dialects[i].language == language) {
509 dialect_gui = dialects[i].gui;
513 n = dialectCO->findText(qt_(dialect_gui));
515 dialectCO->setCurrentIndex(n);
521 languageCO->setEnabled(in_gui);
522 dialectCO->setEnabled(
523 in_gui && dialectCO->count() > 1);
524 } else if (prefixIs(*it, "float")) {
525 floatCB->setChecked(true);
526 inlineCB->setChecked(false);
527 placementLE->setEnabled(true);
528 if (prefixIs(*it, "float="))
529 placementLE->setText(
530 toqstr(plainParam(it->substr(6))));
532 } else if (prefixIs(*it, "numbers=")) {
533 string s = plainParam(it->substr(8));
537 else if (s == "right")
539 numberSideCO->setCurrentIndex(n);
541 } else if (prefixIs(*it, "stepnumber=")) {
542 numberStepLE->setText(
543 toqstr(plainParam(it->substr(11))));
545 } else if (prefixIs(*it, "numberstyle=")) {
546 string par = plainParam(it->substr(12));
547 int n = findToken(font_sizes, par.substr(1));
549 numberFontSizeCO->setCurrentIndex(n);
551 } else if (prefixIs(*it, "firstline=")) {
552 firstlineLE->setText(
553 toqstr(plainParam(it->substr(10))));
555 } else if (prefixIs(*it, "lastline=")) {
557 toqstr(plainParam(it->substr(9))));
559 } else if (prefixIs(*it, "basicstyle=")) {
562 for (int n = 0; font_styles[n][0]; ++n) {
563 string const s = font_styles[n];
564 if (contains(*it, "\\" + s)) {
569 for (int n = 0; font_sizes[n][0]; ++n) {
570 string const s = font_sizes[n];
571 if (contains(*it, "\\" + s)) {
576 if (plainParam(it->substr(11)) == style + size
577 || plainParam(it->substr(11)) == size + style) {
578 if (!style.empty()) {
579 int n = findToken(font_styles, style.substr(1));
581 fontstyleCO->setCurrentIndex(n);
584 int n = findToken(font_sizes, size.substr(1));
586 fontsizeCO->setCurrentIndex(n);
590 } else if (prefixIs(*it, "breaklines=")) {
591 breaklinesCB->setChecked(contains(*it, "true"));
593 } else if (prefixIs(*it, "showspaces=")) {
594 spaceCB->setChecked(contains(*it, "true"));
596 } else if (prefixIs(*it, "showstringspaces=")) {
597 spaceInStringCB->setChecked(contains(*it, "true"));
599 } else if (prefixIs(*it, "extendedchars=")) {
600 extendedcharsCB->setChecked(contains(*it, "true"));
605 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
606 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
607 // parameters that can be handled by widgets are cleared
608 // the rest is put to the extra edit box.
609 string extra = getStringFromVector(pars);
610 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
614 bool GuiListings::isValid()
616 return validate_listings_params().empty();
620 bool GuiListings::initialiseParams(string const & data)
622 InsetListingsMailer::string2params(data, params_);
627 void GuiListings::clearParams()
633 void GuiListings::dispatchParams()
635 string const lfun = InsetListingsMailer::params2string(params_);
636 dispatch(FuncRequest(getLfun(), lfun));
640 void GuiListings::setParams(InsetListingsParams const & params)
646 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
649 } // namespace frontend
653 #include "GuiListings_moc.cpp"