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