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")
172 setViewTitle(_("Program Listing Settings"));
174 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
175 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
176 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
178 connect(languageCO, SIGNAL(currentIndexChanged(int)),
179 this, SLOT(change_adaptor()));
180 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
181 this, SLOT(change_adaptor()));
182 connect(inlineCB, SIGNAL(clicked()),
183 this, SLOT(change_adaptor()));
184 connect(floatCB, SIGNAL(clicked()),
185 this, SLOT(change_adaptor()));
186 connect(placementLE, SIGNAL(textChanged(QString)),
187 this, SLOT(change_adaptor()));
188 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
189 this, SLOT(change_adaptor()));
190 connect(numberStepLE, SIGNAL(textChanged(QString)),
191 this, SLOT(change_adaptor()));
192 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
193 this, SLOT(change_adaptor()));
194 connect(firstlineLE, SIGNAL(textChanged(QString)),
195 this, SLOT(change_adaptor()));
196 connect(lastlineLE, SIGNAL(textChanged(QString)),
197 this, SLOT(change_adaptor()));
198 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
199 this, SLOT(change_adaptor()));
200 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
201 this, SLOT(change_adaptor()));
202 connect(breaklinesCB, SIGNAL(clicked()),
203 this, SLOT(change_adaptor()));
204 connect(spaceCB, SIGNAL(clicked()),
205 this, SLOT(change_adaptor()));
206 connect(spaceInStringCB, SIGNAL(clicked()),
207 this, SLOT(change_adaptor()));
208 connect(extendedcharsCB, SIGNAL(clicked()),
209 this, SLOT(change_adaptor()));
211 connect(listingsED, SIGNAL(textChanged()),
212 this, SLOT(change_adaptor()));
213 connect(listingsED, SIGNAL(textChanged()),
214 this, SLOT(set_listings_msg()));
215 connect(bypassCB, SIGNAL(clicked()),
216 this, SLOT(change_adaptor()));
217 connect(bypassCB, SIGNAL(clicked()),
218 this, SLOT(set_listings_msg()));
220 for (int n = 0; languages[n][0]; ++n)
221 languageCO->addItem(qt_(languages_gui[n]));
223 for (int n = 0; font_styles[n][0]; ++n)
224 fontstyleCO->addItem(qt_(font_styles_gui[n]));
226 for (int n = 0; font_sizes[n][0]; ++n) {
227 QString font = qt_(font_sizes_gui[n]);
228 fontsizeCO->addItem(font);
229 numberFontSizeCO->addItem(font);
233 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
234 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
235 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
236 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
239 bc().setApply(applyPB);
240 bc().setCancel(closePB);
241 listingsTB->setPlainText(
242 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
249 void GuiListings::closeEvent(QCloseEvent * e)
256 void GuiListings::change_adaptor()
262 string GuiListings::construct_params()
264 string language = languages[languageCO->currentIndex()];
266 string const dialect_gui = fromqstr(dialectCO->currentText());
267 if (dialectCO->currentIndex() > 0) {
268 for (size_t i = 0; i != nr_dialects; ++i) {
269 if (dialect_gui == dialects[i].gui
270 && dialects[i].language == language
271 && !dialects[i].is_default) {
272 dialect = dialects[i].dialect;
278 bool float_ = floatCB->isChecked();
280 if (placementLE->isEnabled())
281 placement = fromqstr(placementLE->text());
284 switch (numberSideCO->currentIndex()) {
292 numberSide = "right";
298 string stepnumber = fromqstr(numberStepLE->text());
299 string numberfontsize = font_sizes[numberFontSizeCO->currentIndex()];
300 string firstline = fromqstr(firstlineLE->text());
301 string lastline = fromqstr(lastlineLE->text());
303 string fontsize = font_sizes[fontsizeCO->currentIndex()];
304 string fontstyle = font_styles[fontstyleCO->currentIndex()];
306 if (fontsize != "default")
307 basicstyle = "\\" + fontsize;
308 if (fontstyle != "default")
309 basicstyle += "\\" + fontstyle;
310 bool breakline = breaklinesCB->isChecked();
311 bool space = spaceCB->isChecked();
312 bool spaceInString = spaceInStringCB->isChecked();
313 bool extendedchars = extendedcharsCB->isChecked();
314 string extra = fromqstr(listingsED->toPlainText());
317 InsetListingsParams par;
318 if (language != "no language" && !contains(extra, "language=")) {
320 par.addParam("language", language);
322 par.addParam("language", "{[" + dialect + "]" + language + "}");
324 // this dialog uses float=placement instead of float,floatplacement=placement
325 // because float accepts *tbph and floatplacement accepts bph.
326 // our placement textedit is actually for the float parameter
328 par.addParam("float", placement);
329 if (numberSide != "none")
330 par.addParam("numbers", numberSide);
331 if (numberfontsize != "default" && numberSide != "none")
332 par.addParam("numberstyle", "\\" + numberfontsize);
333 if (!stepnumber.empty() && numberSide != "none")
334 par.addParam("stepnumber", stepnumber);
335 if (!firstline.empty())
336 par.addParam("firstline", firstline);
337 if (!lastline.empty())
338 par.addParam("lastline", lastline);
339 if (!basicstyle.empty())
340 par.addParam("basicstyle", basicstyle);
342 par.addParam("breaklines", "true");
344 par.addParam("showspaces", "true");
346 par.addParam("showstringspaces", "false");
348 par.addParam("extendedchars", "true");
349 par.addParams(extra);
354 docstring GuiListings::validate_listings_params()
356 // use a cache here to avoid repeated validation
357 // of the same parameters
358 static string param_cache;
359 static docstring msg_cache;
361 if (bypassCB->isChecked())
364 string params = construct_params();
365 if (params != param_cache) {
366 param_cache = params;
367 msg_cache = InsetListingsParams(params).validate();
373 void GuiListings::set_listings_msg()
375 static bool isOK = true;
376 docstring msg = validate_listings_params();
381 listingsTB->setPlainText(
382 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
385 listingsTB->setPlainText(toqstr(msg));
390 void GuiListings::on_floatCB_stateChanged(int state)
392 if (state == Qt::Checked) {
393 inlineCB->setChecked(false);
394 placementLE->setEnabled(true);
396 placementLE->setEnabled(false);
400 void GuiListings::on_inlineCB_stateChanged(int state)
402 if (state == Qt::Checked) {
403 floatCB->setChecked(false);
404 placementLE->setEnabled(false);
409 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
411 numberStepLE->setEnabled(index > 0);
412 numberFontSizeCO->setEnabled(index > 0);
416 void GuiListings::on_languageCO_currentIndexChanged(int index)
420 int default_dialect = 0;
421 dialectCO->addItem(qt_("No dialect"));
422 string const language = languages[index];
424 for (size_t i = 0; i != nr_dialects; ++i) {
425 if (language == dialects[i].language) {
426 dialectCO->addItem(qt_(dialects[i].gui));
427 if (dialects[i].is_default)
429 dialectCO->findText(qt_(dialects[i].gui));
432 dialectCO->setCurrentIndex(default_dialect);
433 dialectCO->setEnabled(dialectCO->count() > 1);
437 void GuiListings::applyView()
439 params_.setInline(inlineCB->isChecked());
440 params_.setParams(construct_params());
444 static string plainParam(std::string const & par)
446 // remove enclosing braces
447 if (prefixIs(par, "{") && suffixIs(par, "}"))
448 return par.substr(1, par.size() - 2);
453 void GuiListings::updateContents()
455 // set default values
456 listingsTB->setPlainText(
457 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
458 languageCO->setCurrentIndex(findToken(languages, "no language"));
459 dialectCO->setCurrentIndex(0);
460 floatCB->setChecked(false);
461 placementLE->clear();
462 numberSideCO->setCurrentIndex(0);
463 numberStepLE->clear();
464 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
465 firstlineLE->clear();
467 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
468 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
469 breaklinesCB->setChecked(false);
470 spaceCB->setChecked(false);
471 spaceInStringCB->setChecked(true);
472 extendedcharsCB->setChecked(false);
474 // set values from param string
475 inlineCB->setChecked(params_.isInline());
476 if (params_.isInline()) {
477 floatCB->setChecked(false);
478 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 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 = dialectCO->findText(qt_(dialect_gui));
514 dialectCO->setCurrentIndex(n);
520 languageCO->setEnabled(in_gui);
521 dialectCO->setEnabled(
522 in_gui && dialectCO->count() > 1);
523 } else if (prefixIs(*it, "float")) {
524 floatCB->setChecked(true);
525 inlineCB->setChecked(false);
526 placementLE->setEnabled(true);
527 if (prefixIs(*it, "float="))
528 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 numberSideCO->setCurrentIndex(n);
540 } else if (prefixIs(*it, "stepnumber=")) {
541 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 numberFontSizeCO->setCurrentIndex(n);
550 } else if (prefixIs(*it, "firstline=")) {
551 firstlineLE->setText(
552 toqstr(plainParam(it->substr(10))));
554 } else if (prefixIs(*it, "lastline=")) {
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 fontstyleCO->setCurrentIndex(n);
583 int n = findToken(font_sizes, size.substr(1));
585 fontsizeCO->setCurrentIndex(n);
589 } else if (prefixIs(*it, "breaklines=")) {
590 breaklinesCB->setChecked(contains(*it, "true"));
592 } else if (prefixIs(*it, "showspaces=")) {
593 spaceCB->setChecked(contains(*it, "true"));
595 } else if (prefixIs(*it, "showstringspaces=")) {
596 spaceInStringCB->setChecked(contains(*it, "true"));
598 } else if (prefixIs(*it, "extendedchars=")) {
599 extendedcharsCB->setChecked(contains(*it, "true"));
604 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
605 numberFontSizeCO->setEnabled(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 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
613 bool GuiListings::isValid()
615 return validate_listings_params().empty();
619 bool GuiListings::initialiseParams(string const & data)
621 InsetListingsMailer::string2params(data, params_);
626 void GuiListings::clearParams()
632 void GuiListings::dispatchParams()
634 string const lfun = InsetListingsMailer::params2string(params_);
635 dispatch(FuncRequest(getLfun(), lfun));
639 void GuiListings::setParams(InsetListingsParams const & params)
645 Dialog * createGuiListings(LyXView & lv) { return new GuiListings(lv); }
648 } // namespace frontend
652 #include "GuiListings_moc.cpp"