GuiPrintNomencl.{cpp,h}:
[lyx.git] / src / frontends / qt4 / GuiListings.cpp
blob0b41adc9a68315b6195407875cde13114b648118
1 /**
2 * \file GuiListings.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Bo Peng
7 * \author Jürgen Spitzmüller
9 * Full author contact details are available in file CREDITS.
12 #include <config.h>
14 #include "GuiListings.h"
16 #include "qt_helpers.h"
18 #include "FuncRequest.h"
20 #include "insets/InsetListings.h"
21 #include "insets/InsetListingsParams.h"
23 #include "support/convert.h"
24 #include "support/debug.h"
25 #include "support/gettext.h"
26 #include "support/lstrings.h"
28 #include <QLineEdit>
29 #include <QPushButton>
30 #include <QValidator>
31 #include <QRegExpValidator>
33 using namespace std;
34 using namespace lyx::support;
36 namespace lyx {
37 namespace frontend {
40 /////////////////////////////////////////////////////////////////////
42 // GuiListings
44 /////////////////////////////////////////////////////////////////////
47 char const * languages[] =
48 { "no language", "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic", "C",
49 "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
50 "Eiffel", "Elan", "erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
51 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
52 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
53 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
54 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
55 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
56 "VRML", "XML", "XSLT", "" };
59 char const * languages_gui[] =
60 { N_("No language"), "ABAP", "ACSL", "Ada", "ALGOL", "Assembler", "Awk", "bash", "Basic",
61 "C", "C++", "Caml", "Clean", "Cobol", "Comal 80", "command.com", "Comsol", "csh", "Delphi",
62 "Eiffel", "Elan", "Erlang", "Euphoria", "Fortran", "Gnuplot", "Haskell", "HTML", "IDL", "inform",
63 "Java", "JVMIS", "ksh", "Lingo", "Lisp", "Logo", "make", "Mathematica", "Matlab", "Mercury",
64 "MetaPost", "Miranda", "ML", "Modula-2", "MuPAD", "NASTRAN", "Oberon-2", "OCL", "Octave",
65 "Oz", "Pascal", "Perl", "PHP", "PL/I", "Plasm", "PostScript", "POV", "Prolog", "Promela",
66 "PSTricks", "Python", "R", "Reduce", "Rexx", "RSL", "Ruby", "S", "SAS", "Scilab", "sh",
67 "SHELXL", "Simula", "tcl", "SPARQL", "SQL", "tcl", "TeX", "VBScript", "Verilog", "VHDL",
68 "VRML", "XML", "XSLT", "" };
71 struct dialect_info {
72 /// the dialect
73 char const * dialect;
74 /// the associated language
75 char const * language;
76 /// representation of the dialect in the gui
77 char const * gui;
78 /// is this the default dialect?
79 bool is_default;
83 dialect_info const dialects[] = {
84 { "R/2 4.3", "ABAP", "R/2 4.3", false },
85 { "R/2 5.0", "ABAP", "R/2 5.0", false },
86 { "R/3 3.1", "ABAP", "R/3 3.1", false },
87 { "R/3 4.6C", "ABAP", "R/3 4.6C", false },
88 { "R/3 6.10", "ABAP", "R/3 6.10", true },
89 { "2005", "Ada", "2005", true },
90 { "83", "Ada", "83", false },
91 { "95", "Ada", "95", false },
92 { "60", "Algol", "60", false },
93 { "68", "Algol", "68", true },
94 { "Motorola68k", "Assembler", "Motorola 68xxx", false },
95 { "x86masm", "Assembler", "x86 (MASM)", false },
96 { "gnu", "Awk", "gnu", true },
97 { "POSIX", "Awk", "POSIX", false },
98 { "Visual", "Basic", "Visual", false },
99 { "ANSI", "C", "ANSI", true },
100 { "Handel", "C", "Handel", false },
101 { "Objective", "C", "Objective", false },
102 { "Sharp", "C", "Sharp", false },
103 { "ANSI", "C++", "ANSI", false },
104 { "GNU", "C++", "GNU", false },
105 { "ISO", "C++", "ISO", true },
106 { "Visual", "C++", "Visual", false },
107 { "light", "Caml", "light", true },
108 { "Objective", "Caml", "Objective", false },
109 { "1974", "Cobol", "1974", false },
110 { "1985", "Cobol", "1985", true },
111 { "ibm", "Cobol", "IBM", false },
112 { "WinXP", "command.com", "Windows XP", true },
113 { "77", "Fortran", "77", false },
114 { "90", "Fortran", "90", false },
115 { "95", "Fortran", "95", true },
116 { "CORBA", "IDL", "CORBA", false },
117 { "AspectJ", "Java", "Aspect J", false },
118 { "Auto", "Lisp", "Auto", false },
119 { "gnu", "make", "gnu", false },
120 { "1.0", "Mathematica", "1.0", false },
121 { "3.0", "Mathematica", "3.0", false },
122 { "5.2", "Mathematica", "5.2", true },
123 { "decorative", "OCL", "decorative", false },
124 { "OMG", "OCL", "OMG", true },
125 { "Borland6", "Pascal", "Borland 6", false },
126 { "Standard", "Pascal", "Standard", true },
127 { "XSC", "Pascal", "XSC", false },
128 { "PLUS", "S", "PLUS", false },
129 { "67", "Simula", "67", true },
130 { "CII", "Simula", "CII", false },
131 { "DEC", "Simula", "DEC", false },
132 { "IBM", "Simula", "IBM", false },
133 { "tk", "tcl", "tk", false },
134 { "AlLaTeX", "TeX", "AlLaTeX", false },
135 { "common", "TeX", "common", false },
136 { "LaTeX", "TeX", "LaTeX", false },
137 { "plain", "TeX", "plain", true },
138 { "primitive", "TeX", "primitive", false },
139 { "AMS", "VHDL", "AMS", false },
140 { "97", "VRML", "97", true }
144 size_t const nr_dialects = sizeof(dialects) / sizeof(dialect_info);
147 char const * font_sizes[] =
148 { "default", "tiny", "scriptsize", "footnotesize", "small", "normalsize", "large",
149 "Large", "" };
151 char const * font_sizes_gui[] =
152 { N_("Default"), N_("Tiny"), N_("Smallest"), N_("Smaller"), N_("Small"), N_("Normal"),
153 N_("Large"), N_("Larger"), "" };
155 char const * font_styles[] =
156 { "default", "rmfamily", "ttfamily", "sffamily", "" };
158 char const * font_styles_gui[] =
159 { N_("Default"), N_("Roman"), N_("Typewriter"), N_("Sans Serif"), "" };
163 GuiListings::GuiListings(GuiView & lv)
164 : GuiDialog(lv, "listings", qt_("Program Listing Settings"))
166 setupUi(this);
168 connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
169 connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
170 connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
172 connect(languageCO, SIGNAL(currentIndexChanged(int)),
173 this, SLOT(change_adaptor()));
174 connect(dialectCO, SIGNAL(currentIndexChanged(int)),
175 this, SLOT(change_adaptor()));
176 connect(inlineCB, SIGNAL(clicked()),
177 this, SLOT(change_adaptor()));
178 connect(floatCB, SIGNAL(clicked()),
179 this, SLOT(change_adaptor()));
180 connect(placementLE, SIGNAL(textChanged(QString)),
181 this, SLOT(change_adaptor()));
182 connect(numberSideCO, SIGNAL(currentIndexChanged(int)),
183 this, SLOT(change_adaptor()));
184 connect(numberStepLE, SIGNAL(textChanged(QString)),
185 this, SLOT(change_adaptor()));
186 connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)),
187 this, SLOT(change_adaptor()));
188 connect(firstlineLE, SIGNAL(textChanged(QString)),
189 this, SLOT(change_adaptor()));
190 connect(lastlineLE, SIGNAL(textChanged(QString)),
191 this, SLOT(change_adaptor()));
192 connect(fontsizeCO, SIGNAL(currentIndexChanged(int)),
193 this, SLOT(change_adaptor()));
194 connect(fontstyleCO, SIGNAL(currentIndexChanged(int)),
195 this, SLOT(change_adaptor()));
196 connect(breaklinesCB, SIGNAL(clicked()),
197 this, SLOT(change_adaptor()));
198 connect(spaceCB, SIGNAL(clicked()),
199 this, SLOT(change_adaptor()));
200 connect(spaceInStringCB, SIGNAL(clicked()),
201 this, SLOT(change_adaptor()));
202 connect(tabsizeSB, SIGNAL(valueChanged(int)),
203 this, SLOT(change_adaptor()));
204 connect(extendedcharsCB, SIGNAL(clicked()),
205 this, SLOT(change_adaptor()));
207 connect(listingsED, SIGNAL(textChanged()),
208 this, SLOT(change_adaptor()));
209 connect(listingsED, SIGNAL(textChanged()),
210 this, SLOT(set_listings_msg()));
211 connect(bypassCB, SIGNAL(clicked()),
212 this, SLOT(change_adaptor()));
213 connect(bypassCB, SIGNAL(clicked()),
214 this, SLOT(set_listings_msg()));
216 for (int n = 0; languages[n][0]; ++n)
217 languageCO->addItem(qt_(languages_gui[n]));
219 for (int n = 0; font_styles[n][0]; ++n)
220 fontstyleCO->addItem(qt_(font_styles_gui[n]));
222 for (int n = 0; font_sizes[n][0]; ++n) {
223 QString font = qt_(font_sizes_gui[n]);
224 fontsizeCO->addItem(font);
225 numberFontSizeCO->addItem(font);
228 // set validators
229 numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
230 firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
231 lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
232 placementLE->setValidator(new QRegExpValidator(QRegExp("[\\*tbph]*"), this));
234 bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
235 bc().setOK(okPB);
236 bc().setApply(applyPB);
237 bc().setCancel(closePB);
238 listingsTB->setPlainText(
239 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
241 updateContents();
246 void GuiListings::change_adaptor()
248 changed();
252 string GuiListings::construct_params()
254 string language = languages[qMax(0, languageCO->currentIndex())];
255 string dialect;
256 string const dialect_gui = fromqstr(dialectCO->currentText());
257 if (dialectCO->currentIndex() > 0) {
258 for (size_t i = 0; i != nr_dialects; ++i) {
259 if (dialect_gui == dialects[i].gui
260 && dialects[i].language == language
261 && !dialects[i].is_default) {
262 dialect = dialects[i].dialect;
263 break;
268 bool float_ = floatCB->isChecked();
269 string placement;
270 if (placementLE->isEnabled())
271 placement = fromqstr(placementLE->text());
273 string numberSide;
274 switch (qMax(0, numberSideCO->currentIndex())) {
275 case 0:
276 numberSide = "none";
277 break;
278 case 1:
279 numberSide = "left";
280 break;
281 case 2:
282 numberSide = "right";
283 break;
284 default:
285 numberSide = "none";
286 break;
288 string stepnumber = fromqstr(numberStepLE->text());
289 string numberfontsize = font_sizes[qMax(0, numberFontSizeCO->currentIndex())];
290 string firstline = fromqstr(firstlineLE->text());
291 string lastline = fromqstr(lastlineLE->text());
293 string fontsize = font_sizes[qMax(0, fontsizeCO->currentIndex())];
294 string fontstyle = font_styles[qMax(0, fontstyleCO->currentIndex())];
295 string basicstyle;
296 if (fontsize != "default")
297 basicstyle = "\\" + fontsize;
298 if (fontstyle != "default")
299 basicstyle += "\\" + fontstyle;
300 bool breakline = breaklinesCB->isChecked();
301 bool space = spaceCB->isChecked();
302 int tabsize = tabsizeSB->value();
303 bool spaceInString = spaceInStringCB->isChecked();
304 bool extendedchars = extendedcharsCB->isChecked();
305 string extra = fromqstr(listingsED->toPlainText());
307 // compose a string
308 InsetListingsParams par;
309 if (language != "no language" && !contains(extra, "language=")) {
310 if (dialect.empty())
311 par.addParam("language", language);
312 else
313 par.addParam("language", "{[" + dialect + "]" + language + "}");
315 // this dialog uses float=placement instead of float,floatplacement=placement
316 // because float accepts *tbph and floatplacement accepts bph.
317 // our placement textedit is actually for the float parameter
318 if (float_)
319 par.addParam("float", placement);
320 if (numberSide != "none")
321 par.addParam("numbers", numberSide);
322 if (numberfontsize != "default" && numberSide != "none")
323 par.addParam("numberstyle", "\\" + numberfontsize);
324 if (!stepnumber.empty() && numberSide != "none")
325 par.addParam("stepnumber", stepnumber);
326 if (!firstline.empty())
327 par.addParam("firstline", firstline);
328 if (!lastline.empty())
329 par.addParam("lastline", lastline);
330 if (!basicstyle.empty())
331 par.addParam("basicstyle", basicstyle);
332 if (breakline)
333 par.addParam("breaklines", "true");
334 if (space)
335 par.addParam("showspaces", "true");
336 if (!spaceInString)
337 par.addParam("showstringspaces", "false");
338 if (tabsize != 8)
339 par.addParam("tabsize", convert<string>(tabsize));
340 if (extendedchars)
341 par.addParam("extendedchars", "true");
342 par.addParams(extra);
343 return par.params();
347 docstring GuiListings::validate_listings_params()
349 // use a cache here to avoid repeated validation
350 // of the same parameters
351 static string param_cache;
352 static docstring msg_cache;
354 if (bypassCB->isChecked())
355 return docstring();
357 string params = construct_params();
358 if (params != param_cache) {
359 param_cache = params;
360 msg_cache = InsetListingsParams(params).validate();
362 return msg_cache;
366 void GuiListings::set_listings_msg()
368 static bool isOK = true;
369 docstring msg = validate_listings_params();
370 if (msg.empty()) {
371 if (isOK)
372 return;
373 isOK = true;
374 listingsTB->setPlainText(
375 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
376 } else {
377 isOK = false;
378 listingsTB->setPlainText(toqstr(msg));
383 void GuiListings::on_floatCB_stateChanged(int state)
385 if (state == Qt::Checked) {
386 inlineCB->setChecked(false);
387 placementLE->setEnabled(true);
388 } else
389 placementLE->setEnabled(false);
393 void GuiListings::on_inlineCB_stateChanged(int state)
395 if (state == Qt::Checked) {
396 floatCB->setChecked(false);
397 placementLE->setEnabled(false);
402 void GuiListings::on_numberSideCO_currentIndexChanged(int index)
404 numberStepLE->setEnabled(index > 0);
405 numberFontSizeCO->setEnabled(index > 0);
409 void GuiListings::on_languageCO_currentIndexChanged(int index)
411 dialectCO->clear();
412 // 0 is "no dialect"
413 int default_dialect = 0;
414 dialectCO->addItem(qt_("No dialect"));
415 string const language = languages[index];
417 for (size_t i = 0; i != nr_dialects; ++i) {
418 if (language == dialects[i].language) {
419 dialectCO->addItem(qt_(dialects[i].gui));
420 if (dialects[i].is_default)
421 default_dialect =
422 dialectCO->findText(qt_(dialects[i].gui));
425 dialectCO->setCurrentIndex(default_dialect);
426 dialectCO->setEnabled(dialectCO->count() > 1);
430 void GuiListings::applyView()
432 params_.setInline(inlineCB->isChecked());
433 params_.setParams(construct_params());
437 static string plainParam(string const & par)
439 // remove enclosing braces
440 if (prefixIs(par, "{") && suffixIs(par, "}"))
441 return par.substr(1, par.size() - 2);
442 return par;
446 void GuiListings::updateContents()
448 // set default values
449 listingsTB->setPlainText(
450 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
451 languageCO->setCurrentIndex(findToken(languages, "no language"));
452 dialectCO->setCurrentIndex(0);
453 floatCB->setChecked(false);
454 placementLE->clear();
455 numberSideCO->setCurrentIndex(0);
456 numberStepLE->clear();
457 numberFontSizeCO->setCurrentIndex(findToken(font_sizes, "default"));
458 firstlineLE->clear();
459 lastlineLE->clear();
460 fontstyleCO->setCurrentIndex(findToken(font_styles, "default"));
461 fontsizeCO->setCurrentIndex(findToken(font_sizes, "default"));
462 breaklinesCB->setChecked(false);
463 spaceCB->setChecked(false);
464 spaceInStringCB->setChecked(true);
465 tabsizeSB->setValue(8);
466 extendedcharsCB->setChecked(false);
468 // set values from param string
469 inlineCB->setChecked(params_.isInline());
470 if (params_.isInline()) {
471 floatCB->setChecked(false);
472 placementLE->setEnabled(false);
474 // break other parameters and set values
475 vector<string> pars = getVectorFromString(params_.separatedParams(), "\n");
476 // process each of them
477 for (vector<string>::iterator it = pars.begin();
478 it != pars.end(); ++it) {
479 if (prefixIs(*it, "language=")) {
480 string arg = plainParam(it->substr(9));
481 // has dialect?
482 string language;
483 string dialect;
484 bool in_gui = false;
485 if (prefixIs(arg, "[") && contains(arg, "]")) {
486 size_t end_dialect = arg.find("]");
487 dialect = arg.substr(1, end_dialect - 1);
488 language = arg.substr(end_dialect + 1);
489 } else {
490 language = arg;
492 int n = findToken(languages, language);
493 if (n >= 0) {
494 languageCO->setCurrentIndex(n);
495 in_gui = true;
497 // on_languageCO_currentIndexChanged should have set dialects
498 if (!dialect.empty()) {
499 string dialect_gui;
500 for (size_t i = 0; i != nr_dialects; ++i) {
501 if (dialect == dialects[i].dialect
502 && dialects[i].language == language) {
503 dialect_gui = dialects[i].gui;
504 break;
507 n = dialectCO->findText(qt_(dialect_gui));
508 if (n >= 0)
509 dialectCO->setCurrentIndex(n);
510 else
511 in_gui = false;
513 if (in_gui)
514 *it = "";
515 languageCO->setEnabled(in_gui);
516 dialectCO->setEnabled(
517 in_gui && dialectCO->count() > 1);
518 } else if (prefixIs(*it, "float")) {
519 floatCB->setChecked(true);
520 inlineCB->setChecked(false);
521 placementLE->setEnabled(true);
522 if (prefixIs(*it, "float="))
523 placementLE->setText(
524 toqstr(plainParam(it->substr(6))));
525 *it = "";
526 } else if (prefixIs(*it, "numbers=")) {
527 string s = plainParam(it->substr(8));
528 int n = 0;
529 if (s == "left")
530 n = 1;
531 else if (s == "right")
532 n = 2;
533 numberSideCO->setCurrentIndex(n);
534 *it = "";
535 } else if (prefixIs(*it, "stepnumber=")) {
536 numberStepLE->setText(
537 toqstr(plainParam(it->substr(11))));
538 *it = "";
539 } else if (prefixIs(*it, "numberstyle=")) {
540 string par = plainParam(it->substr(12));
541 int n = findToken(font_sizes, par.substr(1));
542 if (n >= 0)
543 numberFontSizeCO->setCurrentIndex(n);
544 *it = "";
545 } else if (prefixIs(*it, "firstline=")) {
546 firstlineLE->setText(
547 toqstr(plainParam(it->substr(10))));
548 *it = "";
549 } else if (prefixIs(*it, "lastline=")) {
550 lastlineLE->setText(
551 toqstr(plainParam(it->substr(9))));
552 *it = "";
553 } else if (prefixIs(*it, "basicstyle=")) {
554 string style;
555 string size;
556 for (int n = 0; font_styles[n][0]; ++n) {
557 string const s = font_styles[n];
558 if (contains(*it, "\\" + s)) {
559 style = "\\" + s;
560 break;
563 for (int n = 0; font_sizes[n][0]; ++n) {
564 string const s = font_sizes[n];
565 if (contains(*it, "\\" + s)) {
566 size = "\\" + s;
567 break;
570 if (plainParam(it->substr(11)) == style + size
571 || plainParam(it->substr(11)) == size + style) {
572 if (!style.empty()) {
573 int n = findToken(font_styles, style.substr(1));
574 if (n >= 0)
575 fontstyleCO->setCurrentIndex(n);
577 if (!size.empty()) {
578 int n = findToken(font_sizes, size.substr(1));
579 if (n >= 0)
580 fontsizeCO->setCurrentIndex(n);
582 *it = "";
584 } else if (prefixIs(*it, "breaklines=")) {
585 breaklinesCB->setChecked(contains(*it, "true"));
586 *it = "";
587 } else if (prefixIs(*it, "showspaces=")) {
588 spaceCB->setChecked(contains(*it, "true"));
589 *it = "";
590 } else if (prefixIs(*it, "showstringspaces=")) {
591 spaceInStringCB->setChecked(contains(*it, "true"));
592 *it = "";
593 } else if (prefixIs(*it, "tabsize=")) {
594 tabsizeSB->setValue(convert<int>(plainParam(it->substr(8))));
595 *it = "";
596 } else if (prefixIs(*it, "extendedchars=")) {
597 extendedcharsCB->setChecked(contains(*it, "true"));
598 *it = "";
602 numberStepLE->setEnabled(numberSideCO->currentIndex() > 0);
603 numberFontSizeCO->setEnabled(numberSideCO->currentIndex() > 0);
604 // parameters that can be handled by widgets are cleared
605 // the rest is put to the extra edit box.
606 string extra = getStringFromVector(pars);
607 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
611 bool GuiListings::isValid()
613 return validate_listings_params().empty();
617 bool GuiListings::initialiseParams(string const & data)
619 InsetListings::string2params(data, params_);
620 return true;
624 void GuiListings::clearParams()
626 params_.clear();
630 void GuiListings::dispatchParams()
632 string const lfun = InsetListings::params2string(params_);
633 dispatch(FuncRequest(getLfun(), lfun));
637 void GuiListings::setParams(InsetListingsParams const & params)
639 params_ = params;
643 Dialog * createGuiListings(GuiView & lv) { return new GuiListings(lv); }
646 } // namespace frontend
647 } // namespace lyx
650 #include "moc_GuiListings.cpp"