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 "insets/InsetListingsParams.h"
20 #include "support/convert.h"
21 #include "support/lstrings.h"
24 #include <QCloseEvent>
25 #include <QPushButton>
27 #include <QRegExpValidator>
32 using lyx::support::findToken;
33 using lyx::support::getVectorFromString;
34 using lyx::support::getStringFromVector;
35 using lyx::support::prefixIs;
36 using lyx::support::suffixIs;
37 using lyx::support::contains;
42 /////////////////////////////////////////////////////////////////////
46 /////////////////////////////////////////////////////////////////////
49 char const * languages[] =
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", "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", "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 GuiListingsDialog::GuiListingsDialog(GuiListings * form)
170 connect(okPB, SIGNAL(clicked()), form, SLOT(slotOK()));
171 connect(applyPB, SIGNAL(clicked()), form_, SLOT(slotApply()));
172 connect(closePB, SIGNAL(clicked()), form, SLOT(slotClose()));
174 connect(languageCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
175 connect(dialectCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
176 connect(inlineCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
177 connect(floatCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
178 connect(placementLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
179 connect(numberSideCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
180 connect(numberStepLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
181 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
182 connect(firstlineLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
183 connect(lastlineLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
184 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
185 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
186 connect(breaklinesCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
187 connect(spaceCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
188 connect(spaceInStringCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
189 connect(extendedcharsCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
191 connect(listingsED, SIGNAL(textChanged()), this, SLOT(change_adaptor()));
192 connect(listingsED, SIGNAL(textChanged()), this, SLOT(set_listings_msg()));
193 connect(bypassCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
194 connect(bypassCB, SIGNAL(clicked()), this, SLOT(set_listings_msg()));
196 for (int n = 0; languages[n][0]; ++n)
197 languageCO->addItem(qt_(languages_gui[n]));
199 for (int n = 0; font_styles[n][0]; ++n)
200 fontstyleCO->addItem(qt_(font_styles_gui[n]));
202 for (int n = 0; font_sizes[n][0]; ++n) {
203 QString font = qt_(font_sizes_gui[n]);
204 fontsizeCO->addItem(font);
205 numberFontSizeCO->addItem(font);
209 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
210 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
211 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
212 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
216 void GuiListingsDialog::closeEvent(QCloseEvent * e)
223 void GuiListingsDialog::change_adaptor()
229 string GuiListingsDialog::construct_params()
231 string language = languages[languageCO->currentIndex()];
233 string const dialect_gui = fromqstr(dialectCO->currentText());
234 if (dialectCO->currentIndex() > 0) {
235 for (size_t i = 0; i < nr_dialects; ++i) {
236 if (dialect_gui == dialects[i].gui
237 && dialects[i].language == language
238 && !dialects[i].is_default) {
239 dialect = dialects[i].dialect;
245 bool float_ = floatCB->isChecked();
247 if (placementLE->isEnabled())
248 placement = fromqstr(placementLE->text());
251 switch (numberSideCO->currentIndex()) {
259 numberSide = "right";
265 string stepnumber = fromqstr(numberStepLE->text());
266 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
267 string firstline = fromqstr(firstlineLE->text());
268 string lastline = fromqstr(lastlineLE->text());
270 string fontsize = font_sizes[fontsizeCO->currentIndex()];
271 string fontstyle = font_styles[fontstyleCO->currentIndex()];
273 if (fontsize != "default")
274 basicstyle = "\\" + fontsize;
275 if (fontstyle != "default")
276 basicstyle += "\\" + fontstyle;
277 bool breakline = breaklinesCB->isChecked();
278 bool space = spaceCB->isChecked();
279 bool spaceInString = spaceInStringCB->isChecked();
280 bool extendedchars = extendedcharsCB->isChecked();
281 string extra = fromqstr(listingsED->toPlainText());
284 InsetListingsParams par;
285 if (language != "no language" && !contains(extra, "language=")) {
287 par.addParam("language", language);
289 par.addParam("language", "{[" + dialect + "]" + language + "}");
291 // this dialog uses float=placement instead of float,floatplacement=placement
292 // because float accepts *tbph and floatplacement accepts bph.
293 // our placement textedit is actually for the float parameter
295 par.addParam("float", placement);
296 if (numberSide != "none")
297 par.addParam("numbers", numberSide);
298 if (numberfontsize != "default" && numberSide != "none")
299 par.addParam("numberstyle", "\\" + numberfontsize);
300 if (!stepnumber.empty() && numberSide != "none")
301 par.addParam("stepnumber", stepnumber);
302 if (!firstline.empty())
303 par.addParam("firstline", firstline);
304 if (!lastline.empty())
305 par.addParam("lastline", lastline);
306 if (!basicstyle.empty())
307 par.addParam("basicstyle", basicstyle);
309 par.addParam("breaklines", "true");
311 par.addParam("showspaces", "true");
313 par.addParam("showstringspaces", "false");
315 par.addParam("extendedchars", "true");
316 par.addParams(extra);
321 docstring GuiListingsDialog::validate_listings_params()
323 // use a cache here to avoid repeated validation
324 // of the same parameters
325 static string param_cache = string();
326 static docstring msg_cache = docstring();
328 if (bypassCB->isChecked())
331 string params = construct_params();
332 if (params != param_cache) {
333 param_cache = params;
334 msg_cache = InsetListingsParams(params).validate();
340 void GuiListingsDialog::set_listings_msg()
342 static bool isOK = true;
343 docstring msg = validate_listings_params();
348 listingsTB->setPlainText(
349 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
352 listingsTB->setPlainText(toqstr(msg));
357 void GuiListingsDialog::on_floatCB_stateChanged(int state)
359 if (state == Qt::Checked) {
360 inlineCB->setChecked(false);
361 placementLE->setEnabled(true);
363 placementLE->setEnabled(false);
367 void GuiListingsDialog::on_inlineCB_stateChanged(int state)
369 if (state == Qt::Checked) {
370 floatCB->setChecked(false);
371 placementLE->setEnabled(false);
376 void GuiListingsDialog::on_numberSideCO_currentIndexChanged(int index)
378 numberStepLE->setEnabled(index > 0);
379 numberFontSizeCO->setEnabled(index > 0);
383 void GuiListingsDialog::on_languageCO_currentIndexChanged(int index)
387 int default_dialect = 0;
388 dialectCO->addItem(qt_("No dialect"));
389 string const language = languages[index];
391 for (size_t i = 0; i < nr_dialects; ++i) {
392 if (language == dialects[i].language) {
393 dialectCO->addItem(qt_(dialects[i].gui));
394 if (dialects[i].is_default)
396 dialectCO->findText(qt_(dialects[i].gui));
399 dialectCO->setCurrentIndex(default_dialect);
400 dialectCO->setEnabled(dialectCO->count() > 1);
404 /////////////////////////////////////////////////////////////////////
408 /////////////////////////////////////////////////////////////////////
411 GuiListings::GuiListings(Dialog & parent)
412 : GuiView<GuiListingsDialog>(parent, _("Program Listing Settings"))
417 void GuiListings::build_dialog()
419 dialog_.reset(new GuiListingsDialog(this));
421 bcview().setOK(dialog_->okPB);
422 bcview().setApply(dialog_->applyPB);
423 bcview().setCancel(dialog_->closePB);
424 dialog_->listingsTB->setPlainText(
425 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
431 void GuiListings::apply()
433 InsetListingsParams & params = controller().params();
434 params.setInline(dialog_->inlineCB->isChecked());
435 params.setParams(dialog_->construct_params());
436 controller().setParams(params);
442 string plainParam(std::string const & par)
444 // remove enclosing braces
445 if (prefixIs(par, "{") && suffixIs(par, "}"))
446 return par.substr(1, par.size() - 2);
453 void GuiListings::update_contents()
455 // set default values
456 dialog_->listingsTB->setPlainText(
457 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
458 dialog_->languageCO->setCurrentIndex(findToken(languages, "no language"));
459 dialog_->dialectCO->setCurrentIndex(0);
460 dialog_->floatCB->setChecked(false);
461 dialog_->placementLE->clear();
462 dialog_->numberSideCO->setCurrentIndex(0);
463 dialog_->numberStepLE->clear();
464 dialog_->numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
465 dialog_->firstlineLE->clear();
466 dialog_->lastlineLE->clear();
467 dialog_->fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
468 dialog_->fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
469 dialog_->breaklinesCB->setChecked(false);
470 dialog_->spaceCB->setChecked(false);
471 dialog_->spaceInStringCB->setChecked(true);
472 dialog_->extendedcharsCB->setChecked(false);
474 // set values from param string
475 InsetListingsParams & params = controller().params();
476 dialog_->inlineCB->setChecked(params.isInline());
477 if (params.isInline()) {
478 dialog_->floatCB->setChecked(false);
479 dialog_->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 dialog_->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 = dialog_->dialectCO->findText(qt_(dialect_gui));
515 dialog_->dialectCO->setCurrentIndex(n);
521 dialog_->languageCO->setEnabled(in_gui);
522 dialog_->dialectCO->setEnabled(
523 in_gui && dialog_->dialectCO->count() > 1);
524 } else if (prefixIs(*it, "float")) {
525 dialog_->floatCB->setChecked(true);
526 dialog_->inlineCB->setChecked(false);
527 dialog_->placementLE->setEnabled(true);
528 if (prefixIs(*it, "float="))
529 dialog_->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 dialog_->numberSideCO->setCurrentIndex(n);
541 } else if (prefixIs(*it, "stepnumber=")) {
542 dialog_->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 dialog_->numberFontSizeCO->setCurrentIndex(n);
551 } else if (prefixIs(*it, "firstline=")) {
552 dialog_->firstlineLE->setText(
553 toqstr(plainParam(it->substr(10))));
555 } else if (prefixIs(*it, "lastline=")) {
556 dialog_->lastlineLE->setText(
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 dialog_->fontstyleCO->setCurrentIndex(n);
584 int n = findToken(font_sizes, size.substr(1));
586 dialog_->fontsizeCO->setCurrentIndex(n);
590 } else if (prefixIs(*it, "breaklines=")) {
591 dialog_->breaklinesCB->setChecked(contains(*it, "true"));
593 } else if (prefixIs(*it, "showspaces=")) {
594 dialog_->spaceCB->setChecked(contains(*it, "true"));
596 } else if (prefixIs(*it, "showstringspaces=")) {
597 dialog_->spaceInStringCB->setChecked(contains(*it, "true"));
599 } else if (prefixIs(*it, "extendedchars=")) {
600 dialog_->extendedcharsCB->setChecked(contains(*it, "true"));
605 dialog_->numberStepLE->setEnabled(dialog_->numberSideCO->currentIndex() > 0);
606 dialog_->numberFontSizeCO->setEnabled(dialog_->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 dialog_->listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
614 bool GuiListings::isValid()
616 return dialog_->validate_listings_params().empty();
620 } // namespace frontend
624 #include "GuiListings_moc.cpp"