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"
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", "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", "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(LyXView & lv)
169 : GuiDialog(lv, "listings"), Controller(this)
172 setViewTitle(_("Program Listing Settings"));
173 setController(this, false);
175 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
176 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
177 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
179 connect(languageCO, SIGNAL(currentIndexChanged(int)),
180 this, SLOT(change_adaptor()));
181 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
182 this, SLOT(change_adaptor()));
183 connect(inlineCB, SIGNAL(clicked()),
184 this, SLOT(change_adaptor()));
185 connect(floatCB, SIGNAL(clicked()),
186 this, SLOT(change_adaptor()));
187 connect(placementLE, SIGNAL(textChanged(QString)),
188 this, SLOT(change_adaptor()));
189 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
190 this, SLOT(change_adaptor()));
191 connect(numberStepLE, SIGNAL(textChanged(QString)),
192 this, SLOT(change_adaptor()));
193 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
194 this, SLOT(change_adaptor()));
195 connect(firstlineLE, SIGNAL(textChanged(QString)),
196 this, SLOT(change_adaptor()));
197 connect(lastlineLE, SIGNAL(textChanged(QString)),
198 this, SLOT(change_adaptor()));
199 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
200 this, SLOT(change_adaptor()));
201 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
202 this, SLOT(change_adaptor()));
203 connect(breaklinesCB, SIGNAL(clicked()),
204 this, SLOT(change_adaptor()));
205 connect(spaceCB, SIGNAL(clicked()),
206 this, SLOT(change_adaptor()));
207 connect(spaceInStringCB, SIGNAL(clicked()),
208 this, SLOT(change_adaptor()));
209 connect(extendedcharsCB, SIGNAL(clicked()),
210 this, SLOT(change_adaptor()));
212 connect(listingsED, SIGNAL(textChanged()),
213 this, SLOT(change_adaptor()));
214 connect(listingsED, SIGNAL(textChanged()),
215 this, SLOT(set_listings_msg()));
216 connect(bypassCB, SIGNAL(clicked()),
217 this, SLOT(change_adaptor()));
218 connect(bypassCB, SIGNAL(clicked()),
219 this, SLOT(set_listings_msg()));
221 for (int n = 0; languages[n][0]; ++n)
222 languageCO->addItem(qt_(languages_gui[n]));
224 for (int n = 0; font_styles[n][0]; ++n)
225 fontstyleCO->addItem(qt_(font_styles_gui[n]));
227 for (int n = 0; font_sizes[n][0]; ++n) {
228 QString font = qt_(font_sizes_gui[n]);
229 fontsizeCO->addItem(font);
230 numberFontSizeCO->addItem(font);
234 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
235 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
236 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
237 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
240 bc().setApply(applyPB);
241 bc().setCancel(closePB);
242 listingsTB->setPlainText(
243 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
250 void GuiListings::closeEvent(QCloseEvent * e)
257 void GuiListings::change_adaptor()
263 string GuiListings::construct_params()
265 string language = languages[languageCO->currentIndex()];
267 string const dialect_gui = fromqstr(dialectCO->currentText());
268 if (dialectCO->currentIndex() > 0) {
269 for (size_t i = 0; i != nr_dialects; ++i) {
270 if (dialect_gui == dialects[i].gui
271 && dialects[i].language == language
272 && !dialects[i].is_default) {
273 dialect = dialects[i].dialect;
279 bool float_ = floatCB->isChecked();
281 if (placementLE->isEnabled())
282 placement = fromqstr(placementLE->text());
285 switch (numberSideCO->currentIndex()) {
293 numberSide = "right";
299 string stepnumber = fromqstr(numberStepLE->text());
300 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
301 string firstline = fromqstr(firstlineLE->text());
302 string lastline = fromqstr(lastlineLE->text());
304 string fontsize = font_sizes[fontsizeCO->currentIndex()];
305 string fontstyle = font_styles[fontstyleCO->currentIndex()];
307 if (fontsize != "default")
308 basicstyle = "\\" + fontsize;
309 if (fontstyle != "default")
310 basicstyle += "\\" + fontstyle;
311 bool breakline = breaklinesCB->isChecked();
312 bool space = spaceCB->isChecked();
313 bool spaceInString = spaceInStringCB->isChecked();
314 bool extendedchars = extendedcharsCB->isChecked();
315 string extra = fromqstr(listingsED->toPlainText());
318 InsetListingsParams par;
319 if (language != "no language" && !contains(extra, "language=")) {
321 par.addParam("language", language);
323 par.addParam("language", "{[" + dialect + "]" + language + "}");
325 // this dialog uses float=placement instead of float,floatplacement=placement
326 // because float accepts *tbph and floatplacement accepts bph.
327 // our placement textedit is actually for the float parameter
329 par.addParam("float", placement);
330 if (numberSide != "none")
331 par.addParam("numbers", numberSide);
332 if (numberfontsize != "default" && numberSide != "none")
333 par.addParam("numberstyle", "\\" + numberfontsize);
334 if (!stepnumber.empty() && numberSide != "none")
335 par.addParam("stepnumber", stepnumber);
336 if (!firstline.empty())
337 par.addParam("firstline", firstline);
338 if (!lastline.empty())
339 par.addParam("lastline", lastline);
340 if (!basicstyle.empty())
341 par.addParam("basicstyle", basicstyle);
343 par.addParam("breaklines", "true");
345 par.addParam("showspaces", "true");
347 par.addParam("showstringspaces", "false");
349 par.addParam("extendedchars", "true");
350 par.addParams(extra);
355 docstring GuiListings::validate_listings_params()
357 // use a cache here to avoid repeated validation
358 // of the same parameters
359 static string param_cache;
360 static docstring msg_cache;
362 if (bypassCB->isChecked())
365 string params = construct_params();
366 if (params != param_cache) {
367 param_cache = params;
368 msg_cache = InsetListingsParams(params).validate();
374 void GuiListings::set_listings_msg()
376 static bool isOK = true;
377 docstring msg = validate_listings_params();
382 listingsTB->setPlainText(
383 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
386 listingsTB->setPlainText(toqstr(msg));
391 void GuiListings::on_floatCB_stateChanged(int state)
393 if (state == Qt::Checked) {
394 inlineCB->setChecked(false);
395 placementLE->setEnabled(true);
397 placementLE->setEnabled(false);
401 void GuiListings::on_inlineCB_stateChanged(int state)
403 if (state == Qt::Checked) {
404 floatCB->setChecked(false);
405 placementLE->setEnabled(false);
410 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
412 numberStepLE->setEnabled(index > 0);
413 numberFontSizeCO->setEnabled(index > 0);
417 void GuiListings::on_languageCO_currentIndexChanged(int index)
421 int default_dialect = 0;
422 dialectCO->addItem(qt_("No dialect"));
423 string const language = languages[index];
425 for (size_t i = 0; i != nr_dialects; ++i) {
426 if (language == dialects[i].language) {
427 dialectCO->addItem(qt_(dialects[i].gui));
428 if (dialects[i].is_default)
430 dialectCO->findText(qt_(dialects[i].gui));
433 dialectCO->setCurrentIndex(default_dialect);
434 dialectCO->setEnabled(dialectCO->count() > 1);
438 void GuiListings::applyView()
440 params_.setInline(inlineCB->isChecked());
441 params_.setParams(construct_params());
445 static string plainParam(std::string const & par)
447 // remove enclosing braces
448 if (prefixIs(par, "{") && suffixIs(par, "}"))
449 return par.substr(1, par.size() - 2);
454 void GuiListings::updateContents()
456 // set default values
457 listingsTB->setPlainText(
458 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
459 languageCO->setCurrentIndex(findToken(languages, "no language"));
460 dialectCO->setCurrentIndex(0);
461 floatCB->setChecked(false);
462 placementLE->clear();
463 numberSideCO->setCurrentIndex(0);
464 numberStepLE->clear();
465 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
466 firstlineLE->clear();
468 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
469 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
470 breaklinesCB->setChecked(false);
471 spaceCB->setChecked(false);
472 spaceInStringCB->setChecked(true);
473 extendedcharsCB->setChecked(false);
475 // set values from param string
476 inlineCB->setChecked(params_.isInline());
477 if (params_.isInline()) {
478 floatCB->setChecked(false);
479 placementLE->setEnabled(false);
481 // break other parameters and set values
482 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
483 // process each of them
484 for (vector<string>::iterator it = pars.begin();
485 it != pars.end(); ++it) {
486 if (prefixIs(*it, "language=")) {
487 string arg = plainParam(it->substr(9));
492 if (prefixIs(arg, "[") && contains(arg, "]")) {
493 string::size_type end_dialect = arg.find("]");
494 dialect = arg.substr(1, end_dialect - 1);
495 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(LyXView & lv) { return new GuiListings(lv); }
649 } // namespace frontend
653 #include "GuiListings_moc.cpp"