diff options
Diffstat (limited to 'src/quicktemplates/qquicklabel.cpp')
-rw-r--r-- | src/quicktemplates/qquicklabel.cpp | 563 |
1 files changed, 563 insertions, 0 deletions
diff --git a/src/quicktemplates/qquicklabel.cpp b/src/quicktemplates/qquicklabel.cpp new file mode 100644 index 0000000000..ee8723d755 --- /dev/null +++ b/src/quicktemplates/qquicklabel.cpp @@ -0,0 +1,563 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquicklabel_p.h" +#include "qquicklabel_p_p.h" +#include "qquickcontrol_p.h" +#include "qquickcontrol_p_p.h" +#include "qquickdeferredexecute_p_p.h" + +#include <QtQuick/private/qquickitem_p.h> +#include <QtQuick/private/qquicktext_p.h> + +#if QT_CONFIG(accessibility) +#include <QtQuick/private/qquickaccessibleattached_p.h> +#endif + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Label + \inherits Text +//! \instantiates QQuickLabel + \inqmlmodule QtQuick.Controls + \since 5.7 + \ingroup text + \brief Styled text label with inherited font. + + Label extends \l Text with styling and \l {Control::font}{font} + inheritance. The default colors and font are style specific. Label + can also have a visual \l background item. + + \image qtquickcontrols-label.png + + \snippet qtquickcontrols-label.qml 1 + + You can use the properties of \l Text to change the appearance of the text as desired: + + \qml + Label { + text: "Hello world" + font.pixelSize: 22 + font.italic: true + } + \endqml + + \sa {Customizing Label} +*/ + +QQuickLabelPrivate::QQuickLabelPrivate() +{ +#if QT_CONFIG(accessibility) + QAccessible::installActivationObserver(this); +#endif +} + +QQuickLabelPrivate::~QQuickLabelPrivate() +{ +#if QT_CONFIG(accessibility) + QAccessible::removeActivationObserver(this); +#endif +} + +void QQuickLabelPrivate::setTopInset(qreal value, bool reset) +{ + Q_Q(QQuickLabel); + const QMarginsF oldInset = getInset(); + extra.value().topInset = value; + extra.value().hasTopInset = !reset; + if (!qFuzzyCompare(oldInset.top(), value)) { + emit q->topInsetChanged(); + q->insetChange(getInset(), oldInset); + } +} + +void QQuickLabelPrivate::setLeftInset(qreal value, bool reset) +{ + Q_Q(QQuickLabel); + const QMarginsF oldInset = getInset(); + extra.value().leftInset = value; + extra.value().hasLeftInset = !reset; + if (!qFuzzyCompare(oldInset.left(), value)) { + emit q->leftInsetChanged(); + q->insetChange(getInset(), oldInset); + } +} + +void QQuickLabelPrivate::setRightInset(qreal value, bool reset) +{ + Q_Q(QQuickLabel); + const QMarginsF oldInset = getInset(); + extra.value().rightInset = value; + extra.value().hasRightInset = !reset; + if (!qFuzzyCompare(oldInset.right(), value)) { + emit q->rightInsetChanged(); + q->insetChange(getInset(), oldInset); + } +} + +void QQuickLabelPrivate::setBottomInset(qreal value, bool reset) +{ + Q_Q(QQuickLabel); + const QMarginsF oldInset = getInset(); + extra.value().bottomInset = value; + extra.value().hasBottomInset = !reset; + if (!qFuzzyCompare(oldInset.bottom(), value)) { + emit q->bottomInsetChanged(); + q->insetChange(getInset(), oldInset); + } +} + +void QQuickLabelPrivate::resizeBackground() +{ + if (!background) + return; + + resizingBackground = true; + + QQuickItemPrivate *p = QQuickItemPrivate::get(background); + if (((!p->widthValid() || !extra.isAllocated() || !extra->hasBackgroundWidth) && qFuzzyIsNull(background->x())) + || (extra.isAllocated() && (extra->hasLeftInset || extra->hasRightInset))) { + background->setX(getLeftInset()); + background->setWidth(width - getLeftInset() - getRightInset()); + } + if (((!p->heightValid() || !extra.isAllocated() || !extra->hasBackgroundHeight) && qFuzzyIsNull(background->y())) + || (extra.isAllocated() && (extra->hasTopInset || extra->hasBottomInset))) { + background->setY(getTopInset()); + background->setHeight(height - getTopInset() - getBottomInset()); + } + + resizingBackground = false; +} + +/*! + \internal + + Determine which font is implicitly imposed on this control by its ancestors + and QGuiApplication::font, resolve this against its own font (attributes from + the implicit font are copied over). Then propagate this font to this + control's children. +*/ +void QQuickLabelPrivate::resolveFont() +{ + Q_Q(QQuickLabel); + inheritFont(QQuickControlPrivate::parentFont(q)); +} + +void QQuickLabelPrivate::inheritFont(const QFont &font) +{ + QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font; + parentFont.setResolveMask(extra.isAllocated() ? extra->requestedFont.resolveMask() | font.resolveMask() : font.resolveMask()); + + const QFont defaultFont = QQuickTheme::font(QQuickTheme::Label); + QFont resolvedFont = parentFont.resolve(defaultFont); + + setFont_helper(resolvedFont); +} + +/*! + \internal + + Assign \a font to this control, and propagate it to all children. +*/ +void QQuickLabelPrivate::updateFont(const QFont &font) +{ + Q_Q(QQuickLabel); + QFont oldFont = sourceFont; + q->QQuickText::setFont(font); + + QQuickControlPrivate::updateFontRecur(q, font); + + if (oldFont != font) + emit q->fontChanged(); +} + +void QQuickLabelPrivate::textChanged(const QString &text) +{ +#if QT_CONFIG(accessibility) + maybeSetAccessibleName(text); +#else + Q_UNUSED(text); +#endif +} + +#if QT_CONFIG(accessibility) +void QQuickLabelPrivate::accessibilityActiveChanged(bool active) +{ + if (!active) + return; + + Q_Q(QQuickLabel); + QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); + Q_ASSERT(accessibleAttached); + accessibleAttached->setRole(effectiveAccessibleRole()); + maybeSetAccessibleName(text); +} + +QAccessible::Role QQuickLabelPrivate::accessibleRole() const +{ + return QAccessible::StaticText; +} + +void QQuickLabelPrivate::maybeSetAccessibleName(const QString &name) +{ + Q_Q(QQuickLabel); + auto accessibleAttached = qobject_cast<QQuickAccessibleAttached *>( + qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); + if (accessibleAttached) { + if (!accessibleAttached->wasNameExplicitlySet()) + accessibleAttached->setNameImplicitly(name); + } +} +#endif + +void QQuickLabelPrivate::cancelBackground() +{ + Q_Q(QQuickLabel); + quickCancelDeferred(q, backgroundName()); +} + +void QQuickLabelPrivate::executeBackground(bool complete) +{ + Q_Q(QQuickLabel); + if (background.wasExecuted()) + return; + + if (!background || complete) + quickBeginDeferred(q, backgroundName(), background); + if (complete) + quickCompleteDeferred(q, backgroundName(), background); +} + +void QQuickLabelPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) +{ + Q_UNUSED(diff); + if (resizingBackground || item != background || !change.sizeChange()) + return; + + QQuickItemPrivate *p = QQuickItemPrivate::get(item); + extra.value().hasBackgroundWidth = p->widthValid(); + extra.value().hasBackgroundHeight = p->heightValid(); + resizeBackground(); +} + +void QQuickLabelPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickLabel); + if (item == background) + emit q->implicitBackgroundWidthChanged(); +} + +void QQuickLabelPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickLabel); + if (item == background) + emit q->implicitBackgroundHeightChanged(); +} + +void QQuickLabelPrivate::itemDestroyed(QQuickItem *item) +{ + Q_Q(QQuickLabel); + if (item == background) { + background = nullptr; + emit q->implicitBackgroundWidthChanged(); + emit q->implicitBackgroundHeightChanged(); + } +} + +QPalette QQuickLabelPrivate::defaultPalette() const +{ + return QQuickTheme::palette(QQuickTheme::Label); +} + +QQuickLabel::QQuickLabel(QQuickItem *parent) + : QQuickText(*(new QQuickLabelPrivate), parent) +{ + Q_D(QQuickLabel); + QObjectPrivate::connect(this, &QQuickText::textChanged, d, &QQuickLabelPrivate::textChanged); +} + +QQuickLabel::~QQuickLabel() +{ + Q_D(QQuickLabel); + QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry); +} + +QFont QQuickLabel::font() const +{ + Q_D(const QQuickLabel); + QFont font = QQuickText::font(); + // The resolve mask should inherit from the requestedFont + font.setResolveMask(d->extra.value().requestedFont.resolveMask()); + return font; +} + +void QQuickLabel::setFont(const QFont &font) +{ + Q_D(QQuickLabel); + if (d->extra.value().requestedFont.resolveMask() == font.resolveMask() && d->extra.value().requestedFont == font) + return; + + d->extra.value().requestedFont = font; + d->resolveFont(); +} + +/*! + \qmlproperty Item QtQuick.Controls::Label::background + + This property holds the background item. + + \note If the background item has no explicit size specified, it automatically + follows the control's size. In most cases, there is no need to specify + width or height for a background item. + + \sa {Customizing Label} +*/ +QQuickItem *QQuickLabel::background() const +{ + QQuickLabelPrivate *d = const_cast<QQuickLabelPrivate *>(d_func()); + if (!d->background) + d->executeBackground(); + return d->background; +} + +void QQuickLabel::setBackground(QQuickItem *background) +{ + Q_D(QQuickLabel); + if (d->background == background) + return; + + if (!d->background.isExecuting()) + d->cancelBackground(); + + const qreal oldImplicitBackgroundWidth = implicitBackgroundWidth(); + const qreal oldImplicitBackgroundHeight = implicitBackgroundHeight(); + + if (d->extra.isAllocated()) { + d->extra.value().hasBackgroundWidth = false; + d->extra.value().hasBackgroundHeight = false; + } + + QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry); + QQuickControlPrivate::hideOldItem(d->background); + d->background = background; + + if (background) { + background->setParentItem(this); + if (qFuzzyIsNull(background->z())) + background->setZ(-1); + QQuickItemPrivate *p = QQuickItemPrivate::get(background); + if (p->widthValid() || p->heightValid()) { + d->extra.value().hasBackgroundWidth = p->widthValid(); + d->extra.value().hasBackgroundHeight = p->heightValid(); + } + if (isComponentComplete()) + d->resizeBackground(); + QQuickControlPrivate::addImplicitSizeListener(background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry); + } + + if (!qFuzzyCompare(oldImplicitBackgroundWidth, implicitBackgroundWidth())) + emit implicitBackgroundWidthChanged(); + if (!qFuzzyCompare(oldImplicitBackgroundHeight, implicitBackgroundHeight())) + emit implicitBackgroundHeightChanged(); + if (!d->background.isExecuting()) + emit backgroundChanged(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Label::implicitBackgroundWidth + \readonly + + This property holds the implicit background width. + + The value is equal to \c {background ? background.implicitWidth : 0}. + + \sa implicitBackgroundHeight +*/ +qreal QQuickLabel::implicitBackgroundWidth() const +{ + Q_D(const QQuickLabel); + if (!d->background) + return 0; + return d->background->implicitWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Label::implicitBackgroundHeight + \readonly + + This property holds the implicit background height. + + The value is equal to \c {background ? background.implicitHeight : 0}. + + \sa implicitBackgroundWidth +*/ +qreal QQuickLabel::implicitBackgroundHeight() const +{ + Q_D(const QQuickLabel); + if (!d->background) + return 0; + return d->background->implicitHeight(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Label::topInset + + This property holds the top inset for the background. + + \sa {Control Layout}, bottomInset +*/ +qreal QQuickLabel::topInset() const +{ + Q_D(const QQuickLabel); + return d->getTopInset(); +} + +void QQuickLabel::setTopInset(qreal inset) +{ + Q_D(QQuickLabel); + d->setTopInset(inset); +} + +void QQuickLabel::resetTopInset() +{ + Q_D(QQuickLabel); + d->setTopInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Label::leftInset + + This property holds the left inset for the background. + + \sa {Control Layout}, rightInset +*/ +qreal QQuickLabel::leftInset() const +{ + Q_D(const QQuickLabel); + return d->getLeftInset(); +} + +void QQuickLabel::setLeftInset(qreal inset) +{ + Q_D(QQuickLabel); + d->setLeftInset(inset); +} + +void QQuickLabel::resetLeftInset() +{ + Q_D(QQuickLabel); + d->setLeftInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Label::rightInset + + This property holds the right inset for the background. + + \sa {Control Layout}, leftInset +*/ +qreal QQuickLabel::rightInset() const +{ + Q_D(const QQuickLabel); + return d->getRightInset(); +} + +void QQuickLabel::setRightInset(qreal inset) +{ + Q_D(QQuickLabel); + d->setRightInset(inset); +} + +void QQuickLabel::resetRightInset() +{ + Q_D(QQuickLabel); + d->setRightInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Label::bottomInset + + This property holds the bottom inset for the background. + + \sa {Control Layout}, topInset +*/ +qreal QQuickLabel::bottomInset() const +{ + Q_D(const QQuickLabel); + return d->getBottomInset(); +} + +void QQuickLabel::setBottomInset(qreal inset) +{ + Q_D(QQuickLabel); + d->setBottomInset(inset); +} + +void QQuickLabel::resetBottomInset() +{ + Q_D(QQuickLabel); + d->setBottomInset(0, true); +} + +void QQuickLabel::classBegin() +{ + Q_D(QQuickLabel); + QQuickText::classBegin(); + d->resolveFont(); +} + +void QQuickLabel::componentComplete() +{ + Q_D(QQuickLabel); + d->executeBackground(true); + QQuickText::componentComplete(); + d->resizeBackground(); +#if QT_CONFIG(accessibility) + if (QAccessible::isActive()) + d->accessibilityActiveChanged(true); +#endif +} + +void QQuickLabel::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) +{ + Q_D(QQuickLabel); + QQuickText::itemChange(change, value); + switch (change) { + case ItemEnabledHasChanged: + break; + case ItemSceneChange: + case ItemParentHasChanged: + if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) { + d->resolveFont(); + } + break; + default: + break; + } +} + +void QQuickLabel::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + Q_D(QQuickLabel); + QQuickText::geometryChange(newGeometry, oldGeometry); + d->resizeBackground(); +} + +void QQuickLabel::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset) +{ + Q_D(QQuickLabel); + Q_UNUSED(newInset); + Q_UNUSED(oldInset); + d->resizeBackground(); +} + +QT_END_NAMESPACE + +#include "moc_qquicklabel_p.cpp" |