]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QListings.cpp
InsetListings: fix bug 3627
[lyx.git] / src / frontends / qt4 / QListings.cpp
1 /**
2  * \file QListings.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Bo Peng
7  * \author Jürgen Spitzmüller
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "QListings.h"
15 #include "Qt2BC.h"
16 #include "qt_helpers.h"
17 #include "controllers/ControlListings.h"
18 #include "insets/InsetListingsParams.h"
19 #include "debug.h"
20
21 #include "support/convert.h"
22 #include "support/lstrings.h"
23
24 #include <QLineEdit>
25 #include <QCloseEvent>
26 #include <QPushButton>
27 #include <QValidator>
28 #include <QRegExpValidator>
29
30
31 using std::string;
32 using std::vector;
33 using lyx::support::getVectorFromString;
34 using lyx::support::getStringFromVector;
35 using lyx::support::prefixIs;
36 using lyx::support::contains;
37
38 namespace lyx {
39 namespace frontend {
40
41 /////////////////////////////////////////////////////////////////////
42 //
43 // QListingsDialog
44 //
45 /////////////////////////////////////////////////////////////////////
46
47
48 string const allowed_languages = 
49         "no language\nBAP\nACSL\nAda\nALGOL\nC\nC++\nCaml\nClean\nCobol\n"
50         "Comal 80\ncsh\nDelphi\nEiffel\nElan\nEuphoria\nFortran\nHaskell\n"
51         "HTML\nIDL\nJava\nLisp\nLogo\nmake\nMathematica\nMatlab\nMercury\n"
52         "Miranda\nML\nModula-2\nOberon-2\nOCL\nPascal\nPerl\nPHP\nPL/I\nPOV\n"
53         "Python\nProlog\nR\nS\nSAS\nSHELXL\nSimula\ntcl\nSQL\nTeX\nVBScript\n"
54         "VHDL\nXML";
55 string const allowed_fontsizes = "default\ntiny\nscriptsize\nfootnotesize\nsmall\n"
56         "normalsize\nlarge\nLarge";
57 string const allowed_fontstyles = "default\nrmfamily\nttfamily\nsffamily";
58 string const allowed_sides = "none\nleft\nright";
59
60 QListingsDialog::QListingsDialog(QListings * form)
61         : form_(form)
62 {
63         setupUi(this);
64         
65         connect(okPB, SIGNAL(clicked()), form, SLOT(slotOK()));
66         connect(closePB, SIGNAL(clicked()), form, SLOT(slotClose()));
67         
68         connect(languageCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
69         connect(inlineCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
70         connect(floatCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
71         connect(placementLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
72         connect(numberSideCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
73         connect(numberStepLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
74         connect(numberFontSizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
75         connect(firstlineLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
76         connect(lastlineLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
77         connect(fontsizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
78         connect(fontstyleCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
79         connect(breaklinesCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
80         connect(spaceCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
81         connect(extendedcharsCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
82         
83         connect(listingsED,  SIGNAL(textChanged()), this, SLOT(change_adaptor()));
84         connect(listingsED,  SIGNAL(textChanged()), this, SLOT(validate_listings_params()));
85 }
86
87
88 void QListingsDialog::closeEvent(QCloseEvent * e)
89 {
90         form_->slotWMHide();
91         e->accept();
92 }
93
94
95 void QListingsDialog::change_adaptor()
96 {
97         form_->changed();
98 }
99
100
101 string QListingsDialog::construct_params()
102 {
103         string language = fromqstr(languageCO->currentText());
104         
105         bool float_ = floatCB->checkState() == Qt::Checked;
106         string placement = fromqstr(placementLE->text());
107         
108         string numberSide = fromqstr(numberSideCO->currentText());
109         string stepnumber = fromqstr(numberStepLE->text());
110         string numberfontsize = fromqstr(numberFontSizeCO->currentText());
111         string firstline = fromqstr(firstlineLE->text());
112         string lastline = fromqstr(lastlineLE->text());
113         
114         string fontsize = fromqstr(fontsizeCO->currentText());
115         string fontstyle = fromqstr(fontstyleCO->currentText());
116         string basicstyle;
117         if (fontsize != "default")
118                 basicstyle = "\\" + fontsize;
119         if (fontstyle != "default")
120                 basicstyle += "\\" + fontstyle;
121         bool breakline = breaklinesCB->checkState() == Qt::Checked;
122         bool space = spaceCB->checkState() == Qt::Checked;
123         bool extendedchars = extendedcharsCB->checkState() == Qt::Checked;
124         string extra = fromqstr(listingsED->toPlainText());
125
126         // compose a string
127         InsetListingsParams par;
128         if (language != "no language")
129                 par.addParam("language", language);
130         if (float_)
131                 par.addParam("float", "");
132         if (!placement.empty())
133                 par.addParam("floatplacement", placement);
134         if (numberSide != "none")
135                 par.addParam("numbers", numberSide);
136         if (numberfontsize != "default")
137                 par.addParam("numberstyle", "\\" + numberfontsize);
138         if (!firstline.empty())
139                 par.addParam("firstline", firstline);
140         if (!lastline.empty())
141                 par.addParam("lastline", lastline);
142         if (!stepnumber.empty())
143                 par.addParam("stepnumber", stepnumber);
144         if (!basicstyle.empty())
145                 par.addParam("basicstyle", basicstyle);
146         if (breakline)
147                 par.addParam("breaklines", "true");
148         if (space)
149                 par.addParam("showspaces", "true");
150         if (extendedchars)
151                 par.addParam("extendedchars", "true");
152         par.addParams(extra);
153         return par.params();
154 }
155
156
157 void QListingsDialog::validate_listings_params()
158 {
159         static bool isOK = true;
160         try {
161                 InsetListingsParams par(construct_params());
162                 if (!isOK) {
163                         isOK = true;
164                         listingsTB->setPlainText("Input listings parameters on the right. Enter ? for a list of parameters.");
165                         okPB->setEnabled(true);
166                 }
167         } catch (invalidParam & e) {
168                 isOK = false;
169                 listingsTB->setPlainText(e.what());
170                 okPB->setEnabled(false);
171         }
172 }
173
174 /////////////////////////////////////////////////////////////////////
175 //
176 // QListings
177 //
178 /////////////////////////////////////////////////////////////////////
179
180 typedef QController<ControlListings, QView<QListingsDialog> > listings_wrap_base_class;
181
182 QListings::QListings(Dialog & parent)
183         : listings_wrap_base_class(parent, _("Program Listings Settings"))
184 {
185 }
186
187
188 void QListings::build_dialog()
189 {
190         dialog_.reset(new QListingsDialog(this));
191         
192         bcview().setOK(dialog_->okPB);
193         bcview().setCancel(dialog_->closePB);
194         dialog_->listingsTB->setPlainText("Input listings parameters on the right. Enter ? for a list of parameters.");
195
196         update_contents();
197 }
198
199
200 /// not used right now.
201 void QListings::apply()
202 {
203         InsetListingsParams & params = controller().params();
204         params.setInline(dialog_->inlineCB->isChecked());
205         params.setParams(dialog_->construct_params());
206         controller().setParams(params);
207 }
208
209
210 void QListings::update_contents()
211 {
212         // first prepare all choices
213         vector<string> const languages = 
214                 getVectorFromString(allowed_languages, "\n");
215         vector<string> const fontstyles = 
216                 getVectorFromString(allowed_fontstyles, "\n");
217         vector<string> const fontsizes = 
218                 getVectorFromString(allowed_fontsizes, "\n");
219         vector<string> const sides = 
220                 getVectorFromString(allowed_sides, "\n");
221
222         dialog_->languageCO->clear();
223         for (vector<string>::const_iterator it = languages.begin();
224             it != languages.end(); ++it) {
225                 dialog_->languageCO->addItem(toqstr(*it));
226         }
227         dialog_->numberSideCO->clear();
228         for (vector<string>::const_iterator it = sides.begin();
229             it != sides.end(); ++it) {
230                 dialog_->numberSideCO->addItem(toqstr(*it));
231         }
232         dialog_->fontstyleCO->clear();
233         dialog_->fontstyleCO->setEditable(false);
234         for (vector<string>::const_iterator it = fontstyles.begin();
235             it != fontstyles.end(); ++it) {
236                 dialog_->fontstyleCO->addItem(toqstr(*it));
237         }
238         dialog_->fontsizeCO->clear();
239         dialog_->fontsizeCO->setEditable(false);
240         dialog_->numberFontSizeCO->clear();
241         dialog_->numberFontSizeCO->setEditable(false);
242         for (vector<string>::const_iterator it = fontsizes.begin();
243             it != fontsizes.end(); ++it) {
244                 dialog_->fontsizeCO->addItem(toqstr(*it));
245                 dialog_->numberFontSizeCO->addItem(toqstr(*it));
246         }
247
248         // set validators
249         dialog_->numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
250         dialog_->firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
251         dialog_->lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
252         dialog_->placementLE->setValidator(new QRegExpValidator(QRegExp("[tbph]*"), this));
253
254         // set default values 
255         dialog_->listingsTB->setPlainText("Input listings parameters on the right. Enter ? for a list of parameters.");
256         dialog_->languageCO->setCurrentIndex(
257                 dialog_->languageCO->findText(toqstr("no language")));
258         dialog_->floatCB->setChecked(false);
259         dialog_->placementLE->clear();
260         dialog_->numberSideCO->setCurrentIndex(
261                 dialog_->numberSideCO->findText(toqstr("none")));
262         dialog_->numberStepLE->clear();
263         dialog_->numberFontSizeCO->setCurrentIndex(
264                 dialog_->numberFontSizeCO->findText(toqstr("default")));
265         dialog_->firstlineLE->clear();
266         dialog_->lastlineLE->clear();
267         dialog_->fontstyleCO->setCurrentIndex(
268                 dialog_->fontstyleCO->findText(toqstr("default")));
269         dialog_->fontsizeCO->setCurrentIndex(
270                 dialog_->fontsizeCO->findText(toqstr("default")));
271         dialog_->breaklinesCB->setChecked(false);
272         dialog_->spaceCB->setChecked(false);
273         dialog_->extendedcharsCB->setChecked(false);    
274
275         // set values from param string
276         InsetListingsParams & params = controller().params();
277         if (params.isInline())
278                 dialog_->inlineCB->setChecked(true);
279         else
280                 dialog_->inlineCB->setChecked(false);
281         // break other parameters and set values
282         vector<string> pars = getVectorFromString(params.separatedParams(), "\n");
283         // process each of them
284         for (vector<string>::iterator it = pars.begin();
285             it != pars.end(); ++it) {
286                 if (prefixIs(*it, "language=")) {
287                         for (vector<string>::const_iterator st = languages.begin();
288                             st != languages.end(); ++st) {
289                                 if (*it == "language=" + *st) {
290                                         dialog_->languageCO->setCurrentIndex(
291                                                 dialog_->languageCO->findText(toqstr(*st)));
292                                         *it = "";
293                                 }                       
294                         }
295                 } else if (prefixIs(*it, "floatplacement=")) {
296                         dialog_->floatCB->setChecked(true);
297                         dialog_->placementLE->setText(toqstr(it->substr(15)));
298                         *it = "";
299                 } else if (prefixIs(*it, "float")) {
300                         dialog_->floatCB->setChecked(true);
301                         if (prefixIs(*it, "float="))
302                                 dialog_->placementLE->setText(toqstr(it->substr(6)));
303                         *it = "";
304                 } else if (prefixIs(*it, "numbers=")) {
305                         dialog_->numberSideCO->setCurrentIndex(
306                                 dialog_->numberSideCO->findText(toqstr(it->substr(8))));
307                         *it = "";
308                 } else if (prefixIs(*it, "stepnumber=")) {
309                         dialog_->numberStepLE->setText(toqstr(it->substr(11)));
310                         *it = "";
311                 } else if (prefixIs(*it, "numberstyle=")) {
312                         for (vector<string>::const_iterator st = fontsizes.begin();
313                             st != fontsizes.end(); ++st) {
314                                 if (*it == "numberstyle=\\" + *st) {
315                                         dialog_->numberFontSizeCO->setCurrentIndex(
316                                                 dialog_->numberFontSizeCO->findText(toqstr(*st)));
317                                         *it = "";
318                                 }                       
319                         }
320                 } else if (prefixIs(*it, "firstline=")) {
321                         dialog_->firstlineLE->setText(toqstr(it->substr(10)));
322                         *it = "";
323                 } else if (prefixIs(*it, "lastline=")) {
324                         dialog_->lastlineLE->setText(toqstr(it->substr(9)));
325                         *it = "";
326                 } else if (prefixIs(*it, "basicstyle=")) {
327                         string style;
328                         string size;
329                         for (vector<string>::const_iterator st = fontstyles.begin();
330                             st != fontstyles.end(); ++st)
331                                 if (contains(*it, "\\" + *st)) {
332                                         style = "\\" + *st;
333                                         break;
334                                 }
335                         for (vector<string>::const_iterator st = fontsizes.begin();
336                             st != fontsizes.end(); ++st)
337                                 if (contains(*it, "\\" + *st)) {
338                                         size = "\\" + *st;
339                                         break;
340                                 }
341                         if (it->substr(11) == style + size || it->substr(11) == size + style) {
342                                 if (!style.empty())
343                                         dialog_->fontstyleCO->setCurrentIndex(
344                                                 dialog_->fontstyleCO->findText(toqstr(style.substr(1))));
345                                 if (!size.empty())
346                                         dialog_->fontsizeCO->setCurrentIndex(
347                                                 dialog_->fontsizeCO->findText(toqstr(size.substr(1))));
348                                 *it = "";
349                         }
350                 } else if (prefixIs(*it, "breaklines=")) {
351                         dialog_->breaklinesCB->setChecked(contains(*it, "true"));
352                         *it = "";
353                 } else if (prefixIs(*it, "showspaces=")) {
354                         dialog_->spaceCB->setChecked(contains(*it, "true"));
355                         *it = "";
356                 } else if (prefixIs(*it, "extendedchars=")) {
357                         dialog_->extendedcharsCB->setChecked(contains(*it, "true"));
358                         *it = "";
359                 }
360         }
361         // parameters that can be handled by widgets are cleared
362         // the rest is put to the extra edit box.
363         string extra = getStringFromVector(pars);
364         dialog_->listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
365 }
366
367
368 } // namespace frontend
369 } // namespace lyx
370
371
372 #include "QListings_moc.cpp"