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