Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquicktextarea.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
11
12#include <QtQml/qqmlinfo.h>
13#include <QtQuick/private/qquickitem_p.h>
14#include <QtQuick/private/qquickclipnode_p.h>
15#include <QtQuick/private/qquickflickable_p.h>
16
17#if QT_CONFIG(accessibility)
18#include <QtQuick/private/qquickaccessibleattached_p.h>
19#endif
20
22
23using namespace Qt::StringLiterals;
24
25/*!
26 \qmltype TextArea
27 \inherits TextEdit
28//! \nativetype QQuickTextArea
29 \inqmlmodule QtQuick.Controls
30 \since 5.7
31 \ingroup qtquickcontrols-input
32 \brief Multi-line text input area.
33
34 TextArea is a multi-line text editor. TextArea extends TextEdit with
35 a \l {placeholderText}{placeholder text} functionality, and adds decoration.
36
37 \image qtquickcontrols-textarea.png
38
39 \code
40 TextArea {
41 placeholderText: qsTr("Enter description")
42 }
43 \endcode
44
45 TextArea is not scrollable by itself. Especially on screen-size constrained
46 platforms, it is often preferable to make entire application pages scrollable.
47 On such a scrollable page, a non-scrollable TextArea might behave better than
48 nested scrollable controls. Notice, however, that in such a scenario, the background
49 decoration of the TextArea scrolls together with the rest of the scrollable
50 content.
51
52 \section2 Scrollable TextArea
53
54 If you want to make a TextArea scrollable, for example, when it covers
55 an entire application page, it can be placed inside a \l ScrollView.
56
57 \image qtquickcontrols-textarea-scrollable.png
58
59 \snippet qtquickcontrols-textarea-scrollable.qml 1
60
61 A TextArea that is placed inside a \l ScrollView does the following:
62
63 \list
64 \li Sets the content size automatically
65 \li Ensures that the background decoration stays in place
66 \li Clips the content
67 \endlist
68
69 \section2 Tab Focus
70
71 By default, pressing the tab key while TextArea has
72 \l {Item::activeFocus}{active focus} results in a tab character being input
73 into the control itself. To make tab pass active focus onto another item,
74 use the attached \l KeyNavigation properties:
75
76 \code
77 TextField {
78 id: textField
79 }
80
81 TextArea {
82 KeyNavigation.priority: KeyNavigation.BeforeItem
83 KeyNavigation.tab: textField
84 }
85 \endcode
86
87 \sa TextField, {Customizing TextArea}, {Input Controls}
88*/
89
90/*!
91 \qmlsignal QtQuick.Controls::TextArea::pressAndHold(MouseEvent event)
92
93 This signal is emitted when there is a long press (the delay depends on the platform plugin).
94 The \a event parameter provides information about the press, including the x and y
95 coordinates of the press, and which button is pressed.
96
97 \sa pressed, released
98*/
99
100/*!
101 \qmlsignal QtQuick.Controls::TextArea::pressed(MouseEvent event)
102 \since QtQuick.Controls 2.1 (Qt 5.8)
103
104 This signal is emitted when the text area is pressed by the user.
105 The \a event parameter provides information about the press,
106 including the x and y coordinates of the press, and which button is pressed.
107
108 \sa released, pressAndHold
109*/
110
111/*!
112 \qmlsignal QtQuick.Controls::TextArea::released(MouseEvent event)
113 \since QtQuick.Controls 2.1 (Qt 5.8)
114
115 This signal is emitted when the text area is released by the user.
116 The \a event parameter provides information about the release,
117 including the x and y coordinates of the press, and which button
118 is pressed.
119
120 \sa pressed, pressAndHold
121*/
122
123QQuickTextAreaPrivate::QQuickTextAreaPrivate()
124{
125#if QT_CONFIG(accessibility)
126 setAccessible();
127#endif
128}
129
133
134void QQuickTextAreaPrivate::setTopInset(qreal value, bool reset)
135{
136 Q_Q(QQuickTextArea);
137 const QMarginsF oldInset = getInset();
138 extra.value().topInset = value;
139 extra.value().hasTopInset = !reset;
140 if (!qFuzzyCompare(oldInset.top(), value)) {
141 emit q->topInsetChanged();
142 q->insetChange(getInset(), oldInset);
143 }
144}
145
146void QQuickTextAreaPrivate::setLeftInset(qreal value, bool reset)
147{
148 Q_Q(QQuickTextArea);
149 const QMarginsF oldInset = getInset();
150 extra.value().leftInset = value;
151 extra.value().hasLeftInset = !reset;
152 if (!qFuzzyCompare(oldInset.left(), value)) {
153 emit q->leftInsetChanged();
154 q->insetChange(getInset(), oldInset);
155 }
156}
157
158void QQuickTextAreaPrivate::setRightInset(qreal value, bool reset)
159{
160 Q_Q(QQuickTextArea);
161 const QMarginsF oldInset = getInset();
162 extra.value().rightInset = value;
163 extra.value().hasRightInset = !reset;
164 if (!qFuzzyCompare(oldInset.right(), value)) {
165 emit q->rightInsetChanged();
166 q->insetChange(getInset(), oldInset);
167 }
168}
169
170void QQuickTextAreaPrivate::setBottomInset(qreal value, bool reset)
171{
172 Q_Q(QQuickTextArea);
173 const QMarginsF oldInset = getInset();
174 extra.value().bottomInset = value;
175 extra.value().hasBottomInset = !reset;
176 if (!qFuzzyCompare(oldInset.bottom(), value)) {
177 emit q->bottomInsetChanged();
178 q->insetChange(getInset(), oldInset);
179 }
180}
181
183{
184 if (!background)
185 return;
186
187 resizingBackground = true;
188
189 // When using the attached property TextArea.flickable, we reparent the background out
190 // of TextArea and into the Flickable since we don't want the background to move while
191 // flicking. This means that the size of the background should also follow the size of
192 // the Flickable rather than the size of the TextArea.
193 const auto flickable = qobject_cast<QQuickFlickable *>(background->parentItem());
194
195 QQuickItemPrivate *p = QQuickItemPrivate::get(background);
196 if (((!p->widthValid() || !extra.isAllocated() || !extra->hasBackgroundWidth) && qFuzzyIsNull(background->x()))
197 || (extra.isAllocated() && (extra->hasLeftInset || extra->hasRightInset))) {
198 const qreal bgWidth = flickable ? flickable->width() : width;
199 background->setX(getLeftInset());
200 background->setWidth(bgWidth - getLeftInset() - getRightInset());
201 }
202
203 if (((!p->heightValid() || !extra.isAllocated() || !extra->hasBackgroundHeight) && qFuzzyIsNull(background->y()))
204 || (extra.isAllocated() && (extra->hasTopInset || extra->hasBottomInset))) {
205 const qreal bgHeight = flickable ? flickable->height() : height;
206 background->setY(getTopInset());
207 background->setHeight(bgHeight - getTopInset() - getBottomInset());
208 }
209
210 resizingBackground = false;
211}
212
213/*!
214 \internal
215
216 Determine which font is implicitly imposed on this control by its ancestors
217 and QGuiApplication::font, resolve this against its own font (attributes from
218 the implicit font are copied over). Then propagate this font to this
219 control's children.
220*/
222{
223 Q_Q(QQuickTextArea);
224 inheritFont(QQuickControlPrivate::parentFont(q));
225}
226
227void QQuickTextAreaPrivate::inheritFont(const QFont &font)
228{
229 QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font;
230 parentFont.setResolveMask(extra.isAllocated() ? extra->requestedFont.resolveMask() | font.resolveMask() : font.resolveMask());
231
232 const QFont defaultFont = QQuickTheme::font(QQuickTheme::TextArea);
233 QFont resolvedFont = parentFont.resolve(defaultFont);
234
235 setFont_helper(resolvedFont);
236}
237
238/*!
239 \internal
240
241 Assign \a font to this control, and propagate it to all children.
242*/
243void QQuickTextAreaPrivate::updateFont(const QFont &font)
244{
245 Q_Q(QQuickTextArea);
246 QFont oldFont = sourceFont;
247 q->QQuickTextEdit::setFont(font);
248
249 QQuickControlPrivate::updateFontRecur(q, font);
250
251 if (oldFont != font)
252 emit q->fontChanged();
253}
254
255#if QT_CONFIG(quicktemplates2_hover)
256void QQuickTextAreaPrivate::updateHoverEnabled(bool enabled, bool xplicit)
257{
258 Q_Q(QQuickTextArea);
259 if (!xplicit && explicitHoverEnabled)
260 return;
261
262 bool wasEnabled = q->isHoverEnabled();
263 explicitHoverEnabled = xplicit;
264 if (wasEnabled != enabled) {
265 q->setAcceptHoverEvents(enabled);
266 QQuickControlPrivate::updateHoverEnabledRecur(q, enabled);
267 emit q->hoverEnabledChanged();
268 }
269}
270#endif
271
272void QQuickTextAreaPrivate::attachFlickable(QQuickFlickable *item)
273{
274 Q_Q(QQuickTextArea);
275 flickable = item;
276 q->setParentItem(flickable->contentItem());
277
278 if (background)
279 background->setParentItem(flickable);
280
281 QObjectPrivate::connect(q, &QQuickTextArea::contentSizeChanged, this, &QQuickTextAreaPrivate::resizeFlickableContent);
282 QObjectPrivate::connect(q, &QQuickTextEdit::cursorRectangleChanged, this, &QQuickTextAreaPrivate::ensureCursorVisible);
283
284 QObject::connect(flickable, &QQuickFlickable::contentXChanged, q, &QQuickItem::update);
285 QObject::connect(flickable, &QQuickFlickable::contentYChanged, q, &QQuickItem::update);
286
287 QQuickItemPrivate::get(flickable)->updateOrAddGeometryChangeListener(this, QQuickGeometryChange::Size);
288 QQuickItemPrivate::get(flickable)->addItemChangeListener(this, QQuickItemPrivate::Destroyed);
289 QObjectPrivate::connect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl);
290 QObjectPrivate::connect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl);
291
293}
294
296{
297 Q_Q(QQuickTextArea);
298 q->setParentItem(nullptr);
299 if (background && background->parentItem() == flickable)
300 background->setParentItem(q);
301
302 QObjectPrivate::disconnect(q, &QQuickTextArea::contentSizeChanged, this, &QQuickTextAreaPrivate::resizeFlickableContent);
303 QObjectPrivate::disconnect(q, &QQuickTextEdit::cursorRectangleChanged, this, &QQuickTextAreaPrivate::ensureCursorVisible);
304
305 QObject::disconnect(flickable, &QQuickFlickable::contentXChanged, q, &QQuickItem::update);
306 QObject::disconnect(flickable, &QQuickFlickable::contentYChanged, q, &QQuickItem::update);
307
308 QQuickItemPrivate::get(flickable)->updateOrRemoveGeometryChangeListener(this, QQuickGeometryChange::Nothing);
309 QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed);
310 QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl);
311 QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl);
312
313 flickable = nullptr;
314
316}
317
319{
320 Q_Q(QQuickTextArea);
321 if (!flickable)
322 return;
323
324 const qreal cx = flickable->contentX();
325 const qreal cy = flickable->contentY();
326 const qreal w = flickable->width();
327 const qreal h = flickable->height();
328
329 const qreal tp = q->topPadding();
330 const qreal lp = q->leftPadding();
331 const QRectF cr = q->cursorRectangle();
332
333 if (cr.left() <= cx + lp) {
334 flickable->setContentX(cr.left() - lp);
335 } else {
336 // calculate the rectangle of the next character and ensure that
337 // it's visible if it's on the same line with the cursor
338 const qreal rp = q->rightPadding();
339 const QRectF nr = q->cursorPosition() < q->length() ? q->positionToRectangle(q->cursorPosition() + 1) : QRectF();
340 if (qFuzzyCompare(nr.y(), cr.y()) && nr.right() >= cx + lp + w - rp)
341 flickable->setContentX(nr.right() - w + rp);
342 else if (cr.right() >= cx + lp + w - rp)
343 flickable->setContentX(cr.right() - w + rp);
344 }
345
346 if (cr.top() <= cy + tp) {
347 flickable->setContentY(cr.top() - tp);
348 } else {
349 const qreal bp = q->bottomPadding();
350 if (cr.bottom() >= cy + tp + h - bp && cr.bottom() <= flickable->contentHeight())
351 flickable->setContentY(cr.bottom() - h + bp);
352 }
353}
354
356{
357 Q_Q(QQuickTextArea);
358 if (!flickable)
359 return;
360
361 const qreal w = wrapMode == QQuickTextArea::NoWrap ? qMax(flickable->width(), flickable->contentWidth()) : flickable->width();
362 const qreal h = qMax(flickable->height(), flickable->contentHeight());
363 q->setSize(QSizeF(w, h));
364
366}
367
369{
370 Q_Q(QQuickTextArea);
371 if (!flickable)
372 return;
373
374 flickable->setContentWidth(q->implicitWidth());
375 flickable->setContentHeight(q->implicitHeight());
376}
377
378void QQuickTextAreaPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff)
379{
380 Q_UNUSED(diff);
381 if (!resizingBackground && item == background) {
382 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
383 // Only set hasBackgroundWidth/Height if it was a width/height change,
384 // otherwise we're prevented from setting a width/height in the future.
385 if (change.widthChange())
386 extra.value().hasBackgroundWidth = p->widthValid();
387 if (change.heightChange())
388 extra.value().hasBackgroundHeight = p->heightValid();
389 }
390
391 if (flickable)
393 else
395}
396
398{
399 return QQuickItemPrivate::getImplicitWidth();
400}
401
403{
404 return QQuickItemPrivate::getImplicitHeight();
405}
406
408{
409 Q_Q(QQuickTextArea);
410 QQuickItemPrivate::implicitWidthChanged();
411 emit q->implicitWidthChanged3();
412}
413
415{
416 Q_Q(QQuickTextArea);
417 QQuickItemPrivate::implicitHeightChanged();
418 emit q->implicitHeightChanged3();
419}
420
421#if QT_CONFIG(accessibility)
422void QQuickTextAreaPrivate::accessibilityActiveChanged(bool active)
423{
424 QQuickTextEditPrivate::accessibilityActiveChanged(active);
425 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func()))
426 accessibleAttached->setDescriptionImplicitly(placeholder);
427}
428#endif
429
431{
432 Q_Q(QQuickTextArea);
433 quickCancelDeferred(q, backgroundName());
434}
435
437{
438 Q_Q(QQuickTextArea);
439 if (background.wasExecuted())
440 return;
441
442 if (!background || complete)
443 quickBeginDeferred(q, backgroundName(), background);
444 if (complete)
445 quickCompleteDeferred(q, backgroundName(), background);
446}
447
449{
450 Q_Q(QQuickTextArea);
451 if (item == background)
452 emit q->implicitBackgroundWidthChanged();
453}
454
456{
457 Q_Q(QQuickTextArea);
458 if (item == background)
459 emit q->implicitBackgroundHeightChanged();
460}
461
463{
464 Q_Q(QQuickTextArea);
465 if (item == background) {
466 background = nullptr;
467 emit q->implicitBackgroundWidthChanged();
468 emit q->implicitBackgroundHeightChanged();
469 } else if (item == flickable) {
471 }
472}
473
475{
476 return QQuickTheme::palette(QQuickTheme::TextArea);
477}
478
480{
481 Q_Q(QQuickTextArea);
482 const auto focusReasonChanged = QQuickItemPrivate::setLastFocusChangeReason(reason);
483 if (focusReasonChanged)
484 emit q->focusReasonChanged();
485
486 return focusReasonChanged;
487}
488
489QQuickTextArea::QQuickTextArea(QQuickItem *parent)
490 : QQuickTextEdit(*(new QQuickTextAreaPrivate), parent)
491{
492 Q_D(QQuickTextArea);
493 setActiveFocusOnTab(true);
494 setAcceptedMouseButtons(Qt::AllButtons);
495 d->setImplicitResizeEnabled(false);
496 d->pressHandler.control = this;
497
498#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
499 if (qEnvironmentVariable("QT_QUICK_CONTROLS_TEXT_SELECTION_BEHAVIOR") == u"old"_s)
500 QQuickTextEdit::setOldSelectionDefault();
501#endif
502}
503
504QQuickTextArea::~QQuickTextArea()
505{
506 Q_D(QQuickTextArea);
507 if (d->flickable)
508 d->detachFlickable();
509 QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
510}
511
512QQuickTextAreaAttached *QQuickTextArea::qmlAttachedProperties(QObject *object)
513{
514 return new QQuickTextAreaAttached(object);
515}
516
517QFont QQuickTextArea::font() const
518{
519 Q_D(const QQuickTextArea);
520 QFont font = QQuickTextEdit::font();
521 // The resolve mask should inherit from the requestedFont
522 font.setResolveMask(d->extra.value().requestedFont.resolveMask());
523 return font;
524}
525
526void QQuickTextArea::setFont(const QFont &font)
527{
528 Q_D(QQuickTextArea);
529 if (d->extra.value().requestedFont.resolveMask() == font.resolveMask() && d->extra.value().requestedFont == font)
530 return;
531
532 d->extra.value().requestedFont = font;
533 d->resolveFont();
534}
535
536/*!
537 \qmlproperty Item QtQuick.Controls::TextArea::background
538
539 This property holds the background item.
540
541 \input qquickcontrol-background.qdocinc notes
542
543 \sa {Customizing TextArea}
544*/
545QQuickItem *QQuickTextArea::background() const
546{
547 QQuickTextAreaPrivate *d = const_cast<QQuickTextAreaPrivate *>(d_func());
548 if (!d->background)
549 d->executeBackground();
550 return d->background;
551}
552
553void QQuickTextArea::setBackground(QQuickItem *background)
554{
555 Q_D(QQuickTextArea);
556 if (d->background == background)
557 return;
558
559 QQuickControlPrivate::warnIfCustomizationNotSupported(this, background, QStringLiteral("background"));
560
561 if (!d->background.isExecuting())
562 d->cancelBackground();
563
564 const qreal oldImplicitBackgroundWidth = implicitBackgroundWidth();
565 const qreal oldImplicitBackgroundHeight = implicitBackgroundHeight();
566
567 if (d->extra.isAllocated()) {
568 d->extra.value().hasBackgroundWidth = false;
569 d->extra.value().hasBackgroundHeight = false;
570 }
571
572 QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
573 QQuickControlPrivate::hideOldItem(d->background);
574 d->background = background;
575
576 if (background) {
577 QQuickItemPrivate *p = QQuickItemPrivate::get(background);
578 if (p->widthValid() || p->heightValid()) {
579 d->extra.value().hasBackgroundWidth = p->widthValid();
580 d->extra.value().hasBackgroundHeight = p->heightValid();
581 }
582 if (d->flickable)
583 background->setParentItem(d->flickable);
584 else
585 background->setParentItem(this);
586 if (qFuzzyIsNull(background->z()))
587 background->setZ(-1);
588 if (isComponentComplete())
589 d->resizeBackground();
590 QQuickControlPrivate::addImplicitSizeListener(background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
591 }
592
593 if (!qFuzzyCompare(oldImplicitBackgroundWidth, implicitBackgroundWidth()))
594 emit implicitBackgroundWidthChanged();
595 if (!qFuzzyCompare(oldImplicitBackgroundHeight, implicitBackgroundHeight()))
596 emit implicitBackgroundHeightChanged();
597 if (!d->background.isExecuting())
598 emit backgroundChanged();
599}
600
601/*!
602 \qmlproperty string QtQuick.Controls::TextArea::placeholderText
603
604 This property holds the short hint that is displayed in the text area before
605 the user enters a value.
606*/
607QString QQuickTextArea::placeholderText() const
608{
609 Q_D(const QQuickTextArea);
610 return d->placeholder;
611}
612
613void QQuickTextArea::setPlaceholderText(const QString &text)
614{
615 Q_D(QQuickTextArea);
616 if (d->placeholder == text)
617 return;
618
619 d->placeholder = text;
620#if QT_CONFIG(accessibility)
621 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this))
622 accessibleAttached->setDescriptionImplicitly(text);
623#endif
624 emit placeholderTextChanged();
625}
626
627/*!
628 \qmlproperty color QtQuick.Controls::TextArea::placeholderTextColor
629 \since QtQuick.Controls 2.5 (Qt 5.12)
630
631 This property holds the color of placeholderText.
632
633 \sa placeholderText
634*/
635QColor QQuickTextArea::placeholderTextColor() const
636{
637 Q_D(const QQuickTextArea);
638 return d->placeholderColor;
639}
640
641void QQuickTextArea::setPlaceholderTextColor(const QColor &color)
642{
643 Q_D(QQuickTextArea);
644 if (d->placeholderColor == color)
645 return;
646
647 d->placeholderColor = color;
648 emit placeholderTextColorChanged();
649}
650
651/*!
652 \qmlproperty enumeration QtQuick.Controls::TextArea::focusReason
653
654 This property holds the reason of the last focus change.
655
656 \note This property does not indicate whether the item has \l {Item::activeFocus}
657 {active focus}, but the reason why the item either gained or lost focus.
658
659 \value Qt.MouseFocusReason A mouse action occurred.
660 \value Qt.TabFocusReason The Tab key was pressed.
661 \value Qt.BacktabFocusReason A Backtab occurred. The input for this may include the Shift or Control keys; e.g. Shift+Tab.
662 \value Qt.ActiveWindowFocusReason The window system made this window either active or inactive.
663 \value Qt.PopupFocusReason The application opened/closed a pop-up that grabbed/released the keyboard focus.
664 \value Qt.ShortcutFocusReason The user typed a label's buddy shortcut
665 \value Qt.MenuBarFocusReason The menu bar took focus.
666 \value Qt.OtherFocusReason Another reason, usually application-specific.
667
668 \note Prefer \l {QtQuick.Controls::Control::focusReason} to this property.
669*/
670Qt::FocusReason QQuickTextArea::focusReason() const
671{
672 Q_D(const QQuickTextArea);
673 return d->lastFocusChangeReason();
674}
675
676void QQuickTextArea::setFocusReason(Qt::FocusReason reason)
677{
678 Q_D(QQuickTextArea);
679 d->setLastFocusChangeReason(reason);
680}
681
682
683bool QQuickTextArea::contains(const QPointF &point) const
684{
685 Q_D(const QQuickTextArea);
686 if (d->flickable && !d->flickable->contains(d->flickable->mapFromItem(this, point)))
687 return false;
688 return QQuickTextEdit::contains(point);
689}
690
691/*!
692 \since QtQuick.Controls 2.1 (Qt 5.8)
693 \qmlproperty bool QtQuick.Controls::TextArea::hovered
694 \readonly
695
696 This property holds whether the text area is hovered.
697
698 \sa hoverEnabled
699*/
700bool QQuickTextArea::isHovered() const
701{
702#if QT_CONFIG(quicktemplates2_hover)
703 Q_D(const QQuickTextArea);
704 return d->hovered;
705#else
706 return false;
707#endif
708}
709
710void QQuickTextArea::setHovered(bool hovered)
711{
712#if QT_CONFIG(quicktemplates2_hover)
713 Q_D(QQuickTextArea);
714 if (hovered == d->hovered)
715 return;
716
717 d->hovered = hovered;
718 emit hoveredChanged();
719#else
720 Q_UNUSED(hovered);
721#endif
722}
723
724/*!
725 \since QtQuick.Controls 2.1 (Qt 5.8)
726 \qmlproperty bool QtQuick.Controls::TextArea::hoverEnabled
727
728 This property determines whether the text area accepts hover events. The default value is \c true.
729
730 \sa hovered
731*/
732bool QQuickTextArea::isHoverEnabled() const
733{
734#if QT_CONFIG(quicktemplates2_hover)
735 Q_D(const QQuickTextArea);
736 return d->hoverEnabled;
737#else
738 return false;
739#endif
740}
741
742void QQuickTextArea::setHoverEnabled(bool enabled)
743{
744#if QT_CONFIG(quicktemplates2_hover)
745 Q_D(QQuickTextArea);
746 if (d->explicitHoverEnabled && enabled == d->hoverEnabled)
747 return;
748
749 d->updateHoverEnabled(enabled, true); // explicit=true
750#else
751 Q_UNUSED(enabled);
752#endif
753}
754
755void QQuickTextArea::resetHoverEnabled()
756{
757#if QT_CONFIG(quicktemplates2_hover)
758 Q_D(QQuickTextArea);
759 if (!d->explicitHoverEnabled)
760 return;
761
762 d->explicitHoverEnabled = false;
763 d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
764#endif
765}
766
767/*!
768 \since QtQuick.Controls 2.5 (Qt 5.12)
769 \qmlproperty real QtQuick.Controls::TextArea::implicitBackgroundWidth
770 \readonly
771
772 This property holds the implicit background width.
773
774 The value is equal to \c {background ? background.implicitWidth : 0}.
775
776 \sa implicitBackgroundHeight
777*/
778qreal QQuickTextArea::implicitBackgroundWidth() const
779{
780 Q_D(const QQuickTextArea);
781 if (!d->background)
782 return 0;
783 return d->background->implicitWidth();
784}
785
786/*!
787 \since QtQuick.Controls 2.5 (Qt 5.12)
788 \qmlproperty real QtQuick.Controls::TextArea::implicitBackgroundHeight
789 \readonly
790
791 This property holds the implicit background height.
792
793 The value is equal to \c {background ? background.implicitHeight : 0}.
794
795 \sa implicitBackgroundWidth
796*/
797qreal QQuickTextArea::implicitBackgroundHeight() const
798{
799 Q_D(const QQuickTextArea);
800 if (!d->background)
801 return 0;
802 return d->background->implicitHeight();
803}
804
805/*!
806 \since QtQuick.Controls 2.5 (Qt 5.12)
807 \qmlproperty real QtQuick.Controls::TextArea::topInset
808
809 This property holds the top inset for the background.
810
811 \sa {Control Layout}, bottomInset
812*/
813qreal QQuickTextArea::topInset() const
814{
815 Q_D(const QQuickTextArea);
816 return d->getTopInset();
817}
818
819void QQuickTextArea::setTopInset(qreal inset)
820{
821 Q_D(QQuickTextArea);
822 d->setTopInset(inset);
823}
824
825void QQuickTextArea::resetTopInset()
826{
827 Q_D(QQuickTextArea);
828 d->setTopInset(0, true);
829}
830
831/*!
832 \since QtQuick.Controls 2.5 (Qt 5.12)
833 \qmlproperty real QtQuick.Controls::TextArea::leftInset
834
835 This property holds the left inset for the background.
836
837 \sa {Control Layout}, rightInset
838*/
839qreal QQuickTextArea::leftInset() const
840{
841 Q_D(const QQuickTextArea);
842 return d->getLeftInset();
843}
844
845void QQuickTextArea::setLeftInset(qreal inset)
846{
847 Q_D(QQuickTextArea);
848 d->setLeftInset(inset);
849}
850
851void QQuickTextArea::resetLeftInset()
852{
853 Q_D(QQuickTextArea);
854 d->setLeftInset(0, true);
855}
856
857/*!
858 \since QtQuick.Controls 2.5 (Qt 5.12)
859 \qmlproperty real QtQuick.Controls::TextArea::rightInset
860
861 This property holds the right inset for the background.
862
863 \sa {Control Layout}, leftInset
864*/
865qreal QQuickTextArea::rightInset() const
866{
867 Q_D(const QQuickTextArea);
868 return d->getRightInset();
869}
870
871void QQuickTextArea::setRightInset(qreal inset)
872{
873 Q_D(QQuickTextArea);
874 d->setRightInset(inset);
875}
876
877void QQuickTextArea::resetRightInset()
878{
879 Q_D(QQuickTextArea);
880 d->setRightInset(0, true);
881}
882
883/*!
884 \since QtQuick.Controls 2.5 (Qt 5.12)
885 \qmlproperty real QtQuick.Controls::TextArea::bottomInset
886
887 This property holds the bottom inset for the background.
888
889 \sa {Control Layout}, topInset
890*/
891qreal QQuickTextArea::bottomInset() const
892{
893 Q_D(const QQuickTextArea);
894 return d->getBottomInset();
895}
896
897void QQuickTextArea::setBottomInset(qreal inset)
898{
899 Q_D(QQuickTextArea);
900 d->setBottomInset(inset);
901}
902
903void QQuickTextArea::resetBottomInset()
904{
905 Q_D(QQuickTextArea);
906 d->setBottomInset(0, true);
907}
908
909void QQuickTextArea::classBegin()
910{
911 Q_D(QQuickTextArea);
912 QQuickTextEdit::classBegin();
913 d->resolveFont();
914}
915
916void QQuickTextArea::componentComplete()
917{
918 Q_D(QQuickTextArea);
919 d->executeBackground(true);
920 QQuickTextEdit::componentComplete();
921 d->resizeBackground();
922#if QT_CONFIG(quicktemplates2_hover)
923 if (!d->explicitHoverEnabled)
924 setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
925#endif
926}
927
928void QQuickTextArea::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
929{
930 Q_D(QQuickTextArea);
931 QQuickTextEdit::itemChange(change, value);
932 switch (change) {
933 case ItemEnabledHasChanged:
934 break;
935 case ItemSceneChange:
936 case ItemParentHasChanged:
937 if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
938 d->resolveFont();
939#if QT_CONFIG(quicktemplates2_hover)
940 if (!d->explicitHoverEnabled)
941 d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
942#endif
943 if (change == ItemParentHasChanged) {
944 QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(value.item->parentItem());
945 if (flickable) {
946 QQuickScrollView *scrollView = qobject_cast<QQuickScrollView *>(flickable->parentItem());
947 if (scrollView)
948 d->attachFlickable(flickable);
949 }
950 }
951 }
952 break;
953 default:
954 break;
955 }
956}
957
958void QQuickTextArea::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
959{
960 Q_D(QQuickTextArea);
961 QQuickTextEdit::geometryChange(newGeometry, oldGeometry);
962 d->resizeBackground();
963}
964
965void QQuickTextArea::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset)
966{
967 Q_D(QQuickTextArea);
968 Q_UNUSED(newInset);
969 Q_UNUSED(oldInset);
970 d->resizeBackground();
971}
972
973QSGNode *QQuickTextArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
974{
975 Q_D(QQuickTextArea);
976 QQuickDefaultClipNode *clipNode = static_cast<QQuickDefaultClipNode *>(oldNode);
977 if (!clipNode)
978 clipNode = new QQuickDefaultClipNode(QRectF());
979
980 QQuickItem *clipper = this;
981 if (d->flickable)
982 clipper = d->flickable;
983
984 const QRectF cr = clipper->clipRect().adjusted(
985 leftPadding(), topPadding(),
986 (!d->cursorItem && effectiveHAlign() == HAlignment::AlignRight ? 1 : 0) - rightPadding(),
987 -bottomPadding());
988
989 clipNode->setRect(!d->flickable ? cr : cr.translated(d->flickable->contentX(), d->flickable->contentY()));
990 clipNode->update();
991
992 QSGNode *textNode = QQuickTextEdit::updatePaintNode(clipNode->firstChild(), data);
993 if (!textNode->parent())
994 clipNode->appendChildNode(textNode);
995
996 if (d->cursorItem) {
997 QQuickDefaultClipNode *cursorNode = QQuickItemPrivate::get(d->cursorItem)->clipNode();
998 if (cursorNode)
999 cursorNode->setClipRect(d->cursorItem->mapRectFromItem(clipper, cr));
1000 }
1001
1002 return clipNode;
1003}
1004
1005void QQuickTextArea::focusInEvent(QFocusEvent *event)
1006{
1007 QQuickTextEdit::focusInEvent(event);
1008}
1009
1010void QQuickTextArea::focusOutEvent(QFocusEvent *event)
1011{
1012 QQuickTextEdit::focusOutEvent(event);
1013}
1014
1015#if QT_CONFIG(quicktemplates2_hover)
1016void QQuickTextArea::hoverEnterEvent(QHoverEvent *event)
1017{
1018 Q_D(QQuickTextArea);
1019 QQuickTextEdit::hoverEnterEvent(event);
1020 setHovered(d->hoverEnabled);
1021 event->ignore();
1022}
1023
1024void QQuickTextArea::hoverLeaveEvent(QHoverEvent *event)
1025{
1026 QQuickTextEdit::hoverLeaveEvent(event);
1027 setHovered(false);
1028 event->ignore();
1029}
1030#endif
1031
1032void QQuickTextArea::mousePressEvent(QMouseEvent *event)
1033{
1034 Q_D(QQuickTextArea);
1035 d->pressHandler.mousePressEvent(event);
1036 if (d->pressHandler.isActive()) {
1037 if (d->pressHandler.delayedMousePressEvent) {
1038 QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent.get());
1039 d->pressHandler.clearDelayedMouseEvent();
1040 }
1041 // Calling the base class implementation will result in QQuickTextControl's
1042 // press handler being called, which ignores events that aren't Qt::LeftButton.
1043 const bool wasAccepted = event->isAccepted();
1044 QQuickTextEdit::mousePressEvent(event);
1045 if (wasAccepted)
1046 event->accept();
1047 }
1048}
1049
1050void QQuickTextArea::mouseMoveEvent(QMouseEvent *event)
1051{
1052 Q_D(QQuickTextArea);
1053 d->pressHandler.mouseMoveEvent(event);
1054 if (d->pressHandler.isActive()) {
1055 if (d->pressHandler.delayedMousePressEvent) {
1056 QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent.get());
1057 d->pressHandler.clearDelayedMouseEvent();
1058 }
1059 QQuickTextEdit::mouseMoveEvent(event);
1060 }
1061}
1062
1063void QQuickTextArea::mouseReleaseEvent(QMouseEvent *event)
1064{
1065 Q_D(QQuickTextArea);
1066 d->pressHandler.mouseReleaseEvent(event);
1067 if (d->pressHandler.isActive()) {
1068 if (d->pressHandler.delayedMousePressEvent) {
1069 QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent.get());
1070 d->pressHandler.clearDelayedMouseEvent();
1071 }
1072 QQuickTextEdit::mouseReleaseEvent(event);
1073 }
1074}
1075
1076void QQuickTextArea::mouseDoubleClickEvent(QMouseEvent *event)
1077{
1078 Q_D(QQuickTextArea);
1079 if (d->pressHandler.delayedMousePressEvent) {
1080 QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent.get());
1081 d->pressHandler.clearDelayedMouseEvent();
1082 }
1083 QQuickTextEdit::mouseDoubleClickEvent(event);
1084}
1085
1086void QQuickTextArea::timerEvent(QTimerEvent *event)
1087{
1088 Q_D(QQuickTextArea);
1089 if (event->timerId() == d->pressHandler.timer.timerId())
1090 d->pressHandler.timerEvent(event);
1091 else
1092 QQuickTextEdit::timerEvent(event);
1093}
1094
1096{
1097public:
1099};
1100
1101QQuickTextAreaAttached::QQuickTextAreaAttached(QObject *parent)
1102 : QObject(*(new QQuickTextAreaAttachedPrivate), parent)
1103{
1104}
1105
1106/*!
1107 \qmlattachedproperty TextArea QtQuick.Controls::TextArea::flickable
1108
1109 This property attaches a text area to a \l Flickable.
1110
1111 \sa ScrollBar, ScrollIndicator, {Scrollable TextArea}
1112*/
1113QQuickTextArea *QQuickTextAreaAttached::flickable() const
1114{
1115 Q_D(const QQuickTextAreaAttached);
1116 return d->control;
1117}
1118
1119void QQuickTextAreaAttached::setFlickable(QQuickTextArea *control)
1120{
1121 Q_D(QQuickTextAreaAttached);
1122 QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(parent());
1123 if (!flickable) {
1124 qmlWarning(parent()) << "TextArea attached property must be attached to an object deriving from Flickable";
1125 return;
1126 }
1127
1128 if (d->control == control)
1129 return;
1130
1131 if (d->control)
1132 QQuickTextAreaPrivate::get(d->control)->detachFlickable();
1133
1134 d->control = control;
1135
1136 if (control)
1137 QQuickTextAreaPrivate::get(control)->attachFlickable(flickable);
1138
1139 emit flickableChanged();
1140}
1141
1142QT_END_NAMESPACE
1143
1144#include "moc_qquicktextarea_p.cpp"
void implicitWidthChanged() override
qreal getImplicitWidth() const override
bool setLastFocusChangeReason(Qt::FocusReason reason) override
QQuickFlickable * flickable
void setTopInset(qreal value, bool reset=false)
void setLeftInset(qreal value, bool reset=false)
void setRightInset(qreal value, bool reset=false)
void executeBackground(bool complete=false)
void updateFont(const QFont &font)
void setBottomInset(qreal value, bool reset=false)
void itemDestroyed(QQuickItem *item) override
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override
void itemImplicitWidthChanged(QQuickItem *item) override
void attachFlickable(QQuickFlickable *flickable)
void inheritFont(const QFont &font)
qreal getImplicitHeight() const override
void itemImplicitHeightChanged(QQuickItem *item) override
QPalette defaultPalette() const override
void implicitHeightChanged() override
Combined button and popup list for selecting options.