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 "QListings.h"
16 #include "qt_helpers.h"
17 #include "controllers/ControlListings.h"
18 #include "insets/InsetListingsParams.h"
21 #include "support/convert.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;
43 /////////////////////////////////////////////////////////////////////
47 /////////////////////////////////////////////////////////////////////
50 char const * languages[] =
51 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
52 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
53 "Eiffel", "Elan", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
54 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
55 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
56 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
57 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
58 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
59 "VRML", "XML", "XSLT", "" };
62 char const * languages_gui[] =
63 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
64 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
65 "Eiffel", "Elan", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
66 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
67 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
68 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
69 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
70 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
71 "VRML", "XML", "XSLT", "" };
77 /// the associated language
78 char const * language;
79 /// representation of the dialect in the gui
81 /// is this the default dialect?
86 dialect_info const dialects[] = {
87 { "R/2 4.3", "ABAP", "R/2 4.3", false },
88 { "R/2 5.0", "ABAP", "R/2 5.0", false },
89 { "R/3 3.1", "ABAP", "R/3 3.1", false },
90 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
91 { "R/3 6.10", "ABAP", "R/3 6.10", true },
92 { "2005", "Ada", "2005", true },
93 { "83", "Ada", "83", false },
94 { "95", "Ada", "95", false },
95 { "60", "Algol", "60", false },
96 { "68", "Algol", "68", true },
97 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
98 { "x86masm", "Assembler", "x86 (MASM)", false },
99 { "gnu", "Awk", "gnu", true },
100 { "POSIX", "Awk", "POSIX", false },
101 { "Visual", "Basic", "Visual", false },
102 { "ANSI", "C", "ANSI", true },
103 { "Handel", "C", "Handel", false },
104 { "Objective", "C", "Objective", false },
105 { "Sharp", "C", "Sharp", false },
106 { "ANSI", "C++", "ANSI", false },
107 { "GNU", "C++", "GNU", false },
108 { "ISO", "C++", "ISO", true },
109 { "Visual", "C++", "Visual", false },
110 { "light", "Caml", "light", true },
111 { "Objective", "Caml", "Objective", false },
112 { "1974", "Cobol", "1974", false },
113 { "1985", "Cobol", "1985", true },
114 { "ibm", "Cobol", "IBM", false },
115 { "WinXP", "command.com", "Windows XP", true },
116 { "77", "Fortran", "77", false },
117 { "90", "Fortran", "90", false },
118 { "95", "Fortran", "95", true },
119 { "CORBA", "IDL", "CORBA", false },
120 { "AspectJ", "Java", "Aspect J", false },
121 { "Auto", "Lisp", "Auto", false },
122 { "gnu", "make", "gnu", false },
123 { "1.0", "Mathematica", "1.0", false },
124 { "3.0", "Mathematica", "3.0", false },
125 { "5.2", "Mathematica", "5.2", true },
126 { "decorative", "OCL", "decorative", false },
127 { "OMG", "OCL", "OMG", true },
128 { "Borland6", "Pascal", "Borland 6", false },
129 { "Standard", "Pascal", "Standard", true },
130 { "XSC", "Pascal", "XSC", false },
131 { "PLUS", "S", "PLUS", false },
132 { "67", "Simula", "67", true },
133 { "CII", "Simula", "CII", false },
134 { "DEC", "Simula", "DEC", false },
135 { "IBM", "Simula", "IBM", false },
136 { "tk", "tcl", "tk", false },
137 { "AlLaTeX", "TeX", "AlLaTeX", false },
138 { "common", "TeX", N_("common"), false },
139 { "LaTeX", "TeX", "LaTeX", false },
140 { "plain", "TeX", N_("plain"), true },
141 { "primitive", "TeX", N_("primitive"), false },
142 { "AMS", "VHDL", "AMS", false },
143 { "97", "VRML", "97", true }
147 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
150 char const * font_sizes[] =
151 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
154 char const * font_sizes_gui[] =
155 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
156 N_("Large"), N_("Larger"), "" };
158 char const * font_styles[] =
159 { "default", "rmfamily", "ttfamily", "sffamily", "" };
161 char const * font_styles_gui[] =
162 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
166 QListingsDialog::QListingsDialog(QListings * form)
171 connect(okPB, SIGNAL(clicked()), form, SLOT(slotOK()));
172 connect(applyPB, SIGNAL(clicked()), form_, SLOT(slotApply()));
173 connect(closePB, SIGNAL(clicked()), form, SLOT(slotClose()));
175 connect(languageCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
176 connect(dialectCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
177 connect(inlineCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
178 connect(floatCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
179 connect(placementLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
180 connect(numberSideCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
181 connect(numberStepLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
182 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
183 connect(firstlineLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
184 connect(lastlineLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
185 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
186 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
187 connect(breaklinesCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
188 connect(spaceCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
189 connect(spaceInStringCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
190 connect(extendedcharsCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
192 connect(listingsED, SIGNAL(textChanged()), this, SLOT(change_adaptor()));
193 connect(listingsED, SIGNAL(textChanged()), this, SLOT(validate_listings_params()));
195 for (int n = 0; languages[n][0]; ++n)
196 languageCO->addItem(languages_gui[n]);
198 for (int n = 0; font_styles[n][0]; ++n)
199 fontstyleCO->addItem(font_styles_gui[n]);
201 for (int n = 0; font_sizes[n][0]; ++n) {
202 QString font = toqstr(font_sizes_gui[n]);
203 fontsizeCO->addItem(font);
204 numberFontSizeCO->addItem(font);
208 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
209 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
210 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
211 placementLE->setValidator(new QRegExpValidator(QRegExp("[tbph]*"), this));
215 void QListingsDialog::closeEvent(QCloseEvent * e)
222 void QListingsDialog::change_adaptor()
228 string QListingsDialog::construct_params()
230 string language = languages[languageCO->currentIndex()];
232 string const dialect_gui = fromqstr(dialectCO->currentText());
233 if (dialectCO->currentIndex() > 0) {
234 for (size_t i = 0; i < nr_dialects; ++i) {
235 if (dialect_gui == dialects[i].gui
236 && dialects[i].language == language
237 && !dialects[i].is_default) {
238 dialect = dialects[i].dialect;
244 bool float_ = floatCB->isChecked();
246 if (placementLE->isEnabled())
247 placement = fromqstr(placementLE->text());
250 switch (numberSideCO->currentIndex()) {
258 numberSide = "right";
264 string stepnumber = fromqstr(numberStepLE->text());
265 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
266 string firstline = fromqstr(firstlineLE->text());
267 string lastline = fromqstr(lastlineLE->text());
269 string fontsize = font_sizes[fontsizeCO->currentIndex()];
270 string fontstyle = font_styles[fontstyleCO->currentIndex()];
272 if (fontsize != "default")
273 basicstyle = "\\" + fontsize;
274 if (fontstyle != "default")
275 basicstyle += "\\" + fontstyle;
276 bool breakline = breaklinesCB->isChecked();
277 bool space = spaceCB->isChecked();
278 bool spaceInString = spaceInStringCB->isChecked();
279 bool extendedchars = extendedcharsCB->isChecked();
280 string extra = fromqstr(listingsED->toPlainText());
283 InsetListingsParams par;
284 if (language != "no language" && !contains(extra, "language=")) {
286 par.addParam("language", language);
288 par.addParam("language", "{[" + dialect + "]" + language + "}");
291 par.addParam("float", "");
292 if (!placement.empty())
293 par.addParam("floatplacement", placement);
294 if (numberSide != "none")
295 par.addParam("numbers", numberSide);
296 if (numberfontsize != "default" && numberSide != "none")
297 par.addParam("numberstyle", "\\" + numberfontsize);
298 if (!stepnumber.empty() && numberSide != "none")
299 par.addParam("stepnumber", stepnumber);
300 if (!firstline.empty())
301 par.addParam("firstline", firstline);
302 if (!lastline.empty())
303 par.addParam("lastline", lastline);
304 if (!basicstyle.empty())
305 par.addParam("basicstyle", basicstyle);
307 par.addParam("breaklines", "true");
309 par.addParam("showspaces", "true");
311 par.addParam("showstringspaces", "false");
313 par.addParam("extendedchars", "true");
314 par.addParams(extra);
319 void QListingsDialog::validate_listings_params()
321 static bool isOK = true;
323 InsetListingsParams par(construct_params());
326 listingsTB->setPlainText(
327 qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
328 okPB->setEnabled(true);
329 applyPB->setEnabled(true);
331 } catch (invalidParam & e) {
333 listingsTB->setPlainText(toqstr(e.what()));
334 okPB->setEnabled(false);
335 applyPB->setEnabled(false);
340 void QListingsDialog::on_floatCB_stateChanged(int state)
342 if (state == Qt::Checked) {
343 inlineCB->setChecked(false);
344 placementLE->setEnabled(true);
346 placementLE->setEnabled(false);
350 void QListingsDialog::on_inlineCB_stateChanged(int state)
352 if (state == Qt::Checked) {
353 floatCB->setChecked(false);
354 placementLE->setEnabled(false);
359 void QListingsDialog::on_numberSideCO_currentIndexChanged(int index)
361 numberStepLE->setEnabled(index > 0);
362 numberFontSizeCO->setEnabled(index > 0);
366 void QListingsDialog::on_languageCO_currentIndexChanged(int index)
370 int default_dialect = 0;
371 dialectCO->addItem(qt_("No dialect"));
372 string const language = languages[index];
374 for (size_t i = 0; i < nr_dialects; ++i) {
375 if (language == dialects[i].language) {
376 dialectCO->addItem(dialects[i].gui);
377 if (dialects[i].is_default)
379 dialectCO->findText(dialects[i].gui);
382 dialectCO->setCurrentIndex(default_dialect);
383 dialectCO->setEnabled(dialectCO->count() > 1);
387 /////////////////////////////////////////////////////////////////////
391 /////////////////////////////////////////////////////////////////////
393 typedef QController<ControlListings, QView<QListingsDialog> > listings_wrap_base_class;
395 QListings::QListings(Dialog & parent)
396 : listings_wrap_base_class(parent, _("Program Listings Settings"))
401 void QListings::build_dialog()
403 dialog_.reset(new QListingsDialog(this));
405 bcview().setOK(dialog_->okPB);
406 bcview().setApply(dialog_->applyPB);
407 bcview().setCancel(dialog_->closePB);
408 dialog_->listingsTB->setPlainText(
409 qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
415 void QListings::apply()
417 InsetListingsParams & params = controller().params();
418 params.setInline(dialog_->inlineCB->isChecked());
419 params.setParams(dialog_->construct_params());
420 controller().setParams(params);
426 string plainParam(std::string const & par)
428 // remove enclosing braces
429 if (prefixIs(par, "{") && suffixIs(par, "}"))
430 return par.substr(1, par.size() - 2);
437 void QListings::update_contents()
439 // set default values
440 dialog_->listingsTB->setPlainText(
441 qt_("Input listings parameters on the right. Enter ? for a list of parameters."));
442 dialog_->languageCO->setCurrentIndex(findToken(languages, "no language"));
443 dialog_->dialectCO->setCurrentIndex(0);
444 dialog_->floatCB->setChecked(false);
445 dialog_->placementLE->clear();
446 dialog_->numberSideCO->setCurrentIndex(0);
447 dialog_->numberStepLE->clear();
448 dialog_->numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
449 dialog_->firstlineLE->clear();
450 dialog_->lastlineLE->clear();
451 dialog_->fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
452 dialog_->fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
453 dialog_->breaklinesCB->setChecked(false);
454 dialog_->spaceCB->setChecked(false);
455 dialog_->spaceInStringCB->setChecked(true);
456 dialog_->extendedcharsCB->setChecked(false);
458 // set values from param string
459 InsetListingsParams & params = controller().params();
460 dialog_->inlineCB->setChecked(params.isInline());
461 if (params.isInline()) {
462 dialog_->floatCB->setChecked(false);
463 dialog_->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 string::size_type end_dialect = arg.find("]");
478 dialect = arg.substr(1, end_dialect - 1);
479 language = arg.substr(end_dialect + 1);
482 int n = findToken(languages, language);
484 dialog_->languageCO->setCurrentIndex(n);
487 // on_languageCO_currentIndexChanged should have set dialects
488 if (!dialect.empty()) {
490 for (size_t i = 0; i < nr_dialects; ++i) {
491 if (dialect == dialects[i].dialect
492 && dialects[i].language == language) {
493 dialect_gui = dialects[i].gui;
497 n = dialog_->dialectCO->findText(toqstr(dialect_gui));
499 dialog_->dialectCO->setCurrentIndex(n);
505 dialog_->languageCO->setEnabled(in_gui);
506 dialog_->dialectCO->setEnabled(
507 in_gui && dialog_->dialectCO->count() > 1);
508 } else if (prefixIs(*it, "floatplacement=")) {
509 dialog_->floatCB->setChecked(true);
510 dialog_->placementLE->setEnabled(true);
511 dialog_->placementLE->setText(
512 toqstr(plainParam(it->substr(15))));
513 dialog_->inlineCB->setChecked(false);
515 } else if (prefixIs(*it, "float")) {
516 dialog_->floatCB->setChecked(true);
517 dialog_->inlineCB->setChecked(false);
518 dialog_->placementLE->setEnabled(true);
519 if (prefixIs(*it, "float="))
520 dialog_->placementLE->setText(
521 toqstr(plainParam(it->substr(6))));
523 } else if (prefixIs(*it, "numbers=")) {
524 string s = plainParam(it->substr(8));
528 else if (s == "right")
530 dialog_->numberSideCO->setCurrentIndex(n);
532 } else if (prefixIs(*it, "stepnumber=")) {
533 dialog_->numberStepLE->setText(
534 toqstr(plainParam(it->substr(11))));
536 } else if (prefixIs(*it, "numberstyle=")) {
537 string par = plainParam(it->substr(12));
538 int n = findToken(font_sizes, par.substr(1));
540 dialog_->numberFontSizeCO->setCurrentIndex(n);
542 } else if (prefixIs(*it, "firstline=")) {
543 dialog_->firstlineLE->setText(
544 toqstr(plainParam(it->substr(10))));
546 } else if (prefixIs(*it, "lastline=")) {
547 dialog_->lastlineLE->setText(
548 toqstr(plainParam(it->substr(9))));
550 } else if (prefixIs(*it, "basicstyle=")) {
553 for (int n = 0; font_styles[n][0]; ++n) {
554 string const s = font_styles[n];
555 if (contains(*it, "\\" + s)) {
560 for (int n = 0; font_sizes[n][0]; ++n) {
561 string const s = font_sizes[n];
562 if (contains(*it, "\\" + s)) {
567 if (plainParam(it->substr(11)) == style + size
568 || plainParam(it->substr(11)) == size + style) {
569 if (!style.empty()) {
570 int n = findToken(font_styles, style.substr(1));
572 dialog_->fontstyleCO->setCurrentIndex(n);
575 int n = findToken(font_sizes, size.substr(1));
577 dialog_->fontsizeCO->setCurrentIndex(n);
581 } else if (prefixIs(*it, "breaklines=")) {
582 dialog_->breaklinesCB->setChecked(contains(*it, "true"));
584 } else if (prefixIs(*it, "showspaces=")) {
585 dialog_->spaceCB->setChecked(contains(*it, "true"));
587 } else if (prefixIs(*it, "showstringspaces=")) {
588 dialog_->spaceInStringCB->setChecked(contains(*it, "true"));
590 } else if (prefixIs(*it, "extendedchars=")) {
591 dialog_->extendedcharsCB->setChecked(contains(*it, "true"));
596 dialog_->numberStepLE->setEnabled(dialog_->numberSideCO->currentIndex() > 0);
597 dialog_->numberFontSizeCO->setEnabled(dialog_->numberSideCO->currentIndex() > 0);
598 // parameters that can be handled by widgets are cleared
599 // the rest is put to the extra edit box.
600 string extra = getStringFromVector(pars);
601 dialog_->listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
605 } // namespace frontend
609 #include "QListings_moc.cpp"