]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QListings.cpp
InsetListings: properly clear values of widgets when jumping between insets
[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
59 QListingsDialog::QListingsDialog(QListings * form)
60         : form_(form)
61 {
62         setupUi(this);
63         
64         connect(okPB, SIGNAL(clicked()), form, SLOT(slotOK()));
65         connect(closePB, SIGNAL(clicked()), form, SLOT(slotClose()));
66         
67         connect(languageCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
68         connect(inlineCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
69         connect(floatCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
70         connect(placementLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
71         connect(numberLeftCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
72         connect(numberRightCB, SIGNAL(clicked()), 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         bool left = numberLeftCB->checkState() == Qt::Checked;
109         bool right = numberRightCB->checkState() == Qt::Checked;
110         string stepnumber = fromqstr(numberStepLE->text());
111         string numberfontsize = fromqstr(numberFontSizeCO->currentText());
112         string firstline = fromqstr(firstlineLE->text());
113         string lastline = fromqstr(lastlineLE->text());
114         
115         string fontsize = fromqstr(fontsizeCO->currentText());
116         string fontstyle = fromqstr(fontstyleCO->currentText());
117         string basicstyle;
118         if (fontsize != "default")
119                 basicstyle = "\\" + fontsize;
120         if (fontstyle != "default")
121                 basicstyle += "\\" + fontstyle;
122         bool breakline = breaklinesCB->checkState() == Qt::Checked;
123         bool space = spaceCB->checkState() == Qt::Checked;
124         bool extendedchars = extendedcharsCB->checkState() == Qt::Checked;
125         string extra = fromqstr(listingsED->toPlainText());
126
127         // compose a string
128         InsetListingsParams par;
129         if (language != "no language")
130                 par.addParam("language", language);
131         if (float_)
132                 par.addParam("float", "");
133         if (!placement.empty())
134                 par.addParam("floatplacement", placement);
135         if (left)
136                 par.addParam("numbers", "left");
137         else if (right)
138                 par.addParam("numbers", "right");
139         if (numberfontsize != "default")
140                 par.addParam("numberstyle", "\\" + numberfontsize);
141         if (!firstline.empty())
142                 par.addParam("firstline", firstline);
143         if (!lastline.empty())
144                 par.addParam("lastline", lastline);
145         if (!stepnumber.empty())
146                 par.addParam("stepnumber", stepnumber);
147         if (!basicstyle.empty())
148                 par.addParam("basicstyle", basicstyle);
149         if (breakline)
150                 par.addParam("breaklines", "true");
151         if (space)
152                 par.addParam("showspaces", "true");
153         if (extendedchars)
154                 par.addParam("extendedchars", "true");
155         par.addParams(extra);
156         return par.params();
157 }
158
159
160 void QListingsDialog::validate_listings_params()
161 {
162         static bool isOK = true;
163         try {
164                 InsetListingsParams par(construct_params());
165                 if (!isOK) {
166                         isOK = true;
167                         listingsTB->setPlainText("Input listings parameters on the right. Enter ? for a list of parameters.");
168                         okPB->setEnabled(true);
169                 }
170         } catch (invalidParam & e) {
171                 isOK = false;
172                 listingsTB->setPlainText(e.what());
173                 okPB->setEnabled(false);
174         }
175 }
176
177 /////////////////////////////////////////////////////////////////////
178 //
179 // QListings
180 //
181 /////////////////////////////////////////////////////////////////////
182
183 typedef QController<ControlListings, QView<QListingsDialog> > listings_wrap_base_class;
184
185 QListings::QListings(Dialog & parent)
186         : listings_wrap_base_class(parent, _("Program Listings Settings"))
187 {
188 }
189
190
191 void QListings::build_dialog()
192 {
193         dialog_.reset(new QListingsDialog(this));
194         
195         bcview().setOK(dialog_->okPB);
196         bcview().setCancel(dialog_->closePB);
197         dialog_->listingsTB->setPlainText("Input listings parameters on the right. Enter ? for a list of parameters.");
198
199         update_contents();
200 }
201
202
203 /// not used right now.
204 void QListings::apply()
205 {
206         InsetListingsParams & params = controller().params();
207         params.setInline(dialog_->inlineCB->isChecked());
208         params.setParams(dialog_->construct_params());
209         controller().setParams(params);
210 }
211
212
213 void QListings::update_contents()
214 {
215         // first prepare all choices
216         vector<string> const languages = 
217                 getVectorFromString(allowed_languages, "\n");
218         vector<string> const fontstyles = 
219                 getVectorFromString(allowed_fontstyles, "\n");
220         vector<string> const fontsizes = 
221                 getVectorFromString(allowed_fontsizes, "\n");
222
223         dialog_->languageCO->clear();
224         for (vector<string>::const_iterator it = languages.begin();
225             it != languages.end(); ++it) {
226                 dialog_->languageCO->addItem(toqstr(*it));
227         }
228         dialog_->fontstyleCO->clear();
229         dialog_->fontstyleCO->setEditable(false);
230         for (vector<string>::const_iterator it = fontstyles.begin();
231             it != fontstyles.end(); ++it) {
232                 dialog_->fontstyleCO->addItem(toqstr(*it));
233         }
234         dialog_->fontsizeCO->clear();
235         dialog_->fontsizeCO->setEditable(false);
236         dialog_->numberFontSizeCO->clear();
237         dialog_->numberFontSizeCO->setEditable(false);
238         for (vector<string>::const_iterator it = fontsizes.begin();
239             it != fontsizes.end(); ++it) {
240                 dialog_->fontsizeCO->addItem(toqstr(*it));
241                 dialog_->numberFontSizeCO->addItem(toqstr(*it));
242         }
243
244         // set validators
245         dialog_->numberStepLE->setValidator(new QIntValidator(0, 1000000, this));
246         dialog_->firstlineLE->setValidator(new QIntValidator(0, 1000000, this));
247         dialog_->lastlineLE->setValidator(new QIntValidator(0, 1000000, this));
248         dialog_->placementLE->setValidator(new QRegExpValidator(QRegExp("[tbph]*"), this));
249
250         // set default values 
251         dialog_->listingsTB->setPlainText("Input listings parameters on the right. Enter ? for a list of parameters.");
252         dialog_->languageCO->setCurrentIndex(
253                 dialog_->languageCO->findText(toqstr("no language")));
254         dialog_->floatCB->setChecked(false);
255         dialog_->placementLE->clear();
256         dialog_->numberLeftCB->setChecked(false);
257         dialog_->numberRightCB->setChecked(false);
258         dialog_->numberStepLE->clear();
259         dialog_->numberFontSizeCO->setCurrentIndex(
260                 dialog_->numberFontSizeCO->findText(toqstr("default")));
261         dialog_->firstlineLE->clear();
262         dialog_->lastlineLE->clear();
263         dialog_->fontstyleCO->setCurrentIndex(
264                 dialog_->fontstyleCO->findText(toqstr("default")));
265         dialog_->fontsizeCO->setCurrentIndex(
266                 dialog_->fontsizeCO->findText(toqstr("default")));
267         dialog_->breaklinesCB->setChecked(false);
268         dialog_->spaceCB->setChecked(false);
269         dialog_->extendedcharsCB->setChecked(false);    
270
271         // set values from param string
272         InsetListingsParams & params = controller().params();
273         if (params.isInline())
274                 dialog_->inlineCB->setChecked(true);
275         else
276                 dialog_->inlineCB->setChecked(false);
277         // break other parameters and set values
278         vector<string> pars = getVectorFromString(params.separatedParams(), "\n");
279         // process each of them
280         for (vector<string>::iterator it = pars.begin();
281             it != pars.end(); ++it) {
282                 if (prefixIs(*it, "language=")) {
283                         for (vector<string>::const_iterator st = languages.begin();
284                             st != languages.end(); ++st) {
285                                 if (*it == "language=" + *st) {
286                                         dialog_->languageCO->setCurrentIndex(
287                                                 dialog_->languageCO->findText(toqstr(*st)));
288                                         *it = "";
289                                 }                       
290                         }
291                 } else if (prefixIs(*it, "float")) {
292                         if (prefixIs(*it, "float="))
293                                 dialog_->placementLE->setText(toqstr(it->substr(6)));
294                         else
295                                 dialog_->floatCB->setChecked(true);
296                         *it = "";
297                 } else if (prefixIs(*it, "floatplacement=")) {
298                         dialog_->placementLE->setText(toqstr(it->substr(15)));
299                         *it = "";
300                 } else if (prefixIs(*it, "numbers=")) {
301                         if (contains(*it, "left"))
302                                 dialog_->numberLeftCB->setChecked(true);
303                         else if (contains(*it, "right"))
304                                 dialog_->numberRightCB->setChecked(true);
305                         *it = "";
306                 } else if (prefixIs(*it, "stepnumber=")) {
307                         dialog_->numberStepLE->setText(toqstr(it->substr(11)));
308                         *it = "";
309                 } else if (prefixIs(*it, "numberstyle=")) {
310                         for (vector<string>::const_iterator st = fontsizes.begin();
311                             st != fontsizes.end(); ++st) {
312                                 if (*it == "numberstyle=\\" + *st) {
313                                         dialog_->numberFontSizeCO->setCurrentIndex(
314                                                 dialog_->numberFontSizeCO->findText(toqstr(*st)));
315                                         *it = "";
316                                 }                       
317                         }
318                 } else if (prefixIs(*it, "firstline=")) {
319                         dialog_->firstlineLE->setText(toqstr(it->substr(10)));
320                         *it = "";
321                 } else if (prefixIs(*it, "lastline=")) {
322                         dialog_->lastlineLE->setText(toqstr(it->substr(9)));
323                         *it = "";
324                 } else if (prefixIs(*it, "basicstyle=")) {
325                         string style;
326                         string size;
327                         for (vector<string>::const_iterator st = fontstyles.begin();
328                             st != fontstyles.end(); ++st)
329                                 if (contains(*it, "\\" + *st)) {
330                                         style = "\\" + *st;
331                                         break;
332                                 }
333                         for (vector<string>::const_iterator st = fontsizes.begin();
334                             st != fontsizes.end(); ++st)
335                                 if (contains(*it, "\\" + *st)) {
336                                         size = "\\" + *st;
337                                         break;
338                                 }
339                         if (it->substr(11) == style + size || it->substr(11) == size + style) {
340                                 if (!style.empty())
341                                         dialog_->fontstyleCO->setCurrentIndex(
342                                                 dialog_->fontstyleCO->findText(toqstr(style.substr(1))));
343                                 if (!size.empty())
344                                         dialog_->fontsizeCO->setCurrentIndex(
345                                                 dialog_->fontsizeCO->findText(toqstr(size.substr(1))));
346                                 *it = "";
347                         }
348                 } else if (prefixIs(*it, "breaklines=")) {
349                         dialog_->breaklinesCB->setChecked(contains(*it, "true"));
350                         *it = "";
351                 } else if (prefixIs(*it, "showspaces=")) {
352                         dialog_->spaceCB->setChecked(contains(*it, "true"));
353                         *it = "";
354                 } else if (prefixIs(*it, "extendedchars=")) {
355                         dialog_->extendedcharsCB->setChecked(contains(*it, "true"));
356                         *it = "";
357                 }
358         }
359         // parameters that can be handled by widgets are cleared
360         // the rest is put to the extra edit box.
361         string extra = getStringFromVector(pars);
362         dialog_->listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
363 }
364
365
366 } // namespace frontend
367 } // namespace lyx
368
369
370 #include "QListings_moc.cpp"