]> git.lyx.org Git - features.git/blob - src/frontends/qt/Validator.cpp
1ef90ac2c86f86156c4d3eb7a9cb714378601b03
[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                 return (isValidGlueLength(text, &gl)) ?
76                         QValidator::Acceptable : QValidator::Intermediate;
77         }
78
79         Length l;
80         bool const valid_length = isValidLength(text, &l);
81         if (!valid_length)
82                 return QValidator::Intermediate;
83
84         if (no_bottom_)
85                 return QValidator::Acceptable;
86
87         if (unsigned_ && l.value() < 0)
88                 return QValidator::Invalid;
89
90         if (positive_ && l.value() <= 0)
91                 return QValidator::Invalid;
92
93         return bottom_.inPixels(100) <= l.inPixels(100) ?
94                 QValidator::Acceptable : QValidator::Intermediate;
95 }
96
97
98 void LengthValidator::setBottom(Length const & b)
99 {
100         bottom_ = b;
101         no_bottom_ = false;
102 }
103
104
105 void LengthValidator::setBottom(GlueLength const & g)
106 {
107         glue_bottom_ = g;
108         no_bottom_ = false;
109         glue_length_ = true;
110 }
111
112
113 LengthValidator * unsignedLengthValidator(QLineEdit * ed)
114 {
115         LengthValidator * v = new LengthValidator(ed);
116         v->setBottom(Length());
117         v->setUnsigned(true);
118         return v;
119 }
120
121
122 LengthValidator * unsignedGlueLengthValidator(QLineEdit * ed)
123 {
124         LengthValidator * v = new LengthValidator(ed);
125         v->setBottom(GlueLength());
126         v->setUnsigned(true);
127         return v;
128 }
129
130
131 LengthAutoValidator::LengthAutoValidator(QWidget * parent, QString const & autotext)
132         : LengthValidator(parent),
133           autotext_(autotext)
134 {}
135
136
137 QValidator::State LengthAutoValidator::validate(QString & qtext, int & dummy) const
138 {
139         if (qtext == autotext_)
140                 return QValidator::Acceptable;
141         return LengthValidator::validate(qtext, dummy);
142 }
143
144
145 LengthAutoValidator * unsignedLengthAutoValidator(QLineEdit * ed, QString const & autotext)
146 {
147         LengthAutoValidator * v = new LengthAutoValidator(ed, autotext);
148         v->setBottom(Length());
149         v->setUnsigned(true);
150         return v;
151 }
152
153
154 LengthAutoValidator * positiveLengthAutoValidator(QLineEdit * ed, QString const & autotext)
155 {
156         LengthAutoValidator * v = new LengthAutoValidator(ed, autotext);
157         v->setBottom(Length());
158         v->setPositive(true);
159         return v;
160 }
161
162
163 DoubleAutoValidator::DoubleAutoValidator(QWidget * parent, QString const & autotext)
164         : QDoubleValidator(parent),
165           autotext_(autotext)
166 {}
167
168
169 DoubleAutoValidator::DoubleAutoValidator(double bottom,
170                 double top, int decimals, QObject * parent)
171         : QDoubleValidator(bottom, top, decimals, parent)
172 {}
173
174
175 QValidator::State DoubleAutoValidator::validate(QString & input, int & pos) const {
176         if (input == autotext_)
177                 return QValidator::Acceptable;
178         return QDoubleValidator::validate(input, pos);
179 }
180
181
182 NoNewLineValidator::NoNewLineValidator(QWidget * parent)
183         : QValidator(parent)
184 {}
185
186
187 QValidator::State NoNewLineValidator::validate(QString & qtext, int &) const
188 {
189 #if QT_VERSION < 0x060000
190         qtext.remove(QRegExp("[\\n\\r]"));
191 #else
192         qtext.remove(QRegularExpression("[\\n\\r]"));
193 #endif
194         return QValidator::Acceptable;
195 }
196
197
198 PathValidator::PathValidator(bool acceptable_if_empty,
199                              QWidget * parent)
200         : QValidator(parent),
201           acceptable_if_empty_(acceptable_if_empty),
202           latex_doc_(false),
203           tex_allows_spaces_(false)
204 {}
205
206
207 static docstring const printable_list(docstring const & invalid_chars)
208 {
209         docstring s;
210         docstring::const_iterator const begin = invalid_chars.begin();
211         docstring::const_iterator const end = invalid_chars.end();
212         docstring::const_iterator it = begin;
213
214         for (; it != end; ++it) {
215                 if (it != begin)
216                         s += ", ";
217                 if (*it == ' ')
218                         s += _("space");
219                 else
220                         s += *it;
221         }
222
223         return s;
224 }
225
226
227 QValidator::State PathValidator::validate(QString & qtext, int &) const
228 {
229         if (!latex_doc_)
230                 return QValidator::Acceptable;
231
232         docstring const text = support::trim(qstring_to_ucs4(qtext));
233         if (text.empty())
234                 return acceptable_if_empty_ ?
235                         QValidator::Acceptable : QValidator::Intermediate;
236
237         docstring invalid_chars = from_ascii("#$%{}()[]\"^");
238         if (!tex_allows_spaces_)
239                 invalid_chars += ' ';
240
241         if (text.find_first_of(invalid_chars) != docstring::npos) {
242
243                 static int counter = 0;
244                 if (counter == 0) {
245                         Alert::error(_("Invalid filename"),
246                                      _("LyX does not provide LaTeX support for file names containing any of these characters:\n") +
247                                          printable_list(invalid_chars));
248                 }
249                 ++counter;
250                 return QValidator::Intermediate;
251         }
252
253         return QValidator::Acceptable;
254 }
255
256
257 void PathValidator::setChecker(KernelDocType const & type, LyXRC const & rc)
258 {
259         latex_doc_ = type == KernelDocType::LaTeX;
260         tex_allows_spaces_ = rc.tex_allows_spaces;
261 }
262
263
264 PathValidator * getPathValidator(QLineEdit * ed)
265 {
266         if (!ed)
267                 return nullptr;
268         QValidator * validator = const_cast<QValidator *>(ed->validator());
269         if (!validator)
270                 return nullptr;
271         return dynamic_cast<PathValidator *>(validator);
272 }
273
274 } // namespace frontend
275 } // namespace lyx
276
277 #include "moc_Validator.cpp"