]> git.lyx.org Git - features.git/blob - src/frontends/qt/GuiInclude.cpp
Fix problem with edit button.
[features.git] / src / frontends / qt / GuiInclude.cpp
1 /**
2  * \file GuiInclude.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  * \author John Levon
8  * \author Angus Leeming
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "GuiInclude.h"
16
17 #include "Buffer.h"
18 #include "BufferList.h"
19 #include "BufferParams.h"
20 #include "FuncRequest.h"
21 #include "LyXRC.h"
22
23 #include "qt_helpers.h"
24
25 #include "support/gettext.h"
26 #include "support/lstrings.h"
27 #include "support/os.h"
28 #include "support/FileName.h"
29 #include "support/filetools.h"
30
31 #include "frontends/alert.h"
32
33 #include "insets/InsetListingsParams.h"
34 #include "insets/InsetInclude.h"
35
36 #include <QCheckBox>
37 #include <QFile>
38 #include <QLineEdit>
39 #include <QPushButton>
40
41 #include <utility>
42
43 using namespace std;
44 using namespace lyx::support;
45 using namespace lyx::support::os;
46
47 namespace lyx {
48 namespace frontend {
49
50
51 GuiInclude::GuiInclude(GuiView & lv)
52         : GuiDialog(lv, "include", qt_("Child Document")),
53           params_(insetCode("include"))
54 {
55         setupUi(this);
56
57         connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
58                 this, SLOT(slotButtonBox(QAbstractButton *)));
59
60         connect(visiblespaceCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
61         connect(filenameED, SIGNAL(textChanged(const QString &)),
62                 this, SLOT(change_adaptor()));
63         connect(editPB, SIGNAL(clicked()), this, SLOT(edit()));
64         connect(browsePB, SIGNAL(clicked()), this, SLOT(browse()));
65         connect(typeCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
66         connect(typeCO, SIGNAL(activated(int)), this, SLOT(typeChanged(int)));
67         connect(previewCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
68         connect(captionLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
69         connect(labelLE, SIGNAL(textChanged(const QString&)), this, SLOT(change_adaptor()));
70         connect(literalCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
71         connect(listingsED, SIGNAL(textChanged()), this, SLOT(change_adaptor()));
72         connect(listingsED, SIGNAL(textChanged()), this, SLOT(setListingsMsg()));
73         connect(bypassCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
74         connect(bypassCB, SIGNAL(clicked()), this, SLOT(setListingsMsg()));
75
76         setFocusProxy(filenameED);
77
78         bc().setPolicy(ButtonPolicy::OkApplyCancelReadOnlyPolicy);
79         bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
80         bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
81         bc().addReadOnly(filenameED);
82         bc().addReadOnly(browsePB);
83         bc().addReadOnly(visiblespaceCB);
84         bc().addReadOnly(typeCO);
85         bc().addReadOnly(listingsED);
86
87         bc().addCheckedLineEdit(filenameED, filenameLA);
88 }
89
90
91 void GuiInclude::change_adaptor()
92 {
93         changed();
94 }
95
96
97 docstring GuiInclude::validate_listings_params()
98 {
99         if (typeCO->currentIndex() != 3 || bypassCB->isChecked())
100                 return docstring();
101         string params = fromqstr(listingsED->toPlainText());
102         InsetListingsParams lstparams(params);
103         lstparams.setMinted(buffer().params().use_minted);
104         return lstparams.validate();
105 }
106
107
108 void GuiInclude::setListingsMsg()
109 {
110         // FIXME THREAD
111         static bool isOK = true;
112         docstring msg = validate_listings_params();
113         if (msg.empty()) {
114                 if (isOK)
115                         return;
116                 isOK = true;
117                 listingsTB->setPlainText(
118                         qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
119         } else {
120                 isOK = false;
121                 listingsTB->setPlainText(toqstr(msg));
122         }
123 }
124
125
126 void GuiInclude::typeChanged(int v)
127 {
128         switch (v) {
129                 //case Include
130                 case 0:
131                         visiblespaceCB->setEnabled(false);
132                         visiblespaceCB->setChecked(false);
133                         previewCB->setEnabled(false);
134                         previewCB->setChecked(false);
135                         listingsGB->setEnabled(false);
136                         break;
137                 //case Input
138                 case 1:
139                         visiblespaceCB->setEnabled(false);
140                         visiblespaceCB->setChecked(false);
141                         previewCB->setEnabled(true);
142                         listingsGB->setEnabled(false);
143                         break;
144                 //case listings
145                 case 3:
146                         visiblespaceCB->setEnabled(false);
147                         visiblespaceCB->setChecked(false);
148                         previewCB->setEnabled(false);
149                         previewCB->setChecked(false);
150                         listingsGB->setEnabled(true);
151                         break;
152                 //case Verbatim
153                 default:
154                         visiblespaceCB->setEnabled(true);
155                         previewCB->setEnabled(false);
156                         previewCB->setChecked(false);
157                         listingsGB->setEnabled(false);
158                         break;
159         }
160 }
161
162
163 void GuiInclude::paramsToDialog(InsetCommandParams const & icp)
164 {
165         filenameED->setText(toqstr(icp["filename"]));
166
167         visiblespaceCB->setChecked(false);
168         visiblespaceCB->setEnabled(false);
169         previewCB->setChecked(false);
170         previewCB->setEnabled(false);
171         listingsGB->setEnabled(false);
172         captionLE->clear();
173         labelLE->clear();
174         listingsED->clear();
175         listingsTB->setPlainText(
176                 qt_("Input listing parameters on the right. Enter ? for a list of parameters."));
177
178         string cmdname = icp.getCmdName();
179         if (cmdname != "include" &&
180             cmdname != "verbatiminput" &&
181             cmdname != "verbatiminput*" &&
182             cmdname != "lstinputlisting" &&
183             cmdname != "inputminted")
184                 cmdname = "input";
185
186         if (cmdname == "include") {
187                 typeCO->setCurrentIndex(0);
188
189         } else if (cmdname == "input") {
190                 typeCO->setCurrentIndex(1);
191                 previewCB->setEnabled(true);
192                 previewCB->setChecked(icp.preview());
193
194         } else if (cmdname == "verbatiminput*") {
195                 typeCO->setCurrentIndex(2);
196                 visiblespaceCB->setEnabled(true);
197                 visiblespaceCB->setChecked(true);
198
199         } else if (cmdname == "verbatiminput") {
200                 typeCO->setCurrentIndex(2);
201                 visiblespaceCB->setEnabled(true);
202
203         } else if (cmdname == "lstinputlisting" || cmdname == "inputminted") {
204                 typeCO->setCurrentIndex(3);
205                 listingsGB->setEnabled(true);
206                 listingsED->setEnabled(true);
207                 InsetListingsParams par(to_utf8(icp["lstparams"]));
208                 // extract caption and label and put them into their respective editboxes
209                 vector<string> pars = getVectorFromString(par.separatedParams(), "\n");
210                 for (vector<string>::iterator it = pars.begin();
211                         it != pars.end(); ++it) {
212                         if (prefixIs(*it, "caption=")) {
213                                 string cap = it->substr(8);
214                                 if (cap[0] == '{' && cap[cap.size() - 1] == '}') {
215                                         captionLE->setText(toqstr(cap.substr(1, cap.size() - 2)));
216                                         *it = "";
217                                 }
218                         } else if (prefixIs(*it, "label=")) {
219                                 string lbl = it->substr(6);
220                                 if (lbl[0] == '{' && lbl[lbl.size()-1] == '}') {
221                                         labelLE->setText(toqstr(lbl.substr(1, lbl.size() - 2)));
222                                         *it = "";
223                                 }
224                         }
225                 }
226                 // the rest is put to the extra edit box.
227                 string extra = getStringFromVector(pars);
228                 listingsED->setPlainText(toqstr(InsetListingsParams(extra).separatedParams()));
229         }
230         literalCB->setChecked(icp["literal"] == "true");
231
232         // Make sure that the bc is in the INITIAL state
233         if (bc().policy().buttonStatus(ButtonPolicy::OKAY))
234                 bc().restore();
235 }
236
237
238 void GuiInclude::applyView()
239 {
240         params_["filename"] = from_utf8(internal_path(fromqstr(filenameED->text())));
241         params_.preview(previewCB->isChecked());
242
243         int const item = typeCO->currentIndex();
244         if (item == 0) {
245                 params_.setCmdName("include");
246         } else if (item == 1) {
247                 params_.setCmdName("input");
248         } else if (item == 3) {
249                 if (buffer().params().use_minted)
250                         params_.setCmdName("inputminted");
251                 else
252                         params_.setCmdName("lstinputlisting");
253                 // the parameter string should have passed validation
254                 InsetListingsParams par(fromqstr(listingsED->toPlainText()));
255                 string caption = fromqstr(captionLE->text());
256                 string label = fromqstr(labelLE->text());
257                 if (!caption.empty())
258                         par.addParam("caption", "{" + caption + "}");
259                 if (!label.empty())
260                         par.addParam("label", "{" + label + "}");
261                 string const listparams = par.params();
262                 params_["lstparams"] = from_utf8(listparams);
263         } else {
264                 if (visiblespaceCB->isChecked())
265                         params_.setCmdName("verbatiminput*");
266                 else
267                         params_.setCmdName("verbatiminput");
268         }
269         params_["literal"] = literalCB->isChecked()
270                         ? from_ascii("true") : from_ascii("false");
271
272         // Do we need to create a LyX file?
273         if (item == 0 || item == 1) {
274                 QString fname = filenameED->text();
275                 string const mypath = buffer().absFileName();
276                 string const bpath = buffer().filePath();
277                 QString absfname = makeAbsPath(fname, toqstr(bpath));
278                 if (!QFile::exists(absfname)) {
279                         dispatch(FuncRequest(LFUN_BUFFER_NEW, fromqstr(absfname)));
280                         dispatch(FuncRequest(LFUN_BUFFER_WRITE));
281                         dispatch(FuncRequest(LFUN_BUFFER_SWITCH, mypath));
282                 }
283         }
284 }
285
286
287 void GuiInclude::edit()
288 {
289         if (!isValid())
290                 return;
291         if (bc().policy().buttonStatus(ButtonPolicy::OKAY)) {
292                 slotOK();
293                 applyView();
294         } else
295                 hideView();
296         QString const fname = filenameED->text();
297         string const bpath = buffer().filePath();
298         string const absfname = support::makeAbsPath(fromqstr(fname), bpath).absFileName();
299         FileName const absFileName(absfname);
300         Buffer const * buffer = theBufferList().getBuffer(absFileName);
301         if (!buffer) {
302                 // The Buffer is not already open, so try to open it.
303                 if (!absFileName.exists()) {
304                         Alert::warning(_("File does not exist"),
305                                 bformat(_("The requested file\n\t%1$s\ndoes not exist."),
306                                         from_utf8(absfname)));
307                         return;
308                 }
309                 dispatch(FuncRequest(LFUN_BUFFER_NEW, absfname));
310                 // Did we succeed?
311                 if (!theBufferList().getBuffer(absFileName)) {
312                         // We should already have had an error message.
313                         return;
314                 }
315         }
316         // Switch to the requested Buffer
317         dispatch(FuncRequest(LFUN_BUFFER_SWITCH, absfname));
318 }
319
320
321 bool GuiInclude::isValid()
322 {
323         QString fname = filenameED->text();
324         bool fempty = fname.isEmpty();
325         if (fempty || !validate_listings_params().empty()) {
326                 editPB->setEnabled(false);
327                 return false;
328         }
329
330         QPushButton * okbutton = buttonBox->button(QDialogButtonBox::Ok);
331         int const item = typeCO->currentIndex();
332         // Are we inputting or including a LyX file?
333         if (item != 0 && item != 1) {
334                 okbutton->setText("OK");
335                 return true;
336         }
337         // Do we have a LyX filename?
338         if (!support::isLyXFileName(fromqstr(fname))) {
339                 okbutton->setText("OK");
340                 return false;
341         }
342         string const bpath = buffer().filePath();
343         QString absfname = makeAbsPath(fname, toqstr(bpath));
344         bool const fexists = QFile::exists(absfname);
345         okbutton->setText(fexists ? "OK" : "Create");
346         editPB->setEnabled(fexists);
347         return true;
348 }
349
350
351 void GuiInclude::browse()
352 {
353         Type type;
354
355         int const item = typeCO->currentIndex();
356         if (item == 0)
357                 type = INCLUDE;
358         else if (item == 1)
359                 type = INPUT;
360         else if (item == 2)
361                 type = VERBATIM;
362         else
363                 type = LISTINGS;
364
365         QString name = browse(filenameED->text(), type);
366         if (!name.isEmpty())
367                 filenameED->setText(name);
368 }
369
370
371 QString GuiInclude::browse(QString const & in_name, Type in_type) const
372 {
373         QString const title = qt_("Select document to include");
374
375         // input TeX, verbatim, or LyX file ?
376         QStringList filters;
377         switch (in_type) {
378         case INCLUDE:
379         case INPUT:
380                 filters = fileFilters(qt_("LaTeX/LyX Documents (*.tex *.lyx)"));
381                 break;
382         case VERBATIM:
383         case LISTINGS:
384                 filters = fileFilters(QString());
385                 break;
386         }
387
388         QString const docpath = toqstr(support::onlyPath(buffer().absFileName()));
389
390         return browseRelToParent(in_name, docpath, title, filters, false,
391                 qt_("D&ocuments"), toqstr(lyxrc.document_path));
392 }
393
394
395 bool GuiInclude::initialiseParams(std::string const & sdata)
396 {
397         InsetCommand::string2params(sdata, params_);
398         paramsToDialog(params_);
399         return true;
400 }
401
402
403 void GuiInclude::dispatchParams()
404 {
405         std::string const lfun = InsetCommand::params2string(params_);
406         dispatch(FuncRequest(getLfun(), lfun));
407 }
408
409
410 Dialog * createGuiInclude(GuiView & lv) { return new GuiInclude(lv); }
411
412
413 } // namespace frontend
414 } // namespace lyx
415
416 #include "moc_GuiInclude.cpp"