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