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
qquicklabel.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
10
11#include <QtQuick/private/qquickitem_p.h>
12#include <QtQuick/private/qquicktext_p.h>
13
14#if QT_CONFIG(accessibility)
15#include <QtQuick/private/qquickaccessibleattached_p.h>
16#endif
17
19
20/*!
21 \qmltype Label
22 \inherits Text
23//! \nativetype QQuickLabel
24 \inqmlmodule QtQuick.Controls
25 \since 5.7
26 \ingroup text
27 \brief Styled text label with inherited font.
28
29 Label extends \l Text with styling and \l {Control::font}{font}
30 inheritance. The default colors and font are style specific. Label
31 can also have a visual \l background item.
32
33 \image qtquickcontrols-label.png
34
35 \snippet qtquickcontrols-label.qml 1
36
37 You can use the properties of \l Text to change the appearance of the text as desired:
38
39 \qml
40 Label {
41 text: "Hello world"
42 font.pixelSize: 22
43 font.italic: true
44 }
45 \endqml
46
47 \sa {Customizing Label}
48*/
49
50QQuickLabelPrivate::QQuickLabelPrivate()
51{
52#if QT_CONFIG(accessibility)
53 QAccessible::installActivationObserver(this);
54#endif
55}
56
57QQuickLabelPrivate::~QQuickLabelPrivate()
58{
59#if QT_CONFIG(accessibility)
60 QAccessible::removeActivationObserver(this);
61#endif
62}
63
64void QQuickLabelPrivate::setTopInset(qreal value, bool reset)
65{
66 Q_Q(QQuickLabel);
67 const QMarginsF oldInset = getInset();
68 extra.value().topInset = value;
69 extra.value().hasTopInset = !reset;
70 if (!qFuzzyCompare(oldInset.top(), value)) {
71 emit q->topInsetChanged();
72 q->insetChange(getInset(), oldInset);
73 }
74}
75
76void QQuickLabelPrivate::setLeftInset(qreal value, bool reset)
77{
78 Q_Q(QQuickLabel);
79 const QMarginsF oldInset = getInset();
80 extra.value().leftInset = value;
81 extra.value().hasLeftInset = !reset;
82 if (!qFuzzyCompare(oldInset.left(), value)) {
83 emit q->leftInsetChanged();
84 q->insetChange(getInset(), oldInset);
85 }
86}
87
88void QQuickLabelPrivate::setRightInset(qreal value, bool reset)
89{
90 Q_Q(QQuickLabel);
91 const QMarginsF oldInset = getInset();
92 extra.value().rightInset = value;
93 extra.value().hasRightInset = !reset;
94 if (!qFuzzyCompare(oldInset.right(), value)) {
95 emit q->rightInsetChanged();
96 q->insetChange(getInset(), oldInset);
97 }
98}
99
100void QQuickLabelPrivate::setBottomInset(qreal value, bool reset)
101{
102 Q_Q(QQuickLabel);
103 const QMarginsF oldInset = getInset();
104 extra.value().bottomInset = value;
105 extra.value().hasBottomInset = !reset;
106 if (!qFuzzyCompare(oldInset.bottom(), value)) {
107 emit q->bottomInsetChanged();
108 q->insetChange(getInset(), oldInset);
109 }
110}
111
112void QQuickLabelPrivate::resizeBackground()
113{
114 if (!background)
115 return;
116
117 resizingBackground = true;
118
119 QQuickItemPrivate *p = QQuickItemPrivate::get(background);
120 if (((!p->widthValid() || !extra.isAllocated() || !extra->hasBackgroundWidth) && qFuzzyIsNull(background->x()))
121 || (extra.isAllocated() && (extra->hasLeftInset || extra->hasRightInset))) {
122 background->setX(getLeftInset());
123 background->setWidth(width - getLeftInset() - getRightInset());
124 }
125 if (((!p->heightValid() || !extra.isAllocated() || !extra->hasBackgroundHeight) && qFuzzyIsNull(background->y()))
126 || (extra.isAllocated() && (extra->hasTopInset || extra->hasBottomInset))) {
127 background->setY(getTopInset());
128 background->setHeight(height - getTopInset() - getBottomInset());
129 }
130
131 resizingBackground = false;
132}
133
134/*!
135 \internal
136
137 Determine which font is implicitly imposed on this control by its ancestors
138 and QGuiApplication::font, resolve this against its own font (attributes from
139 the implicit font are copied over). Then propagate this font to this
140 control's children.
141*/
142void QQuickLabelPrivate::resolveFont()
143{
144 Q_Q(QQuickLabel);
145 inheritFont(QQuickControlPrivate::parentFont(q));
146}
147
148void QQuickLabelPrivate::inheritFont(const QFont &font)
149{
150 QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font;
151 parentFont.setResolveMask(extra.isAllocated() ? extra->requestedFont.resolveMask() | font.resolveMask() : font.resolveMask());
152
153 const QFont defaultFont = QQuickTheme::font(QQuickTheme::Label);
154 QFont resolvedFont = parentFont.resolve(defaultFont);
155
156 setFont_helper(resolvedFont);
157}
158
159/*!
160 \internal
161
162 Assign \a font to this control, and propagate it to all children.
163*/
164void QQuickLabelPrivate::updateFont(const QFont &font)
165{
166 Q_Q(QQuickLabel);
167 QFont oldFont = sourceFont;
168 q->QQuickText::setFont(font);
169
170 QQuickControlPrivate::updateFontRecur(q, font);
171
172 if (oldFont != font)
173 emit q->fontChanged();
174}
175
176void QQuickLabelPrivate::textChanged(const QString &text)
177{
178#if QT_CONFIG(accessibility)
179 maybeSetAccessibleName(text);
180#else
181 Q_UNUSED(text);
182#endif
183}
184
185#if QT_CONFIG(accessibility)
186void QQuickLabelPrivate::accessibilityActiveChanged(bool active)
187{
188 if (!active)
189 return;
190
191 Q_Q(QQuickLabel);
192 QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
193 Q_ASSERT(accessibleAttached);
194 accessibleAttached->setRole(effectiveAccessibleRole());
195 maybeSetAccessibleName(text);
196}
197
198QAccessible::Role QQuickLabelPrivate::accessibleRole() const
199{
200 return QAccessible::StaticText;
201}
202
203void QQuickLabelPrivate::maybeSetAccessibleName(const QString &name)
204{
205 Q_Q(QQuickLabel);
206 auto accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(
207 qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
208 if (accessibleAttached) {
209 if (!accessibleAttached->wasNameExplicitlySet())
210 accessibleAttached->setNameImplicitly(name);
211 }
212}
213#endif
214
215void QQuickLabelPrivate::cancelBackground()
216{
217 Q_Q(QQuickLabel);
218 quickCancelDeferred(q, backgroundName());
219}
220
221void QQuickLabelPrivate::executeBackground(bool complete)
222{
223 Q_Q(QQuickLabel);
224 if (background.wasExecuted())
225 return;
226
227 if (!background || complete)
228 quickBeginDeferred(q, backgroundName(), background);
229 if (complete)
230 quickCompleteDeferred(q, backgroundName(), background);
231}
232
233void QQuickLabelPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff)
234{
235 Q_UNUSED(diff);
236 if (resizingBackground || item != background || !change.sizeChange())
237 return;
238
239 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
240 extra.value().hasBackgroundWidth = p->widthValid();
241 extra.value().hasBackgroundHeight = p->heightValid();
242 resizeBackground();
243}
244
245void QQuickLabelPrivate::itemImplicitWidthChanged(QQuickItem *item)
246{
247 Q_Q(QQuickLabel);
248 if (item == background)
249 emit q->implicitBackgroundWidthChanged();
250}
251
252void QQuickLabelPrivate::itemImplicitHeightChanged(QQuickItem *item)
253{
254 Q_Q(QQuickLabel);
255 if (item == background)
256 emit q->implicitBackgroundHeightChanged();
257}
258
259void QQuickLabelPrivate::itemDestroyed(QQuickItem *item)
260{
261 Q_Q(QQuickLabel);
262 if (item == background) {
263 background = nullptr;
264 emit q->implicitBackgroundWidthChanged();
265 emit q->implicitBackgroundHeightChanged();
266 }
267}
268
269QPalette QQuickLabelPrivate::defaultPalette() const
270{
271 return QQuickTheme::palette(QQuickTheme::Label);
272}
273
274QQuickLabel::QQuickLabel(QQuickItem *parent)
275 : QQuickText(*(new QQuickLabelPrivate), parent)
276{
277 Q_D(QQuickLabel);
278 QObjectPrivate::connect(this, &QQuickText::textChanged, d, &QQuickLabelPrivate::textChanged);
279}
280
281QQuickLabel::~QQuickLabel()
282{
283 Q_D(QQuickLabel);
284 QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
285}
286
287QFont QQuickLabel::font() const
288{
289 Q_D(const QQuickLabel);
290 QFont font = QQuickText::font();
291 // The resolve mask should inherit from the requestedFont
292 font.setResolveMask(d->extra.value().requestedFont.resolveMask());
293 return font;
294}
295
296void QQuickLabel::setFont(const QFont &font)
297{
298 Q_D(QQuickLabel);
299 if (d->extra.value().requestedFont.resolveMask() == font.resolveMask() && d->extra.value().requestedFont == font)
300 return;
301
302 d->extra.value().requestedFont = font;
303 d->resolveFont();
304}
305
306/*!
307 \qmlproperty Item QtQuick.Controls::Label::background
308
309 This property holds the background item.
310
311 \note If the background item has no explicit size specified, it automatically
312 follows the control's size. In most cases, there is no need to specify
313 width or height for a background item.
314
315 \sa {Customizing Label}
316*/
317QQuickItem *QQuickLabel::background() const
318{
319 QQuickLabelPrivate *d = const_cast<QQuickLabelPrivate *>(d_func());
320 if (!d->background)
321 d->executeBackground();
322 return d->background;
323}
324
325void QQuickLabel::setBackground(QQuickItem *background)
326{
327 Q_D(QQuickLabel);
328 if (d->background == background)
329 return;
330
331 if (!d->background.isExecuting())
332 d->cancelBackground();
333
334 const qreal oldImplicitBackgroundWidth = implicitBackgroundWidth();
335 const qreal oldImplicitBackgroundHeight = implicitBackgroundHeight();
336
337 if (d->extra.isAllocated()) {
338 d->extra.value().hasBackgroundWidth = false;
339 d->extra.value().hasBackgroundHeight = false;
340 }
341
342 QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
343 QQuickControlPrivate::hideOldItem(d->background);
344 d->background = background;
345
346 if (background) {
347 background->setParentItem(this);
348 if (qFuzzyIsNull(background->z()))
349 background->setZ(-1);
350 QQuickItemPrivate *p = QQuickItemPrivate::get(background);
351 if (p->widthValid() || p->heightValid()) {
352 d->extra.value().hasBackgroundWidth = p->widthValid();
353 d->extra.value().hasBackgroundHeight = p->heightValid();
354 }
355 if (isComponentComplete())
356 d->resizeBackground();
357 QQuickControlPrivate::addImplicitSizeListener(background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
358 }
359
360 if (!qFuzzyCompare(oldImplicitBackgroundWidth, implicitBackgroundWidth()))
361 emit implicitBackgroundWidthChanged();
362 if (!qFuzzyCompare(oldImplicitBackgroundHeight, implicitBackgroundHeight()))
363 emit implicitBackgroundHeightChanged();
364 if (!d->background.isExecuting())
365 emit backgroundChanged();
366}
367
368/*!
369 \since QtQuick.Controls 2.5 (Qt 5.12)
370 \qmlproperty real QtQuick.Controls::Label::implicitBackgroundWidth
371 \readonly
372
373 This property holds the implicit background width.
374
375 The value is equal to \c {background ? background.implicitWidth : 0}.
376
377 \sa implicitBackgroundHeight
378*/
379qreal QQuickLabel::implicitBackgroundWidth() const
380{
381 Q_D(const QQuickLabel);
382 if (!d->background)
383 return 0;
384 return d->background->implicitWidth();
385}
386
387/*!
388 \since QtQuick.Controls 2.5 (Qt 5.12)
389 \qmlproperty real QtQuick.Controls::Label::implicitBackgroundHeight
390 \readonly
391
392 This property holds the implicit background height.
393
394 The value is equal to \c {background ? background.implicitHeight : 0}.
395
396 \sa implicitBackgroundWidth
397*/
398qreal QQuickLabel::implicitBackgroundHeight() const
399{
400 Q_D(const QQuickLabel);
401 if (!d->background)
402 return 0;
403 return d->background->implicitHeight();
404}
405
406/*!
407 \since QtQuick.Controls 2.5 (Qt 5.12)
408 \qmlproperty real QtQuick.Controls::Label::topInset
409
410 This property holds the top inset for the background.
411
412 \sa {Control Layout}, bottomInset
413*/
414qreal QQuickLabel::topInset() const
415{
416 Q_D(const QQuickLabel);
417 return d->getTopInset();
418}
419
420void QQuickLabel::setTopInset(qreal inset)
421{
422 Q_D(QQuickLabel);
423 d->setTopInset(inset);
424}
425
426void QQuickLabel::resetTopInset()
427{
428 Q_D(QQuickLabel);
429 d->setTopInset(0, true);
430}
431
432/*!
433 \since QtQuick.Controls 2.5 (Qt 5.12)
434 \qmlproperty real QtQuick.Controls::Label::leftInset
435
436 This property holds the left inset for the background.
437
438 \sa {Control Layout}, rightInset
439*/
440qreal QQuickLabel::leftInset() const
441{
442 Q_D(const QQuickLabel);
443 return d->getLeftInset();
444}
445
446void QQuickLabel::setLeftInset(qreal inset)
447{
448 Q_D(QQuickLabel);
449 d->setLeftInset(inset);
450}
451
452void QQuickLabel::resetLeftInset()
453{
454 Q_D(QQuickLabel);
455 d->setLeftInset(0, true);
456}
457
458/*!
459 \since QtQuick.Controls 2.5 (Qt 5.12)
460 \qmlproperty real QtQuick.Controls::Label::rightInset
461
462 This property holds the right inset for the background.
463
464 \sa {Control Layout}, leftInset
465*/
466qreal QQuickLabel::rightInset() const
467{
468 Q_D(const QQuickLabel);
469 return d->getRightInset();
470}
471
472void QQuickLabel::setRightInset(qreal inset)
473{
474 Q_D(QQuickLabel);
475 d->setRightInset(inset);
476}
477
478void QQuickLabel::resetRightInset()
479{
480 Q_D(QQuickLabel);
481 d->setRightInset(0, true);
482}
483
484/*!
485 \since QtQuick.Controls 2.5 (Qt 5.12)
486 \qmlproperty real QtQuick.Controls::Label::bottomInset
487
488 This property holds the bottom inset for the background.
489
490 \sa {Control Layout}, topInset
491*/
492qreal QQuickLabel::bottomInset() const
493{
494 Q_D(const QQuickLabel);
495 return d->getBottomInset();
496}
497
498void QQuickLabel::setBottomInset(qreal inset)
499{
500 Q_D(QQuickLabel);
501 d->setBottomInset(inset);
502}
503
504void QQuickLabel::resetBottomInset()
505{
506 Q_D(QQuickLabel);
507 d->setBottomInset(0, true);
508}
509
510void QQuickLabel::classBegin()
511{
512 Q_D(QQuickLabel);
513 QQuickText::classBegin();
514 d->resolveFont();
515}
516
517void QQuickLabel::componentComplete()
518{
519 Q_D(QQuickLabel);
520 d->executeBackground(true);
521 QQuickText::componentComplete();
522 d->resizeBackground();
523#if QT_CONFIG(accessibility)
524 if (QAccessible::isActive())
525 d->accessibilityActiveChanged(true);
526#endif
527}
528
529void QQuickLabel::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
530{
531 Q_D(QQuickLabel);
532 QQuickText::itemChange(change, value);
533 switch (change) {
534 case ItemEnabledHasChanged:
535 break;
536 case ItemSceneChange:
537 case ItemParentHasChanged:
538 if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
539 d->resolveFont();
540 }
541 break;
542 default:
543 break;
544 }
545}
546
547void QQuickLabel::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
548{
549 Q_D(QQuickLabel);
550 QQuickText::geometryChange(newGeometry, oldGeometry);
551 d->resizeBackground();
552}
553
554void QQuickLabel::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset)
555{
556 Q_D(QQuickLabel);
557 Q_UNUSED(newInset);
558 Q_UNUSED(oldInset);
559 d->resizeBackground();
560}
561
562QT_END_NAMESPACE
563
564#include "moc_qquicklabel_p.cpp"