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>
31 using namespace lyx::support;
37 /////////////////////////////////////////////////////////////////////
41 /////////////////////////////////////////////////////////////////////
44 char const * languages[] =
45 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
46 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
47 "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
48 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
49 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
50 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
51 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
52 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
53 "VRML", "XML", "XSLT", "" };
56 char const * languages_gui[] =
57 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
58 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
59 "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
60 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
61 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
62 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
63 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
64 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
65 "VRML", "XML", "XSLT", "" };
71 /// the associated language
72 char const * language;
73 /// representation of the dialect in the gui
75 /// is this the default dialect?
80 dialect_info const dialects[] = {
81 { "R/2 4.3", "ABAP", "R/2 4.3", false },
82 { "R/2 5.0", "ABAP", "R/2 5.0", false },
83 { "R/3 3.1", "ABAP", "R/3 3.1", false },
84 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
85 { "R/3 6.10", "ABAP", "R/3 6.10", true },
86 { "2005", "Ada", "2005", true },
87 { "83", "Ada", "83", false },
88 { "95", "Ada", "95", false },
89 { "60", "Algol", "60", false },
90 { "68", "Algol", "68", true },
91 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
92 { "x86masm", "Assembler", "x86 (MASM)", false },
93 { "gnu", "Awk", "gnu", true },
94 { "POSIX", "Awk", "POSIX", false },
95 { "Visual", "Basic", "Visual", false },
96 { "ANSI", "C", "ANSI", true },
97 { "Handel", "C", "Handel", false },
98 { "Objective", "C", "Objective", false },
99 { "Sharp", "C", "Sharp", false },
100 { "ANSI", "C++", "ANSI", false },
101 { "GNU", "C++", "GNU", false },
102 { "ISO", "C++", "ISO", true },
103 { "Visual", "C++", "Visual", false },
104 { "light", "Caml", "light", true },
105 { "Objective", "Caml", "Objective", false },
106 { "1974", "Cobol", "1974", false },
107 { "1985", "Cobol", "1985", true },
108 { "ibm", "Cobol", "IBM", false },
109 { "WinXP", "command.com", "Windows XP", true },
110 { "77", "Fortran", "77", false },
111 { "90", "Fortran", "90", false },
112 { "95", "Fortran", "95", true },
113 { "CORBA", "IDL", "CORBA", false },
114 { "AspectJ", "Java", "Aspect J", false },
115 { "Auto", "Lisp", "Auto", false },
116 { "gnu", "make", "gnu", false },
117 { "1.0", "Mathematica", "1.0", false },
118 { "3.0", "Mathematica", "3.0", false },
119 { "5.2", "Mathematica", "5.2", true },
120 { "decorative", "OCL", "decorative", false },
121 { "OMG", "OCL", "OMG", true },
122 { "Borland6", "Pascal", "Borland 6", false },
123 { "Standard", "Pascal", "Standard", true },
124 { "XSC", "Pascal", "XSC", false },
125 { "PLUS", "S", "PLUS", false },
126 { "67", "Simula", "67", true },
127 { "CII", "Simula", "CII", false },
128 { "DEC", "Simula", "DEC", false },
129 { "IBM", "Simula", "IBM", false },
130 { "tk", "tcl", "tk", false },
131 { "AlLaTeX", "TeX", "AlLaTeX", false },
132 { "common", "TeX", "common", false },
133 { "LaTeX", "TeX", "LaTeX", false },
134 { "plain", "TeX", "plain", true },
135 { "primitive", "TeX", "primitive", false },
136 { "AMS", "VHDL", "AMS", false },
137 { "97", "VRML", "97", true }
141 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
144 char const * font_sizes[] =
145 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
148 char const * font_sizes_gui[] =
149 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
150 N_("Large"), N_("Larger"), "" };
152 char const * font_styles[] =
153 { "default", "rmfamily", "ttfamily", "sffamily", "" };
155 char const * font_styles_gui[] =
156 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
160 GuiListings::GuiListings(GuiView & lv)
161 : GuiDialog(lv, "listings")
164 setViewTitle(_("Program Listing Settings"));
166 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
167 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
168 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
170 connect(languageCO, SIGNAL(currentIndexChanged(int)),
171 this, SLOT(change_adaptor()));
172 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
173 this, SLOT(change_adaptor()));
174 connect(inlineCB, SIGNAL(clicked()),
175 this, SLOT(change_adaptor()));
176 connect(floatCB, SIGNAL(clicked()),
177 this, SLOT(change_adaptor()));
178 connect(placementLE, SIGNAL(textChanged(QString)),
179 this, SLOT(change_adaptor()));
180 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
181 this, SLOT(change_adaptor()));
182 connect(numberStepLE, SIGNAL(textChanged(QString)),
183 this, SLOT(change_adaptor()));
184 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
185 this, SLOT(change_adaptor()));
186 connect(firstlineLE, SIGNAL(textChanged(QString)),
187 this, SLOT(change_adaptor()));
188 connect(lastlineLE, SIGNAL(textChanged(QString)),
189 this, SLOT(change_adaptor()));
190 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
191 this, SLOT(change_adaptor()));
192 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
193 this, SLOT(change_adaptor()));
194 connect(breaklinesCB, SIGNAL(clicked()),
195 this, SLOT(change_adaptor()));
196 connect(spaceCB, SIGNAL(clicked()),
197 this, SLOT(change_adaptor()));
198 connect(spaceInStringCB, SIGNAL(clicked()),
199 this, SLOT(change_adaptor()));
200 connect(extendedcharsCB, SIGNAL(clicked()),
201 this, SLOT(change_adaptor()));
203 connect(listingsED, SIGNAL(textChanged()),
204 this, SLOT(change_adaptor()));
205 connect(listingsED, SIGNAL(textChanged()),
206 this, SLOT(set_listings_msg()));
207 connect(bypassCB, SIGNAL(clicked()),
208 this, SLOT(change_adaptor()));
209 connect(bypassCB, SIGNAL(clicked()),
210 this, SLOT(set_listings_msg()));
212 for (int n = 0; languages[n][0]; ++n)
213 languageCO->addItem(qt_(languages_gui[n]));
215 for (int n = 0; font_styles[n][0]; ++n)
216 fontstyleCO->addItem(qt_(font_styles_gui[n]));
218 for (int n = 0; font_sizes[n][0]; ++n) {
219 QString font = qt_(font_sizes_gui[n]);
220 fontsizeCO->addItem(font);
221 numberFontSizeCO->addItem(font);
225 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
226 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
227 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
228 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
231 bc().setApply(applyPB);
232 bc().setCancel(closePB);
233 listingsTB->setPlainText(
234 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
241 void GuiListings::closeEvent(QCloseEvent * e)
248 void GuiListings::change_adaptor()
254 string GuiListings::construct_params()
256 string language = languages[languageCO->currentIndex()];
258 string const dialect_gui = fromqstr(dialectCO->currentText());
259 if (dialectCO->currentIndex() > 0) {
260 for (size_t i = 0; i != nr_dialects; ++i) {
261 if (dialect_gui == dialects[i].gui
262 && dialects[i].language == language
263 && !dialects[i].is_default) {
264 dialect = dialects[i].dialect;
270 bool float_ = floatCB->isChecked();
272 if (placementLE->isEnabled())
273 placement = fromqstr(placementLE->text());
276 switch (numberSideCO->currentIndex()) {
284 numberSide = "right";
290 string stepnumber = fromqstr(numberStepLE->text());
291 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
292 string firstline = fromqstr(firstlineLE->text());
293 string lastline = fromqstr(lastlineLE->text());
295 string fontsize = font_sizes[fontsizeCO->currentIndex()];
296 string fontstyle = font_styles[fontstyleCO->currentIndex()];
298 if (fontsize != "default")
299 basicstyle = "\\" + fontsize;
300 if (fontstyle != "default")
301 basicstyle += "\\" + fontstyle;
302 bool breakline = breaklinesCB->isChecked();
303 bool space = spaceCB->isChecked();
304 bool spaceInString = spaceInStringCB->isChecked();
305 bool extendedchars = extendedcharsCB->isChecked();
306 string extra = fromqstr(listingsED->toPlainText());
309 InsetListingsParams par;
310 if (language != "no language" && !contains(extra, "language=")) {
312 par.addParam("language", language);
314 par.addParam("language", "{[" + dialect + "]" + language + "}");
316 // this dialog uses float=placement instead of float,floatplacement=placement
317 // because float accepts *tbph and floatplacement accepts bph.
318 // our placement textedit is actually for the float parameter
320 par.addParam("float", placement);
321 if (numberSide != "none")
322 par.addParam("numbers", numberSide);
323 if (numberfontsize != "default" && numberSide != "none")
324 par.addParam("numberstyle", "\\" + numberfontsize);
325 if (!stepnumber.empty() && numberSide != "none")
326 par.addParam("stepnumber", stepnumber);
327 if (!firstline.empty())
328 par.addParam("firstline", firstline);
329 if (!lastline.empty())
330 par.addParam("lastline", lastline);
331 if (!basicstyle.empty())
332 par.addParam("basicstyle", basicstyle);
334 par.addParam("breaklines", "true");
336 par.addParam("showspaces", "true");
338 par.addParam("showstringspaces", "false");
340 par.addParam("extendedchars", "true");
341 par.addParams(extra);
346 docstring GuiListings::validate_listings_params()
348 // use a cache here to avoid repeated validation
349 // of the same parameters
350 static string param_cache;
351 static docstring msg_cache;
353 if (bypassCB->isChecked())
356 string params = construct_params();
357 if (params != param_cache) {
358 param_cache = params;
359 msg_cache = InsetListingsParams(params).validate();
365 void GuiListings::set_listings_msg()
367 static bool isOK = true;
368 docstring msg = validate_listings_params();
373 listingsTB->setPlainText(
374 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
377 listingsTB->setPlainText(toqstr(msg));
382 void GuiListings::on_floatCB_stateChanged(int state)
384 if (state == Qt::Checked) {
385 inlineCB->setChecked(false);
386 placementLE->setEnabled(true);
388 placementLE->setEnabled(false);
392 void GuiListings::on_inlineCB_stateChanged(int state)
394 if (state == Qt::Checked) {
395 floatCB->setChecked(false);
396 placementLE->setEnabled(false);
401 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
403 numberStepLE->setEnabled(index > 0);
404 numberFontSizeCO->setEnabled(index > 0);
408 void GuiListings::on_languageCO_currentIndexChanged(int index)
412 int default_dialect = 0;
413 dialectCO->addItem(qt_("No dialect"));
414 string const language = languages[index];
416 for (size_t i = 0; i != nr_dialects; ++i) {
417 if (language == dialects[i].language) {
418 dialectCO->addItem(qt_(dialects[i].gui));
419 if (dialects[i].is_default)
421 dialectCO->findText(qt_(dialects[i].gui));
424 dialectCO->setCurrentIndex(default_dialect);
425 dialectCO->setEnabled(dialectCO->count() > 1);
429 void GuiListings::applyView()
431 params_.setInline(inlineCB->isChecked());
432 params_.setParams(construct_params());
436 static string plainParam(string const & par)
438 // remove enclosing braces
439 if (prefixIs(par, "{") && suffixIs(par, "}"))
440 return par.substr(1, par.size() - 2);
445 void GuiListings::updateContents()
447 // set default values
448 listingsTB->setPlainText(
449 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
450 languageCO->setCurrentIndex(findToken(languages, "no language"));
451 dialectCO->setCurrentIndex(0);
452 floatCB->setChecked(false);
453 placementLE->clear();
454 numberSideCO->setCurrentIndex(0);
455 numberStepLE->clear();
456 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
457 firstlineLE->clear();
459 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
460 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
461 breaklinesCB->setChecked(false);
462 spaceCB->setChecked(false);
463 spaceInStringCB->setChecked(true);
464 extendedcharsCB->setChecked(false);
466 // set values from param string
467 inlineCB->setChecked(params_.isInline());
468 if (params_.isInline()) {
469 floatCB->setChecked(false);
470 placementLE->setEnabled(false);
472 // break other parameters and set values
473 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
474 // process each of them
475 for (vector<string>::iterator it = pars.begin();
476 it != pars.end(); ++it) {
477 if (prefixIs(*it, "language=")) {
478 string arg = plainParam(it->substr(9));
483 if (prefixIs(arg, "[") && contains(arg, "]")) {
484 size_t end_dialect = arg.find("]");
485 dialect = arg.substr(1, end_dialect - 1);
486 language = arg.substr(end_dialect + 1);
490 int n = findToken(languages, language);
492 languageCO->setCurrentIndex(n);
495 // on_languageCO_currentIndexChanged should have set dialects
496 if (!dialect.empty()) {
498 for (size_t i = 0; i != nr_dialects; ++i) {
499 if (dialect == dialects[i].dialect
500 && dialects[i].language == language) {
501 dialect_gui = dialects[i].gui;
505 n = dialectCO->findText(qt_(dialect_gui));
507 dialectCO->setCurrentIndex(n);
513 languageCO->setEnabled(in_gui);
514 dialectCO->setEnabled(
515 in_gui && dialectCO->count() > 1);
516 } else if (prefixIs(*it, "float")) {
517 floatCB->setChecked(true);
518 inlineCB->setChecked(false);
519 placementLE->setEnabled(true);
520 if (prefixIs(*it, "float="))
521 placementLE->setText(
522 toqstr(plainParam(it->substr(6))));
524 } else if (prefixIs(*it, "numbers=")) {
525 string s = plainParam(it->substr(8));
529 else if (s == "right")
531 numberSideCO->setCurrentIndex(n);
533 } else if (prefixIs(*it, "stepnumber=")) {
534 numberStepLE->setText(
535 toqstr(plainParam(it->substr(11))));
537 } else if (prefixIs(*it, "numberstyle=")) {
538 string par = plainParam(it->substr(12));
539 int n = findToken(font_sizes, par.substr(1));
541 numberFontSizeCO->setCurrentIndex(n);
543 } else if (prefixIs(*it, "firstline=")) {
544 firstlineLE->setText(
545 toqstr(plainParam(it->substr(10))));
547 } else if (prefixIs(*it, "lastline=")) {
549 toqstr(plainParam(it->substr(9))));
551 } else if (prefixIs(*it, "basicstyle=")) {
554 for (int n = 0; font_styles[n][0]; ++n) {
555 string const s = font_styles[n];
556 if (contains(*it, "\\" + s)) {
561 for (int n = 0; font_sizes[n][0]; ++n) {
562 string const s = font_sizes[n];
563 if (contains(*it, "\\" + s)) {
568 if (plainParam(it->substr(11)) == style + size
569 || plainParam(it->substr(11)) == size + style) {
570 if (!style.empty()) {
571 int n = findToken(font_styles, style.substr(1));
573 fontstyleCO->setCurrentIndex(n);
576 int n = findToken(font_sizes, size.substr(1));
578 fontsizeCO->setCurrentIndex(n);
582 } else if (prefixIs(*it, "breaklines=")) {
583 breaklinesCB->setChecked(contains(*it, "true"));
585 } else if (prefixIs(*it, "showspaces=")) {
586 spaceCB->setChecked(contains(*it, "true"));
588 } else if (prefixIs(*it, "showstringspaces=")) {
589 spaceInStringCB->setChecked(contains(*it, "true"));
591 } else if (prefixIs(*it, "extendedchars=")) {
592 extendedcharsCB->setChecked(contains(*it, "true"));
597 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
598 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
599 // parameters that can be handled by widgets are cleared
600 // the rest is put to the extra edit box.
601 string extra = getStringFromVector(pars);
602 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
606 bool GuiListings::isValid()
608 return validate_listings_params().empty();
612 bool GuiListings::initialiseParams(string const & data)
614 InsetListingsMailer::string2params(data, params_);
619 void GuiListings::clearParams()
625 void GuiListings::dispatchParams()
627 string const lfun = InsetListingsMailer::params2string(params_);
628 dispatch(FuncRequest(getLfun(), lfun));
632 void GuiListings::setParams(InsetListingsParams const & params)
638 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
641 } // namespace frontend
645 #include "GuiListings_moc.cpp"