]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/qt_helpers.cpp
less string conversions as long as we stay in the frontend
[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 "FileDialog.h"
18 #include "LengthCombo.h"
19
20 #include "frontends/alert.h"
21
22 #include "Language.h"
23 #include "Length.h"
24
25 #include "support/debug.h"
26 #include "support/filetools.h"
27 #include "support/foreach.h"
28 #include "support/gettext.h"
29 #include "support/lstrings.h"
30 #include "support/lyxalgo.h"
31 #include "support/os.h"
32 #include "support/Package.h"
33 #include "support/Path.h"
34 #include "support/Systemcall.h"
35
36 #include <QCheckBox>
37 #include <QComboBox>
38 #include <QLineEdit>
39 #include <QPalette>
40 #include <QSet>
41
42 #include <algorithm>
43 #include <fstream>
44 #include <locale>
45
46 using namespace std;
47 using namespace lyx::support;
48
49 namespace lyx {
50
51 FileName libFileSearch(QString const & dir, QString const & name,
52                                 QString const & ext)
53 {
54         return support::libFileSearch(fromqstr(dir), fromqstr(name), fromqstr(ext));
55 }
56
57 namespace frontend {
58
59 string widgetsToLength(QLineEdit const * input, LengthCombo const * combo)
60 {
61         QString const length = input->text();
62         if (length.isEmpty())
63                 return string();
64
65         // Don't return unit-from-choice if the input(field) contains a unit
66         if (isValidGlueLength(fromqstr(length)))
67                 return fromqstr(length);
68
69         Length::UNIT const unit = combo->currentLengthItem();
70
71         return Length(length.toDouble(), unit).asString();
72 }
73
74
75 Length widgetsToLength(QLineEdit const * input, QComboBox const * combo)
76 {
77         QString const length = input->text();
78         if (length.isEmpty())
79                 return Length();
80
81         // don't return unit-from-choice if the input(field) contains a unit
82         if (isValidGlueLength(fromqstr(length)))
83                 return Length(fromqstr(length));
84
85         Length::UNIT const unit = unitFromString(fromqstr(combo->currentText()));
86
87         return Length(length.toDouble(), unit);
88 }
89
90
91 void lengthToWidgets(QLineEdit * input, LengthCombo * combo,
92                      Length const & len, Length::UNIT /*defaultUnit*/)
93 {
94         combo->setCurrentItem(len.unit());
95         input->setText(QString::number(Length(len).value()));
96 }
97
98
99 void lengthToWidgets(QLineEdit * input, LengthCombo * combo,
100         string const & len, Length::UNIT defaultUnit)
101 {
102         if (len.empty()) {
103                 // no length (UNIT_NONE)
104                 combo->setCurrentItem(defaultUnit);
105                 input->setText("");
106         } else if (!isValidLength(len) && !isStrDbl(len)) {
107                 // use input field only for gluelengths
108                 combo->setCurrentItem(defaultUnit);
109                 input->setText(toqstr(len));
110         } else {
111                 lengthToWidgets(input, combo, Length(len), defaultUnit);
112         }
113 }
114
115
116 void lengthAutoToWidgets(QLineEdit * input, LengthCombo * combo,
117         Length const & len, Length::UNIT defaultUnit)
118 {
119         if (len.value() == 0)
120                 lengthToWidgets(input, combo, "auto", defaultUnit);
121         else
122                 lengthToWidgets(input, combo, len, defaultUnit);
123 }
124
125
126 void setValid(QWidget * widget, bool valid)
127 {
128         if (valid) {
129                 widget->setPalette(QPalette());
130         } else {
131                 QPalette pal = widget->palette();
132                 pal.setColor(QPalette::Active, QPalette::Foreground, QColor(255, 0, 0));
133                 widget->setPalette(pal);
134         }
135 }
136
137 } // namespace frontend
138
139 QString const qt_(char const * str, const char *)
140 {
141         return toqstr(_(str));
142 }
143
144
145 QString const qt_(string const & str)
146 {
147         return toqstr(_(str));
148 }
149
150 namespace {
151
152 class Sorter
153 {
154 public:
155 #if !defined(USE_WCHAR_T) && defined(__GNUC__)
156         bool operator()(LanguagePair const & lhs, LanguagePair const & rhs) const
157         {
158                 return lhs.first < rhs.first;
159         }
160 #else
161         Sorter() : loc_ok(true)
162         {
163                 try {
164                         loc_ = locale("");
165                 } catch (...) {
166                         loc_ok = false;
167                 }
168         }
169
170         bool operator()(LanguagePair const & lhs, LanguagePair const & rhs) const
171         {
172                 //  FIXME: would that be "QString::localeAwareCompare()"?
173                 if (loc_ok)
174                         return loc_(fromqstr(lhs.first), fromqstr(rhs.first));
175                 else
176                         return lhs.first < rhs.first;
177         }
178 private:
179         locale loc_;
180         bool loc_ok;
181 #endif
182 };
183
184
185 } // namespace anon
186
187
188 QList<LanguagePair> languageData(bool character_dlg)
189 {
190         size_t const offset = character_dlg ? 2 : 0;
191         vector<LanguagePair> langs(languages.size() + offset);
192
193         if (character_dlg) {
194                 langs[0].first = qt_("No change");
195                 langs[0].second = "ignore";
196                 langs[1].first = qt_("Reset");
197                 langs[1].second = "reset";
198         }
199
200         Languages::const_iterator it = languages.begin();
201         for (size_t i = 0; i != languages.size(); ++i, ++it) {
202                 langs[i + offset].first  = qt_(it->second.display());
203                 langs[i + offset].second = toqstr(it->second.lang());
204         }
205
206         // Don't sort "ignore" and "reset"
207         vector<LanguagePair>::iterator begin = langs.begin() + offset;
208         sort(begin, langs.end(), Sorter());
209
210         QList<LanguagePair> list;
211         foreach (LanguagePair const & l, langs)
212                 list.append(l);
213         return list;
214 }
215
216
217 void rescanTexStyles()
218 {
219         // Run rescan in user lyx directory
220         PathChanger p(package().user_support());
221         FileName const command = libFileSearch("scripts", "TeXFiles.py");
222         Systemcall one;
223         int const status = one.startscript(Systemcall::Wait,
224                         os::python() + ' ' +
225                         quoteName(command.toFilesystemEncoding()));
226         if (status == 0)
227                 return;
228         // FIXME UNICODE
229         frontend::Alert::error(_("Could not update TeX information"),
230                 bformat(_("The script `%s' failed."), from_utf8(command.absFilename())));
231 }
232
233
234 QStringList texFileList(QString const & filename)
235 {
236         QStringList list;
237         FileName const file = libFileSearch(QString(), filename);
238         if (file.empty())
239                 return list;
240
241         // FIXME Unicode.
242         vector<docstring> doclist = 
243                 getVectorFromString(file.fileContents("UTF-8"), from_ascii("\n"));
244
245         // Normalise paths like /foo//bar ==> /foo/bar
246         QSet<QString> set;
247         for (size_t i = 0; i != doclist.size(); ++i) {
248                 QString file = toqstr(doclist[i]);
249                 while (file.contains("//"))
250                         file.replace("//", "/");
251                 if (!file.isEmpty())
252                         set.insert(file);
253         }
254
255         // remove duplicates
256         return QList<QString>::fromSet(set);
257 }
258
259
260 QString internalPath(const QString & str)
261 {
262         return toqstr(os::internal_path(fromqstr(str)));
263 }
264
265
266 QString onlyFilename(const QString & str)
267 {
268         return toqstr(support::onlyFilename(fromqstr(str)));
269 }
270
271
272 QString onlyPath(const QString & str)
273 {
274         return toqstr(support::onlyPath(fromqstr(str)));
275 }
276
277
278 QString changeExtension(QString const & oldname, QString const & ext)
279 {
280         return toqstr(support::changeExtension(fromqstr(oldname), fromqstr(ext)));
281 }
282
283 /// Remove the extension from \p name
284 QString removeExtension(QString const & name)
285 {
286         return toqstr(support::removeExtension(fromqstr(name)));
287 }
288
289 /** Add the extension \p ext to \p name.
290  Use this instead of changeExtension if you know that \p name is without
291  extension, because changeExtension would wrongly interpret \p name if it
292  contains a dot.
293  */
294 QString addExtension(QString const & name, QString const & ext)
295 {
296         return toqstr(support::addExtension(fromqstr(name), fromqstr(ext)));
297 }
298
299 /// Return the extension of the file (not including the .)
300 QString getExtension(QString const & name)
301 {
302         return toqstr(support::getExtension(fromqstr(name)));
303 }
304
305 } // namespace lyx