Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
textpropertyeditor.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
7
8#include <QtWidgets/qlineedit.h>
9#include <QtGui/qvalidator.h>
10#include <QtGui/qevent.h>
11#include <QtWidgets/qcompleter.h>
12#include <QtWidgets/qabstractitemview.h>
13#include <QtCore/qregularexpression.h>
14#include <QtCore/qurl.h>
15#include <QtCore/qfile.h>
16#include <QtCore/qdebug.h>
17
19
20using namespace Qt::StringLiterals;
21
22namespace {
23 const QChar NewLineChar(u'\n');
24 const auto EscapedNewLine = "\\n"_L1;
25
26 // A validator that replaces offending strings
27 class ReplacementValidator : public QValidator {
28 public:
29 ReplacementValidator (QObject * parent,
30 const QString &offending,
31 const QString &replacement);
32 void fixup ( QString & input ) const override;
33 State validate ( QString & input, int &pos) const override;
34 private:
35 const QString m_offending;
36 const QString m_replacement;
37 };
38
39 ReplacementValidator::ReplacementValidator (QObject * parent,
40 const QString &offending,
41 const QString &replacement) :
42 QValidator(parent ),
43 m_offending(offending),
44 m_replacement(replacement)
45 {
46 }
47
48 void ReplacementValidator::fixup ( QString & input ) const {
49 input.replace(m_offending, m_replacement);
50 }
51
52 QValidator::State ReplacementValidator::validate ( QString & input, int &/* pos */) const {
53 fixup (input);
54 return Acceptable;
55 }
56
57 // A validator for style sheets. Does newline handling and validates sheets.
58 class StyleSheetValidator : public ReplacementValidator {
59 public:
60 StyleSheetValidator (QObject * parent);
61 State validate(QString & input, int &pos) const override;
62 };
63
64 StyleSheetValidator::StyleSheetValidator (QObject * parent) :
65 ReplacementValidator(parent, NewLineChar, EscapedNewLine)
66 {
67 }
68
69 QValidator::State StyleSheetValidator::validate ( QString & input, int &pos) const
70 {
71 // base class
72 const State state = ReplacementValidator:: validate(input, pos);
73 if (state != Acceptable)
74 return state;
75 // now check style sheet, create string with newlines
76 const QString styleSheet = qdesigner_internal::TextPropertyEditor::editorStringToString(input, qdesigner_internal::ValidationStyleSheet);
77 const bool valid = qdesigner_internal::StyleSheetEditorDialog::isStyleSheetValid(styleSheet);
78 return valid ? Acceptable : Intermediate;
79 }
80
81 // A validator for URLs based on QUrl. Enforces complete protocol
82 // specification with a completer (adds a trailing slash)
83 class UrlValidator : public QValidator {
84 public:
85 UrlValidator(QCompleter *completer, QObject *parent);
86
87 State validate(QString &input, int &pos) const override;
88 void fixup(QString &input) const override;
89 private:
90 QUrl guessUrlFromString(const QString &string) const;
91 QCompleter *m_completer;
92 };
93
94 UrlValidator::UrlValidator(QCompleter *completer, QObject *parent) :
95 QValidator(parent),
96 m_completer(completer)
97 {
98 }
99
100 QValidator::State UrlValidator::validate(QString &input, int &pos) const
101 {
102 Q_UNUSED(pos);
103
104 if (input.isEmpty())
105 return Acceptable;
106
107 const QUrl url(input, QUrl::StrictMode);
108
109 if (!url.isValid() || url.isEmpty())
110 return Intermediate;
111
112 if (url.scheme().isEmpty())
113 return Intermediate;
114
115 if (url.host().isEmpty() && url.path().isEmpty())
116 return Intermediate;
117
118 return Acceptable;
119 }
120
121 void UrlValidator::fixup(QString &input) const
122 {
123 // Don't try to fixup if the user is busy selecting a completion proposal
124 if (const QAbstractItemView *iv = m_completer->popup()) {
125 if (iv->isVisible())
126 return;
127 }
128
129 input = guessUrlFromString(input).toString();
130 }
131
132 QUrl UrlValidator::guessUrlFromString(const QString &string) const
133 {
134 const QString urlStr = string.trimmed();
135 const QRegularExpression qualifiedUrl(u"^[a-zA-Z]+\\:.*$"_s);
136 Q_ASSERT(qualifiedUrl.isValid());
137
138 // Check if it looks like a qualified URL. Try parsing it and see.
139 const bool hasSchema = qualifiedUrl.match(urlStr).hasMatch();
140 if (hasSchema) {
141 const QUrl url(urlStr, QUrl::TolerantMode);
142 if (url.isValid())
143 return url;
144 }
145
146 // Might be a Qt resource
147 if (string.startsWith(":/"_L1))
148 return QUrl("qrc"_L1 + string);
149
150 // Might be a file.
151 if (QFile::exists(urlStr))
152 return QUrl::fromLocalFile(urlStr);
153
154 // Might be a short url - try to detect the schema.
155 if (!hasSchema) {
156 const int dotIndex = urlStr.indexOf(u'.');
157 if (dotIndex != -1) {
158 const QString prefix = urlStr.left(dotIndex).toLower();
159 QString urlString;
160 if (prefix == "ftp"_L1)
161 urlString += prefix;
162 else
163 urlString += "http"_L1;
164 urlString += "://"_L1;
165 urlString += urlStr;
166 const QUrl url(urlString, QUrl::TolerantMode);
167 if (url.isValid())
168 return url;
169 }
170 }
171
172 // Fall back to QUrl's own tolerant parser.
173 return QUrl(string, QUrl::TolerantMode);
174 }
175}
176
177namespace qdesigner_internal {
178 // TextPropertyEditor
207
211 switch (m_validationMode) {
214 m_lineEdit->setCompleter(nullptr);
215 break;
218 // Set a validator that replaces newline characters by literal "\\n".
219 // While it is not possible to actually type a newline characters,
220 // it can be pasted into the line edit.
222 m_lineEdit->setCompleter(nullptr);
223 break;
225 // Set a validator that replaces newline characters by a blank.
227 m_lineEdit->setCompleter(nullptr);
228 break;
230 setRegularExpressionValidator(u"^[_a-zA-Z][_a-zA-Z0-9]{1,1023}$"_s);
231 m_lineEdit->setCompleter(nullptr);
232 break;
234 setRegularExpressionValidator(u"^[_a-zA-Z:][_a-zA-Z0-9:]{1,1023}$"_s);
235 m_lineEdit->setCompleter(nullptr);
236 break;
237 case ValidationURL: {
238 static const QStringList urlCompletions = {
239 u"about:blank"_s,
240 u"http://"_s,
241 u"http://www."_s,
242 u"http://qt.io"_s,
243 u"file://"_s,
244 u"ftp://"_s,
245 u"data:"_s,
246 u"data:text/html,"_s,
247 u"qrc:/"_s,
248 };
252 }
253 break;
254 }
255
259 }
260
262 {
266 }
267
269 {
270 return m_cachedText;
271 }
272
274 {
277 } else {
281 }
282
283 }
284
292
294 {
295 m_textEdited = true;
296 }
297
303 }
304
306 {
309 m_textEdited = false;
310 }
311 }
312
316
318 m_lineEdit->clear();
319 }
320
324
330
334
336 return m_lineEdit->sizeHint ();
337 }
338
342
343 // Returns whether newline characters are valid in validationMode.
347
348 // Replace newline characters literal "\n" for inline editing in mode ValidationMultiLine
351 return s;
352
353 QString rc(s);
354 // protect backslashes
355 rc.replace('\\'_L1, "\\\\"_L1);
356 // escape newlines
357 rc.replace(u'\n', EscapedNewLine);
358 return rc;
359
360 }
361
362 // Replace literal "\n" by actual new lines for inline editing in mode ValidationMultiLine
363 // Note: As the properties are updated while the user types, it is important
364 // that trailing slashes ('bla\') are not deleted nor ignored, else this will
365 // cause jumping of the cursor
368 return s;
369
370 QString rc(s);
371 for (qsizetype pos = 0; (pos = rc.indexOf(u'\\', pos)) >= 0 ; ) {
372 // found an escaped character. If not a newline or at end of string, leave as is, else insert '\n'
373 const qsizetype nextpos = pos + 1;
374 if (nextpos >= rc.size()) // trailing '\\'
375 break;
376 // Escaped NewLine
377 if (rc.at(nextpos) == u'n')
378 rc[nextpos] = u'\n';
379 // Remove escape, go past escaped
380 rc.remove(pos,1);
381 pos++;
382 }
383 return rc;
384 }
385
389}
390
391QT_END_NAMESPACE
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.