]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/qt_helpers.cpp
cosmetics
[lyx.git] / src / frontends / qt4 / qt_helpers.cpp
1 /**
2  * \file qt_helpers.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Dekel Tsur
7  * \author Jürgen Spitzmüller
8  * \author Richard Heck
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "qt_helpers.h"
16
17 #include "LengthCombo.h"
18
19 #include "debug.h"
20 #include "gettext.h"
21 #include "Language.h"
22 #include "Length.h"
23
24 #include "frontends/FileDialog.h"
25 #include "frontends/alert.h"
26
27 #include "support/filetools.h"
28 #include "support/lstrings.h"
29 #include "support/lyxalgo.h"
30 #include "support/os.h"
31 #include "support/Package.h"
32 #include "support/Path.h"
33 #include "support/Systemcall.h"
34
35 #include <QComboBox>
36 #include <QCheckBox>
37 #include <QPalette>
38 #include <QLineEdit>
39
40 #include <boost/cregex.hpp>
41
42 #include <algorithm>
43 #include <fstream>
44
45 using std::string;
46 using std::vector;
47 using std::endl;
48
49 namespace lyx {
50
51 using support::addName;
52 using support::bformat;
53 using support::FileFilterList;
54 using support::FileName;
55 using support::getExtension;
56 using support::getVectorFromString;
57 using support::libFileSearch;
58 using support::makeAbsPath;
59 using support::makeRelPath;
60 using support::onlyFilename;
61 using support::onlyPath;
62 using support::package;
63 using support::prefixIs;
64 using support::quoteName;
65 using support::removeExtension;
66 using support::Systemcall;
67 using support::token;
68 using support::isStrDbl;
69
70 namespace frontend {
71
72 string widgetsToLength(QLineEdit const * input, LengthCombo const * combo)
73 {
74         QString const length = input->text();
75         if (length.isEmpty())
76                 return string();
77
78         // Don't return unit-from-choice if the input(field) contains a unit
79         if (isValidGlueLength(fromqstr(length)))
80                 return fromqstr(length);
81
82         Length::UNIT const unit = combo->currentLengthItem();
83
84         return Length(length.toDouble(), unit).asString();
85 }
86
87
88 Length widgetsToLength(QLineEdit const * input, QComboBox const * combo)
89 {
90         QString const length = input->text();
91         if (length.isEmpty())
92                 return Length();
93
94         // don't return unit-from-choice if the input(field) contains a unit
95         if (isValidGlueLength(fromqstr(length)))
96                 return Length(fromqstr(length));
97
98         Length::UNIT const unit = unitFromString(fromqstr(combo->currentText()));
99
100         return Length(length.toDouble(), unit);
101 }
102
103
104 void lengthToWidgets(QLineEdit * input, LengthCombo * combo,
105                      Length const & len, Length::UNIT /*defaultUnit*/)
106 {
107         combo->setCurrentItem(len.unit());
108         input->setText(QString::number(Length(len).value()));
109 }
110
111
112 void lengthToWidgets(QLineEdit * input, LengthCombo * combo,
113         string const & len, Length::UNIT defaultUnit)
114 {
115         if (len.empty()) {
116                 // no length (UNIT_NONE)
117                 combo->setCurrentItem(defaultUnit);
118                 input->setText("");
119         } else if (!isValidLength(len) && !isStrDbl(len)) {
120                 // use input field only for gluelengths
121                 combo->setCurrentItem(defaultUnit);
122                 input->setText(toqstr(len));
123         } else {
124                 lengthToWidgets(input, combo, Length(len), defaultUnit);
125         }
126 }
127
128
129 void lengthAutoToWidgets(QLineEdit * input, LengthCombo * combo,
130         Length const & len, Length::UNIT defaultUnit)
131 {
132         if (len.value() == 0)
133                 lengthToWidgets(input, combo, "auto", defaultUnit);
134         else
135                 lengthToWidgets(input, combo, len, defaultUnit);
136 }
137
138
139 void setValid(QWidget * widget, bool valid)
140 {
141         if (valid) {
142                 widget->setPalette(QPalette());
143         } else {
144                 QPalette pal = widget->palette();
145                 pal.setColor(QPalette::Active, QPalette::Foreground, QColor(255, 0, 0));
146                 widget->setPalette(pal);
147         }
148 }
149
150 } // namespace frontend
151
152 QString const qt_(char const * str, const char *)
153 {
154         return toqstr(_(str));
155 }
156
157
158 QString const qt_(string const & str)
159 {
160         return toqstr(_(str));
161 }
162
163 namespace {
164
165 struct Sorter
166 {
167         bool operator()(LanguagePair const & lhs, LanguagePair const & rhs) const {
168                 return lhs.first < rhs.first;
169         }
170 };
171
172
173 } // namespace anon
174
175
176 vector<LanguagePair> const getLanguageData(bool character_dlg)
177 {
178         vector<LanguagePair>::size_type const size = character_dlg ?
179                 languages.size() + 2 : languages.size();
180
181         vector<LanguagePair> langs(size);
182
183         if (character_dlg) {
184                 langs[0].first = _("No change");
185                 langs[0].second = "ignore";
186                 langs[1].first = _("Reset");
187                 langs[1].second = "reset";
188         }
189
190         vector<string>::size_type i = character_dlg ? 2 : 0;
191         for (Languages::const_iterator cit = languages.begin();
192              cit != languages.end(); ++cit) {
193                 langs[i].first  = _(cit->second.display());
194                 langs[i].second = cit->second.lang();
195                 ++i;
196         }
197
198         // Don't sort "ignore" and "reset"
199         vector<LanguagePair>::iterator begin = character_dlg ?
200                 langs.begin() + 2 : langs.begin();
201
202         std::sort(begin, langs.end(), Sorter());
203
204         return langs;
205 }
206
207
208 docstring browseFile(docstring const & filename, docstring const & title,
209         FileFilterList const & filters, bool save,
210         docstring const & label1, docstring const & dir1,
211         docstring const & label2, docstring const & dir2)
212 {
213         docstring lastPath = from_ascii(".");
214         if (!filename.empty())
215                 lastPath = from_utf8(onlyPath(to_utf8(filename)));
216
217         FileDialog dlg(title, LFUN_SELECT_FILE_SYNC);
218         dlg.setButton1(label1, dir1);
219         dlg.setButton2(label2, dir2);
220
221         FileDialog::Result result;
222
223         if (save)
224                 result = dlg.save(lastPath, filters,
225                                       from_utf8(onlyFilename(to_utf8(filename))));
226         else
227                 result = dlg.open(lastPath, filters,
228                                       from_utf8(onlyFilename(to_utf8(filename))));
229
230         return result.second;
231 }
232
233
234 docstring browseRelFile(docstring const & filename, docstring const & refpath,
235         docstring const & title, FileFilterList const & filters, bool save,
236         docstring const & label1, docstring const & dir1,
237         docstring const & label2, docstring const & dir2)
238 {
239         docstring const fname = from_utf8(makeAbsPath(
240                 to_utf8(filename), to_utf8(refpath)).absFilename());
241
242         docstring const outname = browseFile(fname, title, filters, save,
243                                           label1, dir1, label2, dir2);
244         docstring const reloutname = makeRelPath(outname, refpath);
245         if (prefixIs(reloutname, from_ascii("../")))
246                 return outname;
247         else
248                 return reloutname;
249 }
250
251
252 docstring browseLibFile(docstring const & dir, docstring const & name,
253         docstring const & ext, docstring const & title,
254         FileFilterList const & filters)
255 {
256         // FIXME UNICODE
257         docstring const label1 = _("System files|#S#s");
258         docstring const dir1 =
259                 from_utf8(addName(package().system_support().absFilename(), to_utf8(dir)));
260
261         docstring const label2 = _("User files|#U#u");
262         docstring const dir2 =
263                 from_utf8(addName(package().user_support().absFilename(), to_utf8(dir)));
264
265         docstring const result = browseFile(from_utf8(
266                 libFileSearch(to_utf8(dir), to_utf8(name), to_utf8(ext)).absFilename()),
267                 title, filters, false, dir1, dir2);
268
269         // remove the extension if it is the default one
270         docstring noextresult;
271         if (from_utf8(getExtension(to_utf8(result))) == ext)
272                 noextresult = from_utf8(removeExtension(to_utf8(result)));
273         else
274                 noextresult = result;
275
276         // remove the directory, if it is the default one
277         docstring const file = from_utf8(onlyFilename(to_utf8(noextresult)));
278         if (from_utf8(libFileSearch(to_utf8(dir), to_utf8(file), to_utf8(ext)).absFilename()) == result)
279                 return file;
280         else
281                 return noextresult;
282 }
283
284
285 docstring browseDir(docstring const & pathname, docstring const & title,
286         docstring const & label1, docstring const & dir1,
287         docstring const & label2, docstring const & dir2)
288 {
289         docstring lastPath = from_ascii(".");
290         if (!pathname.empty())
291                 lastPath = from_utf8(onlyPath(to_utf8(pathname)));
292
293         FileDialog dlg(title, LFUN_SELECT_FILE_SYNC);
294         dlg.setButton1(label1, dir1);
295         dlg.setButton2(label2, dir2);
296
297         FileDialog::Result const result =
298                 dlg.opendir(lastPath, from_utf8(onlyFilename(to_utf8(pathname))));
299
300         return result.second;
301 }
302
303
304 void rescanTexStyles()
305 {
306         // Run rescan in user lyx directory
307         support::PathChanger p(package().user_support());
308         FileName const command = libFileSearch("scripts", "TeXFiles.py");
309         Systemcall one;
310         int const status = one.startscript(Systemcall::Wait,
311                         support::os::python() + ' ' +
312                         quoteName(command.toFilesystemEncoding()));
313         if (status == 0)
314                 return;
315         // FIXME UNICODE
316         frontend::Alert::error(_("Could not update TeX information"),
317                 bformat(_("The script `%s' failed."), from_utf8(command.absFilename())));
318 }
319
320
321 void getTexFileList(string const & filename, std::vector<string> & list)
322 {
323         list.clear();
324         FileName const file = libFileSearch("", filename);
325         if (file.empty())
326                 return;
327
328         list = getVectorFromString(file.fileContents(), "\n");
329
330         // Normalise paths like /foo//bar ==> /foo/bar
331         boost::RegEx regex("/{2,}");
332         std::vector<string>::iterator it  = list.begin();
333         std::vector<string>::iterator end = list.end();
334         for (; it != end; ++it)
335                 *it = regex.Merge((*it), "/");
336
337         // remove empty items and duplicates
338         list.erase(std::remove(list.begin(), list.end(), ""), list.end());
339         eliminate_duplicates(list);
340 }
341
342 } // namespace lyx