]> git.lyx.org Git - features.git/blob - src/frontends/qt/Validator.cpp
Fix broken Apple speller interface
[features.git] / src / frontends / qt / Validator.cpp
1 /**
2  * \file Validator.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  * \author Richard Kimberly Heck
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12
13 #include <config.h>
14
15 #include "Validator.h"
16
17 #include "Dialog.h"
18 #include "LyXRC.h"
19 #include "qt_helpers.h"
20
21 #include "frontends/alert.h"
22
23 #include "support/docstring.h"
24 #include "support/gettext.h"
25 #include "support/lstrings.h"
26
27 #include <QLineEdit>
28 #include <QLocale>
29 #include <QWidget>
30
31 using namespace std;
32
33 namespace lyx {
34 namespace frontend {
35
36 LengthValidator::LengthValidator(QWidget * parent)
37         : QValidator(parent)
38 {}
39
40
41 QValidator::State LengthValidator::validate(QString & qtext, int &) const
42 {
43         QLocale loc;
44         bool ok;
45         double d = loc.toDouble(qtext.trimmed(), &ok);
46         // QLocale::toDouble accepts something like "1."
47         // We don't.
48         bool dp = qtext.endsWith(loc.decimalPoint());
49         if (!ok) {
50                 // Fall back to C
51                 QLocale c(QLocale::C);
52                 d = c.toDouble(qtext.trimmed(), &ok);
53                 dp = qtext.endsWith(c.decimalPoint());
54         }
55
56         if (ok && unsigned_ && d < 0)
57                 return QValidator::Invalid;
58
59         if (ok && positive_ && d == 0)
60                 // A plausible intermediate value, see #12508
61                 return QValidator::Intermediate;
62
63         if (ok && positive_ && d < 0)
64                 return QValidator::Invalid;
65
66         if (qtext.isEmpty() || (ok && !dp))
67                 return QValidator::Acceptable;
68
69         string const text = fromqstr(qtext);
70
71         if (glue_length_) {
72                 GlueLength gl;
73                 if (unsigned_ && gl.len().value() < 0)
74                         return QValidator::Invalid;
75                 if (isValidGlueLength(text, &gl))
76                         return QValidator::Acceptable;
77                 // Also check for localized variant
78                 if (isValidGlueLength(fromqstr(unlocLengthString(qtext)), &gl))
79                         return QValidator::Acceptable;
80                 return QValidator::Intermediate;
81         }
82
83         Length l;
84         bool const valid_length = isValidLength(text, &l);
85         if (!valid_length)
86                 return QValidator::Intermediate;
87
88         if (no_bottom_)
89                 return QValidator::Acceptable;
90
91         if (unsigned_ && l.value() < 0)
92                 return QValidator::Invalid;
93
94         if (positive_ && l.value() <= 0)
95                 return QValidator::Invalid;
96
97         return bottom_.inPixels(100) <= l.inPixels(100) ?
98                 QValidator::Acceptable : QValidator::Intermediate;
99 }
100
101
102 void LengthValidator::setBottom(Length const & b)
103 {
104         bottom_ = b;
105         no_bottom_ = false;
106 }
107
108
109 void LengthValidator::setBottom(GlueLength const & g)
110 {
111         glue_bottom_ = g;
112         no_bottom_ = false;
113         glue_length_ = true;
114 }
115
116
117 LengthValidator * unsignedLengthValidator(QLineEdit * ed)
118 {
119         LengthValidator * v = new LengthValidator(ed);
120         v->setBottom(Length());
121         v->setUnsigned(true);
122         return v;
123 }
124
125
126 LengthValidator * unsignedGlueLengthValidator(QLineEdit * ed)
127 {
128         LengthValidator * v = new LengthValidator(ed);
129         v->setBottom(GlueLength());
130         v->setUnsigned(true);
131         return v;
132 }
133
134
135 LengthAutoValidator::LengthAutoValidator(QWidget * parent, QString const & autotext)
136         : LengthValidator(parent),
137           autotext_(autotext)
138 {}
139
140
141 QValidator::State LengthAutoValidator::validate(QString & qtext, int & dummy) const
142 {
143         if (qtext == autotext_)
144                 return QValidator::Acceptable;
145         return LengthValidator::validate(qtext, dummy);
146 }
147
148
149 LengthAutoValidator * unsignedLengthAutoValidator(QLineEdit * ed, QString const & autotext)
150 {
151         LengthAutoValidator * v = new LengthAutoValidator(ed, autotext);
152         v->setBottom(Length());
153         v->setUnsigned(true);
154         return v;
155 }
156
157
158 LengthAutoValidator * positiveLengthAutoValidator(QLineEdit * ed, QString const & autotext)
159 {
160         LengthAutoValidator * v = new LengthAutoValidator(ed, autotext);
161         v->setBottom(Length());
162         v->setPositive(true);
163         return v;
164 }
165
166
167 DoubleAutoValidator::DoubleAutoValidator(QWidget * parent, QString const & autotext)
168         : QDoubleValidator(parent),
169           autotext_(autotext)
170 {}
171
172
173 DoubleAutoValidator::DoubleAutoValidator(double bottom,
174                 double top, int decimals, QObject * parent)
175         : QDoubleValidator(bottom, top, decimals, parent)
176 {}
177
178
179 QValidator::State DoubleAutoValidator::validate(QString & input, int & pos) const {
180         if (input == autotext_)
181                 return QValidator::Acceptable;
182         return QDoubleValidator::validate(input, pos);
183 }
184
185
186 NoNewLineValidator::NoNewLineValidator(QWidget * parent)
187         : QValidator(parent)
188 {}
189
190
191 QValidator::State NoNewLineValidator::validate(QString & qtext, int &) const
192 {
193 #if QT_VERSION < 0x060000
194         qtext.remove(QRegExp("[\\n\\r]"));
195 #else
196         qtext.remove(QRegularExpression("[\\n\\r]"));
197 #endif
198         return QValidator::Acceptable;
199 }
200
201
202 PathValidator::PathValidator(bool acceptable_if_empty,
203                              QWidget * parent)
204         : QValidator(parent),
205           acceptable_if_empty_(acceptable_if_empty),
206           latex_doc_(false),
207           tex_allows_spaces_(false)
208 {}
209
210
211 static docstring const printable_list(docstring const & invalid_chars)
212 {
213         docstring s;
214         docstring::const_iterator const begin = invalid_chars.begin();
215         docstring::const_iterator const end = invalid_chars.end();
216         docstring::const_iterator it = begin;
217
218         for (; it != end; ++it) {
219                 if (it != begin)
220                         s += ", ";
221                 if (*it == ' ')
222                         s += _("space");
223                 else
224                         s += *it;
225         }
226
227         return s;
228 }
229
230
231 QValidator::State PathValidator::validate(QString & qtext, int &) const
232 {
233         if (!latex_doc_)
234                 return QValidator::Acceptable;
235
236         docstring const text = support::trim(qstring_to_ucs4(qtext));
237         if (text.empty())
238                 return acceptable_if_empty_ ?
239                         QValidator::Acceptable : QValidator::Intermediate;
240
241         docstring invalid_chars = from_ascii("#$%{}()[]\"^");
242         if (!tex_allows_spaces_)
243                 invalid_chars += ' ';
244
245         if (text.find_first_of(invalid_chars) != docstring::npos) {
246
247                 static int counter = 0;
248                 if (counter == 0) {
249                         Alert::error(_("Invalid filename"),
250                                      _("LyX does not provide LaTeX support for file names containing any of these characters:\n") +
251                                          printable_list(invalid_chars));
252                 }
253                 ++counter;
254                 return QValidator::Intermediate;
255         }
256
257         return QValidator::Acceptable;
258 }
259
260
261 void PathValidator::setChecker(KernelDocType const & type, LyXRC const & rc)
262 {
263         latex_doc_ = type == KernelDocType::LaTeX;
264         tex_allows_spaces_ = rc.tex_allows_spaces;
265 }
266
267
268 PathValidator * getPathValidator(QLineEdit * ed)
269 {
270         if (!ed)
271                 return nullptr;
272         QValidator * validator = const_cast<QValidator *>(ed->validator());
273         if (!validator)
274                 return nullptr;
275         return dynamic_cast<PathValidator *>(validator);
276 }
277
278 } // namespace frontend
279 } // namespace lyx
280
281 #include "moc_Validator.cpp"