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 if (!initialized) {
413 QQuickTextEditPrivate::implicitWidthChanged();
414 return;
415 }
416 Q_Q(QQuickTextArea);
417 QQuickItemPrivate::implicitWidthChanged();
418 emit q->implicitWidthChanged3();
419}
420
422{
423 if (!initialized) {
424 QQuickTextEditPrivate::implicitHeightChanged();
425 return;
426 }
427 Q_Q(QQuickTextArea);
428 QQuickItemPrivate::implicitHeightChanged();
429 emit q->implicitHeightChanged3();
430}
431
432#if QT_CONFIG(accessibility)
433void QQuickTextAreaPrivate::accessibilityActiveChanged(bool active)
434{
435 QQuickTextEditPrivate::accessibilityActiveChanged(active);
436 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func()))
437 accessibleAttached->setDescriptionImplicitly(placeholder);
438}
439#endif
440
442{
443 Q_Q(QQuickTextArea);
444 quickCancelDeferred(q, backgroundName());
445}
446
448{
449 Q_Q(QQuickTextArea);
450 if (background.wasExecuted())
451 return;
452
453 if (!background || complete)
454 quickBeginDeferred(q, backgroundName(), background);
455 if (complete)
456 quickCompleteDeferred(q, backgroundName(), background);
457}
458
460{
461 Q_Q(QQuickTextArea);
462 if (item == background)
463 emit q->implicitBackgroundWidthChanged();
464}
465
467{
468 Q_Q(QQuickTextArea);
469 if (item == background)
470 emit q->implicitBackgroundHeightChanged();
471}
472
474{
475 Q_Q(QQuickTextArea);
476 if (item == background) {
477 background = nullptr;
478 emit q->implicitBackgroundWidthChanged();
479 emit q->implicitBackgroundHeightChanged();
480 } else if (item == flickable) {
482 }
483}
484
486{
487 return QQuickTheme::palette(QQuickTheme::TextArea);
488}
489
491{
492 Q_Q(QQuickTextArea);
493 const auto focusReasonChanged = QQuickItemPrivate::setLastFocusChangeReason(reason);
494 if (focusReasonChanged)
495 emit q->focusReasonChanged();
496
497 return focusReasonChanged;
498}
499
500QQuickTextArea::QQuickTextArea(QQuickItem *parent)
501 : QQuickTextEdit(*(new QQuickTextAreaPrivate), parent)
502{
503 Q_D(QQuickTextArea);
504 d->initialized = true;
505 setActiveFocusOnTab(true);
506 setAcceptedMouseButtons(Qt::AllButtons);
507 d->setImplicitResizeEnabled(false);
508 d->pressHandler.control = this;
509
510#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
511 if (qEnvironmentVariable("QT_QUICK_CONTROLS_TEXT_SELECTION_BEHAVIOR") == u"old"_s)
512 QQuickTextEdit::setOldSelectionDefault();
513#endif
514}
515
516QQuickTextArea::~QQuickTextArea()
517{
518 Q_D(QQuickTextArea);
519 if (d->flickable)
520 d->detachFlickable();
521 QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
522}
523
524QQuickTextAreaAttached *QQuickTextArea::qmlAttachedProperties(QObject *object)
525{
526 return new QQuickTextAreaAttached(object);
527}
528
529QFont QQuickTextArea::font() const
530{
531 Q_D(const QQuickTextArea);
532 QFont font = QQuickTextEdit::font();
533 // The resolve mask should inherit from the requestedFont
534 font.setResolveMask(d->extra.isAllocated() ? d->extra->requestedFont.resolveMask() : 0);
535 return font;
536}
537
538void QQuickTextArea::setFont(const QFont &font)
539{
540 Q_D(QQuickTextArea);
541 if (d->extra.isAllocated()
542 && d->extra.value().requestedFont.resolveMask() == font.resolveMask()
543 && d->extra.value().requestedFont == font)
544 return;
545
546 d->extra.value().requestedFont = font;
547 d->resolveFont();
548}
549
550/*!
551 \qmlproperty Item QtQuick.Controls::TextArea::background
552
553 This property holds the background item.
554
555 \input qquickcontrol-background.qdocinc notes
556
557 \sa {Customizing TextArea}
558*/
559QQuickItem *QQuickTextArea::background() const
560{
561 QQuickTextAreaPrivate *d = const_cast<QQuickTextAreaPrivate *>(d_func());
562 if (!d->background)
563 d->executeBackground();
564 return d->background;
565}
566
567void QQuickTextArea::setBackground(QQuickItem *background)
568{
569 Q_D(QQuickTextArea);
570 if (d->background == background)
571 return;
572
573 QQuickControlPrivate::warnIfCustomizationNotSupported(this, background, QStringLiteral("background"));
574
575 if (!d->background.isExecuting())
576 d->cancelBackground();
577
578 const qreal oldImplicitBackgroundWidth = implicitBackgroundWidth();
579 const qreal oldImplicitBackgroundHeight = implicitBackgroundHeight();
580
581 if (d->extra.isAllocated()) {
582 d->extra.value().hasBackgroundWidth = false;
583 d->extra.value().hasBackgroundHeight = false;
584 }
585
586 QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
587 QQuickControlPrivate::hideOldItem(d->background);
588 d->background = background;
589
590 if (background) {
591 QQuickItemPrivate *p = QQuickItemPrivate::get(background);
592 if (p->widthValid() || p->heightValid()) {
593 d->extra.value().hasBackgroundWidth = p->widthValid();
594 d->extra.value().hasBackgroundHeight = p->heightValid();
595 }
596 if (d->flickable)
597 background->setParentItem(d->flickable);
598 else
599 background->setParentItem(this);
600 if (qFuzzyIsNull(background->z()))
601 background->setZ(-1);
602 if (isComponentComplete())
603 d->resizeBackground();
604 QQuickControlPrivate::addImplicitSizeListener(background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
605 }
606
607 if (!qFuzzyCompare(oldImplicitBackgroundWidth, implicitBackgroundWidth()))
608 emit implicitBackgroundWidthChanged();
609 if (!qFuzzyCompare(oldImplicitBackgroundHeight, implicitBackgroundHeight()))
610 emit implicitBackgroundHeightChanged();
611 if (!d->background.isExecuting())
612 emit backgroundChanged();
613}
614
615/*!
616 \qmlproperty string QtQuick.Controls::TextArea::placeholderText
617
618 This property holds the short hint that is displayed in the text area before
619 the user enters a value.
620*/
621QString QQuickTextArea::placeholderText() const
622{
623 Q_D(const QQuickTextArea);
624 return d->placeholder;
625}
626
627void QQuickTextArea::setPlaceholderText(const QString &text)
628{
629 Q_D(QQuickTextArea);
630 if (d->placeholder == text)
631 return;
632
633 d->placeholder = text;
634#if QT_CONFIG(accessibility)
635 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this))
636 accessibleAttached->setDescriptionImplicitly(text);
637#endif
638 emit placeholderTextChanged();
639}
640
641/*!
642 \qmlproperty color QtQuick.Controls::TextArea::placeholderTextColor
643 \since QtQuick.Controls 2.5 (Qt 5.12)
644
645 This property holds the color of placeholderText.
646
647 \sa placeholderText
648*/
649QColor QQuickTextArea::placeholderTextColor() const
650{
651 Q_D(const QQuickTextArea);
652 return d->placeholderColor;
653}
654
655void QQuickTextArea::setPlaceholderTextColor(const QColor &color)
656{
657 Q_D(QQuickTextArea);
658 if (d->placeholderColor == color)
659 return;
660
661 d->placeholderColor = color;
662 emit placeholderTextColorChanged();
663}
664
665/*!
666 \qmlproperty enumeration QtQuick.Controls::TextArea::focusReason
667
668 This property holds the reason of the last focus change.
669
670 \note This property does not indicate whether the item has \l {Item::activeFocus}
671 {active focus}, but the reason why the item either gained or lost focus.
672
673 \value Qt.MouseFocusReason A mouse action occurred.
674 \value Qt.TabFocusReason The Tab key was pressed.
675 \value Qt.BacktabFocusReason A Backtab occurred. The input for this may include the Shift or Control keys; e.g. Shift+Tab.
676 \value Qt.ActiveWindowFocusReason The window system made this window either active or inactive.
677 \value Qt.PopupFocusReason The application opened/closed a pop-up that grabbed/released the keyboard focus.
678 \value Qt.ShortcutFocusReason The user typed a label's buddy shortcut
679 \value Qt.MenuBarFocusReason The menu bar took focus.
680 \value Qt.OtherFocusReason Another reason, usually application-specific.
681
682 \note Prefer \l {QtQuick.Controls::Control::focusReason} to this property.
683*/
684Qt::FocusReason QQuickTextArea::focusReason() const
685{
686 Q_D(const QQuickTextArea);
687 return d->lastFocusChangeReason();
688}
689
690void QQuickTextArea::setFocusReason(Qt::FocusReason reason)
691{
692 Q_D(QQuickTextArea);
693 d->setLastFocusChangeReason(reason);
694}
695
696
697bool QQuickTextArea::contains(const QPointF &point) const
698{
699 Q_D(const QQuickTextArea);
700 if (d->flickable && !d->flickable->contains(d->flickable->mapFromItem(this, point)))
701 return false;
702 return QQuickTextEdit::contains(point);
703}
704
705/*!
706 \since QtQuick.Controls 2.1 (Qt 5.8)
707 \qmlproperty bool QtQuick.Controls::TextArea::hovered
708 \readonly
709
710 This property holds whether the text area is hovered.
711
712 \sa hoverEnabled
713*/
714bool QQuickTextArea::isHovered() const
715{
716#if QT_CONFIG(quicktemplates2_hover)
717 Q_D(const QQuickTextArea);
718 return d->hovered;
719#else
720 return false;
721#endif
722}
723
724void QQuickTextArea::setHovered(bool hovered)
725{
726#if QT_CONFIG(quicktemplates2_hover)
727 Q_D(QQuickTextArea);
728 if (hovered == d->hovered)
729 return;
730
731 d->hovered = hovered;
732 emit hoveredChanged();
733 QQuickToolTipAttachedPrivate::maybeSetVisibleImplicitly(this, hovered);
734#else
735 Q_UNUSED(hovered);
736#endif
737}
738
739/*!
740 \since QtQuick.Controls 2.1 (Qt 5.8)
741 \qmlproperty bool QtQuick.Controls::TextArea::hoverEnabled
742
743 This property determines whether the text area accepts hover events. The default value is \c true.
744
745 \sa hovered
746*/
747bool QQuickTextArea::isHoverEnabled() const
748{
749#if QT_CONFIG(quicktemplates2_hover)
750 Q_D(const QQuickTextArea);
751 return d->hoverEnabled;
752#else
753 return false;
754#endif
755}
756
757void QQuickTextArea::setHoverEnabled(bool enabled)
758{
759#if QT_CONFIG(quicktemplates2_hover)
760 Q_D(QQuickTextArea);
761 if (d->explicitHoverEnabled && enabled == d->hoverEnabled)
762 return;
763
764 d->updateHoverEnabled(enabled, true); // explicit=true
765#else
766 Q_UNUSED(enabled);
767#endif
768}
769
770void QQuickTextArea::resetHoverEnabled()
771{
772#if QT_CONFIG(quicktemplates2_hover)
773 Q_D(QQuickTextArea);
774 if (!d->explicitHoverEnabled)
775 return;
776
777 d->explicitHoverEnabled = false;
778 d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
779#endif
780}
781
782/*!
783 \since QtQuick.Controls 2.5 (Qt 5.12)
784 \qmlproperty real QtQuick.Controls::TextArea::implicitBackgroundWidth
785 \readonly
786
787 This property holds the implicit background width.
788
789 The value is equal to \c {background ? background.implicitWidth : 0}.
790
791 \sa implicitBackgroundHeight
792*/
793qreal QQuickTextArea::implicitBackgroundWidth() const
794{
795 Q_D(const QQuickTextArea);
796 if (!d->background)
797 return 0;
798 return d->background->implicitWidth();
799}
800
801/*!
802 \since QtQuick.Controls 2.5 (Qt 5.12)
803 \qmlproperty real QtQuick.Controls::TextArea::implicitBackgroundHeight
804 \readonly
805
806 This property holds the implicit background height.
807
808 The value is equal to \c {background ? background.implicitHeight : 0}.
809
810 \sa implicitBackgroundWidth
811*/
812qreal QQuickTextArea::implicitBackgroundHeight() const
813{
814 Q_D(const QQuickTextArea);
815 if (!d->background)
816 return 0;
817 return d->background->implicitHeight();
818}
819
820/*!
821 \since QtQuick.Controls 2.5 (Qt 5.12)
822 \qmlproperty real QtQuick.Controls::TextArea::topInset
823
824 This property holds the top inset for the background.
825
826 \sa {Control Layout}, bottomInset
827*/
828qreal QQuickTextArea::topInset() const
829{
830 Q_D(const QQuickTextArea);
831 return d->getTopInset();
832}
833
834void QQuickTextArea::setTopInset(qreal inset)
835{
836 Q_D(QQuickTextArea);
837 d->setTopInset(inset);
838}
839
840void QQuickTextArea::resetTopInset()
841{
842 Q_D(QQuickTextArea);
843 d->setTopInset(0, true);
844}
845
846/*!
847 \since QtQuick.Controls 2.5 (Qt 5.12)
848 \qmlproperty real QtQuick.Controls::TextArea::leftInset
849
850 This property holds the left inset for the background.
851
852 \sa {Control Layout}, rightInset
853*/
854qreal QQuickTextArea::leftInset() const
855{
856 Q_D(const QQuickTextArea);
857 return d->getLeftInset();
858}
859
860void QQuickTextArea::setLeftInset(qreal inset)
861{
862 Q_D(QQuickTextArea);
863 d->setLeftInset(inset);
864}
865
866void QQuickTextArea::resetLeftInset()
867{
868 Q_D(QQuickTextArea);
869 d->setLeftInset(0, true);
870}
871
872/*!
873 \since QtQuick.Controls 2.5 (Qt 5.12)
874 \qmlproperty real QtQuick.Controls::TextArea::rightInset
875
876 This property holds the right inset for the background.
877
878 \sa {Control Layout}, leftInset
879*/
880qreal QQuickTextArea::rightInset() const
881{
882 Q_D(const QQuickTextArea);
883 return d->getRightInset();
884}
885
886void QQuickTextArea::setRightInset(qreal inset)
887{
888 Q_D(QQuickTextArea);
889 d->setRightInset(inset);
890}
891
892void QQuickTextArea::resetRightInset()
893{
894 Q_D(QQuickTextArea);
895 d->setRightInset(0, true);
896}
897
898/*!
899 \since QtQuick.Controls 2.5 (Qt 5.12)
900 \qmlproperty real QtQuick.Controls::TextArea::bottomInset
901
902 This property holds the bottom inset for the background.
903
904 \sa {Control Layout}, topInset
905*/
906qreal QQuickTextArea::bottomInset() const
907{
908 Q_D(const QQuickTextArea);
909 return d->getBottomInset();
910}
911
912void QQuickTextArea::setBottomInset(qreal inset)
913{
914 Q_D(QQuickTextArea);
915 d->setBottomInset(inset);
916}
917
918void QQuickTextArea::resetBottomInset()
919{
920 Q_D(QQuickTextArea);
921 d->setBottomInset(0, true);
922}
923
924void QQuickTextArea::classBegin()
925{
926 Q_D(QQuickTextArea);
927 QQuickTextEdit::classBegin();
928 d->resolveFont();
929}
930
931void QQuickTextArea::componentComplete()
932{
933 Q_D(QQuickTextArea);
934 d->executeBackground(true);
935 QQuickTextEdit::componentComplete();
936 d->resizeBackground();
937#if QT_CONFIG(quicktemplates2_hover)
938 if (!d->explicitHoverEnabled)
939 setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
940#endif
941}
942
943void QQuickTextArea::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
944{
945 Q_D(QQuickTextArea);
946 QQuickTextEdit::itemChange(change, value);
947 switch (change) {
948 case ItemEnabledHasChanged:
949 break;
950 case ItemSceneChange:
951 case ItemParentHasChanged:
952 if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
953 d->resolveFont();
954#if QT_CONFIG(quicktemplates2_hover)
955 if (!d->explicitHoverEnabled)
956 d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
957#endif
958 if (change == ItemParentHasChanged) {
959 QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(value.item->parentItem());
960 if (flickable) {
961 QQuickScrollView *scrollView = qobject_cast<QQuickScrollView *>(flickable->parentItem());
962 if (scrollView)
963 d->attachFlickable(flickable);
964 }
965 }
966 }
967 break;
968 default:
969 break;
970 }
971}
972
973void QQuickTextArea::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
974{
975 Q_D(QQuickTextArea);
976 QQuickTextEdit::geometryChange(newGeometry, oldGeometry);
977 d->resizeBackground();
978}
979
980void QQuickTextArea::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset)
981{
982 Q_D(QQuickTextArea);
983 Q_UNUSED(newInset);
984 Q_UNUSED(oldInset);
985 d->resizeBackground();
986}
987
988QSGNode *QQuickTextArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
989{
990 Q_D(QQuickTextArea);
991 QQuickDefaultClipNode *clipNode = static_cast<QQuickDefaultClipNode *>(oldNode);
992 if (!clipNode)
993 clipNode = new QQuickDefaultClipNode(QRectF());
994
995 QQuickItem *clipper = this;
996 if (d->flickable)
997 clipper = d->flickable;
998
999 const QRectF cr = clipper->clipRect().adjusted(
1000 leftPadding(), topPadding(),
1001 (!d->cursorItem && effectiveHAlign() == HAlignment::AlignRight ? 1 : 0) - rightPadding(),
1002 -bottomPadding());
1003
1004 clipNode->setRect(!d->flickable ? cr : cr.translated(d->flickable->contentX(), d->flickable->contentY()));
1005 clipNode->update();
1006
1007 QSGNode *textNode = QQuickTextEdit::updatePaintNode(clipNode->firstChild(), data);
1008 if (!textNode->parent())
1009 clipNode->appendChildNode(textNode);
1010
1011 if (d->cursorItem) {
1012 QQuickDefaultClipNode *cursorNode = QQuickItemPrivate::get(d->cursorItem)->clipNode();
1013 if (cursorNode)
1014 cursorNode->setClipRect(d->cursorItem->mapRectFromItem(clipper, cr));
1015 }
1016
1017 return clipNode;
1018}
1019
1020void QQuickTextArea::focusInEvent(QFocusEvent *event)
1021{
1022 QQuickTextEdit::focusInEvent(event);
1023}
1024
1025void QQuickTextArea::focusOutEvent(QFocusEvent *event)
1026{
1027 QQuickTextEdit::focusOutEvent(event);
1028}
1029
1030#if QT_CONFIG(quicktemplates2_hover)
1031void QQuickTextArea::hoverEnterEvent(QHoverEvent *event)
1032{
1033 Q_D(QQuickTextArea);
1034 QQuickTextEdit::hoverEnterEvent(event);
1035 setHovered(d->hoverEnabled);
1036 event->ignore();
1037}
1038
1039void QQuickTextArea::hoverLeaveEvent(QHoverEvent *event)
1040{
1041 QQuickTextEdit::hoverLeaveEvent(event);
1042 setHovered(false);
1043 event->ignore();
1044}
1045#endif
1046
1047void QQuickTextArea::mousePressEvent(QMouseEvent *event)
1048{
1049 Q_D(QQuickTextArea);
1050 d->pressHandler.mousePressEvent(event);
1051 if (d->pressHandler.isActive()) {
1052 if (d->pressHandler.delayedMousePressEvent) {
1053 QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent.get());
1054 d->pressHandler.clearDelayedMouseEvent();
1055 }
1056 // Calling the base class implementation will result in QQuickTextControl's
1057 // press handler being called, which ignores events that aren't Qt::LeftButton.
1058 const bool wasAccepted = event->isAccepted();
1059 QQuickTextEdit::mousePressEvent(event);
1060 if (wasAccepted)
1061 event->accept();
1062 }
1063}
1064
1065void QQuickTextArea::mouseMoveEvent(QMouseEvent *event)
1066{
1067 Q_D(QQuickTextArea);
1068 d->pressHandler.mouseMoveEvent(event);
1069 if (d->pressHandler.isActive()) {
1070 if (d->pressHandler.delayedMousePressEvent) {
1071 QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent.get());
1072 d->pressHandler.clearDelayedMouseEvent();
1073 }
1074 QQuickTextEdit::mouseMoveEvent(event);
1075 }
1076}
1077
1078void QQuickTextArea::mouseReleaseEvent(QMouseEvent *event)
1079{
1080 Q_D(QQuickTextArea);
1081 d->pressHandler.mouseReleaseEvent(event);
1082 if (d->pressHandler.isActive()) {
1083 if (d->pressHandler.delayedMousePressEvent) {
1084 QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent.get());
1085 d->pressHandler.clearDelayedMouseEvent();
1086 }
1087 QQuickTextEdit::mouseReleaseEvent(event);
1088 }
1089}
1090
1091void QQuickTextArea::mouseDoubleClickEvent(QMouseEvent *event)
1092{
1093 Q_D(QQuickTextArea);
1094 if (d->pressHandler.delayedMousePressEvent) {
1095 QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent.get());
1096 d->pressHandler.clearDelayedMouseEvent();
1097 }
1098 QQuickTextEdit::mouseDoubleClickEvent(event);
1099}
1100
1101void QQuickTextArea::timerEvent(QTimerEvent *event)
1102{
1103 Q_D(QQuickTextArea);
1104 if (event->timerId() == d->pressHandler.timer.timerId())
1105 d->pressHandler.timerEvent(event);
1106 else
1107 QQuickTextEdit::timerEvent(event);
1108}
1109
1111{
1112public:
1114};
1115
1116QQuickTextAreaAttached::QQuickTextAreaAttached(QObject *parent)
1117 : QObject(*(new QQuickTextAreaAttachedPrivate), parent)
1118{
1119}
1120
1121/*!
1122 \qmlattachedproperty TextArea QtQuick.Controls::TextArea::flickable
1123
1124 This property attaches a text area to a \l Flickable.
1125
1126 \sa ScrollBar, ScrollIndicator, {Scrollable TextArea}
1127*/
1128QQuickTextArea *QQuickTextAreaAttached::flickable() const
1129{
1130 Q_D(const QQuickTextAreaAttached);
1131 return d->control;
1132}
1133
1134void QQuickTextAreaAttached::setFlickable(QQuickTextArea *control)
1135{
1136 Q_D(QQuickTextAreaAttached);
1137 QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(parent());
1138 if (!flickable) {
1139 qmlWarning(parent()) << "TextArea attached property must be attached to an object deriving from Flickable";
1140 return;
1141 }
1142
1143 if (d->control == control)
1144 return;
1145
1146 if (d->control)
1147 QQuickTextAreaPrivate::get(d->control)->detachFlickable();
1148
1149 d->control = control;
1150
1151 if (control)
1152 QQuickTextAreaPrivate::get(control)->attachFlickable(flickable);
1153
1154 emit flickableChanged();
1155}
1156
1157QT_END_NAMESPACE
1158
1159#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.