1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36
37 #include "qquicktextfield_p.h"
38 #include "qquicktextfield_p_p.h"
39 #include "qquickcontrol_p.h"
40 #include "qquickcontrol_p_p.h"
41 #include "qquickdeferredexecute_p_p.h"
42
43 #include <QtQuick/private/qquickitem_p.h>
44 #include <QtQuick/private/qquicktextinput_p.h>
45 #include <QtQuick/private/qquickclipnode_p.h>
46
47 #if QT_CONFIG(accessibility)
48 #include <QtQuick/private/qquickaccessibleattached_p.h>
49 #endif
50
51 QT_BEGIN_NAMESPACE
52
53 /*!
54 \qmltype TextField
55 \inherits TextInput
56 //! \instantiates QQuickTextField
57 \inqmlmodule QtQuick.Controls
58 \since 5.7
59 \ingroup qtquickcontrols2-input
60 \brief Single-line text input field.
61
62 TextField is a single line text editor. TextField extends TextInput with
63 a \l {placeholderText}{placeholder text} functionality, and adds decoration.
64
65 \table
66 \row \li \image qtquickcontrols2-textfield-normal.png
67 \li A text field in its normal state.
68 \row \li \image qtquickcontrols2-textfield-focused.png
69 \li A text field that has active focus.
70 \row \li \image qtquickcontrols2-textfield-disabled.png
71 \li A text field that is disabled.
72 \endtable
73
74 \code
75 TextField {
76 placeholderText: qsTr("Enter name")
77 }
78 \endcode
79
80 \sa TextArea, {Customizing TextField}, {Input Controls}
81 */
82
83 /*!
84 \qmlsignal QtQuick.Controls::TextField::pressAndHold(MouseEvent event)
85
86 This signal is emitted when there is a long press (the delay depends on the platform plugin).
87 The \a event parameter provides information about the press, including the x and y
88 coordinates of the press, and which button is pressed.
89
90 \sa pressed, released
91 */
92
93 /*!
94 \qmlsignal QtQuick.Controls::TextField::pressed(MouseEvent event)
95 \since QtQuick.Controls 2.1 (Qt 5.8)
96
97 This signal is emitted when the text field is pressed by the user.
98 The \a event parameter provides information about the press,
99 including the x and y coordinates of the press, and which button
100 is pressed.
101
102 \sa released, pressAndHold
103 */
104
105 /*!
106 \qmlsignal QtQuick.Controls::TextField::released(MouseEvent event)
107 \since QtQuick.Controls 2.1 (Qt 5.8)
108
109 This signal is emitted when the text field is released by the user.
110 The \a event parameter provides information about the release,
111 including the x and y coordinates of the press, and which button
112 is pressed.
113
114 \sa pressed, pressAndHold
115 */
116
QQuickTextFieldPrivate()117 QQuickTextFieldPrivate::QQuickTextFieldPrivate()
118 {
119 #if QT_CONFIG(accessibility)
120 QAccessible::installActivationObserver(this);
121 #endif
122 }
123
~QQuickTextFieldPrivate()124 QQuickTextFieldPrivate::~QQuickTextFieldPrivate()
125 {
126 #if QT_CONFIG(accessibility)
127 QAccessible::removeActivationObserver(this);
128 #endif
129 }
130
setTopInset(qreal value,bool reset)131 void QQuickTextFieldPrivate::setTopInset(qreal value, bool reset)
132 {
133 Q_Q(QQuickTextField);
134 const QMarginsF oldInset = getInset();
135 extra.value().topInset = value;
136 extra.value().hasTopInset = !reset;
137 if (!qFuzzyCompare(oldInset.top(), value)) {
138 emit q->topInsetChanged();
139 q->insetChange(getInset(), oldInset);
140 }
141 }
142
setLeftInset(qreal value,bool reset)143 void QQuickTextFieldPrivate::setLeftInset(qreal value, bool reset)
144 {
145 Q_Q(QQuickTextField);
146 const QMarginsF oldInset = getInset();
147 extra.value().leftInset = value;
148 extra.value().hasLeftInset = !reset;
149 if (!qFuzzyCompare(oldInset.left(), value)) {
150 emit q->leftInsetChanged();
151 q->insetChange(getInset(), oldInset);
152 }
153 }
154
setRightInset(qreal value,bool reset)155 void QQuickTextFieldPrivate::setRightInset(qreal value, bool reset)
156 {
157 Q_Q(QQuickTextField);
158 const QMarginsF oldInset = getInset();
159 extra.value().rightInset = value;
160 extra.value().hasRightInset = !reset;
161 if (!qFuzzyCompare(oldInset.right(), value)) {
162 emit q->rightInsetChanged();
163 q->insetChange(getInset(), oldInset);
164 }
165 }
166
setBottomInset(qreal value,bool reset)167 void QQuickTextFieldPrivate::setBottomInset(qreal value, bool reset)
168 {
169 Q_Q(QQuickTextField);
170 const QMarginsF oldInset = getInset();
171 extra.value().bottomInset = value;
172 extra.value().hasBottomInset = !reset;
173 if (!qFuzzyCompare(oldInset.bottom(), value)) {
174 emit q->bottomInsetChanged();
175 q->insetChange(getInset(), oldInset);
176 }
177 }
178
resizeBackground()179 void QQuickTextFieldPrivate::resizeBackground()
180 {
181 if (!background)
182 return;
183
184 resizingBackground = true;
185
186 QQuickItemPrivate *p = QQuickItemPrivate::get(background);
187 if (((!p->widthValid || !extra.isAllocated() || !extra->hasBackgroundWidth) && qFuzzyIsNull(background->x()))
188 || (extra.isAllocated() && (extra->hasLeftInset || extra->hasRightInset))) {
189 const bool wasWidthValid = p->widthValid;
190 background->setX(getLeftInset());
191 background->setWidth(width - getLeftInset() - getRightInset());
192 // If the user hadn't previously set the width, that shouldn't change when we set it for them.
193 if (!wasWidthValid)
194 p->widthValid = false;
195 }
196 if (((!p->heightValid || !extra.isAllocated() || !extra->hasBackgroundHeight) && qFuzzyIsNull(background->y()))
197 || (extra.isAllocated() && (extra->hasTopInset || extra->hasBottomInset))) {
198 const bool wasHeightValid = p->heightValid;
199 background->setY(getTopInset());
200 background->setHeight(height - getTopInset() - getBottomInset());
201 if (!wasHeightValid)
202 p->heightValid = false;
203 }
204
205 resizingBackground = false;
206 }
207
208 /*!
209 \internal
210
211 Determine which font is implicitly imposed on this control by its ancestors
212 and QGuiApplication::font, resolve this against its own font (attributes from
213 the implicit font are copied over). Then propagate this font to this
214 control's children.
215 */
resolveFont()216 void QQuickTextFieldPrivate::resolveFont()
217 {
218 Q_Q(QQuickTextField);
219 inheritFont(QQuickControlPrivate::parentFont(q));
220 }
221
inheritFont(const QFont & font)222 void QQuickTextFieldPrivate::inheritFont(const QFont &font)
223 {
224 QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font;
225 parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve());
226
227 const QFont defaultFont = QQuickTheme::font(QQuickTheme::TextField);
228 QFont resolvedFont = parentFont.resolve(defaultFont);
229 // See comment in QQuickControlPrivate::inheritFont
230 if (defaultFont.families().isEmpty())
231 resolvedFont.setFamilies(QStringList());
232
233 setFont_helper(resolvedFont);
234 }
235
236 /*!
237 \internal
238
239 Assign \a font to this control, and propagate it to all children.
240 */
updateFont(const QFont & font)241 void QQuickTextFieldPrivate::updateFont(const QFont &font)
242 {
243 Q_Q(QQuickTextField);
244 QFont oldFont = sourceFont;
245 q->QQuickTextInput::setFont(font);
246
247 QQuickControlPrivate::updateFontRecur(q, font);
248
249 if (oldFont != font)
250 emit q->fontChanged();
251 }
252
253 /*!
254 \internal
255
256 Determine which palette is implicitly imposed on this control by its ancestors
257 and QGuiApplication::palette, resolve this against its own palette (attributes from
258 the implicit palette are copied over). Then propagate this palette to this
259 control's children.
260 */
resolvePalette()261 void QQuickTextFieldPrivate::resolvePalette()
262 {
263 Q_Q(QQuickTextField);
264 inheritPalette(QQuickControlPrivate::parentPalette(q));
265 }
266
inheritPalette(const QPalette & palette)267 void QQuickTextFieldPrivate::inheritPalette(const QPalette &palette)
268 {
269 QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette;
270 parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve());
271
272 const QPalette defaultPalette = QQuickTheme::palette(QQuickTheme::TextField);
273 const QPalette resolvedPalette = parentPalette.resolve(defaultPalette);
274
275 setPalette_helper(resolvedPalette);
276 }
277
updatePalette(const QPalette & palette)278 void QQuickTextFieldPrivate::updatePalette(const QPalette &palette)
279 {
280 Q_Q(QQuickTextField);
281 QPalette oldPalette = resolvedPalette;
282 resolvedPalette = palette;
283
284 QQuickControlPrivate::updatePaletteRecur(q, palette);
285
286 if (oldPalette != palette)
287 emit q->paletteChanged();
288 }
289
290 #if QT_CONFIG(quicktemplates2_hover)
updateHoverEnabled(bool enabled,bool xplicit)291 void QQuickTextFieldPrivate::updateHoverEnabled(bool enabled, bool xplicit)
292 {
293 Q_Q(QQuickTextField);
294 if (!xplicit && explicitHoverEnabled)
295 return;
296
297 bool wasEnabled = q->isHoverEnabled();
298 explicitHoverEnabled = xplicit;
299 if (wasEnabled != enabled) {
300 q->setAcceptHoverEvents(enabled);
301 QQuickControlPrivate::updateHoverEnabledRecur(q, enabled);
302 emit q->hoverEnabledChanged();
303 }
304 }
305 #endif
306
getImplicitWidth() const307 qreal QQuickTextFieldPrivate::getImplicitWidth() const
308 {
309 return QQuickItemPrivate::getImplicitWidth();
310 }
311
getImplicitHeight() const312 qreal QQuickTextFieldPrivate::getImplicitHeight() const
313 {
314 return QQuickItemPrivate::getImplicitHeight();
315 }
316
implicitWidthChanged()317 void QQuickTextFieldPrivate::implicitWidthChanged()
318 {
319 Q_Q(QQuickTextField);
320 QQuickItemPrivate::implicitWidthChanged();
321 emit q->implicitWidthChanged3();
322 }
323
implicitHeightChanged()324 void QQuickTextFieldPrivate::implicitHeightChanged()
325 {
326 Q_Q(QQuickTextField);
327 QQuickItemPrivate::implicitHeightChanged();
328 emit q->implicitHeightChanged3();
329 }
330
readOnlyChanged(bool isReadOnly)331 void QQuickTextFieldPrivate::readOnlyChanged(bool isReadOnly)
332 {
333 Q_UNUSED(isReadOnly);
334 #if QT_CONFIG(accessibility)
335 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func()))
336 accessibleAttached->set_readOnly(isReadOnly);
337 #endif
338 #if QT_CONFIG(cursor)
339 q_func()->setCursor(isReadOnly ? Qt::ArrowCursor : Qt::IBeamCursor);
340 #endif
341 }
342
echoModeChanged(QQuickTextField::EchoMode echoMode)343 void QQuickTextFieldPrivate::echoModeChanged(QQuickTextField::EchoMode echoMode)
344 {
345 #if QT_CONFIG(accessibility)
346 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func()))
347 accessibleAttached->set_passwordEdit((echoMode == QQuickTextField::Password || echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false);
348 #else
349 Q_UNUSED(echoMode)
350 #endif
351 }
352
353 #if QT_CONFIG(accessibility)
accessibilityActiveChanged(bool active)354 void QQuickTextFieldPrivate::accessibilityActiveChanged(bool active)
355 {
356 if (!active)
357 return;
358
359 Q_Q(QQuickTextField);
360 QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
361 Q_ASSERT(accessibleAttached);
362 accessibleAttached->setRole(accessibleRole());
363 accessibleAttached->set_readOnly(m_readOnly);
364 accessibleAttached->set_passwordEdit((m_echoMode == QQuickTextField::Password || m_echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false);
365 accessibleAttached->setDescription(placeholder);
366 }
367
accessibleRole() const368 QAccessible::Role QQuickTextFieldPrivate::accessibleRole() const
369 {
370 return QAccessible::EditableText;
371 }
372 #endif
373
backgroundName()374 static inline QString backgroundName() { return QStringLiteral("background"); }
375
cancelBackground()376 void QQuickTextFieldPrivate::cancelBackground()
377 {
378 Q_Q(QQuickTextField);
379 quickCancelDeferred(q, backgroundName());
380 }
381
executeBackground(bool complete)382 void QQuickTextFieldPrivate::executeBackground(bool complete)
383 {
384 Q_Q(QQuickTextField);
385 if (background.wasExecuted())
386 return;
387
388 if (!background || complete)
389 quickBeginDeferred(q, backgroundName(), background);
390 if (complete)
391 quickCompleteDeferred(q, backgroundName(), background);
392 }
393
itemGeometryChanged(QQuickItem * item,QQuickGeometryChange change,const QRectF & diff)394 void QQuickTextFieldPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff)
395 {
396 Q_UNUSED(diff);
397 if (resizingBackground || item != background || !change.sizeChange())
398 return;
399
400 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
401 // QTBUG-71875: only allocate the extra data if we have to.
402 // resizeBackground() relies on the value of extra.isAllocated()
403 // as part of its checks to see whether it should resize the background or not.
404 if (p->widthValid || extra.isAllocated())
405 extra.value().hasBackgroundWidth = p->widthValid;
406 if (p->heightValid || extra.isAllocated())
407 extra.value().hasBackgroundHeight = p->heightValid;
408 resizeBackground();
409 }
410
itemImplicitWidthChanged(QQuickItem * item)411 void QQuickTextFieldPrivate::itemImplicitWidthChanged(QQuickItem *item)
412 {
413 Q_Q(QQuickTextField);
414 if (item == background)
415 emit q->implicitBackgroundWidthChanged();
416 }
417
itemImplicitHeightChanged(QQuickItem * item)418 void QQuickTextFieldPrivate::itemImplicitHeightChanged(QQuickItem *item)
419 {
420 Q_Q(QQuickTextField);
421 if (item == background)
422 emit q->implicitBackgroundHeightChanged();
423 }
424
itemDestroyed(QQuickItem * item)425 void QQuickTextFieldPrivate::itemDestroyed(QQuickItem *item)
426 {
427 Q_Q(QQuickTextField);
428 if (item == background) {
429 background = nullptr;
430 emit q->implicitBackgroundWidthChanged();
431 emit q->implicitBackgroundHeightChanged();
432 }
433 }
434
QQuickTextField(QQuickItem * parent)435 QQuickTextField::QQuickTextField(QQuickItem *parent)
436 : QQuickTextInput(*(new QQuickTextFieldPrivate), parent)
437 {
438 Q_D(QQuickTextField);
439 d->pressHandler.control = this;
440 d->setImplicitResizeEnabled(false);
441 setAcceptedMouseButtons(Qt::AllButtons);
442 setActiveFocusOnTab(true);
443 #if QT_CONFIG(cursor)
444 setCursor(Qt::IBeamCursor);
445 #endif
446 QObjectPrivate::connect(this, &QQuickTextInput::readOnlyChanged, d, &QQuickTextFieldPrivate::readOnlyChanged);
447 QObjectPrivate::connect(this, &QQuickTextInput::echoModeChanged, d, &QQuickTextFieldPrivate::echoModeChanged);
448 }
449
~QQuickTextField()450 QQuickTextField::~QQuickTextField()
451 {
452 Q_D(QQuickTextField);
453 QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
454 }
455
font() const456 QFont QQuickTextField::font() const
457 {
458 return QQuickTextInput::font();
459 }
460
setFont(const QFont & font)461 void QQuickTextField::setFont(const QFont &font)
462 {
463 Q_D(QQuickTextField);
464 if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font)
465 return;
466
467 d->extra.value().requestedFont = font;
468 d->resolveFont();
469 }
470
471 /*!
472 \qmlproperty Item QtQuick.Controls::TextField::background
473
474 This property holds the background item.
475
476 \input qquickcontrol-background.qdocinc notes
477
478 \sa {Customizing TextField}
479 */
background() const480 QQuickItem *QQuickTextField::background() const
481 {
482 QQuickTextFieldPrivate *d = const_cast<QQuickTextFieldPrivate *>(d_func());
483 if (!d->background)
484 d->executeBackground();
485 return d->background;
486 }
487
setBackground(QQuickItem * background)488 void QQuickTextField::setBackground(QQuickItem *background)
489 {
490 Q_D(QQuickTextField);
491 if (d->background == background)
492 return;
493
494 if (!d->background.isExecuting())
495 d->cancelBackground();
496
497 const qreal oldImplicitBackgroundWidth = implicitBackgroundWidth();
498 const qreal oldImplicitBackgroundHeight = implicitBackgroundHeight();
499
500 if (d->extra.isAllocated()) {
501 d->extra.value().hasBackgroundWidth = false;
502 d->extra.value().hasBackgroundHeight = false;
503 }
504
505 QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
506 QQuickControlPrivate::hideOldItem(d->background);
507 d->background = background;
508
509 if (background) {
510 background->setParentItem(this);
511 if (qFuzzyIsNull(background->z()))
512 background->setZ(-1);
513 QQuickItemPrivate *p = QQuickItemPrivate::get(background);
514 if (p->widthValid || p->heightValid) {
515 d->extra.value().hasBackgroundWidth = p->widthValid;
516 d->extra.value().hasBackgroundHeight = p->heightValid;
517 }
518 if (isComponentComplete())
519 d->resizeBackground();
520 QQuickControlPrivate::addImplicitSizeListener(background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
521 }
522
523 if (!qFuzzyCompare(oldImplicitBackgroundWidth, implicitBackgroundWidth()))
524 emit implicitBackgroundWidthChanged();
525 if (!qFuzzyCompare(oldImplicitBackgroundHeight, implicitBackgroundHeight()))
526 emit implicitBackgroundHeightChanged();
527 if (!d->background.isExecuting())
528 emit backgroundChanged();
529 }
530
531 /*!
532 \qmlproperty string QtQuick.Controls::TextField::placeholderText
533
534 This property holds the hint that is displayed in the TextField before the user
535 enters text.
536 */
placeholderText() const537 QString QQuickTextField::placeholderText() const
538 {
539 Q_D(const QQuickTextField);
540 return d->placeholder;
541 }
542
setPlaceholderText(const QString & text)543 void QQuickTextField::setPlaceholderText(const QString &text)
544 {
545 Q_D(QQuickTextField);
546 if (d->placeholder == text)
547 return;
548
549 d->placeholder = text;
550 #if QT_CONFIG(accessibility)
551 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this))
552 accessibleAttached->setDescription(text);
553 #endif
554 emit placeholderTextChanged();
555 }
556
557 /*!
558 \qmlproperty color QtQuick.Controls::TextField::placeholderTextColor
559 \since QtQuick.Controls 2.5 (Qt 5.12)
560
561 This property holds the color of placeholderText.
562
563 \sa placeholderText
564 */
placeholderTextColor() const565 QColor QQuickTextField::placeholderTextColor() const
566 {
567 Q_D(const QQuickTextField);
568 return d->placeholderColor;
569 }
570
setPlaceholderTextColor(const QColor & color)571 void QQuickTextField::setPlaceholderTextColor(const QColor &color)
572 {
573 Q_D(QQuickTextField);
574 if (d->placeholderColor == color)
575 return;
576
577 d->placeholderColor = color;
578 emit placeholderTextColorChanged();
579 }
580
581 /*!
582 \qmlproperty enumeration QtQuick.Controls::TextField::focusReason
583
584 \include qquickcontrol-focusreason.qdocinc
585 */
focusReason() const586 Qt::FocusReason QQuickTextField::focusReason() const
587 {
588 Q_D(const QQuickTextField);
589 return d->focusReason;
590 }
591
setFocusReason(Qt::FocusReason reason)592 void QQuickTextField::setFocusReason(Qt::FocusReason reason)
593 {
594 Q_D(QQuickTextField);
595 if (d->focusReason == reason)
596 return;
597
598 d->focusReason = reason;
599 emit focusReasonChanged();
600 }
601
602 /*!
603 \since QtQuick.Controls 2.1 (Qt 5.8)
604 \qmlproperty bool QtQuick.Controls::TextField::hovered
605 \readonly
606
607 This property holds whether the text field is hovered.
608
609 \sa hoverEnabled
610 */
isHovered() const611 bool QQuickTextField::isHovered() const
612 {
613 #if QT_CONFIG(quicktemplates2_hover)
614 Q_D(const QQuickTextField);
615 return d->hovered;
616 #else
617 return false;
618 #endif
619 }
620
setHovered(bool hovered)621 void QQuickTextField::setHovered(bool hovered)
622 {
623 #if QT_CONFIG(quicktemplates2_hover)
624 Q_D(QQuickTextField);
625 if (hovered == d->hovered)
626 return;
627
628 d->hovered = hovered;
629 emit hoveredChanged();
630 #else
631 Q_UNUSED(hovered);
632 #endif
633 }
634
635 /*!
636 \since QtQuick.Controls 2.1 (Qt 5.8)
637 \qmlproperty bool QtQuick.Controls::TextField::hoverEnabled
638
639 This property determines whether the text field accepts hover events. The default value is \c false.
640
641 \sa hovered
642 */
isHoverEnabled() const643 bool QQuickTextField::isHoverEnabled() const
644 {
645 #if QT_CONFIG(quicktemplates2_hover)
646 Q_D(const QQuickTextField);
647 return d->hoverEnabled;
648 #else
649 return false;
650 #endif
651 }
652
setHoverEnabled(bool enabled)653 void QQuickTextField::setHoverEnabled(bool enabled)
654 {
655 #if QT_CONFIG(quicktemplates2_hover)
656 Q_D(QQuickTextField);
657 if (d->explicitHoverEnabled && enabled == d->hoverEnabled)
658 return;
659
660 d->updateHoverEnabled(enabled, true); // explicit=true
661 #else
662 Q_UNUSED(enabled);
663 #endif
664 }
665
resetHoverEnabled()666 void QQuickTextField::resetHoverEnabled()
667 {
668 #if QT_CONFIG(quicktemplates2_hover)
669 Q_D(QQuickTextField);
670 if (!d->explicitHoverEnabled)
671 return;
672
673 d->explicitHoverEnabled = false;
674 d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
675 #endif
676 }
677
678 /*!
679 \since QtQuick.Controls 2.3 (Qt 5.10)
680 \qmlproperty palette QtQuick.Controls::TextField::palette
681
682 This property holds the palette currently set for the text field.
683
684 \sa Control::palette
685 */
palette() const686 QPalette QQuickTextField::palette() const
687 {
688 Q_D(const QQuickTextField);
689 QPalette palette = d->resolvedPalette;
690 if (!isEnabled())
691 palette.setCurrentColorGroup(QPalette::Disabled);
692 return palette;
693 }
694
setPalette(const QPalette & palette)695 void QQuickTextField::setPalette(const QPalette &palette)
696 {
697 Q_D(QQuickTextField);
698 if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette)
699 return;
700
701 d->extra.value().requestedPalette = palette;
702 d->resolvePalette();
703 }
704
resetPalette()705 void QQuickTextField::resetPalette()
706 {
707 setPalette(QPalette());
708 }
709
classBegin()710 void QQuickTextField::classBegin()
711 {
712 Q_D(QQuickTextField);
713 QQuickTextInput::classBegin();
714 d->resolveFont();
715 d->resolvePalette();
716 }
717
718 /*!
719 \since QtQuick.Controls 2.5 (Qt 5.12)
720 \qmlproperty real QtQuick.Controls::TextField::implicitBackgroundWidth
721 \readonly
722
723 This property holds the implicit background width.
724
725 The value is equal to \c {background ? background.implicitWidth : 0}.
726
727 \sa implicitBackgroundHeight
728 */
implicitBackgroundWidth() const729 qreal QQuickTextField::implicitBackgroundWidth() const
730 {
731 Q_D(const QQuickTextField);
732 if (!d->background)
733 return 0;
734 return d->background->implicitWidth();
735 }
736
737 /*!
738 \since QtQuick.Controls 2.5 (Qt 5.12)
739 \qmlproperty real QtQuick.Controls::TextField::implicitBackgroundHeight
740 \readonly
741
742 This property holds the implicit background height.
743
744 The value is equal to \c {background ? background.implicitHeight : 0}.
745
746 \sa implicitBackgroundWidth
747 */
implicitBackgroundHeight() const748 qreal QQuickTextField::implicitBackgroundHeight() const
749 {
750 Q_D(const QQuickTextField);
751 if (!d->background)
752 return 0;
753 return d->background->implicitHeight();
754 }
755
756 /*!
757 \since QtQuick.Controls 2.5 (Qt 5.12)
758 \qmlproperty real QtQuick.Controls::TextField::topInset
759
760 This property holds the top inset for the background.
761
762 \sa {Control Layout}, bottomInset
763 */
topInset() const764 qreal QQuickTextField::topInset() const
765 {
766 Q_D(const QQuickTextField);
767 return d->getTopInset();
768 }
769
setTopInset(qreal inset)770 void QQuickTextField::setTopInset(qreal inset)
771 {
772 Q_D(QQuickTextField);
773 d->setTopInset(inset);
774 }
775
resetTopInset()776 void QQuickTextField::resetTopInset()
777 {
778 Q_D(QQuickTextField);
779 d->setTopInset(0, true);
780 }
781
782 /*!
783 \since QtQuick.Controls 2.5 (Qt 5.12)
784 \qmlproperty real QtQuick.Controls::TextField::leftInset
785
786 This property holds the left inset for the background.
787
788 \sa {Control Layout}, rightInset
789 */
leftInset() const790 qreal QQuickTextField::leftInset() const
791 {
792 Q_D(const QQuickTextField);
793 return d->getLeftInset();
794 }
795
setLeftInset(qreal inset)796 void QQuickTextField::setLeftInset(qreal inset)
797 {
798 Q_D(QQuickTextField);
799 d->setLeftInset(inset);
800 }
801
resetLeftInset()802 void QQuickTextField::resetLeftInset()
803 {
804 Q_D(QQuickTextField);
805 d->setLeftInset(0, true);
806 }
807
808 /*!
809 \since QtQuick.Controls 2.5 (Qt 5.12)
810 \qmlproperty real QtQuick.Controls::TextField::rightInset
811
812 This property holds the right inset for the background.
813
814 \sa {Control Layout}, leftInset
815 */
rightInset() const816 qreal QQuickTextField::rightInset() const
817 {
818 Q_D(const QQuickTextField);
819 return d->getRightInset();
820 }
821
setRightInset(qreal inset)822 void QQuickTextField::setRightInset(qreal inset)
823 {
824 Q_D(QQuickTextField);
825 d->setRightInset(inset);
826 }
827
resetRightInset()828 void QQuickTextField::resetRightInset()
829 {
830 Q_D(QQuickTextField);
831 d->setRightInset(0, true);
832 }
833
834 /*!
835 \since QtQuick.Controls 2.5 (Qt 5.12)
836 \qmlproperty real QtQuick.Controls::TextField::bottomInset
837
838 This property holds the bottom inset for the background.
839
840 \sa {Control Layout}, topInset
841 */
bottomInset() const842 qreal QQuickTextField::bottomInset() const
843 {
844 Q_D(const QQuickTextField);
845 return d->getBottomInset();
846 }
847
setBottomInset(qreal inset)848 void QQuickTextField::setBottomInset(qreal inset)
849 {
850 Q_D(QQuickTextField);
851 d->setBottomInset(inset);
852 }
853
resetBottomInset()854 void QQuickTextField::resetBottomInset()
855 {
856 Q_D(QQuickTextField);
857 d->setBottomInset(0, true);
858 }
859
componentComplete()860 void QQuickTextField::componentComplete()
861 {
862 Q_D(QQuickTextField);
863 d->executeBackground(true);
864 QQuickTextInput::componentComplete();
865 d->resizeBackground();
866 #if QT_CONFIG(quicktemplates2_hover)
867 if (!d->explicitHoverEnabled)
868 setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
869 #endif
870 #if QT_CONFIG(accessibility)
871 if (QAccessible::isActive())
872 d->accessibilityActiveChanged(true);
873 #endif
874 }
875
itemChange(QQuickItem::ItemChange change,const QQuickItem::ItemChangeData & value)876 void QQuickTextField::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
877 {
878 Q_D(QQuickTextField);
879 QQuickTextInput::itemChange(change, value);
880 switch (change) {
881 case ItemEnabledHasChanged:
882 emit paletteChanged();
883 break;
884 case ItemSceneChange:
885 case ItemParentHasChanged:
886 if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
887 d->resolveFont();
888 d->resolvePalette();
889 #if QT_CONFIG(quicktemplates2_hover)
890 if (!d->explicitHoverEnabled)
891 d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
892 #endif
893 }
894 break;
895 default:
896 break;
897 }
898 }
899
geometryChanged(const QRectF & newGeometry,const QRectF & oldGeometry)900 void QQuickTextField::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
901 {
902 Q_D(QQuickTextField);
903 QQuickTextInput::geometryChanged(newGeometry, oldGeometry);
904 d->resizeBackground();
905 }
906
insetChange(const QMarginsF & newInset,const QMarginsF & oldInset)907 void QQuickTextField::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset)
908 {
909 Q_D(QQuickTextField);
910 Q_UNUSED(newInset);
911 Q_UNUSED(oldInset);
912 d->resizeBackground();
913 }
updatePaintNode(QSGNode * oldNode,UpdatePaintNodeData * data)914 QSGNode *QQuickTextField::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
915 {
916 QQuickDefaultClipNode *clipNode = static_cast<QQuickDefaultClipNode *>(oldNode);
917 if (!clipNode)
918 clipNode = new QQuickDefaultClipNode(QRectF());
919
920 clipNode->setRect(clipRect().adjusted(leftPadding(), topPadding(), -rightPadding(), -bottomPadding()));
921 clipNode->update();
922
923 QSGNode *textNode = QQuickTextInput::updatePaintNode(clipNode->firstChild(), data);
924 if (!textNode->parent())
925 clipNode->appendChildNode(textNode);
926
927 return clipNode;
928 }
929
focusInEvent(QFocusEvent * event)930 void QQuickTextField::focusInEvent(QFocusEvent *event)
931 {
932 QQuickTextInput::focusInEvent(event);
933 setFocusReason(event->reason());
934 }
935
focusOutEvent(QFocusEvent * event)936 void QQuickTextField::focusOutEvent(QFocusEvent *event)
937 {
938 QQuickTextInput::focusOutEvent(event);
939 setFocusReason(event->reason());
940 }
941
942 #if QT_CONFIG(quicktemplates2_hover)
hoverEnterEvent(QHoverEvent * event)943 void QQuickTextField::hoverEnterEvent(QHoverEvent *event)
944 {
945 Q_D(QQuickTextField);
946 QQuickTextInput::hoverEnterEvent(event);
947 setHovered(d->hoverEnabled);
948 event->setAccepted(d->hoverEnabled);
949 }
950
hoverLeaveEvent(QHoverEvent * event)951 void QQuickTextField::hoverLeaveEvent(QHoverEvent *event)
952 {
953 Q_D(QQuickTextField);
954 QQuickTextInput::hoverLeaveEvent(event);
955 setHovered(false);
956 event->setAccepted(d->hoverEnabled);
957 }
958 #endif
959
mousePressEvent(QMouseEvent * event)960 void QQuickTextField::mousePressEvent(QMouseEvent *event)
961 {
962 Q_D(QQuickTextField);
963 d->pressHandler.mousePressEvent(event);
964 if (d->pressHandler.isActive()) {
965 if (d->pressHandler.delayedMousePressEvent) {
966 QQuickTextInput::mousePressEvent(d->pressHandler.delayedMousePressEvent);
967 d->pressHandler.clearDelayedMouseEvent();
968 }
969 if (event->buttons() != Qt::RightButton)
970 QQuickTextInput::mousePressEvent(event);
971 }
972 }
973
mouseMoveEvent(QMouseEvent * event)974 void QQuickTextField::mouseMoveEvent(QMouseEvent *event)
975 {
976 Q_D(QQuickTextField);
977 d->pressHandler.mouseMoveEvent(event);
978 if (d->pressHandler.isActive()) {
979 if (d->pressHandler.delayedMousePressEvent) {
980 QQuickTextInput::mousePressEvent(d->pressHandler.delayedMousePressEvent);
981 d->pressHandler.clearDelayedMouseEvent();
982 }
983 if (event->buttons() != Qt::RightButton)
984 QQuickTextInput::mouseMoveEvent(event);
985 }
986 }
987
mouseReleaseEvent(QMouseEvent * event)988 void QQuickTextField::mouseReleaseEvent(QMouseEvent *event)
989 {
990 Q_D(QQuickTextField);
991 d->pressHandler.mouseReleaseEvent(event);
992 if (d->pressHandler.isActive()) {
993 if (d->pressHandler.delayedMousePressEvent) {
994 QQuickTextInput::mousePressEvent(d->pressHandler.delayedMousePressEvent);
995 d->pressHandler.clearDelayedMouseEvent();
996 }
997 if (event->buttons() != Qt::RightButton)
998 QQuickTextInput::mouseReleaseEvent(event);
999 }
1000 }
1001
mouseDoubleClickEvent(QMouseEvent * event)1002 void QQuickTextField::mouseDoubleClickEvent(QMouseEvent *event)
1003 {
1004 Q_D(QQuickTextField);
1005 if (d->pressHandler.delayedMousePressEvent) {
1006 QQuickTextInput::mousePressEvent(d->pressHandler.delayedMousePressEvent);
1007 d->pressHandler.clearDelayedMouseEvent();
1008 }
1009 if (event->buttons() != Qt::RightButton)
1010 QQuickTextInput::mouseDoubleClickEvent(event);
1011 }
1012
timerEvent(QTimerEvent * event)1013 void QQuickTextField::timerEvent(QTimerEvent *event)
1014 {
1015 Q_D(QQuickTextField);
1016 if (event->timerId() == d->pressHandler.timer.timerId())
1017 d->pressHandler.timerEvent(event);
1018 else
1019 QQuickTextInput::timerEvent(event);
1020 }
1021
1022 QT_END_NAMESPACE
1023