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