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// Qt-Security score:significant reason:default
4
8
9#include <QtWidgets/qlineedit.h>
10#include <QtGui/qvalidator.h>
11#include <QtGui/qevent.h>
12#include <QtWidgets/qcompleter.h>
13#include <QtWidgets/qabstractitemview.h>
14#include <QtCore/qregularexpression.h>
15#include <QtCore/qurl.h>
16#include <QtCore/qfile.h>
17#include <QtCore/qdebug.h>
18
20
21using namespace Qt::StringLiterals;
22
23namespace {
24 const QChar NewLineChar(u'\n');
25 const auto EscapedNewLine = "\\n"_L1;
26
27 // A validator that replaces offending strings
28 class ReplacementValidator : public QValidator {
29 public:
30 ReplacementValidator (QObject * parent,
31 const QString &offending,
32 const QString &replacement);
33 void fixup ( QString & input ) const override;
34 State validate ( QString & input, int &pos) const override;
35 private:
36 const QString m_offending;
37 const QString m_replacement;
38 };
39
40 ReplacementValidator::ReplacementValidator (QObject * parent,
41 const QString &offending,
42 const QString &replacement) :
43 QValidator(parent ),
44 m_offending(offending),
45 m_replacement(replacement)
46 {
47 }
48
49 void ReplacementValidator::fixup ( QString & input ) const {
50 input.replace(m_offending, m_replacement);
51 }
52
53 QValidator::State ReplacementValidator::validate ( QString & input, int &/* pos */) const {
54 fixup (input);
55 return Acceptable;
56 }
57
58 // A validator for style sheets. Does newline handling and validates sheets.
59 class StyleSheetValidator : public ReplacementValidator {
60 public:
61 StyleSheetValidator (QObject * parent);
62 State validate(QString & input, int &pos) const override;
63 };
64
65 StyleSheetValidator::StyleSheetValidator (QObject * parent) :
66 ReplacementValidator(parent, NewLineChar, EscapedNewLine)
67 {
68 }
69
70 QValidator::State StyleSheetValidator::validate ( QString & input, int &pos) const
71 {
72 // base class
73 const State state = ReplacementValidator:: validate(input, pos);
74 if (state != Acceptable)
75 return state;
76 // now check style sheet, create string with newlines
77 const QString styleSheet = qdesigner_internal::TextPropertyEditor::editorStringToString(input, qdesigner_internal::ValidationStyleSheet);
78 const bool valid = qdesigner_internal::StyleSheetEditorDialog::isStyleSheetValid(styleSheet);
79 return valid ? Acceptable : Intermediate;
80 }
81
82 // A validator for URLs based on QUrl. Enforces complete protocol
83 // specification with a completer (adds a trailing slash)
84 class UrlValidator : public QValidator {
85 public:
86 UrlValidator(QCompleter *completer, QObject *parent);
87
88 State validate(QString &input, int &pos) const override;
89 void fixup(QString &input) const override;
90 private:
91 QUrl guessUrlFromString(const QString &string) const;
92 QCompleter *m_completer;
93 };
94
95 UrlValidator::UrlValidator(QCompleter *completer, QObject *parent) :
96 QValidator(parent),
97 m_completer(completer)
98 {
99 }
100
101 QValidator::State UrlValidator::validate(QString &input, int &pos) const
102 {
103 Q_UNUSED(pos);
104
105 if (input.isEmpty())
106 return Acceptable;
107
108 const QUrl url(input, QUrl::StrictMode);
109
110 if (!url.isValid() || url.isEmpty())
111 return Intermediate;
112
113 if (url.scheme().isEmpty())
114 return Intermediate;
115
116 if (url.host().isEmpty() && url.path().isEmpty())
117 return Intermediate;
118
119 return Acceptable;
120 }
121
122 void UrlValidator::fixup(QString &input) const
123 {
124 // Don't try to fixup if the user is busy selecting a completion proposal
125 if (const QAbstractItemView *iv = m_completer->popup()) {
126 if (iv->isVisible())
127 return;
128 }
129
130 input = guessUrlFromString(input).toString();
131 }
132
133 QUrl UrlValidator::guessUrlFromString(const QString &string) const
134 {
135 const QString urlStr = string.trimmed();
136 const QRegularExpression qualifiedUrl(u"^[a-zA-Z]+\\:.*$"_s);
137 Q_ASSERT(qualifiedUrl.isValid());
138
139 // Check if it looks like a qualified URL. Try parsing it and see.
140 const bool hasSchema = qualifiedUrl.match(urlStr).hasMatch();
141 if (hasSchema) {
142 const QUrl url(urlStr, QUrl::TolerantMode);
143 if (url.isValid())
144 return url;
145 }
146
147 // Might be a Qt resource
148 if (string.startsWith(":/"_L1))
149 return QUrl("qrc"_L1 + string);
150
151 // Might be a file.
152 if (QFile::exists(urlStr))
153 return QUrl::fromLocalFile(urlStr);
154
155 // Might be a short url - try to detect the schema.
156 if (!hasSchema) {
157 const int dotIndex = urlStr.indexOf(u'.');
158 if (dotIndex != -1) {
159 const QString prefix = urlStr.left(dotIndex).toLower();
160 QString urlString;
161 if (prefix == "ftp"_L1)
162 urlString += prefix;
163 else
164 urlString += "http"_L1;
165 urlString += "://"_L1;
166 urlString += urlStr;
167 const QUrl url(urlString, QUrl::TolerantMode);
168 if (url.isValid())
169 return url;
170 }
171 }
172
173 // Fall back to QUrl's own tolerant parser.
174 return QUrl(string, QUrl::TolerantMode);
175 }
176}
177
178namespace qdesigner_internal {
179 // TextPropertyEditor
208
210 {
211 // QTBUG-143311: Slots may be triggered after deletion in conjunction
212 // with deferred delete when switching between inline editors in different forms.
213 m_lineEdit->disconnect(this);
214 }
215
219 switch (m_validationMode) {
222 m_lineEdit->setCompleter(nullptr);
223 break;
226 // Set a validator that replaces newline characters by literal "\\n".
227 // While it is not possible to actually type a newline characters,
228 // it can be pasted into the line edit.
230 m_lineEdit->setCompleter(nullptr);
231 break;
233 // Set a validator that replaces newline characters by a blank.
235 m_lineEdit->setCompleter(nullptr);
236 break;
238 setRegularExpressionValidator(u"^[_a-zA-Z][_a-zA-Z0-9]{1,1023}$"_s);
239 m_lineEdit->setCompleter(nullptr);
240 break;
242 setRegularExpressionValidator(u"^[_a-zA-Z:][_a-zA-Z0-9:]{1,1023}$"_s);
243 m_lineEdit->setCompleter(nullptr);
244 break;
245 case ValidationURL: {
246 static const QStringList urlCompletions = {
247 u"about:blank"_s,
248 u"https://"_s,
249 u"https://www."_s,
250 u"https://qt.io"_s,
251 u"file://"_s,
252 u"ftp://"_s,
253 u"data:"_s,
254 u"data:text/html,"_s,
255 u"qrc:/"_s,
256 };
260 }
261 break;
262 }
263
267 }
268
270 {
274 }
275
277 {
278 return m_cachedText;
279 }
280
282 {
285 } else {
289 }
290
291 }
292
300
302 {
303 m_textEdited = true;
304 }
305
311 }
312
314 {
317 m_textEdited = false;
318 }
319 }
320
324
326 m_lineEdit->clear();
327 }
328
332
338
342
344 return m_lineEdit->sizeHint ();
345 }
346
350
351 // Returns whether newline characters are valid in validationMode.
355
356 // Replace newline characters literal "\n" for inline editing in mode ValidationMultiLine
359 return s;
360
361 QString rc(s);
362 // protect backslashes
363 rc.replace('\\'_L1, "\\\\"_L1);
364 // escape newlines
365 rc.replace(u'\n', EscapedNewLine);
366 return rc;
367
368 }
369
370 // Replace literal "\n" by actual new lines for inline editing in mode ValidationMultiLine
371 // Note: As the properties are updated while the user types, it is important
372 // that trailing slashes ('bla\') are not deleted nor ignored, else this will
373 // cause jumping of the cursor
376 return s;
377
378 QString rc(s);
379 for (qsizetype pos = 0; (pos = rc.indexOf(u'\\', pos)) >= 0 ; ) {
380 // found an escaped character. If not a newline or at end of string, leave as is, else insert '\n'
381 const qsizetype nextpos = pos + 1;
382 if (nextpos >= rc.size()) // trailing '\\'
383 break;
384 // Escaped NewLine
385 if (rc.at(nextpos) == u'n')
386 rc[nextpos] = u'\n';
387 // Remove escape, go past escaped
388 rc.remove(pos,1);
389 pos++;
390 }
391 return rc;
392 }
393
397}
398
399QT_END_NAMESPACE
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.