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"
15 #include "qt_helpers.h"
16 #include "insets/InsetListingsParams.h"
19 #include "support/convert.h"
20 #include "support/lstrings.h"
23 #include <QCloseEvent>
24 #include <QPushButton>
26 #include <QRegExpValidator>
31 using lyx::support::findToken;
32 using lyx::support::getVectorFromString;
33 using lyx::support::getStringFromVector;
34 using lyx::support::prefixIs;
35 using lyx::support::suffixIs;
36 using lyx::support::contains;
41 /////////////////////////////////////////////////////////////////////
45 /////////////////////////////////////////////////////////////////////
48 char const * languages[] =
49 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
50 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
51 "Eiffel", "Elan", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
52 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
53 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
54 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
55 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
56 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
57 "VRML", "XML", "XSLT", "" };
60 char const * languages_gui[] =
61 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
62 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
63 "Eiffel", "Elan", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
64 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
65 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
66 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
67 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
68 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
69 "VRML", "XML", "XSLT", "" };
75 /// the associated language
76 char const * language;
77 /// representation of the dialect in the gui
79 /// is this the default dialect?
84 dialect_info const dialects[] = {
85 { "R/2 4.3", "ABAP", "R/2 4.3", false },
86 { "R/2 5.0", "ABAP", "R/2 5.0", false },
87 { "R/3 3.1", "ABAP", "R/3 3.1", false },
88 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
89 { "R/3 6.10", "ABAP", "R/3 6.10", true },
90 { "2005", "Ada", "2005", true },
91 { "83", "Ada", "83", false },
92 { "95", "Ada", "95", false },
93 { "60", "Algol", "60", false },
94 { "68", "Algol", "68", true },
95 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
96 { "x86masm", "Assembler", "x86 (MASM)", false },
97 { "gnu", "Awk", "gnu", true },
98 { "POSIX", "Awk", "POSIX", false },
99 { "Visual", "Basic", "Visual", false },
100 { "ANSI", "C", "ANSI", true },
101 { "Handel", "C", "Handel", false },
102 { "Objective", "C", "Objective", false },
103 { "Sharp", "C", "Sharp", false },
104 { "ANSI", "C++", "ANSI", false },
105 { "GNU", "C++", "GNU", false },
106 { "ISO", "C++", "ISO", true },
107 { "Visual", "C++", "Visual", false },
108 { "light", "Caml", "light", true },
109 { "Objective", "Caml", "Objective", false },
110 { "1974", "Cobol", "1974", false },
111 { "1985", "Cobol", "1985", true },
112 { "ibm", "Cobol", "IBM", false },
113 { "WinXP", "command.com", "Windows XP", true },
114 { "77", "Fortran", "77", false },
115 { "90", "Fortran", "90", false },
116 { "95", "Fortran", "95", true },
117 { "CORBA", "IDL", "CORBA", false },
118 { "AspectJ", "Java", "Aspect J", false },
119 { "Auto", "Lisp", "Auto", false },
120 { "gnu", "make", "gnu", false },
121 { "1.0", "Mathematica", "1.0", false },
122 { "3.0", "Mathematica", "3.0", false },
123 { "5.2", "Mathematica", "5.2", true },
124 { "decorative", "OCL", "decorative", false },
125 { "OMG", "OCL", "OMG", true },
126 { "Borland6", "Pascal", "Borland 6", false },
127 { "Standard", "Pascal", "Standard", true },
128 { "XSC", "Pascal", "XSC", false },
129 { "PLUS", "S", "PLUS", false },
130 { "67", "Simula", "67", true },
131 { "CII", "Simula", "CII", false },
132 { "DEC", "Simula", "DEC", false },
133 { "IBM", "Simula", "IBM", false },
134 { "tk", "tcl", "tk", false },
135 { "AlLaTeX", "TeX", "AlLaTeX", false },
136 { "common", "TeX", "common", false },
137 { "LaTeX", "TeX", "LaTeX", false },
138 { "plain", "TeX", "plain", true },
139 { "primitive", "TeX", "primitive", false },
140 { "AMS", "VHDL", "AMS", false },
141 { "97", "VRML", "97", true }
145 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
148 char const * font_sizes[] =
149 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
152 char const * font_sizes_gui[] =
153 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
154 N_("Large"), N_("Larger"), "" };
156 char const * font_styles[] =
157 { "default", "rmfamily", "ttfamily", "sffamily", "" };
159 char const * font_styles_gui[] =
160 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
164 GuiListingsDialog::GuiListingsDialog(GuiListings * form)
169 connect(okPB, SIGNAL(clicked()), form, SLOT(slotOK()));
170 connect(applyPB, SIGNAL(clicked()), form_, SLOT(slotApply()));
171 connect(closePB, SIGNAL(clicked()), form, SLOT(slotClose()));
173 connect(languageCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
174 connect(dialectCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
175 connect(inlineCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
176 connect(floatCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
177 connect(placementLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
178 connect(numberSideCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
179 connect(numberStepLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
180 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
181 connect(firstlineLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
182 connect(lastlineLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
183 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
184 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
185 connect(breaklinesCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
186 connect(spaceCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
187 connect(spaceInStringCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
188 connect(extendedcharsCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
190 connect(listingsED, SIGNAL(textChanged()), this, SLOT(change_adaptor()));
191 connect(listingsED, SIGNAL(textChanged()), this, SLOT(set_listings_msg()));
192 connect(bypassCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
193 connect(bypassCB, SIGNAL(clicked()), this, SLOT(set_listings_msg()));
195 for (int n = 0; languages[n][0]; ++n)
196 languageCO->addItem(qt_(languages_gui[n]));
198 for (int n = 0; font_styles[n][0]; ++n)
199 fontstyleCO->addItem(qt_(font_styles_gui[n]));
201 for (int n = 0; font_sizes[n][0]; ++n) {
202 QString font = qt_(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 GuiListingsDialog::closeEvent(QCloseEvent * e)
222 void GuiListingsDialog::change_adaptor()
228 string GuiListingsDialog::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 + "}");
290 // this dialog uses float=placement instead of float,floatplacement=placement
291 // because float accepts *tbph and floatplacement accepts bph.
292 // our placement textedit is actually for the float parameter
294 par.addParam("float", placement);
295 if (numberSide != "none")
296 par.addParam("numbers", numberSide);
297 if (numberfontsize != "default" && numberSide != "none")
298 par.addParam("numberstyle", "\\" + numberfontsize);
299 if (!stepnumber.empty() && numberSide != "none")
300 par.addParam("stepnumber", stepnumber);
301 if (!firstline.empty())
302 par.addParam("firstline", firstline);
303 if (!lastline.empty())
304 par.addParam("lastline", lastline);
305 if (!basicstyle.empty())
306 par.addParam("basicstyle", basicstyle);
308 par.addParam("breaklines", "true");
310 par.addParam("showspaces", "true");
312 par.addParam("showstringspaces", "false");
314 par.addParam("extendedchars", "true");
315 par.addParams(extra);
320 docstring GuiListingsDialog::validate_listings_params()
322 // use a cache here to avoid repeated validation
323 // of the same parameters
324 static string param_cache = string();
325 static docstring msg_cache = docstring();
327 if (bypassCB->isChecked())
330 string params = construct_params();
331 if (params != param_cache) {
332 param_cache = params;
333 msg_cache = InsetListingsParams(params).validate();
339 void GuiListingsDialog::set_listings_msg()
341 static bool isOK = true;
342 docstring msg = validate_listings_params();
347 listingsTB->setPlainText(
348 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
351 listingsTB->setPlainText(toqstr(msg));
356 void GuiListingsDialog::on_floatCB_stateChanged(int state)
358 if (state == Qt::Checked) {
359 inlineCB->setChecked(false);
360 placementLE->setEnabled(true);
362 placementLE->setEnabled(false);
366 void GuiListingsDialog::on_inlineCB_stateChanged(int state)
368 if (state == Qt::Checked) {
369 floatCB->setChecked(false);
370 placementLE->setEnabled(false);
375 void GuiListingsDialog::on_numberSideCO_currentIndexChanged(int index)
377 numberStepLE->setEnabled(index > 0);
378 numberFontSizeCO->setEnabled(index > 0);
382 void GuiListingsDialog::on_languageCO_currentIndexChanged(int index)
386 int default_dialect = 0;
387 dialectCO->addItem(qt_("No dialect"));
388 string const language = languages[index];
390 for (size_t i = 0; i < nr_dialects; ++i) {
391 if (language == dialects[i].language) {
392 dialectCO->addItem(qt_(dialects[i].gui));
393 if (dialects[i].is_default)
395 dialectCO->findText(qt_(dialects[i].gui));
398 dialectCO->setCurrentIndex(default_dialect);
399 dialectCO->setEnabled(dialectCO->count() > 1);
403 /////////////////////////////////////////////////////////////////////
407 /////////////////////////////////////////////////////////////////////
410 GuiListings::GuiListings(GuiDialog & parent)
411 : GuiView<GuiListingsDialog>(parent, _("Program Listing Settings"))
416 void GuiListings::build_dialog()
418 dialog_.reset(new GuiListingsDialog(this));
420 bc().setOK(dialog_->okPB);
421 bc().setApply(dialog_->applyPB);
422 bc().setCancel(dialog_->closePB);
423 dialog_->listingsTB->setPlainText(
424 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
430 void GuiListings::applyView()
432 InsetListingsParams & params = controller().params();
433 params.setInline(dialog_->inlineCB->isChecked());
434 params.setParams(dialog_->construct_params());
435 controller().setParams(params);
441 string plainParam(std::string const & par)
443 // remove enclosing braces
444 if (prefixIs(par, "{") && suffixIs(par, "}"))
445 return par.substr(1, par.size() - 2);
452 void GuiListings::update_contents()
454 // set default values
455 dialog_->listingsTB->setPlainText(
456 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
457 dialog_->languageCO->setCurrentIndex(findToken(languages, "no language"));
458 dialog_->dialectCO->setCurrentIndex(0);
459 dialog_->floatCB->setChecked(false);
460 dialog_->placementLE->clear();
461 dialog_->numberSideCO->setCurrentIndex(0);
462 dialog_->numberStepLE->clear();
463 dialog_->numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
464 dialog_->firstlineLE->clear();
465 dialog_->lastlineLE->clear();
466 dialog_->fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
467 dialog_->fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
468 dialog_->breaklinesCB->setChecked(false);
469 dialog_->spaceCB->setChecked(false);
470 dialog_->spaceInStringCB->setChecked(true);
471 dialog_->extendedcharsCB->setChecked(false);
473 // set values from param string
474 InsetListingsParams & params = controller().params();
475 dialog_->inlineCB->setChecked(params.isInline());
476 if (params.isInline()) {
477 dialog_->floatCB->setChecked(false);
478 dialog_->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 string::size_type end_dialect = arg.find("]");
493 dialect = arg.substr(1, end_dialect - 1);
494 language = arg.substr(end_dialect + 1);
497 int n = findToken(languages, language);
499 dialog_->languageCO->setCurrentIndex(n);
502 // on_languageCO_currentIndexChanged should have set dialects
503 if (!dialect.empty()) {
505 for (size_t i = 0; i < nr_dialects; ++i) {
506 if (dialect == dialects[i].dialect
507 && dialects[i].language == language) {
508 dialect_gui = dialects[i].gui;
512 n = dialog_->dialectCO->findText(qt_(dialect_gui));
514 dialog_->dialectCO->setCurrentIndex(n);
520 dialog_->languageCO->setEnabled(in_gui);
521 dialog_->dialectCO->setEnabled(
522 in_gui && dialog_->dialectCO->count() > 1);
523 } else if (prefixIs(*it, "float")) {
524 dialog_->floatCB->setChecked(true);
525 dialog_->inlineCB->setChecked(false);
526 dialog_->placementLE->setEnabled(true);
527 if (prefixIs(*it, "float="))
528 dialog_->placementLE->setText(
529 toqstr(plainParam(it->substr(6))));
531 } else if (prefixIs(*it, "numbers=")) {
532 string s = plainParam(it->substr(8));
536 else if (s == "right")
538 dialog_->numberSideCO->setCurrentIndex(n);
540 } else if (prefixIs(*it, "stepnumber=")) {
541 dialog_->numberStepLE->setText(
542 toqstr(plainParam(it->substr(11))));
544 } else if (prefixIs(*it, "numberstyle=")) {
545 string par = plainParam(it->substr(12));
546 int n = findToken(font_sizes, par.substr(1));
548 dialog_->numberFontSizeCO->setCurrentIndex(n);
550 } else if (prefixIs(*it, "firstline=")) {
551 dialog_->firstlineLE->setText(
552 toqstr(plainParam(it->substr(10))));
554 } else if (prefixIs(*it, "lastline=")) {
555 dialog_->lastlineLE->setText(
556 toqstr(plainParam(it->substr(9))));
558 } else if (prefixIs(*it, "basicstyle=")) {
561 for (int n = 0; font_styles[n][0]; ++n) {
562 string const s = font_styles[n];
563 if (contains(*it, "\\" + s)) {
568 for (int n = 0; font_sizes[n][0]; ++n) {
569 string const s = font_sizes[n];
570 if (contains(*it, "\\" + s)) {
575 if (plainParam(it->substr(11)) == style + size
576 || plainParam(it->substr(11)) == size + style) {
577 if (!style.empty()) {
578 int n = findToken(font_styles, style.substr(1));
580 dialog_->fontstyleCO->setCurrentIndex(n);
583 int n = findToken(font_sizes, size.substr(1));
585 dialog_->fontsizeCO->setCurrentIndex(n);
589 } else if (prefixIs(*it, "breaklines=")) {
590 dialog_->breaklinesCB->setChecked(contains(*it, "true"));
592 } else if (prefixIs(*it, "showspaces=")) {
593 dialog_->spaceCB->setChecked(contains(*it, "true"));
595 } else if (prefixIs(*it, "showstringspaces=")) {
596 dialog_->spaceInStringCB->setChecked(contains(*it, "true"));
598 } else if (prefixIs(*it, "extendedchars=")) {
599 dialog_->extendedcharsCB->setChecked(contains(*it, "true"));
604 dialog_->numberStepLE->setEnabled(dialog_->numberSideCO->currentIndex() > 0);
605 dialog_->numberFontSizeCO->setEnabled(dialog_->numberSideCO->currentIndex() > 0);
606 // parameters that can be handled by widgets are cleared
607 // the rest is put to the extra edit box.
608 string extra = getStringFromVector(pars);
609 dialog_->listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
613 bool GuiListings::isValid()
615 return dialog_->validate_listings_params().empty();
619 } // namespace frontend
623 #include "GuiListings_moc.cpp"