diff options
Diffstat (limited to 'src/quicktemplates2')
105 files changed, 5156 insertions, 1147 deletions
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index 47ed0fff..dd38b80e 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -357,6 +357,22 @@ void QQuickAbstractButtonPrivate::executeIndicator(bool complete) quickCompleteDeferred(q, indicatorName(), indicator); } +void QQuickAbstractButtonPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickAbstractButton); + QQuickControlPrivate::itemImplicitWidthChanged(item); + if (item == indicator) + emit q->implicitIndicatorWidthChanged(); +} + +void QQuickAbstractButtonPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickAbstractButton); + QQuickControlPrivate::itemImplicitHeightChanged(item); + if (item == indicator) + emit q->implicitIndicatorHeightChanged(); +} + QQuickAbstractButton *QQuickAbstractButtonPrivate::findCheckedButton() const { Q_Q(const QQuickAbstractButton); @@ -427,6 +443,7 @@ QQuickAbstractButton::QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQui QQuickAbstractButton::~QQuickAbstractButton() { Q_D(QQuickAbstractButton); + d->removeImplicitSizeListener(d->indicator); if (d->group) d->group->removeButton(this); d->ungrabShortcut(); @@ -675,13 +692,24 @@ void QQuickAbstractButton::setIndicator(QQuickItem *indicator) if (!d->indicator.isExecuting()) d->cancelIndicator(); + const qreal oldImplicitIndicatorWidth = implicitIndicatorWidth(); + const qreal oldImplicitIndicatorHeight = implicitIndicatorHeight(); + + d->removeImplicitSizeListener(d->indicator); delete d->indicator; d->indicator = indicator; + if (indicator) { if (!indicator->parentItem()) indicator->setParentItem(this); indicator->setAcceptedMouseButtons(Qt::LeftButton); + d->addImplicitSizeListener(indicator); } + + if (!qFuzzyCompare(oldImplicitIndicatorWidth, implicitIndicatorWidth())) + emit implicitIndicatorWidthChanged(); + if (!qFuzzyCompare(oldImplicitIndicatorHeight, implicitIndicatorHeight())) + emit implicitIndicatorHeightChanged(); if (!d->indicator.isExecuting()) emit indicatorChanged(); } @@ -909,6 +937,50 @@ qreal QQuickAbstractButton::pressY() const } /*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::AbstractButton::implicitIndicatorWidth + \readonly + + This property holds the implicit indicator width. + + The value is equal to \c {indicator ? indicator.implicitWidth : 0}. + + This is typically used, together with \l {Control::}{implicitContentWidth} and + \l {Control::}{implicitBackgroundWidth}, to calculate the \l {Item::}{implicitWidth}. + + \sa implicitIndicatorHeight +*/ +qreal QQuickAbstractButton::implicitIndicatorWidth() const +{ + Q_D(const QQuickAbstractButton); + if (!d->indicator) + return 0; + return d->indicator->implicitWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::AbstractButton::implicitIndicatorHeight + \readonly + + This property holds the implicit indicator height. + + The value is equal to \c {indicator ? indicator.implicitHeight : 0}. + + This is typically used, together with \l {Control::}{implicitContentHeight} and + \l {Control::}{implicitBackgroundHeight}, to calculate the \l {Item::}{implicitHeight}. + + \sa implicitIndicatorWidth +*/ +qreal QQuickAbstractButton::implicitIndicatorHeight() const +{ + Q_D(const QQuickAbstractButton); + if (!d->indicator) + return 0; + return d->indicator->implicitHeight(); +} + +/*! \qmlmethod void QtQuick.Controls::AbstractButton::toggle() Toggles the checked state of the button. diff --git a/src/quicktemplates2/qquickabstractbutton_p.h b/src/quicktemplates2/qquickabstractbutton_p.h index de0c26ab..0fa48980 100644 --- a/src/quicktemplates2/qquickabstractbutton_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p.h @@ -76,6 +76,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButton : public QQuickContr Q_PROPERTY(int autoRepeatInterval READ autoRepeatInterval WRITE setAutoRepeatInterval NOTIFY autoRepeatIntervalChanged FINAL REVISION 4) Q_PROPERTY(qreal pressX READ pressX NOTIFY pressXChanged FINAL REVISION 4) Q_PROPERTY(qreal pressY READ pressY NOTIFY pressYChanged FINAL REVISION 4) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal implicitIndicatorWidth READ implicitIndicatorWidth NOTIFY implicitIndicatorWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitIndicatorHeight READ implicitIndicatorHeight NOTIFY implicitIndicatorHeightChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background,contentItem,indicator") public: @@ -141,6 +144,10 @@ public: qreal pressX() const; qreal pressY() const; + // 2.5 (Qt 5.12) + qreal implicitIndicatorWidth() const; + qreal implicitIndicatorHeight() const; + public Q_SLOTS: void toggle(); @@ -170,6 +177,9 @@ Q_SIGNALS: Q_REVISION(4) void autoRepeatIntervalChanged(); Q_REVISION(4) void pressXChanged(); Q_REVISION(4) void pressYChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void implicitIndicatorWidthChanged(); + Q_REVISION(5) void implicitIndicatorHeightChanged(); protected: QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQuickItem *parent); diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h index 1b3b59ba..718498a8 100644 --- a/src/quicktemplates2/qquickabstractbutton_p_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p_p.h @@ -103,6 +103,9 @@ public: void cancelIndicator(); void executeIndicator(bool complete = false); + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + // copied from qabstractbutton.cpp static const int AUTO_REPEAT_DELAY = 300; static const int AUTO_REPEAT_INTERVAL = 100; diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp index be28cb2a..f5d80fb9 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -35,6 +35,7 @@ ****************************************************************************/ #include "qquickapplicationwindow_p.h" +#include "qquickcontentitem_p.h" #include "qquickoverlay_p.h" #include "qquickpopup_p_p.h" #include "qquickcontrol_p_p.h" @@ -128,6 +129,8 @@ public: return window->d_func(); } + QQmlListProperty<QObject> contentData(); + void relayout(); void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; @@ -262,7 +265,7 @@ void QQuickApplicationWindowPrivate::updateFont(const QFont &f) void QQuickApplicationWindowPrivate::resolveFont() { - QFont resolvedFont = font.resolve(QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont)); + QFont resolvedFont = font.resolve(QQuickTheme::font(QQuickTheme::System)); setFont_helper(resolvedFont); } @@ -284,7 +287,7 @@ void QQuickApplicationWindowPrivate::updatePalette(const QPalette &p) void QQuickApplicationWindowPrivate::resolvePalette() { - QPalette resolvedPalette = palette.resolve(QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette)); + QPalette resolvedPalette = palette.resolve(QQuickTheme::palette(QQuickTheme::System)); setPalette_helper(resolvedPalette); } @@ -548,9 +551,10 @@ void QQuickApplicationWindow::setFooter(QQuickItem *footer) \sa contentItem */ -QQmlListProperty<QObject> QQuickApplicationWindow::contentData() +QQmlListProperty<QObject> QQuickApplicationWindowPrivate::contentData() { - return QQmlListProperty<QObject>(contentItem(), this, + Q_Q(QQuickApplicationWindow); + return QQmlListProperty<QObject>(q->contentItem(), q, QQuickApplicationWindowPrivate::contentData_append, QQuickItemPrivate::data_count, QQuickItemPrivate::data_at, @@ -572,7 +576,7 @@ QQuickItem *QQuickApplicationWindow::contentItem() const { QQuickApplicationWindowPrivate *d = const_cast<QQuickApplicationWindowPrivate *>(d_func()); if (!d->contentItem) { - d->contentItem = new QQuickItem(QQuickWindow::contentItem()); + d->contentItem = new QQuickContentItem(this, QQuickWindow::contentItem()); d->contentItem->setFlag(QQuickItem::ItemIsFocusScope); d->contentItem->setFocus(true); d->relayout(); @@ -679,7 +683,7 @@ void QQuickApplicationWindow::setFont(const QFont &font) if (d->font.resolve() == font.resolve() && d->font == font) return; - QFont resolvedFont = font.resolve(QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont)); + QFont resolvedFont = font.resolve(QQuickTheme::font(QQuickTheme::System)); d->setFont_helper(resolvedFont); } @@ -758,7 +762,7 @@ void QQuickApplicationWindow::setPalette(const QPalette &palette) if (d->palette.resolve() == palette.resolve() && d->palette == palette) return; - QPalette resolvedPalette = palette.resolve(QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette)); + QPalette resolvedPalette = palette.resolve(QQuickTheme::palette(QQuickTheme::System)); d->setPalette_helper(resolvedPalette); } diff --git a/src/quicktemplates2/qquickapplicationwindow_p.h b/src/quicktemplates2/qquickapplicationwindow_p.h index d74d3c9d..c004ee3a 100644 --- a/src/quicktemplates2/qquickapplicationwindow_p.h +++ b/src/quicktemplates2/qquickapplicationwindow_p.h @@ -66,7 +66,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickApplicationWindow : public QQuickWi Q_OBJECT Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL) Q_PROPERTY(QQuickItem *contentItem READ contentItem CONSTANT FINAL) - Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) + Q_PRIVATE_PROPERTY(QQuickApplicationWindow::d_func(), QQmlListProperty<QObject> contentData READ contentData FINAL) Q_PROPERTY(QQuickItem *activeFocusControl READ activeFocusControl NOTIFY activeFocusControlChanged FINAL) Q_PROPERTY(QQuickItem *header READ header WRITE setHeader NOTIFY headerChanged FINAL) Q_PROPERTY(QQuickItem *footer READ footer WRITE setFooter NOTIFY footerChanged FINAL) @@ -89,7 +89,6 @@ public: void setBackground(QQuickItem *background); QQuickItem *contentItem() const; - QQmlListProperty<QObject> contentData(); QQuickItem *activeFocusControl() const; diff --git a/src/quicktemplates2/qquickbutton.cpp b/src/quicktemplates2/qquickbutton.cpp index 74b78408..fbce5225 100644 --- a/src/quicktemplates2/qquickbutton.cpp +++ b/src/quicktemplates2/qquickbutton.cpp @@ -96,12 +96,12 @@ QQuickButton::QQuickButton(QQuickButtonPrivate &dd, QQuickItem *parent) QFont QQuickButton::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::PushButtonFont); + return QQuickTheme::font(QQuickTheme::Button); } QPalette QQuickButton::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::ButtonPalette); + return QQuickTheme::palette(QQuickTheme::Button); } /*! diff --git a/src/quicktemplates2/qquickcheckbox.cpp b/src/quicktemplates2/qquickcheckbox.cpp index 1f66966c..461fae30 100644 --- a/src/quicktemplates2/qquickcheckbox.cpp +++ b/src/quicktemplates2/qquickcheckbox.cpp @@ -183,12 +183,12 @@ void QQuickCheckBox::setCheckState(Qt::CheckState state) QFont QQuickCheckBox::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::CheckBoxFont); + return QQuickTheme::font(QQuickTheme::CheckBox); } QPalette QQuickCheckBox::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::CheckBoxPalette); + return QQuickTheme::palette(QQuickTheme::CheckBox); } void QQuickCheckBox::buttonChange(ButtonChange change) diff --git a/src/quicktemplates2/qquickcheckdelegate.cpp b/src/quicktemplates2/qquickcheckdelegate.cpp index f02c0bfa..17f1f0b2 100644 --- a/src/quicktemplates2/qquickcheckdelegate.cpp +++ b/src/quicktemplates2/qquickcheckdelegate.cpp @@ -170,7 +170,12 @@ void QQuickCheckDelegate::setCheckState(Qt::CheckState state) QFont QQuickCheckDelegate::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::ListViewFont); + return QQuickTheme::font(QQuickTheme::ListView); +} + +QPalette QQuickCheckDelegate::defaultPalette() const +{ + return QQuickTheme::palette(QQuickTheme::ListView); } void QQuickCheckDelegate::buttonChange(ButtonChange change) diff --git a/src/quicktemplates2/qquickcheckdelegate_p.h b/src/quicktemplates2/qquickcheckdelegate_p.h index 67dcf706..2d5a5cb2 100644 --- a/src/quicktemplates2/qquickcheckdelegate_p.h +++ b/src/quicktemplates2/qquickcheckdelegate_p.h @@ -79,6 +79,7 @@ Q_SIGNALS: protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; void buttonChange(ButtonChange change) override; void nextCheckState() override; diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index f7b5f157..77abee07 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -261,6 +261,9 @@ public: void cancelPopup(); void executePopup(bool complete = false); + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + bool flat = false; bool down = false; bool hasDown = false; @@ -724,6 +727,22 @@ void QQuickComboBoxPrivate::executePopup(bool complete) quickCompleteDeferred(q, popupName(), popup); } +void QQuickComboBoxPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickComboBox); + QQuickControlPrivate::itemImplicitWidthChanged(item); + if (item == indicator) + emit q->implicitIndicatorWidthChanged(); +} + +void QQuickComboBoxPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickComboBox); + QQuickControlPrivate::itemImplicitHeightChanged(item); + if (item == indicator) + emit q->implicitIndicatorHeightChanged(); +} + QQuickComboBox::QQuickComboBox(QQuickItem *parent) : QQuickControl(*(new QQuickComboBoxPrivate), parent) { @@ -739,6 +758,7 @@ QQuickComboBox::QQuickComboBox(QQuickItem *parent) QQuickComboBox::~QQuickComboBox() { Q_D(QQuickComboBox); + d->removeImplicitSizeListener(d->indicator); if (d->popup) { // Disconnect visibleChanged() to avoid a spurious highlightedIndexChanged() signal // emission during the destruction of the (visible) popup. (QTBUG-57650) @@ -1047,12 +1067,22 @@ void QQuickComboBox::setIndicator(QQuickItem *indicator) if (!d->indicator.isExecuting()) d->cancelIndicator(); + const qreal oldImplicitIndicatorWidth = implicitIndicatorWidth(); + const qreal oldImplicitIndicatorHeight = implicitIndicatorHeight(); + + d->removeImplicitSizeListener(d->indicator); delete d->indicator; d->indicator = indicator; if (indicator) { if (!indicator->parentItem()) indicator->setParentItem(this); + d->addImplicitSizeListener(indicator); } + + if (!qFuzzyCompare(oldImplicitIndicatorWidth, implicitIndicatorWidth())) + emit implicitIndicatorWidthChanged(); + if (!qFuzzyCompare(oldImplicitIndicatorHeight, implicitIndicatorHeight())) + emit implicitIndicatorHeightChanged(); if (!d->indicator.isExecuting()) emit indicatorChanged(); } @@ -1364,6 +1394,50 @@ bool QQuickComboBox::hasAcceptableInput() const } /*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::ComboBox::implicitIndicatorWidth + \readonly + + This property holds the implicit indicator width. + + The value is equal to \c {indicator ? indicator.implicitWidth : 0}. + + This is typically used, together with \l {Control::}{implicitContentWidth} and + \l {Control::}{implicitBackgroundWidth}, to calculate the \l {Item::}{implicitWidth}. + + \sa implicitIndicatorHeight +*/ +qreal QQuickComboBox::implicitIndicatorWidth() const +{ + Q_D(const QQuickComboBox); + if (!d->indicator) + return 0; + return d->indicator->implicitWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::ComboBox::implicitIndicatorHeight + \readonly + + This property holds the implicit indicator height. + + The value is equal to \c {indicator ? indicator.implicitHeight : 0}. + + This is typically used, together with \l {Control::}{implicitContentHeight} and + \l {Control::}{implicitBackgroundHeight}, to calculate the \l {Item::}{implicitHeight}. + + \sa implicitIndicatorWidth +*/ +qreal QQuickComboBox::implicitIndicatorHeight() const +{ + Q_D(const QQuickComboBox); + if (!d->indicator) + return 0; + return d->indicator->implicitHeight(); +} + +/*! \qmlmethod string QtQuick.Controls::ComboBox::textAt(int index) Returns the text for the specified \a index, or an empty string @@ -1690,12 +1764,12 @@ void QQuickComboBox::localeChange(const QLocale &newLocale, const QLocale &oldLo QFont QQuickComboBox::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::ComboMenuItemFont); + return QQuickTheme::font(QQuickTheme::ComboBox); } QPalette QQuickComboBox::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::ComboBoxPalette); + return QQuickTheme::palette(QQuickTheme::ComboBox); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickcombobox_p.h b/src/quicktemplates2/qquickcombobox_p.h index 2faff745..75e535a9 100644 --- a/src/quicktemplates2/qquickcombobox_p.h +++ b/src/quicktemplates2/qquickcombobox_p.h @@ -82,6 +82,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickComboBox : public QQuickControl Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged FINAL REVISION 2) Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged FINAL REVISION 2) Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged FINAL REVISION 2) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal implicitIndicatorWidth READ implicitIndicatorWidth NOTIFY implicitIndicatorWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitIndicatorHeight READ implicitIndicatorHeight NOTIFY implicitIndicatorHeightChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background,contentItem,indicator,popup") public: @@ -148,6 +151,10 @@ public: bool isInputMethodComposing() const; bool hasAcceptableInput() const; + // 2.5 (Qt 5.12) + qreal implicitIndicatorWidth() const; + qreal implicitIndicatorHeight() const; + public Q_SLOTS: void incrementCurrentIndex(); void decrementCurrentIndex(); @@ -179,6 +186,9 @@ Q_SIGNALS: Q_REVISION(2) void inputMethodHintsChanged(); Q_REVISION(2) void inputMethodComposingChanged(); Q_REVISION(2) void acceptableInputChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void implicitIndicatorWidthChanged(); + Q_REVISION(5) void implicitIndicatorHeightChanged(); protected: bool eventFilter(QObject *object, QEvent *event) override; diff --git a/src/quicktemplates2/qquickcontainer.cpp b/src/quicktemplates2/qquickcontainer.cpp index 3dfefdc0..6015eca7 100644 --- a/src/quicktemplates2/qquickcontainer.cpp +++ b/src/quicktemplates2/qquickcontainer.cpp @@ -198,6 +198,8 @@ void QQuickContainerPrivate::init() contentModel = new QQmlObjectModel(q); QObject::connect(contentModel, &QQmlObjectModel::countChanged, q, &QQuickContainer::countChanged); QObject::connect(contentModel, &QQmlObjectModel::childrenChanged, q, &QQuickContainer::contentChildrenChanged); + connect(q, &QQuickControl::implicitContentWidthChanged, this, &QQuickContainerPrivate::updateContentWidth); + connect(q, &QQuickControl::implicitContentHeightChanged, this, &QQuickContainerPrivate::updateContentHeight); } void QQuickContainerPrivate::cleanup() @@ -369,6 +371,8 @@ void QQuickContainerPrivate::itemDestroyed(QQuickItem *item) int index = contentModel->indexOf(item, nullptr); if (index != -1) removeItem(index, item); + else + QQuickControlPrivate::itemDestroyed(item); } void QQuickContainerPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj) @@ -428,6 +432,26 @@ void QQuickContainerPrivate::contentChildren_clear(QQmlListProperty<QQuickItem> return QQuickContainerPrivate::get(q)->contentModel->clear(); } +void QQuickContainerPrivate::updateContentWidth() +{ + Q_Q(QQuickContainer); + if (hasContentWidth || qFuzzyCompare(contentWidth, implicitContentWidth)) + return; + + contentWidth = implicitContentWidth; + emit q->contentWidthChanged(); +} + +void QQuickContainerPrivate::updateContentHeight() +{ + Q_Q(QQuickContainer); + if (hasContentHeight || qFuzzyCompare(contentHeight, implicitContentHeight)) + return; + + contentHeight = implicitContentHeight; + emit q->contentHeightChanged(); +} + QQuickContainer::QQuickContainer(QQuickItem *parent) : QQuickControl(*(new QQuickContainerPrivate), parent) { @@ -743,6 +767,84 @@ QQuickItem *QQuickContainer::currentItem() const return itemAt(d->currentIndex); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Container::contentWidth + + This property holds the content width. It is used for calculating the total + implicit width of the container. + + Unless explicitly overridden, the content width is automatically calculated + based on the implicit width of the items in the container. + + \sa contentHeight +*/ +qreal QQuickContainer::contentWidth() const +{ + Q_D(const QQuickContainer); + return d->contentWidth; +} + +void QQuickContainer::setContentWidth(qreal width) +{ + Q_D(QQuickContainer); + d->hasContentWidth = true; + if (qFuzzyCompare(d->contentWidth, width)) + return; + + d->contentWidth = width; + emit contentWidthChanged(); +} + +void QQuickContainer::resetContentWidth() +{ + Q_D(QQuickContainer); + if (!d->hasContentWidth) + return; + + d->hasContentWidth = false; + d->updateContentWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Container::contentHeight + + This property holds the content height. It is used for calculating the total + implicit height of the container. + + Unless explicitly overridden, the content height is automatically calculated + based on the implicit height of the items in the container. + + \sa contentWidth +*/ +qreal QQuickContainer::contentHeight() const +{ + Q_D(const QQuickContainer); + return d->contentHeight; +} + +void QQuickContainer::setContentHeight(qreal height) +{ + Q_D(QQuickContainer); + d->hasContentHeight = true; + if (qFuzzyCompare(d->contentHeight, height)) + return; + + d->contentHeight = height; + emit contentHeightChanged(); +} + +void QQuickContainer::resetContentHeight() +{ + Q_D(QQuickContainer); + if (!d->hasContentHeight) + return; + + d->hasContentHeight = false; + d->updateContentHeight(); +} + void QQuickContainer::componentComplete() { Q_D(QQuickContainer); @@ -768,7 +870,7 @@ void QQuickContainer::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem static const int slotIndex = metaObject()->indexOfSlot("_q_currentIndexChanged()"); if (oldItem) { - QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Children); + QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Children | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight); QQuickItem *oldContentItem = effectiveContentItem(oldItem); if (oldContentItem != oldItem) QQuickItemPrivate::get(oldContentItem)->removeItemChangeListener(d, QQuickItemPrivate::Children); @@ -779,7 +881,7 @@ void QQuickContainer::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem } if (newItem) { - QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Children); + QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Children | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight); QQuickItem *newContentItem = effectiveContentItem(newItem); if (newContentItem != newItem) QQuickItemPrivate::get(newContentItem)->addItemChangeListener(d, QQuickItemPrivate::Children); diff --git a/src/quicktemplates2/qquickcontainer_p.h b/src/quicktemplates2/qquickcontainer_p.h index 030497cf..310aacd1 100644 --- a/src/quicktemplates2/qquickcontainer_p.h +++ b/src/quicktemplates2/qquickcontainer_p.h @@ -64,6 +64,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickContainer : public QQuickControl Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL) Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL) Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged FINAL) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL REVISION 5) Q_CLASSINFO("DefaultProperty", "contentData") public: @@ -87,6 +90,15 @@ public: int currentIndex() const; QQuickItem *currentItem() const; + // 2.5 (Qt 5.12) + qreal contentWidth() const; + void setContentWidth(qreal width); + void resetContentWidth(); + + qreal contentHeight() const; + void setContentHeight(qreal height); + void resetContentHeight(); + public Q_SLOTS: void setCurrentIndex(int index); // 2.1 (Qt 5.8) @@ -98,6 +110,9 @@ Q_SIGNALS: void contentChildrenChanged(); void currentIndexChanged(); void currentItemChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void contentWidthChanged(); + Q_REVISION(5) void contentHeightChanged(); protected: QQuickContainer(QQuickContainerPrivate &dd, QQuickItem *parent); diff --git a/src/quicktemplates2/qquickcontainer_p_p.h b/src/quicktemplates2/qquickcontainer_p_p.h index 4e53aa8f..16e9c9f6 100644 --- a/src/quicktemplates2/qquickcontainer_p_p.h +++ b/src/quicktemplates2/qquickcontainer_p_p.h @@ -50,12 +50,11 @@ #include <QtQuickTemplates2/private/qquickcontainer_p.h> #include <QtQuickTemplates2/private/qquickcontrol_p_p.h> -#include <QtQuick/private/qquickitemchangelistener_p.h> #include <QtQml/private/qqmlobjectmodel_p.h> QT_BEGIN_NAMESPACE -class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickContainerPrivate : public QQuickControlPrivate, public QQuickItemChangeListener +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickContainerPrivate : public QQuickControlPrivate { Q_DECLARE_PUBLIC(QQuickContainer) @@ -91,6 +90,13 @@ public: static QQuickItem *contentChildren_at(QQmlListProperty<QQuickItem> *prop, int index); static void contentChildren_clear(QQmlListProperty<QQuickItem> *prop); + void updateContentWidth(); + void updateContentHeight(); + + bool hasContentWidth = false; + bool hasContentHeight = false; + qreal contentWidth = 0; + qreal contentHeight = 0; QObjectList contentData; QQmlObjectModel *contentModel = nullptr; int currentIndex = -1; diff --git a/src/quicktemplates2/qquickcontentitem.cpp b/src/quicktemplates2/qquickcontentitem.cpp new file mode 100644 index 00000000..95665f70 --- /dev/null +++ b/src/quicktemplates2/qquickcontentitem.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickcontentitem_p.h" + +#include <QtQml/private/qqmlmetatype_p.h> + +QT_BEGIN_NAMESPACE + +/*! + \internal + + Helper class that aids debugging by producing more useful debugging output. +*/ + +QQuickContentItem::QQuickContentItem(QQuickItem *parent) + : QQuickItem(parent) +{ + setObjectName(QQmlMetaType::prettyTypeName(parent)); +} + +QQuickContentItem::QQuickContentItem(const QObject *scope, QQuickItem *parent) + : QQuickItem(parent) +{ + setObjectName(QQmlMetaType::prettyTypeName(scope)); +} + +QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickcontentitem_p.h b/src/quicktemplates2/qquickcontentitem_p.h new file mode 100644 index 00000000..df0f0b24 --- /dev/null +++ b/src/quicktemplates2/qquickcontentitem_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKCONTENTITEM_P_H +#define QQUICKCONTENTITEM_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuick/qquickitem.h> +#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> + +QT_BEGIN_NAMESPACE + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickContentItem : public QQuickItem +{ + Q_OBJECT + +public: + explicit QQuickContentItem(QQuickItem *parent = nullptr); + explicit QQuickContentItem(const QObject *scope, QQuickItem *parent); + +private: + Q_DISABLE_COPY(QQuickContentItem) +}; + +QT_END_NAMESPACE + +#endif // QQUICKCONTENTITEM_P_H diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index 28e8c429..38f3212a 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -50,9 +50,6 @@ #include "qquickapplicationwindow_p.h" #include "qquickdeferredexecute_p_p.h" -#include <QtGui/private/qguiapplication_p.h> -#include <QtGui/qpa/qplatformtheme.h> - #if QT_CONFIG(accessibility) #include <QtQuick/private/qquickaccessibleattached_p.h> #endif @@ -79,15 +76,48 @@ QT_BEGIN_NAMESPACE The \l {Item::}{implicitWidth} and \l {Item::}{implicitHeight} of a control are typically based on the implicit sizes of the background and the content - item plus any \l {Control::}{padding}. These properties determine how large + item plus any insets and paddings. These properties determine how large the control will be when no explicit \l {Item::}{width} or \l {Item::}{height} is specified. + The geometry of the \l {Control::}{contentItem} is determined by the padding. + The following example reserves 10px padding between the boundaries of the + control and its content: + + \code + Control { + padding: 10 + + contentItem: Text { + text: "Content" + } + } + \endcode + The \l {Control::}{background} item fills the entire width and height of the - control, unless an explicit size has been given for it. + control, unless insets or an explicit size have been given for it. Background + insets are useful for extending the touchable/interactive area of a control + without affecting its visual size. This is often used on touch devices to + ensure that a control is not too small to be interacted with by the user. + Insets affect the size of the control, and hence will affect how much space + they take up in a layout, for example. - The geometry of the \l {Control::}{contentItem} is determined by the - padding. + Negative insets can be used to make the background larger than the control. + The following example uses negative insets to place a shadow outside the + control's boundaries: + + \code + Control { + topInset: -2 + leftInset: -2 + rightInset: -6 + bottomInset: -6 + + background: BorderImage { + source: ":/images/shadowed-background.png" + } + } + \endcode \section1 Event Handling @@ -100,6 +130,8 @@ QT_BEGIN_NAMESPACE \sa ApplicationWindow, Container */ +const QQuickItemPrivate::ChangeTypes QQuickControlPrivate::ImplicitSizeChanges = QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed; + static bool isKeyFocusReason(Qt::FocusReason reason) { return reason == Qt::TabFocusReason || reason == Qt::BacktabFocusReason || reason == Qt::ShortcutFocusReason; @@ -119,6 +151,12 @@ QQuickControlPrivate::~QQuickControlPrivate() #endif } +void QQuickControlPrivate::init() +{ + Q_Q(QQuickControl); + QObject::connect(q, &QQuickItem::baselineOffsetChanged, q, &QQuickControl::baselineOffsetChanged); +} + #if QT_CONFIG(quicktemplates2_multitouch) bool QQuickControlPrivate::acceptTouch(const QTouchEvent::TouchPoint &point) { @@ -182,75 +220,163 @@ void QQuickControlPrivate::mirrorChange() void QQuickControlPrivate::setTopPadding(qreal value, bool reset) { Q_Q(QQuickControl); - qreal oldPadding = q->topPadding(); - topPadding = value; - hasTopPadding = !reset; - if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + const QMarginsF oldPadding = getPadding(); + extra.value().topPadding = value; + extra.value().hasTopPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding.top(), value)) || (reset && !qFuzzyCompare(oldPadding.top(), getVerticalPadding()))) { emit q->topPaddingChanged(); emit q->availableHeightChanged(); - q->paddingChange(QMarginsF(leftPadding, topPadding, rightPadding, bottomPadding), - QMarginsF(leftPadding, oldPadding, rightPadding, bottomPadding)); + q->paddingChange(getPadding(), oldPadding); } } void QQuickControlPrivate::setLeftPadding(qreal value, bool reset) { Q_Q(QQuickControl); - qreal oldPadding = q->leftPadding(); - leftPadding = value; - hasLeftPadding = !reset; - if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + const QMarginsF oldPadding = getPadding(); + extra.value().leftPadding = value; + extra.value().hasLeftPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding.left(), value)) || (reset && !qFuzzyCompare(oldPadding.left(), getHorizontalPadding()))) { emit q->leftPaddingChanged(); emit q->availableWidthChanged(); - q->paddingChange(QMarginsF(leftPadding, topPadding, rightPadding, bottomPadding), - QMarginsF(oldPadding, topPadding, rightPadding, bottomPadding)); + q->paddingChange(getPadding(), oldPadding); } } void QQuickControlPrivate::setRightPadding(qreal value, bool reset) { Q_Q(QQuickControl); - qreal oldPadding = q->rightPadding(); - rightPadding = value; - hasRightPadding = !reset; - if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + const QMarginsF oldPadding = getPadding(); + extra.value().rightPadding = value; + extra.value().hasRightPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding.right(), value)) || (reset && !qFuzzyCompare(oldPadding.right(), getHorizontalPadding()))) { emit q->rightPaddingChanged(); emit q->availableWidthChanged(); - q->paddingChange(QMarginsF(leftPadding, topPadding, rightPadding, bottomPadding), - QMarginsF(leftPadding, topPadding, oldPadding, bottomPadding)); + q->paddingChange(getPadding(), oldPadding); } } void QQuickControlPrivate::setBottomPadding(qreal value, bool reset) { Q_Q(QQuickControl); - qreal oldPadding = q->bottomPadding(); - bottomPadding = value; - hasBottomPadding = !reset; - if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + const QMarginsF oldPadding = getPadding(); + extra.value().bottomPadding = value; + extra.value().hasBottomPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding.bottom(), value)) || (reset && !qFuzzyCompare(oldPadding.bottom(), getVerticalPadding()))) { emit q->bottomPaddingChanged(); emit q->availableHeightChanged(); - q->paddingChange(QMarginsF(leftPadding, topPadding, rightPadding, bottomPadding), - QMarginsF(leftPadding, topPadding, rightPadding, oldPadding)); + q->paddingChange(getPadding(), oldPadding); } } -void QQuickControlPrivate::resizeBackground() +void QQuickControlPrivate::setHorizontalPadding(qreal value, bool reset) { Q_Q(QQuickControl); - if (background) { - QQuickItemPrivate *p = QQuickItemPrivate::get(background); - if (!p->widthValid && qFuzzyIsNull(background->x())) { - background->setWidth(q->width()); - p->widthValid = false; - } - if (!p->heightValid && qFuzzyIsNull(background->y())) { - background->setHeight(q->height()); - p->heightValid = false; - } + const QMarginsF oldPadding = getPadding(); + const qreal oldHorizontalPadding = getHorizontalPadding(); + horizontalPadding = value; + hasHorizontalPadding = !reset; + if ((!reset && !qFuzzyCompare(oldHorizontalPadding, value)) || (reset && !qFuzzyCompare(oldHorizontalPadding, padding))) { + const QMarginsF newPadding = getPadding(); + if (!qFuzzyCompare(newPadding.left(), oldPadding.left())) + emit q->leftPaddingChanged(); + if (!qFuzzyCompare(newPadding.right(), oldPadding.right())) + emit q->rightPaddingChanged(); + emit q->horizontalPaddingChanged(); + emit q->availableWidthChanged(); + q->paddingChange(newPadding, oldPadding); } } +void QQuickControlPrivate::setVerticalPadding(qreal value, bool reset) +{ + Q_Q(QQuickControl); + const QMarginsF oldPadding = getPadding(); + const qreal oldVerticalPadding = getVerticalPadding(); + verticalPadding = value; + hasVerticalPadding = !reset; + if ((!reset && !qFuzzyCompare(oldVerticalPadding, value)) || (reset && !qFuzzyCompare(oldVerticalPadding, padding))) { + const QMarginsF newPadding = getPadding(); + if (!qFuzzyCompare(newPadding.top(), oldPadding.top())) + emit q->topPaddingChanged(); + if (!qFuzzyCompare(newPadding.bottom(), oldPadding.bottom())) + emit q->bottomPaddingChanged(); + emit q->verticalPaddingChanged(); + emit q->availableHeightChanged(); + q->paddingChange(newPadding, oldPadding); + } +} + +void QQuickControlPrivate::setTopInset(qreal value, bool reset) +{ + Q_Q(QQuickControl); + 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 QQuickControlPrivate::setLeftInset(qreal value, bool reset) +{ + Q_Q(QQuickControl); + 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 QQuickControlPrivate::setRightInset(qreal value, bool reset) +{ + Q_Q(QQuickControl); + 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 QQuickControlPrivate::setBottomInset(qreal value, bool reset) +{ + Q_Q(QQuickControl); + 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 QQuickControlPrivate::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; +} + void QQuickControlPrivate::resizeContent() { Q_Q(QQuickControl); @@ -276,21 +402,73 @@ void QQuickControlPrivate::setContentItem_helper(QQuickItem *item, bool notify) if (!contentItem.isExecuting()) cancelContentItem(); - q->contentItemChange(item, contentItem); - delete contentItem; + QQuickItem *oldContentItem = contentItem; + if (oldContentItem) { + disconnect(oldContentItem, &QQuickItem::baselineOffsetChanged, this, &QQuickControlPrivate::updateBaselineOffset); + removeImplicitSizeListener(oldContentItem); + } + contentItem = item; + q->contentItemChange(item, oldContentItem); + delete oldContentItem; if (item) { + connect(contentItem, &QQuickItem::baselineOffsetChanged, this, &QQuickControlPrivate::updateBaselineOffset); if (!item->parentItem()) item->setParentItem(q); if (componentComplete) resizeContent(); + addImplicitSizeListener(contentItem); } + updateImplicitContentSize(); + updateBaselineOffset(); + if (notify && !contentItem.isExecuting()) emit q->contentItemChanged(); } +qreal QQuickControlPrivate::getContentWidth() const +{ + return contentItem ? contentItem->implicitWidth() : 0; +} + +qreal QQuickControlPrivate::getContentHeight() const +{ + return contentItem ? contentItem->implicitHeight() : 0; +} + +void QQuickControlPrivate::updateImplicitContentWidth() +{ + Q_Q(QQuickControl); + const qreal oldWidth = implicitContentWidth; + implicitContentWidth = getContentWidth(); + if (!qFuzzyCompare(implicitContentWidth, oldWidth)) + emit q->implicitContentWidthChanged(); +} + +void QQuickControlPrivate::updateImplicitContentHeight() +{ + Q_Q(QQuickControl); + const qreal oldHeight = implicitContentHeight; + implicitContentHeight = getContentHeight(); + if (!qFuzzyCompare(implicitContentHeight, oldHeight)) + emit q->implicitContentHeightChanged(); +} + +void QQuickControlPrivate::updateImplicitContentSize() +{ + Q_Q(QQuickControl); + const qreal oldWidth = implicitContentWidth; + const qreal oldHeight = implicitContentHeight; + implicitContentWidth = getContentWidth(); + implicitContentHeight = getContentHeight(); + if (!qFuzzyCompare(implicitContentWidth, oldWidth)) + emit q->implicitContentWidthChanged(); + if (!qFuzzyCompare(implicitContentHeight, oldHeight)) + emit q->implicitContentHeightChanged(); +} + #if QT_CONFIG(accessibility) void QQuickControlPrivate::accessibilityActiveChanged(bool active) { @@ -337,21 +515,7 @@ QFont QQuickControlPrivate::parentFont(const QQuickItem *item) if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(item->window())) return window->font(); - return themeFont(QPlatformTheme::SystemFont); -} - -QFont QQuickControlPrivate::themeFont(QPlatformTheme::Font type) -{ - if (QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { - if (const QFont *font = theme->font(type)) { - QFont f = *font; - if (type == QPlatformTheme::SystemFont) - f.resolve(0); - return f; - } - } - - return QFont(); + return QQuickTheme::font(QQuickTheme::System); } /*! @@ -442,21 +606,7 @@ QPalette QQuickControlPrivate::parentPalette(const QQuickItem *item) if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(item->window())) return window->palette(); - return themePalette(QPlatformTheme::SystemPalette); -} - -QPalette QQuickControlPrivate::themePalette(QPlatformTheme::Palette type) -{ - if (QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { - if (const QPalette *palette = theme->palette(type)) { - QPalette p = *palette; - if (type == QPlatformTheme::SystemPalette) - p.resolve(0); - return p; - } - } - - return QPalette(); + return QQuickTheme::palette(QQuickTheme::System); } /*! @@ -672,14 +822,108 @@ void QQuickControlPrivate::executeBackground(bool complete) quickCompleteDeferred(q, backgroundName(), background); } +void QQuickControlPrivate::updateBaselineOffset() +{ + Q_Q(QQuickControl); + if (extra.isAllocated() && extra.value().hasBaselineOffset) + return; + + if (!contentItem) + q->QQuickItem::setBaselineOffset(0); + else + q->QQuickItem::setBaselineOffset(getTopPadding() + contentItem->baselineOffset()); +} + +void QQuickControlPrivate::addImplicitSizeListener(QQuickItem *item, ChangeTypes changes) +{ + addImplicitSizeListener(item, this, changes); +} + +void QQuickControlPrivate::removeImplicitSizeListener(QQuickItem *item, ChangeTypes changes) +{ + removeImplicitSizeListener(item, this, changes); +} + +void QQuickControlPrivate::addImplicitSizeListener(QQuickItem *item, QQuickItemChangeListener *listener, ChangeTypes changes) +{ + if (!item || !listener) + return; + QQuickItemPrivate::get(item)->addItemChangeListener(listener, changes); +} + +void QQuickControlPrivate::removeImplicitSizeListener(QQuickItem *item, QQuickItemChangeListener *listener, ChangeTypes changes) +{ + if (!item || !listener) + return; + QQuickItemPrivate::get(item)->removeItemChangeListener(listener, changes); +} + +void QQuickControlPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickControl); + if (item == background) + emit q->implicitBackgroundWidthChanged(); + else if (item == contentItem) + updateImplicitContentWidth(); +} + +void QQuickControlPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickControl); + if (item == background) + emit q->implicitBackgroundHeightChanged(); + else if (item == contentItem) + updateImplicitContentHeight(); +} + +void QQuickControlPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) +{ + Q_UNUSED(diff); + if (resizingBackground || item != background || !change.sizeChange()) + return; + + QQuickItemPrivate *p = QQuickItemPrivate::get(item); + // Only set hasBackgroundWidth/Height if it was a width/height change, + // otherwise we're prevented from setting a width/height in the future. + if (change.widthChange()) + extra.value().hasBackgroundWidth = p->widthValid; + if (change.heightChange()) + extra.value().hasBackgroundHeight = p->heightValid; + resizeBackground(); +} + +void QQuickControlPrivate::itemDestroyed(QQuickItem *item) +{ + Q_Q(QQuickControl); + if (item == background) { + background = nullptr; + emit q->implicitBackgroundWidthChanged(); + emit q->implicitBackgroundHeightChanged(); + } else if (item == contentItem) { + contentItem = nullptr; + updateImplicitContentSize(); + } +} + QQuickControl::QQuickControl(QQuickItem *parent) : QQuickItem(*(new QQuickControlPrivate), parent) { + Q_D(QQuickControl); + d->init(); } QQuickControl::QQuickControl(QQuickControlPrivate &dd, QQuickItem *parent) : QQuickItem(dd, parent) { + Q_D(QQuickControl); + d->init(); +} + +QQuickControl::~QQuickControl() +{ + Q_D(QQuickControl); + d->removeImplicitSizeListener(d->background, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry); + d->removeImplicitSizeListener(d->contentItem); } void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) @@ -841,10 +1085,18 @@ void QQuickControl::setPadding(qreal padding) Q_D(QQuickControl); if (qFuzzyCompare(d->padding, padding)) return; - QMarginsF oldPadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); + + const QMarginsF oldPadding = d->getPadding(); + const qreal oldVerticalPadding = d->getVerticalPadding(); + const qreal oldHorizontalPadding = d->getHorizontalPadding(); + d->padding = padding; emit paddingChanged(); - QMarginsF newPadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); + + const QMarginsF newPadding = d->getPadding(); + const qreal newVerticalPadding = d->getVerticalPadding(); + const qreal newHorizontalPadding = d->getHorizontalPadding(); + if (!qFuzzyCompare(newPadding.top(), oldPadding.top())) emit topPaddingChanged(); if (!qFuzzyCompare(newPadding.left(), oldPadding.left())) @@ -853,10 +1105,15 @@ void QQuickControl::setPadding(qreal padding) emit rightPaddingChanged(); if (!qFuzzyCompare(newPadding.bottom(), oldPadding.bottom())) emit bottomPaddingChanged(); + if (!qFuzzyCompare(newVerticalPadding, oldVerticalPadding)) + emit verticalPaddingChanged(); + if (!qFuzzyCompare(newHorizontalPadding, oldHorizontalPadding)) + emit horizontalPaddingChanged(); if (!qFuzzyCompare(newPadding.top(), oldPadding.top()) || !qFuzzyCompare(newPadding.bottom(), oldPadding.bottom())) emit availableHeightChanged(); if (!qFuzzyCompare(newPadding.left(), oldPadding.left()) || !qFuzzyCompare(newPadding.right(), oldPadding.right())) emit availableWidthChanged(); + paddingChange(newPadding, oldPadding); } @@ -868,16 +1125,15 @@ void QQuickControl::resetPadding() /*! \qmlproperty real QtQuick.Controls::Control::topPadding - This property holds the top padding. + This property holds the top padding. Unless explicitly set, the value + is equal to \c verticalPadding. - \sa {Control Layout}, padding, bottomPadding, availableHeight + \sa {Control Layout}, padding, bottomPadding, verticalPadding, availableHeight */ qreal QQuickControl::topPadding() const { Q_D(const QQuickControl); - if (d->hasTopPadding) - return d->topPadding; - return d->padding; + return d->getTopPadding(); } void QQuickControl::setTopPadding(qreal padding) @@ -895,16 +1151,15 @@ void QQuickControl::resetTopPadding() /*! \qmlproperty real QtQuick.Controls::Control::leftPadding - This property holds the left padding. + This property holds the left padding. Unless explicitly set, the value + is equal to \c horizontalPadding. - \sa {Control Layout}, padding, rightPadding, availableWidth + \sa {Control Layout}, padding, rightPadding, horizontalPadding, availableWidth */ qreal QQuickControl::leftPadding() const { Q_D(const QQuickControl); - if (d->hasLeftPadding) - return d->leftPadding; - return d->padding; + return d->getLeftPadding(); } void QQuickControl::setLeftPadding(qreal padding) @@ -922,16 +1177,15 @@ void QQuickControl::resetLeftPadding() /*! \qmlproperty real QtQuick.Controls::Control::rightPadding - This property holds the right padding. + This property holds the right padding. Unless explicitly set, the value + is equal to \c horizontalPadding. - \sa {Control Layout}, padding, leftPadding, availableWidth + \sa {Control Layout}, padding, leftPadding, horizontalPadding, availableWidth */ qreal QQuickControl::rightPadding() const { Q_D(const QQuickControl); - if (d->hasRightPadding) - return d->rightPadding; - return d->padding; + return d->getRightPadding(); } void QQuickControl::setRightPadding(qreal padding) @@ -949,16 +1203,15 @@ void QQuickControl::resetRightPadding() /*! \qmlproperty real QtQuick.Controls::Control::bottomPadding - This property holds the bottom padding. + This property holds the bottom padding. Unless explicitly set, the value + is equal to \c verticalPadding. - \sa {Control Layout}, padding, topPadding, availableHeight + \sa {Control Layout}, padding, topPadding, verticalPadding, availableHeight */ qreal QQuickControl::bottomPadding() const { Q_D(const QQuickControl); - if (d->hasBottomPadding) - return d->bottomPadding; - return d->padding; + return d->getBottomPadding(); } void QQuickControl::setBottomPadding(qreal padding) @@ -1291,15 +1544,36 @@ void QQuickControl::setBackground(QQuickItem *background) 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; + } + + d->removeImplicitSizeListener(d->background, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry); delete 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(); + d->addImplicitSizeListener(background, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry); } + + if (!qFuzzyCompare(oldImplicitBackgroundWidth, implicitBackgroundWidth())) + emit implicitBackgroundWidthChanged(); + if (!qFuzzyCompare(oldImplicitBackgroundHeight, implicitBackgroundHeight())) + emit implicitBackgroundHeightChanged(); if (!d->background.isExecuting()) emit backgroundChanged(); } @@ -1346,6 +1620,30 @@ void QQuickControl::setContentItem(QQuickItem *item) d->setContentItem_helper(item, true); } +qreal QQuickControl::baselineOffset() const +{ + Q_D(const QQuickControl); + return d->baselineOffset; +} + +void QQuickControl::setBaselineOffset(qreal offset) +{ + Q_D(QQuickControl); + d->extra.value().hasBaselineOffset = true; + QQuickItem::setBaselineOffset(offset); +} + +void QQuickControl::resetBaselineOffset() +{ + Q_D(QQuickControl); + if (!d->extra.isAllocated() || !d->extra.value().hasBaselineOffset) + return; + + if (d->extra.isAllocated()) + d->extra.value().hasBaselineOffset = false; + d->updateBaselineOffset(); +} + /*! \since QtQuick.Controls 2.3 (Qt 5.10) \qmlproperty palette QtQuick.Controls::Control::palette @@ -1415,6 +1713,278 @@ void QQuickControl::resetPalette() setPalette(QPalette()); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::horizontalPadding + + This property holds the horizontal padding. Unless explicitly set, the value + is equal to \c padding. + + \sa {Control Layout}, padding, leftPadding, rightPadding, verticalPadding +*/ +qreal QQuickControl::horizontalPadding() const +{ + Q_D(const QQuickControl); + return d->getHorizontalPadding(); +} + +void QQuickControl::setHorizontalPadding(qreal padding) +{ + Q_D(QQuickControl); + d->setHorizontalPadding(padding); +} + +void QQuickControl::resetHorizontalPadding() +{ + Q_D(QQuickControl); + d->setHorizontalPadding(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::verticalPadding + + This property holds the vertical padding. Unless explicitly set, the value + is equal to \c padding. + + \sa {Control Layout}, padding, topPadding, bottomPadding, horizontalPadding +*/ +qreal QQuickControl::verticalPadding() const +{ + Q_D(const QQuickControl); + return d->getVerticalPadding(); +} + +void QQuickControl::setVerticalPadding(qreal padding) +{ + Q_D(QQuickControl); + d->setVerticalPadding(padding); +} + +void QQuickControl::resetVerticalPadding() +{ + Q_D(QQuickControl); + d->setVerticalPadding(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::implicitContentWidth + \readonly + + This property holds the implicit content width. + + For basic controls, the value is equal to \c {contentItem ? contentItem.implicitWidth : 0}. + For types that inherit Container or Pane, the value is calculated based on the content children. + + This is typically used, together with \l implicitBackgroundWidth, to calculate + the \l {Item::}{implicitWidth}: + + \code + Control { + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + } + \endcode + + \sa implicitContentHeight, implicitBackgroundWidth +*/ +qreal QQuickControl::implicitContentWidth() const +{ + Q_D(const QQuickControl); + return d->implicitContentWidth; +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::implicitContentHeight + \readonly + + This property holds the implicit content height. + + For basic controls, the value is equal to \c {contentItem ? contentItem.implicitHeight : 0}. + For types that inherit Container or Pane, the value is calculated based on the content children. + + This is typically used, together with \l implicitBackgroundHeight, to calculate + the \l {Item::}{implicitHeight}: + + \code + Control { + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + } + \endcode + + \sa implicitContentWidth, implicitBackgroundHeight +*/ +qreal QQuickControl::implicitContentHeight() const +{ + Q_D(const QQuickControl); + return d->implicitContentHeight; +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::implicitBackgroundWidth + \readonly + + This property holds the implicit background width. + + The value is equal to \c {background ? background.implicitWidth : 0}. + + This is typically used, together with \l implicitContentWidth, to calculate + the \l {Item::}{implicitWidth}: + + \code + Control { + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + } + \endcode + + \sa implicitBackgroundHeight, implicitContentWidth +*/ +qreal QQuickControl::implicitBackgroundWidth() const +{ + Q_D(const QQuickControl); + if (!d->background) + return 0; + return d->background->implicitWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::implicitBackgroundHeight + \readonly + + This property holds the implicit background height. + + The value is equal to \c {background ? background.implicitHeight : 0}. + + This is typically used, together with \l implicitContentHeight, to calculate + the \l {Item::}{implicitHeight}: + + \code + Control { + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + } + \endcode + + \sa implicitBackgroundWidth, implicitContentHeight +*/ +qreal QQuickControl::implicitBackgroundHeight() const +{ + Q_D(const QQuickControl); + if (!d->background) + return 0; + return d->background->implicitHeight(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::topInset + + This property holds the top inset for the background. + + \sa {Control Layout}, bottomInset +*/ +qreal QQuickControl::topInset() const +{ + Q_D(const QQuickControl); + return d->getTopInset(); +} + +void QQuickControl::setTopInset(qreal inset) +{ + Q_D(QQuickControl); + d->setTopInset(inset); +} + +void QQuickControl::resetTopInset() +{ + Q_D(QQuickControl); + d->setTopInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::leftInset + + This property holds the left inset for the background. + + \sa {Control Layout}, rightInset +*/ +qreal QQuickControl::leftInset() const +{ + Q_D(const QQuickControl); + return d->getLeftInset(); +} + +void QQuickControl::setLeftInset(qreal inset) +{ + Q_D(QQuickControl); + d->setLeftInset(inset); +} + +void QQuickControl::resetLeftInset() +{ + Q_D(QQuickControl); + d->setLeftInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::rightInset + + This property holds the right inset for the background. + + \sa {Control Layout}, leftInset +*/ +qreal QQuickControl::rightInset() const +{ + Q_D(const QQuickControl); + return d->getRightInset(); +} + +void QQuickControl::setRightInset(qreal inset) +{ + Q_D(QQuickControl); + d->setRightInset(inset); +} + +void QQuickControl::resetRightInset() +{ + Q_D(QQuickControl); + d->setRightInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Control::bottomInset + + This property holds the bottom inset for the background. + + \sa {Control Layout}, topInset +*/ +qreal QQuickControl::bottomInset() const +{ + Q_D(const QQuickControl); + return d->getBottomInset(); +} + +void QQuickControl::setBottomInset(qreal inset) +{ + Q_D(QQuickControl); + d->setBottomInset(inset); +} + +void QQuickControl::resetBottomInset() +{ + Q_D(QQuickControl); + d->setBottomInset(0, true); +} + void QQuickControl::classBegin() { Q_D(QQuickControl); @@ -1431,6 +2001,7 @@ void QQuickControl::componentComplete() QQuickItem::componentComplete(); d->resizeBackground(); d->resizeContent(); + d->updateBaselineOffset(); if (!d->hasLocale) d->locale = QQuickControlPrivate::calcLocale(d->parentItem); #if QT_CONFIG(quicktemplates2_hover) @@ -1445,12 +2016,12 @@ void QQuickControl::componentComplete() QFont QQuickControl::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont); + return QQuickTheme::font(QQuickTheme::System); } QPalette QQuickControl::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette); + return QQuickTheme::palette(QQuickTheme::System); } void QQuickControl::focusInEvent(QFocusEvent *event) @@ -1612,6 +2183,7 @@ void QQuickControl::paddingChange(const QMarginsF &newPadding, const QMarginsF & Q_UNUSED(newPadding); Q_UNUSED(oldPadding); d->resizeContent(); + d->updateBaselineOffset(); } void QQuickControl::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) @@ -1632,6 +2204,14 @@ void QQuickControl::paletteChange(const QPalette &newPalette, const QPalette &ol Q_UNUSED(oldPalette); } +void QQuickControl::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset) +{ + Q_D(QQuickControl); + Q_UNUSED(newInset); + Q_UNUSED(oldInset); + d->resizeBackground(); +} + #if QT_CONFIG(accessibility) QAccessible::Role QQuickControl::accessibleRole() const { diff --git a/src/quicktemplates2/qquickcontrol_p.h b/src/quicktemplates2/qquickcontrol_p.h index 6b2d48d6..a38e34f9 100644 --- a/src/quicktemplates2/qquickcontrol_p.h +++ b/src/quicktemplates2/qquickcontrol_p.h @@ -79,12 +79,25 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickControl : public QQuickItem Q_PROPERTY(bool wheelEnabled READ isWheelEnabled WRITE setWheelEnabled NOTIFY wheelEnabledChanged FINAL) Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL) Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged FINAL) + Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset RESET resetBaselineOffset NOTIFY baselineOffsetChanged FINAL) // 2.3 (Qt 5.10) Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal horizontalPadding READ horizontalPadding WRITE setHorizontalPadding RESET resetHorizontalPadding NOTIFY horizontalPaddingChanged FINAL REVISION 5) + Q_PROPERTY(qreal verticalPadding READ verticalPadding WRITE setVerticalPadding RESET resetVerticalPadding NOTIFY verticalPaddingChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitContentWidth READ implicitContentWidth NOTIFY implicitContentWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitContentHeight READ implicitContentHeight NOTIFY implicitContentHeightChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitBackgroundWidth READ implicitBackgroundWidth NOTIFY implicitBackgroundWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitBackgroundHeight READ implicitBackgroundHeight NOTIFY implicitBackgroundHeightChanged FINAL REVISION 5) + Q_PROPERTY(qreal topInset READ topInset WRITE setTopInset RESET resetTopInset NOTIFY topInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal leftInset READ leftInset WRITE setLeftInset RESET resetLeftInset NOTIFY leftInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal rightInset READ rightInset WRITE setRightInset RESET resetRightInset NOTIFY rightInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal bottomInset READ bottomInset WRITE setBottomInset RESET resetBottomInset NOTIFY bottomInsetChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background,contentItem") public: explicit QQuickControl(QQuickItem *parent = nullptr); + ~QQuickControl(); QFont font() const; void setFont(const QFont &font); @@ -147,11 +160,46 @@ public: QQuickItem *contentItem() const; void setContentItem(QQuickItem *item); + qreal baselineOffset() const; + void setBaselineOffset(qreal offset); + void resetBaselineOffset(); + // 2.3 (Qt 5.10) QPalette palette() const; void setPalette(const QPalette &palette); void resetPalette(); + // 2.5 (Qt 5.12) + qreal horizontalPadding() const; + void setHorizontalPadding(qreal padding); + void resetHorizontalPadding(); + + qreal verticalPadding() const; + void setVerticalPadding(qreal padding); + void resetVerticalPadding(); + + qreal implicitContentWidth() const; + qreal implicitContentHeight() const; + + qreal implicitBackgroundWidth() const; + qreal implicitBackgroundHeight() const; + + qreal topInset() const; + void setTopInset(qreal inset); + void resetTopInset(); + + qreal leftInset() const; + void setLeftInset(qreal inset); + void resetLeftInset(); + + qreal rightInset() const; + void setRightInset(qreal inset); + void resetRightInset(); + + qreal bottomInset() const; + void setBottomInset(qreal inset); + void resetBottomInset(); + Q_SIGNALS: void fontChanged(); void availableWidthChanged(); @@ -172,8 +220,20 @@ Q_SIGNALS: void wheelEnabledChanged(); void backgroundChanged(); void contentItemChanged(); + void baselineOffsetChanged(); // 2.3 (Qt 5.10) Q_REVISION(3) void paletteChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void horizontalPaddingChanged(); + Q_REVISION(5) void verticalPaddingChanged(); + Q_REVISION(5) void implicitContentWidthChanged(); + Q_REVISION(5) void implicitContentHeightChanged(); + Q_REVISION(5) void implicitBackgroundWidthChanged(); + Q_REVISION(5) void implicitBackgroundHeightChanged(); + Q_REVISION(5) void topInsetChanged(); + Q_REVISION(5) void leftInsetChanged(); + Q_REVISION(5) void rightInsetChanged(); + Q_REVISION(5) void bottomInsetChanged(); protected: virtual QFont defaultFont() const; @@ -217,6 +277,7 @@ protected: virtual void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem); virtual void localeChange(const QLocale &newLocale, const QLocale &oldLocale); virtual void paletteChange(const QPalette &newPalette, const QPalette &oldPalette); + virtual void insetChange(const QMarginsF &newInset, const QMarginsF &oldInset); #if QT_CONFIG(accessibility) virtual QAccessible::Role accessibleRole() const; diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h index f90bb094..a657307b 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -50,10 +50,11 @@ #include <QtQuickTemplates2/private/qquickcontrol_p.h> #include <QtQuickTemplates2/private/qquickdeferredpointer_p_p.h> +#include <QtQuickTemplates2/private/qquicktheme_p.h> #include <QtQuick/private/qquickitem_p.h> +#include <QtQuick/private/qquickitemchangelistener_p.h> #include <QtQml/private/qlazilyallocated_p.h> -#include <qpa/qplatformtheme.h> #if QT_CONFIG(accessibility) #include <QtGui/qaccessible.h> @@ -63,7 +64,7 @@ QT_BEGIN_NAMESPACE class QQuickAccessibleAttached; -class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickControlPrivate : public QQuickItemPrivate +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickControlPrivate : public QQuickItemPrivate, public QQuickItemChangeListener #if QT_CONFIG(accessibility) , public QAccessible::ActivationObserver #endif @@ -79,6 +80,8 @@ public: return control->d_func(); } + void init(); + #if QT_CONFIG(quicktemplates2_multitouch) virtual bool acceptTouch(const QTouchEvent::TouchPoint &point); #endif @@ -89,10 +92,31 @@ public: void mirrorChange() override; + inline QMarginsF getPadding() const { return QMarginsF(getLeftPadding(), getTopPadding(), getRightPadding(), getBottomPadding()); } + inline qreal getTopPadding() const { return extra.isAllocated() && extra->hasTopPadding ? extra->topPadding : getVerticalPadding(); } + inline qreal getLeftPadding() const { return extra.isAllocated() && extra->hasLeftPadding ? extra->leftPadding : getHorizontalPadding(); } + inline qreal getRightPadding() const { return extra.isAllocated() && extra->hasRightPadding ? extra->rightPadding : getHorizontalPadding(); } + inline qreal getBottomPadding() const { return extra.isAllocated() && extra->hasBottomPadding ? extra->bottomPadding : getVerticalPadding(); } + inline qreal getHorizontalPadding() const { return hasHorizontalPadding ? horizontalPadding : padding; } + inline qreal getVerticalPadding() const { return hasVerticalPadding ? verticalPadding : padding; } + void setTopPadding(qreal value, bool reset = false); void setLeftPadding(qreal value, bool reset = false); void setRightPadding(qreal value, bool reset = false); void setBottomPadding(qreal value, bool reset = false); + void setHorizontalPadding(qreal value, bool reset = false); + void setVerticalPadding(qreal value, bool reset = false); + + inline QMarginsF getInset() const { return QMarginsF(getLeftInset(), getTopInset(), getRightInset(), getBottomInset()); } + inline qreal getTopInset() const { return extra.isAllocated() ? extra->topInset : 0; } + inline qreal getLeftInset() const { return extra.isAllocated() ? extra->leftInset : 0; } + inline qreal getRightInset() const { return extra.isAllocated() ? extra->rightInset : 0; } + inline qreal getBottomInset() const { return extra.isAllocated() ? extra->bottomInset : 0; } + + void setTopInset(qreal value, bool reset = false); + void setLeftInset(qreal value, bool reset = false); + void setRightInset(qreal value, bool reset = false); + void setBottomInset(qreal value, bool reset = false); void resizeBackground(); virtual void resizeContent(); @@ -116,7 +140,6 @@ public: updateFont(font); } static QFont parentFont(const QQuickItem *item); - static QFont themeFont(QPlatformTheme::Font type); virtual void resolvePalette(); void inheritPalette(const QPalette &palette); @@ -128,7 +151,6 @@ public: updatePalette(palette); } static QPalette parentPalette(const QQuickItem *item); - static QPalette themePalette(QPlatformTheme::Palette type); void updateLocale(const QLocale &l, bool e); static void updateLocaleRecur(QQuickItem *item, const QLocale &l); @@ -146,28 +168,68 @@ public: virtual void cancelBackground(); virtual void executeBackground(bool complete = false); + void updateBaselineOffset(); + + static const ChangeTypes ImplicitSizeChanges; + + void addImplicitSizeListener(QQuickItem *item, ChangeTypes changes = ImplicitSizeChanges); + void removeImplicitSizeListener(QQuickItem *item, ChangeTypes changes = ImplicitSizeChanges); + + static void addImplicitSizeListener(QQuickItem *item, QQuickItemChangeListener *listener, ChangeTypes changes = ImplicitSizeChanges); + static void removeImplicitSizeListener(QQuickItem *item, QQuickItemChangeListener *listener, ChangeTypes changes = ImplicitSizeChanges); + + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; + void itemDestroyed(QQuickItem *item) override; + + virtual qreal getContentWidth() const; + virtual qreal getContentHeight() const; + + void updateImplicitContentWidth(); + void updateImplicitContentHeight(); + void updateImplicitContentSize(); + struct ExtraData { + bool hasTopPadding = false; + bool hasLeftPadding = false; + bool hasRightPadding = false; + bool hasBottomPadding = false; + bool hasBaselineOffset = false; + bool hasTopInset = false; + bool hasLeftInset = false; + bool hasRightInset = false; + bool hasBottomInset = false; + bool hasBackgroundWidth = false; + bool hasBackgroundHeight = false; + qreal topPadding = 0; + qreal leftPadding = 0; + qreal rightPadding = 0; + qreal bottomPadding = 0; + qreal topInset = 0; + qreal leftInset = 0; + qreal rightInset = 0; + qreal bottomInset = 0; QFont requestedFont; QPalette requestedPalette; }; QLazilyAllocated<ExtraData> extra; - bool hasTopPadding = false; - bool hasLeftPadding = false; - bool hasRightPadding = false; - bool hasBottomPadding = false; + bool hasHorizontalPadding = false; + bool hasVerticalPadding = false; bool hasLocale = false; bool wheelEnabled = false; #if QT_CONFIG(quicktemplates2_hover) bool hovered = false; bool explicitHoverEnabled = false; #endif + bool resizingBackground = false; int touchId = -1; qreal padding = 0; - qreal topPadding = 0; - qreal leftPadding = 0; - qreal rightPadding = 0; - qreal bottomPadding = 0; + qreal horizontalPadding = 0; + qreal verticalPadding = 0; + qreal implicitContentWidth = 0; + qreal implicitContentHeight = 0; qreal spacing = 0; QLocale locale; QFont resolvedFont; diff --git a/src/quicktemplates2/qquickdelaybutton.cpp b/src/quicktemplates2/qquickdelaybutton.cpp index 5b32fc71..ba5953a0 100644 --- a/src/quicktemplates2/qquickdelaybutton.cpp +++ b/src/quicktemplates2/qquickdelaybutton.cpp @@ -256,12 +256,12 @@ void QQuickDelayButton::nextCheckState() QFont QQuickDelayButton::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::PushButtonFont); + return QQuickTheme::font(QQuickTheme::Button); } QPalette QQuickDelayButton::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::ButtonPalette); + return QQuickTheme::palette(QQuickTheme::Button); } QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp index a4124678..123f9b1b 100644 --- a/src/quicktemplates2/qquickdial.cpp +++ b/src/quicktemplates2/qquickdial.cpp @@ -75,6 +75,8 @@ QT_BEGIN_NAMESPACE \row \li Set \l value to \l to \li \c Qt.Key_End \endtable + \include qquickdial.qdocinc inputMode + \sa {Customizing Dial}, {Input Controls} */ @@ -99,9 +101,12 @@ public: qreal valueAt(qreal position) const; qreal snapPosition(qreal position) const; qreal positionAt(const QPointF &point) const; + qreal circularPositionAt(const QPointF &point) const; + qreal linearPositionAt(const QPointF &point) const; void setPosition(qreal position); void updatePosition(); bool isLargeChange(const QPointF &eventPos, qreal proposedPosition) const; + bool isHorizontalOrVertical() const; void handlePress(const QPointF &point) override; void handleMove(const QPointF &point) override; @@ -119,7 +124,9 @@ public: qreal stepSize = 0; bool pressed = false; QPointF pressPoint; + qreal positionBeforePress = 0; QQuickDial::SnapMode snapMode = QQuickDial::NoSnap; + QQuickDial::InputMode inputMode = QQuickDial::Circular; bool wrap = false; bool live = true; QQuickDeferredPointer<QQuickItem> handle; @@ -145,6 +152,11 @@ qreal QQuickDialPrivate::snapPosition(qreal position) const qreal QQuickDialPrivate::positionAt(const QPointF &point) const { + return inputMode == QQuickDial::Circular ? circularPositionAt(point) : linearPositionAt(point); +} + +qreal QQuickDialPrivate::circularPositionAt(const QPointF &point) const +{ qreal yy = height / 2.0 - point.y(); qreal xx = point.x() - width / 2.0; qreal angle = (xx || yy) ? std::atan2(yy, xx) : 0; @@ -156,6 +168,32 @@ qreal QQuickDialPrivate::positionAt(const QPointF &point) const return normalizedAngle; } +qreal QQuickDialPrivate::linearPositionAt(const QPointF &point) const +{ + // This value determines the range (either horizontal or vertical) + // within which the dial can be dragged. + // The larger this value is, the further the drag distance + // must be to go from a position of e.g. 0.0 to 1.0. + qreal dragArea = 0; + + // The linear input mode uses a "relative" input system, + // where the distance from the press point is used to calculate + // the change in position. Moving the mouse above the press + // point increases the position (when inputMode is Vertical), + // and vice versa. This prevents the dial from jumping when clicked. + qreal dragDistance = 0; + + if (inputMode == QQuickDial::Horizontal) { + dragArea = width * 2; + dragDistance = pressPoint.x() - point.x(); + } else { + dragArea = height * 2; + dragDistance = point.y() - pressPoint.y(); + } + const qreal normalisedDifference = dragDistance / dragArea; + return qBound(0.0, positionBeforePress - normalisedDifference, 1.0); +} + void QQuickDialPrivate::setPosition(qreal pos) { Q_Q(QQuickDial); @@ -184,11 +222,17 @@ bool QQuickDialPrivate::isLargeChange(const QPointF &eventPos, qreal proposedPos return qAbs(proposedPosition - position) >= 0.5 && eventPos.y() >= height / 2; } +bool QQuickDialPrivate::isHorizontalOrVertical() const +{ + return inputMode == QQuickDial::Horizontal || inputMode == QQuickDial::Vertical; +} + void QQuickDialPrivate::handlePress(const QPointF &point) { Q_Q(QQuickDial); QQuickControlPrivate::handlePress(point); pressPoint = point; + positionBeforePress = position; q->setPressed(true); } @@ -201,7 +245,7 @@ void QQuickDialPrivate::handleMove(const QPointF &point) if (snapMode == QQuickDial::SnapAlways) pos = snapPosition(pos); - if (wrap || (!wrap && !isLargeChange(point, pos))) { + if (wrap || (!wrap && (isHorizontalOrVertical() || !isLargeChange(point, pos)))) { if (live) q->setValue(valueAt(pos)); else @@ -221,7 +265,7 @@ void QQuickDialPrivate::handleRelease(const QPointF &point) if (snapMode != QQuickDial::NoSnap) pos = snapPosition(pos); - if (wrap || (!wrap && !isLargeChange(point, pos))) + if (wrap || (!wrap && (isHorizontalOrVertical() || !isLargeChange(point, pos)))) q->setValue(valueAt(pos)); if (!qFuzzyCompare(pos, oldPos)) emit q->moved(); @@ -232,6 +276,7 @@ void QQuickDialPrivate::handleRelease(const QPointF &point) q->setPressed(false); pressPoint = QPointF(); + positionBeforePress = 0; } void QQuickDialPrivate::handleUngrab() @@ -239,6 +284,7 @@ void QQuickDialPrivate::handleUngrab() Q_Q(QQuickDial); QQuickControlPrivate::handleUngrab(); pressPoint = QPointF(); + positionBeforePress = 0; q->setPressed(false); } @@ -454,6 +500,32 @@ void QQuickDial::setSnapMode(SnapMode mode) } /*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty enumeration QtQuick.Controls::Dial::inputMode + + This property holds the input mode. + + \include qquickdial.qdocinc inputMode + + The default value is \c Dial.Circular. +*/ +QQuickDial::InputMode QQuickDial::inputMode() const +{ + Q_D(const QQuickDial); + return d->inputMode; +} + +void QQuickDial::setInputMode(QQuickDial::InputMode mode) +{ + Q_D(QQuickDial); + if (d->inputMode == mode) + return; + + d->inputMode = mode; + emit inputModeChanged(); +} + +/*! \qmlproperty bool QtQuick.Controls::Dial::wrap This property holds whether the dial wraps when dragged. diff --git a/src/quicktemplates2/qquickdial_p.h b/src/quicktemplates2/qquickdial_p.h index d2caccfc..cc641c78 100644 --- a/src/quicktemplates2/qquickdial_p.h +++ b/src/quicktemplates2/qquickdial_p.h @@ -72,6 +72,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDial : public QQuickControl Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL) // 2.2 (Qt 5.9) Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2) + // 2.5 (Qt 5.12) + Q_PROPERTY(InputMode inputMode READ inputMode WRITE setInputMode NOTIFY inputModeChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background,handle") public: @@ -103,6 +105,13 @@ public: SnapMode snapMode() const; void setSnapMode(SnapMode mode); + enum InputMode { + Circular, + Horizontal, + Vertical, + }; + Q_ENUM(InputMode) + bool wrap() const; void setWrap(bool wrap); @@ -116,6 +125,10 @@ public: bool live() const; void setLive(bool live); + // 2.5 (Qt 5.12) + InputMode inputMode() const; + void setInputMode(InputMode mode); + public Q_SLOTS: void increase(); void decrease(); @@ -134,6 +147,8 @@ Q_SIGNALS: // 2.2 (Qt 5.9) Q_REVISION(2) void moved(); Q_REVISION(2) void liveChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void inputModeChanged(); protected: void keyPressEvent(QKeyEvent *event) override; diff --git a/src/quicktemplates2/qquickdialog.cpp b/src/quicktemplates2/qquickdialog.cpp index cce1ae47..7d3152e2 100644 --- a/src/quicktemplates2/qquickdialog.cpp +++ b/src/quicktemplates2/qquickdialog.cpp @@ -183,7 +183,13 @@ QQuickDialog::QQuickDialog(QObject *parent) : QQuickPopup(*(new QQuickDialogPrivate), parent) { Q_D(QQuickDialog); - d->layout.reset(new QQuickPageLayout(d->popupItem)); + connect(d->popupItem, &QQuickPopupItem::titleChanged, this, &QQuickDialog::titleChanged); + connect(d->popupItem, &QQuickPopupItem::headerChanged, this, &QQuickDialog::headerChanged); + connect(d->popupItem, &QQuickPopupItem::footerChanged, this, &QQuickDialog::footerChanged); + connect(d->popupItem, &QQuickPopupItem::implicitHeaderWidthChanged, this, &QQuickDialog::implicitHeaderWidthChanged); + connect(d->popupItem, &QQuickPopupItem::implicitHeaderHeightChanged, this, &QQuickDialog::implicitHeaderHeightChanged); + connect(d->popupItem, &QQuickPopupItem::implicitFooterWidthChanged, this, &QQuickDialog::implicitFooterWidthChanged); + connect(d->popupItem, &QQuickPopupItem::implicitFooterHeightChanged, this, &QQuickDialog::implicitFooterHeightChanged); } /*! @@ -206,18 +212,14 @@ QQuickDialog::QQuickDialog(QObject *parent) QString QQuickDialog::title() const { Q_D(const QQuickDialog); - return d->title; + return d->popupItem->title(); } void QQuickDialog::setTitle(const QString &title) { Q_D(QQuickDialog); - if (d->title == title) - return; - - d->title = title; + d->popupItem->setTitle(title); setAccessibleName(title); - emit titleChanged(); } /*! @@ -239,14 +241,14 @@ void QQuickDialog::setTitle(const QString &title) QQuickItem *QQuickDialog::header() const { Q_D(const QQuickDialog); - return d->layout->header(); + return d->popupItem->header(); } void QQuickDialog::setHeader(QQuickItem *header) { Q_D(QQuickDialog); - QQuickItem *oldHeader = d->layout->header(); - if (!d->layout->setHeader(header)) + QQuickItem *oldHeader = d->popupItem->header(); + if (oldHeader == header) return; if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldHeader)) { @@ -256,6 +258,7 @@ void QQuickDialog::setHeader(QQuickItem *header) if (d->buttonBox == buttonBox) d->buttonBox = nullptr; } + if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(header)) { connect(buttonBox, &QQuickDialogButtonBox::accepted, this, &QQuickDialog::accept); connect(buttonBox, &QQuickDialogButtonBox::rejected, this, &QQuickDialog::reject); @@ -264,9 +267,7 @@ void QQuickDialog::setHeader(QQuickItem *header) buttonBox->setStandardButtons(d->standardButtons); } - if (isComponentComplete()) - d->layout->update(); - emit headerChanged(); + d->popupItem->setHeader(header); } /*! @@ -288,14 +289,14 @@ void QQuickDialog::setHeader(QQuickItem *header) QQuickItem *QQuickDialog::footer() const { Q_D(const QQuickDialog); - return d->layout->footer(); + return d->popupItem->footer(); } void QQuickDialog::setFooter(QQuickItem *footer) { Q_D(QQuickDialog); - QQuickItem *oldFooter = d->layout->footer(); - if (!d->layout->setFooter(footer)) + QQuickItem *oldFooter = d->popupItem->footer(); + if (oldFooter == footer) return; if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldFooter)) { @@ -313,9 +314,7 @@ void QQuickDialog::setFooter(QQuickItem *footer) buttonBox->setStandardButtons(d->standardButtons); } - if (isComponentComplete()) - d->layout->update(); - emit footerChanged(); + d->popupItem->setFooter(footer); } /*! @@ -413,6 +412,74 @@ void QQuickDialog::setResult(int result) } /*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Dialog::implicitHeaderWidth + \readonly + + This property holds the implicit header width. + + The value is equal to \c {header && header.visible ? header.implicitWidth : 0}. + + \sa implicitHeaderHeight, implicitFooterWidth +*/ +qreal QQuickDialog::implicitHeaderWidth() const +{ + Q_D(const QQuickDialog); + return d->popupItem->implicitHeaderWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Dialog::implicitHeaderHeight + \readonly + + This property holds the implicit header height. + + The value is equal to \c {header && header.visible ? header.implicitHeight : 0}. + + \sa implicitHeaderWidth, implicitFooterHeight +*/ +qreal QQuickDialog::implicitHeaderHeight() const +{ + Q_D(const QQuickDialog); + return d->popupItem->implicitHeaderHeight(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Dialog::implicitFooterWidth + \readonly + + This property holds the implicit footer width. + + The value is equal to \c {footer && footer.visible ? footer.implicitWidth : 0}. + + \sa implicitFooterHeight, implicitHeaderWidth +*/ +qreal QQuickDialog::implicitFooterWidth() const +{ + Q_D(const QQuickDialog); + return d->popupItem->implicitFooterWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Dialog::implicitFooterHeight + \readonly + + This property holds the implicit footer height. + + The value is equal to \c {footer && footer.visible ? footer.implicitHeight : 0}. + + \sa implicitFooterWidth, implicitHeaderHeight +*/ +qreal QQuickDialog::implicitFooterHeight() const +{ + Q_D(const QQuickDialog); + return d->popupItem->implicitFooterHeight(); +} + +/*! \qmlmethod void QtQuick.Controls::Dialog::accept() Closes the dialog and emits the \l accepted() signal. @@ -457,27 +524,6 @@ void QQuickDialog::done(int result) emit rejected(); } -void QQuickDialog::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) -{ - Q_D(QQuickDialog); - QQuickPopup::geometryChanged(newGeometry, oldGeometry); - d->layout->update(); -} - -void QQuickDialog::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) -{ - Q_D(QQuickDialog); - QQuickPopup::paddingChange(newPadding, oldPadding); - d->layout->update(); -} - -void QQuickDialog::spacingChange(qreal newSpacing, qreal oldSpacing) -{ - Q_D(QQuickDialog); - QQuickPopup::spacingChange(newSpacing, oldSpacing); - d->layout->update(); -} - #if QT_CONFIG(accessibility) QAccessible::Role QQuickDialog::accessibleRole() const { @@ -490,7 +536,7 @@ void QQuickDialog::accessibilityActiveChanged(bool active) QQuickPopup::accessibilityActiveChanged(active); if (active) - setAccessibleName(d->title); + setAccessibleName(d->popupItem->title()); } #endif diff --git a/src/quicktemplates2/qquickdialog_p.h b/src/quicktemplates2/qquickdialog_p.h index d22685b6..38a1b396 100644 --- a/src/quicktemplates2/qquickdialog_p.h +++ b/src/quicktemplates2/qquickdialog_p.h @@ -66,6 +66,11 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDialog : public QQuickPopup // 2.3 (Qt 5.10) Q_PROPERTY(int result READ result WRITE setResult NOTIFY resultChanged FINAL REVISION 3) Q_FLAGS(QPlatformDialogHelper::StandardButtons) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal implicitHeaderWidth READ implicitHeaderWidth NOTIFY implicitHeaderWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitHeaderHeight READ implicitHeaderHeight NOTIFY implicitHeaderHeightChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitFooterWidth READ implicitFooterWidth NOTIFY implicitFooterWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitFooterHeight READ implicitFooterHeight NOTIFY implicitFooterHeightChanged FINAL REVISION 5) public: explicit QQuickDialog(QObject *parent = nullptr); @@ -90,6 +95,13 @@ public: int result() const; void setResult(int result); + // 2.5 (Qt 5.12) + qreal implicitHeaderWidth() const; + qreal implicitHeaderHeight() const; + + qreal implicitFooterWidth() const; + qreal implicitFooterHeight() const; + public Q_SLOTS: virtual void accept(); virtual void reject(); @@ -108,12 +120,13 @@ Q_SIGNALS: Q_REVISION(3) void discarded(); Q_REVISION(3) void helpRequested(); Q_REVISION(3) void resultChanged(); + // 2.5 (Qt 5.12) + void implicitHeaderWidthChanged(); + void implicitHeaderHeightChanged(); + void implicitFooterWidthChanged(); + void implicitFooterHeightChanged(); protected: - void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; - void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override; - void spacingChange(qreal newSpacing, qreal oldSpacing) override; - #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; void accessibilityActiveChanged(bool active) override; diff --git a/src/quicktemplates2/qquickdialog_p_p.h b/src/quicktemplates2/qquickdialog_p_p.h index e8008cec..20dce56c 100644 --- a/src/quicktemplates2/qquickdialog_p_p.h +++ b/src/quicktemplates2/qquickdialog_p_p.h @@ -50,7 +50,6 @@ #include <QtQuickTemplates2/private/qquickdialog_p.h> #include <QtQuickTemplates2/private/qquickpopup_p_p.h> -#include <QtQuickTemplates2/private/qquickpagelayout_p_p.h> #include <QtGui/qpa/qplatformdialoghelper.h> QT_BEGIN_NAMESPACE @@ -75,7 +74,6 @@ public: int result = 0; QString title; QQuickDialogButtonBox *buttonBox = nullptr; - QScopedPointer<QQuickPageLayout> layout; QPlatformDialogHelper::StandardButtons standardButtons = QPlatformDialogHelper::NoButton; }; diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp index e53313b1..31b2e646 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox.cpp +++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp @@ -192,16 +192,27 @@ QT_BEGIN_NAMESPACE \sa accepted(), rejected(), helpRequested() */ +static QQuickDialogButtonBox::ButtonLayout platformButtonLayout() +{ + return QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::DialogButtonBoxLayout).value<QQuickDialogButtonBox::ButtonLayout>(); +} + void QQuickDialogButtonBoxPrivate::itemImplicitWidthChanged(QQuickItem *item) { - Q_UNUSED(item); - resizeContent(); + QQuickContainerPrivate::itemImplicitWidthChanged(item); + if (item == contentItem) + resizeContent(); + else + updateImplicitContentWidth(); } void QQuickDialogButtonBoxPrivate::itemImplicitHeightChanged(QQuickItem *item) { - Q_UNUSED(item); - resizeContent(); + QQuickContainerPrivate::itemImplicitHeightChanged(item); + if (item == contentItem) + resizeContent(); + else + updateImplicitContentHeight(); } // adapted from QStyle::alignedRect() @@ -212,7 +223,7 @@ static QRectF alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment qreal y = rectangle.y(); qreal w = size.width(); qreal h = size.height(); - if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter) + if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter || (alignment & Qt::AlignVertical_Mask) == 0) y += (rectangle.size().height() - h) / 2; else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom) y += rectangle.size().height() - h; @@ -230,11 +241,8 @@ void QQuickDialogButtonBoxPrivate::resizeContent() return; QRectF geometry = q->boundingRect().adjusted(q->leftPadding(), q->topPadding(), -q->rightPadding(), -q->bottomPadding()); - if (alignment != 0) { - qreal cw = (alignment & Qt::AlignHorizontal_Mask) == 0 ? q->availableWidth() : contentItem->property("contentWidth").toReal(); - qreal ch = (alignment & Qt::AlignVertical_Mask) == 0 ? q->availableHeight() : contentItem->property("contentHeight").toReal(); - geometry = alignedRect(q->isMirrored() ? Qt::RightToLeft : Qt::LeftToRight, alignment, QSizeF(cw, ch), geometry); - } + if (alignment != 0) + geometry = alignedRect(q->isMirrored() ? Qt::RightToLeft : Qt::LeftToRight, alignment, QSizeF(contentWidth, contentHeight), geometry); contentItem->setPosition(geometry.topLeft()); contentItem->setSize(geometry.size()); @@ -251,8 +259,8 @@ void QQuickDialogButtonBoxPrivate::updateLayout() const int valign = alignment & Qt::AlignVertical_Mask; QVector<QQuickAbstractButton *> buttons; - const qreal maxItemWidth = ((contentItem ? contentItem->width() : q->availableWidth()) - qMax(0, count - 1) * spacing) / count; - const qreal maxItemHeight = contentItem ? contentItem->height() : q->availableHeight(); + const qreal cw = (alignment & Qt::AlignHorizontal_Mask) == 0 ? q->availableWidth() : contentWidth; + const qreal itemWidth = (cw - qMax(0, count - 1) * spacing) / count; for (int i = 0; i < count; ++i) { QQuickItem *item = q->itemAt(i); @@ -260,11 +268,11 @@ void QQuickDialogButtonBoxPrivate::updateLayout() QQuickItemPrivate *p = QQuickItemPrivate::get(item); if (!p->widthValid) { if (!halign) - item->setWidth(maxItemWidth); + item->setWidth(itemWidth); else item->resetWidth(); if (!valign) - item->setHeight(maxItemHeight); + item->setHeight(contentHeight); else item->resetHeight(); p->widthValid = false; @@ -274,6 +282,11 @@ void QQuickDialogButtonBoxPrivate::updateLayout() } struct ButtonLayout { + ButtonLayout(QPlatformDialogHelper::ButtonLayout layout) + : m_layout(QPlatformDialogHelper::buttonLayout(Qt::Horizontal, layout)) + { + } + bool operator()(QQuickAbstractButton *first, QQuickAbstractButton *second) { const QPlatformDialogHelper::ButtonRole firstRole = QQuickDialogPrivate::buttonRole(first); @@ -296,20 +309,47 @@ void QQuickDialogButtonBoxPrivate::updateLayout() return firstRole != QPlatformDialogHelper::InvalidRole; } - static const int *themeButtonLayout() - { - const int hint = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::DialogButtonBoxLayout).toInt(); - return QPlatformDialogHelper::buttonLayout(Qt::Horizontal, static_cast<QPlatformDialogHelper::ButtonLayout>(hint)); - } - const int *m_layout = themeButtonLayout(); + const int *m_layout; }; - std::sort(buttons.begin(), buttons.end(), ButtonLayout()); + std::sort(buttons.begin(), buttons.end(), ButtonLayout(static_cast<QPlatformDialogHelper::ButtonLayout>(buttonLayout))); for (int i = 0; i < buttons.count() - 1; ++i) q->insertItem(i, buttons.at(i)); } +qreal QQuickDialogButtonBoxPrivate::getContentWidth() const +{ + Q_Q(const QQuickDialogButtonBox); + const int count = contentModel->count(); + const qreal totalSpacing = qMax(0, count - 1) * spacing; + qreal totalWidth = totalSpacing; + qreal maxWidth = 0; + for (int i = 0; i < count; ++i) { + QQuickItem *item = q->itemAt(i); + if (item) { + totalWidth += item->implicitWidth(); + maxWidth = qMax(maxWidth, item->implicitWidth()); + } + } + if ((alignment & Qt::AlignHorizontal_Mask) == 0) + totalWidth = qMax(totalWidth, count * maxWidth + totalSpacing); + return totalWidth; +} + +qreal QQuickDialogButtonBoxPrivate::getContentHeight() const +{ + Q_Q(const QQuickDialogButtonBox); + const int count = contentModel->count(); + qreal maxHeight = 0; + for (int i = 0; i < count; ++i) { + QQuickItem *item = q->itemAt(i); + if (item) + maxHeight = qMax(maxHeight, item->implicitHeight()); + } + return maxHeight; +} + void QQuickDialogButtonBoxPrivate::handleClick() { Q_Q(QQuickDialogButtonBox); @@ -405,6 +445,9 @@ void QQuickDialogButtonBoxPrivate::removeStandardButtons() QQuickDialogButtonBox::QQuickDialogButtonBox(QQuickItem *parent) : QQuickContainer(*(new QQuickDialogButtonBoxPrivate), parent) { + Q_D(QQuickDialogButtonBox); + d->changeTypes |= QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight; + d->buttonLayout = platformButtonLayout(); } QQuickDialogButtonBox::~QQuickDialogButtonBox() @@ -596,6 +639,43 @@ QQuickDialogButtonBoxAttached *QQuickDialogButtonBox::qmlAttachedProperties(QObj return new QQuickDialogButtonBoxAttached(object); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty enumeration QtQuick.Controls::DialogButtonBox::buttonLayout + + This property holds the button layout policy to be used when arranging the buttons contained in the button box. + The default value is platform-specific. + + Available values: + \value DialogButtonBox.WinLayout Use a policy appropriate for applications on Windows. + \value DialogButtonBox.MacLayout Use a policy appropriate for applications on macOS. + \value DialogButtonBox.KdeLayout Use a policy appropriate for applications on KDE. + \value DialogButtonBox.GnomeLayout Use a policy appropriate for applications on GNOME. + \value DialogButtonBox.AndroidLayout Use a policy appropriate for applications on Android. +*/ +QQuickDialogButtonBox::ButtonLayout QQuickDialogButtonBox::buttonLayout() const +{ + Q_D(const QQuickDialogButtonBox); + return d->buttonLayout; +} + +void QQuickDialogButtonBox::setButtonLayout(ButtonLayout layout) +{ + Q_D(QQuickDialogButtonBox); + if (d->buttonLayout == layout) + return; + + d->buttonLayout = layout; + if (isComponentComplete()) + d->updateLayout(); + emit buttonLayoutChanged(); +} + +void QQuickDialogButtonBox::resetButtonLayout() +{ + setButtonLayout(platformButtonLayout()); +} + void QQuickDialogButtonBox::updatePolish() { Q_D(QQuickDialogButtonBox); @@ -640,6 +720,7 @@ void QQuickDialogButtonBox::itemAdded(int index, QQuickItem *item) QObjectPrivate::connect(button, &QQuickAbstractButton::clicked, d, &QQuickDialogButtonBoxPrivate::handleClick); if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(item, false))) QQuickDialogButtonBoxAttachedPrivate::get(attached)->setButtonBox(this); + d->updateImplicitContentSize(); if (isComponentComplete()) polish(); } @@ -652,6 +733,7 @@ void QQuickDialogButtonBox::itemRemoved(int index, QQuickItem *item) QObjectPrivate::disconnect(button, &QQuickAbstractButton::clicked, d, &QQuickDialogButtonBoxPrivate::handleClick); if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(item, false))) QQuickDialogButtonBoxAttachedPrivate::get(attached)->setButtonBox(nullptr); + d->updateImplicitContentSize(); if (isComponentComplete()) polish(); } diff --git a/src/quicktemplates2/qquickdialogbuttonbox_p.h b/src/quicktemplates2/qquickdialogbuttonbox_p.h index 1e3cdeef..df302e54 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox_p.h +++ b/src/quicktemplates2/qquickdialogbuttonbox_p.h @@ -66,6 +66,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDialogButtonBox : public QQuickCont Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment RESET resetAlignment NOTIFY alignmentChanged FINAL) Q_PROPERTY(QPlatformDialogHelper::StandardButtons standardButtons READ standardButtons WRITE setStandardButtons NOTIFY standardButtonsChanged FINAL) Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL) + // 2.5 (Qt 5.12) + Q_PROPERTY(ButtonLayout buttonLayout READ buttonLayout WRITE setButtonLayout RESET resetButtonLayout NOTIFY buttonLayoutChanged FINAL REVISION 5) Q_FLAGS(QPlatformDialogHelper::StandardButtons) public: @@ -94,6 +96,24 @@ public: static QQuickDialogButtonBoxAttached *qmlAttachedProperties(QObject *object); + // 2.5 (Qt 5.12) + + // ### TODO: use Q_ENUMS(QPlatformDialogHelper::ButtonLayout) + enum ButtonLayout { + UnknownLayout = -1, + WinLayout, + MacLayout, + KdeLayout, + GnomeLayout, + MacModelessLayout, + AndroidLayout + }; + Q_ENUM(ButtonLayout) + + ButtonLayout buttonLayout() const; + void setButtonLayout(ButtonLayout layout); + void resetButtonLayout(); + Q_SIGNALS: void accepted(); void rejected(); @@ -107,6 +127,8 @@ Q_SIGNALS: Q_REVISION(3) void applied(); Q_REVISION(3) void reset(); Q_REVISION(3) void discarded(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void buttonLayoutChanged(); protected: void updatePolish() override; diff --git a/src/quicktemplates2/qquickdialogbuttonbox_p_p.h b/src/quicktemplates2/qquickdialogbuttonbox_p_p.h index a98a299b..5d64918a 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox_p_p.h +++ b/src/quicktemplates2/qquickdialogbuttonbox_p_p.h @@ -67,7 +67,12 @@ public: void itemImplicitHeightChanged(QQuickItem *item) override; void resizeContent() override; + void updateLayout(); + + qreal getContentWidth() const override; + qreal getContentHeight() const override; + void handleClick(); QQuickAbstractButton *createStandardButton(QPlatformDialogHelper::StandardButton button); @@ -76,6 +81,7 @@ public: Qt::Alignment alignment = 0; QQuickDialogButtonBox::Position position = QQuickDialogButtonBox::Footer; QPlatformDialogHelper::StandardButtons standardButtons = QPlatformDialogHelper::NoButton; + QQuickDialogButtonBox::ButtonLayout buttonLayout = QQuickDialogButtonBox::UnknownLayout; QQmlComponent *delegate = nullptr; }; diff --git a/src/quicktemplates2/qquickdrawer.cpp b/src/quicktemplates2/qquickdrawer.cpp index e06d9bba..f2d74b31 100644 --- a/src/quicktemplates2/qquickdrawer.cpp +++ b/src/quicktemplates2/qquickdrawer.cpp @@ -37,6 +37,7 @@ #include "qquickdrawer_p.h" #include "qquickdrawer_p_p.h" #include "qquickpopupitem_p_p.h" +#include "qquickpopuppositioner_p_p.h" #include <QtGui/qstylehints.h> #include <QtGui/private/qguiapplication_p.h> @@ -171,6 +172,14 @@ QT_BEGIN_NAMESPACE \sa SwipeView, {Customizing Drawer}, {Navigation Controls}, {Popup Controls} */ +class QQuickDrawerPositioner : public QQuickPopupPositioner +{ +public: + QQuickDrawerPositioner(QQuickDrawer *drawer) : QQuickPopupPositioner(drawer) { } + + void reposition() override; +}; + qreal QQuickDrawerPrivate::offsetAt(const QPointF &point) const { qreal offset = positionAt(point) - position; @@ -203,14 +212,24 @@ qreal QQuickDrawerPrivate::positionAt(const QPointF &point) const } } -void QQuickDrawerPrivate::reposition() +QQuickPopupPositioner *QQuickDrawerPrivate::getPositioner() { Q_Q(QQuickDrawer); - QQuickWindow *window = q->window(); + if (!positioner) + positioner = new QQuickDrawerPositioner(q); + return positioner; +} + +void QQuickDrawerPositioner::reposition() +{ + QQuickDrawer *drawer = static_cast<QQuickDrawer*>(popup()); + QQuickWindow *window = drawer->window(); if (!window) return; - switch (edge) { + const qreal position = drawer->position(); + QQuickItem *popupItem = drawer->popupItem(); + switch (drawer->edge()) { case Qt::LeftEdge: popupItem->setX((position - 1.0) * popupItem->width()); break; @@ -225,7 +244,7 @@ void QQuickDrawerPrivate::reposition() break; } - QQuickPopupPrivate::reposition(); + QQuickPopupPositioner::reposition(); } void QQuickDrawerPrivate::showOverlay() diff --git a/src/quicktemplates2/qquickdrawer_p_p.h b/src/quicktemplates2/qquickdrawer_p_p.h index 00055cee..5f1086de 100644 --- a/src/quicktemplates2/qquickdrawer_p_p.h +++ b/src/quicktemplates2/qquickdrawer_p_p.h @@ -67,7 +67,7 @@ public: qreal offsetAt(const QPointF &point) const; qreal positionAt(const QPointF &point) const; - void reposition() override; + QQuickPopupPositioner *getPositioner() override; void showOverlay() override; void hideOverlay() override; void resizeOverlay() override; diff --git a/src/quicktemplates2/qquickgroupbox.cpp b/src/quicktemplates2/qquickgroupbox.cpp index 8cc91f11..7f3c7a2d 100644 --- a/src/quicktemplates2/qquickgroupbox.cpp +++ b/src/quicktemplates2/qquickgroupbox.cpp @@ -92,6 +92,9 @@ public: void cancelLabel(); void executeLabel(bool complete = false); + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + QString title; QQuickDeferredPointer<QQuickItem> label; }; @@ -116,11 +119,33 @@ void QQuickGroupBoxPrivate::executeLabel(bool complete) quickCompleteDeferred(q, labelName(), label); } +void QQuickGroupBoxPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickGroupBox); + QQuickFramePrivate::itemImplicitWidthChanged(item); + if (item == label) + emit q->implicitLabelWidthChanged(); +} + +void QQuickGroupBoxPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickGroupBox); + QQuickFramePrivate::itemImplicitHeightChanged(item); + if (item == label) + emit q->implicitLabelHeightChanged(); +} + QQuickGroupBox::QQuickGroupBox(QQuickItem *parent) : QQuickFrame(*(new QQuickGroupBoxPrivate), parent) { } +QQuickGroupBox::~QQuickGroupBox() +{ + Q_D(QQuickGroupBox); + d->removeImplicitSizeListener(d->label); +} + /*! \qmlproperty string QtQuick.Controls::GroupBox::title @@ -170,14 +195,65 @@ void QQuickGroupBox::setLabel(QQuickItem *label) if (!d->label.isExecuting()) d->cancelLabel(); + const qreal oldImplicitLabelWidth = implicitLabelWidth(); + const qreal oldImplicitLabelHeight = implicitLabelHeight(); + + d->removeImplicitSizeListener(d->label); delete d->label; d->label = label; - if (label && !label->parentItem()) - label->setParentItem(this); + + if (label) { + if (!label->parentItem()) + label->setParentItem(this); + d->addImplicitSizeListener(label); + } + + if (!qFuzzyCompare(oldImplicitLabelWidth, implicitLabelWidth())) + emit implicitLabelWidthChanged(); + if (!qFuzzyCompare(oldImplicitLabelHeight, implicitLabelHeight())) + emit implicitLabelHeightChanged(); if (!d->label.isExecuting()) emit labelChanged(); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::GroupBox::implicitLabelWidth + \readonly + + This property holds the implicit label width. + + The value is equal to \c {label ? label.implicitWidth : 0}. + + \sa implicitLabelHeight +*/ +qreal QQuickGroupBox::implicitLabelWidth() const +{ + Q_D(const QQuickGroupBox); + if (!d->label) + return 0; + return d->label->implicitWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::GroupBox::implicitLabelHeight + \readonly + + This property holds the implicit label height. + + The value is equal to \c {label ? label.implicitHeight : 0}. + + \sa implicitLabelWidth +*/ +qreal QQuickGroupBox::implicitLabelHeight() const +{ + Q_D(const QQuickGroupBox); + if (!d->label) + return 0; + return d->label->implicitHeight(); +} + void QQuickGroupBox::componentComplete() { Q_D(QQuickGroupBox); @@ -187,12 +263,12 @@ void QQuickGroupBox::componentComplete() QFont QQuickGroupBox::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::GroupBoxTitleFont); + return QQuickTheme::font(QQuickTheme::GroupBox); } QPalette QQuickGroupBox::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::GroupBoxPalette); + return QQuickTheme::palette(QQuickTheme::GroupBox); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickgroupbox_p.h b/src/quicktemplates2/qquickgroupbox_p.h index b46d91fd..de36d7d7 100644 --- a/src/quicktemplates2/qquickgroupbox_p.h +++ b/src/quicktemplates2/qquickgroupbox_p.h @@ -59,10 +59,14 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickGroupBox : public QQuickFrame Q_OBJECT Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL) Q_PROPERTY(QQuickItem *label READ label WRITE setLabel NOTIFY labelChanged FINAL) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal implicitLabelWidth READ implicitLabelWidth NOTIFY implicitLabelWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitLabelHeight READ implicitLabelHeight NOTIFY implicitLabelHeightChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background,contentItem,label") public: explicit QQuickGroupBox(QQuickItem *parent = nullptr); + ~QQuickGroupBox(); QString title() const; void setTitle(const QString &title); @@ -70,9 +74,16 @@ public: QQuickItem *label() const; void setLabel(QQuickItem *label); + // 2.5 (Qt 5.12) + qreal implicitLabelWidth() const; + qreal implicitLabelHeight() const; + Q_SIGNALS: void titleChanged(); void labelChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void implicitLabelWidthChanged(); + Q_REVISION(5) void implicitLabelHeightChanged(); protected: void componentComplete() override; diff --git a/src/quicktemplates2/qquickitemdelegate.cpp b/src/quicktemplates2/qquickitemdelegate.cpp index c13cd7ed..ac409118 100644 --- a/src/quicktemplates2/qquickitemdelegate.cpp +++ b/src/quicktemplates2/qquickitemdelegate.cpp @@ -117,12 +117,12 @@ void QQuickItemDelegate::setHighlighted(bool highlighted) QFont QQuickItemDelegate::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::ItemViewFont); + return QQuickTheme::font(QQuickTheme::ItemView); } QPalette QQuickItemDelegate::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::ItemViewPalette); + return QQuickTheme::palette(QQuickTheme::ItemView); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquicklabel.cpp b/src/quicktemplates2/qquicklabel.cpp index 2b23616a..124483fb 100644 --- a/src/quicktemplates2/qquicklabel.cpp +++ b/src/quicktemplates2/qquicklabel.cpp @@ -93,22 +93,76 @@ QQuickLabelPrivate::~QQuickLabelPrivate() #endif } -void QQuickLabelPrivate::resizeBackground() +void QQuickLabelPrivate::setTopInset(qreal value, bool reset) { Q_Q(QQuickLabel); - if (background) { - QQuickItemPrivate *p = QQuickItemPrivate::get(background); - if (!p->widthValid) { - background->setWidth(q->width()); - p->widthValid = false; - } - if (!p->heightValid) { - background->setHeight(q->height()); - p->heightValid = false; - } + 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 @@ -128,7 +182,7 @@ void QQuickLabelPrivate::inheritFont(const QFont &font) QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font; parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve()); - const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::LabelFont); + const QFont defaultFont = QQuickTheme::font(QQuickTheme::Label); const QFont resolvedFont = parentFont.resolve(defaultFont); setFont_helper(resolvedFont); @@ -170,7 +224,7 @@ void QQuickLabelPrivate::inheritPalette(const QPalette &palette) QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette; parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve()); - const QPalette defaultPalette = QQuickControlPrivate::themePalette(QPlatformTheme::LabelPalette); + const QPalette defaultPalette = QQuickTheme::palette(QQuickTheme::Label); const QPalette resolvedPalette = parentPalette.resolve(defaultPalette); setPalette_helper(resolvedPalette); @@ -238,6 +292,42 @@ void QQuickLabelPrivate::executeBackground(bool 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(); + } +} + QQuickLabel::QQuickLabel(QQuickItem *parent) : QQuickText(*(new QQuickLabelPrivate), parent) { @@ -245,6 +335,12 @@ QQuickLabel::QQuickLabel(QQuickItem *parent) 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 { return QQuickText::font(); @@ -288,15 +384,36 @@ void QQuickLabel::setBackground(QQuickItem *background) 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); delete 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(); } @@ -333,6 +450,148 @@ void QQuickLabel::resetPalette() setPalette(QPalette()); } +/*! + \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); @@ -380,4 +639,12 @@ void QQuickLabel::geometryChanged(const QRectF &newGeometry, const QRectF &oldGe 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 diff --git a/src/quicktemplates2/qquicklabel_p.h b/src/quicktemplates2/qquicklabel_p.h index 5486d311..89c9c77b 100644 --- a/src/quicktemplates2/qquicklabel_p.h +++ b/src/quicktemplates2/qquicklabel_p.h @@ -63,10 +63,18 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickLabel : public QQuickText Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL) // 2.3 (Qt 5.10) Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal implicitBackgroundWidth READ implicitBackgroundWidth NOTIFY implicitBackgroundWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitBackgroundHeight READ implicitBackgroundHeight NOTIFY implicitBackgroundHeightChanged FINAL REVISION 5) + Q_PROPERTY(qreal topInset READ topInset WRITE setTopInset RESET resetTopInset NOTIFY topInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal leftInset READ leftInset WRITE setLeftInset RESET resetLeftInset NOTIFY leftInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal rightInset READ rightInset WRITE setRightInset RESET resetRightInset NOTIFY rightInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal bottomInset READ bottomInset WRITE setBottomInset RESET resetBottomInset NOTIFY bottomInsetChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background") public: explicit QQuickLabel(QQuickItem *parent = nullptr); + ~QQuickLabel(); QFont font() const; void setFont(const QFont &font); @@ -79,11 +87,38 @@ public: void setPalette(const QPalette &palette); void resetPalette(); + // 2.5 (Qt 5.12) + qreal implicitBackgroundWidth() const; + qreal implicitBackgroundHeight() const; + + qreal topInset() const; + void setTopInset(qreal inset); + void resetTopInset(); + + qreal leftInset() const; + void setLeftInset(qreal inset); + void resetLeftInset(); + + qreal rightInset() const; + void setRightInset(qreal inset); + void resetRightInset(); + + qreal bottomInset() const; + void setBottomInset(qreal inset); + void resetBottomInset(); + Q_SIGNALS: void fontChanged(); void backgroundChanged(); // 2.3 (Qt 5.10) Q_REVISION(3) void paletteChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void implicitBackgroundWidthChanged(); + Q_REVISION(5) void implicitBackgroundHeightChanged(); + Q_REVISION(5) void topInsetChanged(); + Q_REVISION(5) void leftInsetChanged(); + Q_REVISION(5) void rightInsetChanged(); + Q_REVISION(5) void bottomInsetChanged(); protected: void classBegin() override; @@ -91,6 +126,7 @@ protected: void itemChange(ItemChange change, const ItemChangeData &value) override; void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + virtual void insetChange(const QMarginsF &newInset, const QMarginsF &oldInset); private: Q_DISABLE_COPY(QQuickLabel) diff --git a/src/quicktemplates2/qquicklabel_p_p.h b/src/quicktemplates2/qquicklabel_p_p.h index 4d6c7de7..e1010698 100644 --- a/src/quicktemplates2/qquicklabel_p_p.h +++ b/src/quicktemplates2/qquicklabel_p_p.h @@ -50,6 +50,7 @@ #include <QtQml/private/qlazilyallocated_p.h> #include <QtQuick/private/qquicktext_p_p.h> +#include <QtQuick/private/qquickitemchangelistener_p.h> #include <QtQuickTemplates2/private/qquickdeferredpointer_p_p.h> #if QT_CONFIG(accessibility) @@ -58,7 +59,7 @@ QT_BEGIN_NAMESPACE -class QQuickLabelPrivate : public QQuickTextPrivate +class QQuickLabelPrivate : public QQuickTextPrivate, public QQuickItemChangeListener #if QT_CONFIG(accessibility) , public QAccessible::ActivationObserver #endif @@ -74,6 +75,17 @@ public: return static_cast<QQuickLabelPrivate *>(QObjectPrivate::get(item)); } + inline QMarginsF getInset() const { return QMarginsF(getLeftInset(), getTopInset(), getRightInset(), getBottomInset()); } + inline qreal getTopInset() const { return extra.isAllocated() ? extra->topInset : 0; } + inline qreal getLeftInset() const { return extra.isAllocated() ? extra->leftInset : 0; } + inline qreal getRightInset() const { return extra.isAllocated() ? extra->rightInset : 0; } + inline qreal getBottomInset() const { return extra.isAllocated() ? extra->bottomInset : 0; } + + void setTopInset(qreal value, bool reset = false); + void setLeftInset(qreal value, bool reset = false); + void setRightInset(qreal value, bool reset = false); + void setBottomInset(qreal value, bool reset = false); + void resizeBackground(); void resolveFont(); @@ -104,12 +116,28 @@ public: void cancelBackground(); void executeBackground(bool complete = false); + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + void itemDestroyed(QQuickItem *item) override; + struct ExtraData { + bool hasTopInset = false; + bool hasLeftInset = false; + bool hasRightInset = false; + bool hasBottomInset = false; + bool hasBackgroundWidth = false; + bool hasBackgroundHeight = false; + qreal topInset = 0; + qreal leftInset = 0; + qreal rightInset = 0; + qreal bottomInset = 0; QFont requestedFont; QPalette requestedPalette; }; QLazilyAllocated<ExtraData> extra; + bool resizingBackground = false; QPalette resolvedPalette; QQuickDeferredPointer<QQuickItem> background; }; diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp index ecdd2825..f52405c9 100644 --- a/src/quicktemplates2/qquickmenu.cpp +++ b/src/quicktemplates2/qquickmenu.cpp @@ -40,6 +40,7 @@ #include "qquickmenubaritem_p.h" #include "qquickmenubar_p.h" #include "qquickpopupitem_p_p.h" +#include "qquickpopuppositioner_p_p.h" #include "qquickaction_p.h" #include <QtGui/qevent.h> @@ -183,6 +184,14 @@ static bool shouldCascade() #endif } +class QQuickMenuPositioner : public QQuickPopupPositioner +{ +public: + QQuickMenuPositioner(QQuickMenu *menu) : QQuickPopupPositioner(menu) { } + + void reposition() override; +}; + QQuickMenuPrivate::QQuickMenuPrivate() { Q_Q(QQuickMenu); @@ -355,21 +364,30 @@ void QQuickMenuPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, resizeItems(); } -void QQuickMenuPrivate::reposition() +QQuickPopupPositioner *QQuickMenuPrivate::getPositioner() { Q_Q(QQuickMenu); - if (parentMenu) { - if (cascade) { - if (popupItem->isMirrored()) - q->setPosition(QPointF(-q->width() - parentMenu->leftPadding() + q->overlap(), -q->topPadding())); - else if (parentItem) - q->setPosition(QPointF(parentItem->width() + parentMenu->rightPadding() - q->overlap(), -q->topPadding())); + if (!positioner) + positioner = new QQuickMenuPositioner(q); + return positioner; +} + +void QQuickMenuPositioner::reposition() +{ + QQuickMenu *menu = static_cast<QQuickMenu *>(popup()); + QQuickMenuPrivate *p = QQuickMenuPrivate::get(menu); + if (p->parentMenu) { + if (p->cascade) { + if (p->popupItem->isMirrored()) + menu->setPosition(QPointF(-menu->width() - p->parentMenu->leftPadding() + menu->overlap(), -menu->topPadding())); + else if (p->parentItem) + menu->setPosition(QPointF(p->parentItem->width() + p->parentMenu->rightPadding() - menu->overlap(), -menu->topPadding())); } else { - q->setPosition(QPointF(parentMenu->x() + (parentMenu->width() - q->width()) / 2, - parentMenu->y() + (parentMenu->height() - q->height()) / 2)); + menu->setPosition(QPointF(p->parentMenu->x() + (p->parentMenu->width() - menu->width()) / 2, + p->parentMenu->y() + (p->parentMenu->height() - menu->height()) / 2)); } } - QQuickPopupPrivate::reposition(); + QQuickPopupPositioner::reposition(); } bool QQuickMenuPrivate::prepareEnterTransition() @@ -1426,12 +1444,12 @@ void QQuickMenu::timerEvent(QTimerEvent *event) QFont QQuickMenu::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::MenuFont); + return QQuickTheme::font(QQuickTheme::Menu); } QPalette QQuickMenu::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::MenuPalette); + return QQuickTheme::palette(QQuickTheme::Menu); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickmenu_p_p.h b/src/quicktemplates2/qquickmenu_p_p.h index 83fe3e36..6146b960 100644 --- a/src/quicktemplates2/qquickmenu_p_p.h +++ b/src/quicktemplates2/qquickmenu_p_p.h @@ -93,7 +93,7 @@ public: void itemDestroyed(QQuickItem *item) override; void itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &diff) override; - void reposition() override; + QQuickPopupPositioner *getPositioner() override; bool prepareEnterTransition() override; bool prepareExitTransition() override; bool blockInput(QQuickItem *item, const QPointF &point) const override; diff --git a/src/quicktemplates2/qquickmenubar.cpp b/src/quicktemplates2/qquickmenubar.cpp index efb83a17..6016e70d 100644 --- a/src/quicktemplates2/qquickmenubar.cpp +++ b/src/quicktemplates2/qquickmenubar.cpp @@ -211,49 +211,44 @@ void QQuickMenuBarPrivate::onMenuAboutToHide() activateItem(nullptr); } -void QQuickMenuBarPrivate::updateContentSize() +qreal QQuickMenuBarPrivate::getContentWidth() const { - Q_Q(QQuickMenuBar); - if (hasContentWidth && hasContentHeight) - return; - + Q_Q(const QQuickMenuBar); const int count = contentModel->count(); - if (count <= 0 || !contentItem) - return; - - qreal maxHeight = 0; qreal totalWidth = qMax(0, count - 1) * spacing; - for (int i = 0; i < count; ++i) { QQuickItem *item = q->itemAt(i); - if (item) { - totalWidth += item->width(); - maxHeight = qMax(maxHeight, item->implicitHeight()); - } - } - - bool contentWidthChange = false; - if (!hasContentWidth && !qFuzzyCompare(contentWidth, totalWidth)) { - contentWidth = totalWidth; - contentWidthChange = true; + if (item) + totalWidth += item->implicitWidth(); } + return totalWidth; +} - bool contentHeightChange = false; - if (!hasContentHeight && !qFuzzyCompare(contentHeight, maxHeight)) { - contentHeight = maxHeight; - contentHeightChange = true; +qreal QQuickMenuBarPrivate::getContentHeight() const +{ + Q_Q(const QQuickMenuBar); + const int count = contentModel->count(); + qreal maxHeight = 0; + for (int i = 0; i < count; ++i) { + QQuickItem *item = q->itemAt(i); + if (item) + maxHeight = qMax(maxHeight, item->implicitHeight()); } + return maxHeight; +} - if (contentWidthChange) - emit q->contentWidthChanged(); - if (contentHeightChange) - emit q->contentHeightChanged(); +void QQuickMenuBarPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + QQuickContainerPrivate::itemImplicitWidthChanged(item); + if (item != contentItem) + updateImplicitContentWidth(); } -void QQuickMenuBarPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &) +void QQuickMenuBarPrivate::itemImplicitHeightChanged(QQuickItem *item) { - if ((change.widthChange() && !hasContentWidth) || (change.heightChange() && !hasContentHeight)) - updateContentSize(); + QQuickContainerPrivate::itemImplicitHeightChanged(item); + if (item != contentItem) + updateImplicitContentHeight(); } void QQuickMenuBarPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj) @@ -405,83 +400,30 @@ QQuickMenu *QQuickMenuBar::takeMenu(int index) } /*! + \since QtQuick.Controls 2.3 (Qt 5.10) \qmlproperty real QtQuick.Controls::MenuBar::contentWidth This property holds the content width. It is used for calculating the total implicit width of the menu bar. - Unless explicitly overridden, the content width is automatically calculated - based on the total implicit width of the items and the \l {Control::}{spacing} - of the menu bar. + \note This property is available in MenuBar since QtQuick.Controls 2.3 (Qt 5.10), + but it was promoted to the Container base type in QtQuick.Controls 2.5 (Qt 5.12). - \sa contentHeight + \sa Container::contentWidth */ -qreal QQuickMenuBar::contentWidth() const -{ - Q_D(const QQuickMenuBar); - return d->contentWidth; -} - -void QQuickMenuBar::setContentWidth(qreal width) -{ - Q_D(QQuickMenuBar); - d->hasContentWidth = true; - if (qFuzzyCompare(d->contentWidth, width)) - return; - - d->contentWidth = width; - emit contentWidthChanged(); -} - -void QQuickMenuBar::resetContentWidth() -{ - Q_D(QQuickMenuBar); - if (!d->hasContentWidth) - return; - - d->hasContentWidth = false; - if (isComponentComplete()) - d->updateContentSize(); -} /*! + \since QtQuick.Controls 2.3 (Qt 5.10) \qmlproperty real QtQuick.Controls::MenuBar::contentHeight This property holds the content height. It is used for calculating the total implicit height of the menu bar. - Unless explicitly overridden, the content height is automatically calculated - based on the maximum implicit height of the items. + \note This property is available in MenuBar since QtQuick.Controls 2.3 (Qt 5.10), + but it was promoted to the Container base type in QtQuick.Controls 2.5 (Qt 5.12). - \sa contentWidth + \sa Container::contentHeight */ -qreal QQuickMenuBar::contentHeight() const -{ - Q_D(const QQuickMenuBar); - return d->contentHeight; -} - -void QQuickMenuBar::setContentHeight(qreal height) -{ - Q_D(QQuickMenuBar); - d->hasContentHeight = true; - if (qFuzzyCompare(d->contentHeight, height)) - return; - - d->contentHeight = height; - emit contentHeightChanged(); -} - -void QQuickMenuBar::resetContentHeight() -{ - Q_D(QQuickMenuBar); - if (!d->hasContentHeight) - return; - - d->hasContentHeight = false; - if (isComponentComplete()) - d->updateContentSize(); -} /*! \qmlproperty list<Menu> QtQuick.Controls::MenuBar::menus @@ -492,38 +434,26 @@ void QQuickMenuBar::resetContentHeight() of the menu bar, and also menus that have been dynamically added or inserted using the \l addMenu() and \l insertMenu() methods, respectively. */ -QQmlListProperty<QQuickMenu> QQuickMenuBar::menus() +QQmlListProperty<QQuickMenu> QQuickMenuBarPrivate::menus() { - return QQmlListProperty<QQuickMenu>(this, nullptr, + Q_Q(QQuickMenuBar); + return QQmlListProperty<QQuickMenu>(q, nullptr, QQuickMenuBarPrivate::menus_append, QQuickMenuBarPrivate::menus_count, QQuickMenuBarPrivate::menus_at, QQuickMenuBarPrivate::menus_clear); } -QQmlListProperty<QObject> QQuickMenuBar::contentData() +QQmlListProperty<QObject> QQuickMenuBarPrivate::contentData() { - return QQmlListProperty<QObject>(this, nullptr, + Q_Q(QQuickMenuBar); + return QQmlListProperty<QObject>(q, nullptr, QQuickMenuBarPrivate::contentData_append, QQuickContainerPrivate::contentData_count, QQuickContainerPrivate::contentData_at, QQuickContainerPrivate::contentData_clear); } -void QQuickMenuBar::updatePolish() -{ - Q_D(QQuickMenuBar); - QQuickContainer::updatePolish(); - d->updateContentSize(); -} - -void QQuickMenuBar::componentComplete() -{ - Q_D(QQuickMenuBar); - QQuickContainer::componentComplete(); - d->updateContentSize(); -} - bool QQuickMenuBar::eventFilter(QObject *object, QEvent *event) { return QObject::eventFilter(object, event); @@ -604,10 +534,7 @@ void QQuickMenuBar::itemAdded(int index, QQuickItem *item) if (QQuickMenu *menu = menuBarItem->menu()) QObjectPrivate::connect(menu, &QQuickPopup::aboutToHide, d, &QQuickMenuBarPrivate::onMenuAboutToHide); } - if (isComponentComplete()) - polish(); - if (isComponentComplete()) - polish(); + d->updateImplicitContentSize(); emit menusChanged(); } @@ -628,17 +555,18 @@ void QQuickMenuBar::itemRemoved(int index, QQuickItem *item) if (QQuickMenu *menu = menuBarItem->menu()) QObjectPrivate::disconnect(menu, &QQuickPopup::aboutToHide, d, &QQuickMenuBarPrivate::onMenuAboutToHide); } + d->updateImplicitContentSize(); emit menusChanged(); } QFont QQuickMenuBar::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::MenuBarFont); + return QQuickTheme::font(QQuickTheme::MenuBar); } QPalette QQuickMenuBar::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::MenuBarPalette); + return QQuickTheme::palette(QQuickTheme::MenuBar); } #if QT_CONFIG(accessibility) @@ -649,3 +577,5 @@ QAccessible::Role QQuickMenuBar::accessibleRole() const #endif QT_END_NAMESPACE + +#include "moc_qquickmenubar_p.cpp" diff --git a/src/quicktemplates2/qquickmenubar_p.h b/src/quicktemplates2/qquickmenubar_p.h index 8c703f25..af37d0f2 100644 --- a/src/quicktemplates2/qquickmenubar_p.h +++ b/src/quicktemplates2/qquickmenubar_p.h @@ -59,10 +59,10 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuBar : public QQuickContainer { Q_OBJECT Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL) - Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL) - Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL) - Q_PROPERTY(QQmlListProperty<QQuickMenu> menus READ menus NOTIFY menusChanged FINAL) - Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) + Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL) // re-declare QQuickContainer::contentWidth (REV 5) + Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL) // re-declare QQuickContainer::contentHeight (REV 5) + Q_PRIVATE_PROPERTY(QQuickMenuBar::d_func(), QQmlListProperty<QQuickMenu> menus READ menus NOTIFY menusChanged FINAL) + Q_PRIVATE_PROPERTY(QQuickMenuBar::d_func(), QQmlListProperty<QObject> contentData READ contentData FINAL) public: explicit QQuickMenuBar(QQuickItem *parent = nullptr); @@ -76,27 +76,11 @@ public: Q_INVOKABLE void removeMenu(QQuickMenu *menu); Q_INVOKABLE QQuickMenu *takeMenu(int index); - qreal contentWidth() const; - void setContentWidth(qreal width); - void resetContentWidth(); - - qreal contentHeight() const; - void setContentHeight(qreal height); - void resetContentHeight(); - - QQmlListProperty<QQuickMenu> menus(); - QQmlListProperty<QObject> contentData(); - Q_SIGNALS: void delegateChanged(); - void contentWidthChanged(); - void contentHeightChanged(); void menusChanged(); protected: - void updatePolish() override; - void componentComplete() override; - bool eventFilter(QObject *object, QEvent *event) override; void keyPressEvent(QKeyEvent *event) override; void keyReleaseEvent(QKeyEvent *event) override; diff --git a/src/quicktemplates2/qquickmenubar_p_p.h b/src/quicktemplates2/qquickmenubar_p_p.h index b6fdc9eb..75fbed73 100644 --- a/src/quicktemplates2/qquickmenubar_p_p.h +++ b/src/quicktemplates2/qquickmenubar_p_p.h @@ -66,6 +66,9 @@ public: return menuBar->d_func(); } + QQmlListProperty<QQuickMenu> menus(); + QQmlListProperty<QObject> contentData(); + QQuickItem *beginCreateItem(); void completeCreateItem(); @@ -80,8 +83,11 @@ public: void onItemTriggered(); void onMenuAboutToHide(); - void updateContentSize(); - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; + qreal getContentWidth() const override; + qreal getContentHeight() const override; + + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; static void contentData_append(QQmlListProperty<QObject> *prop, QObject *obj); @@ -92,10 +98,6 @@ public: bool popupMode = false; bool triggering = false; - bool hasContentWidth = false; - bool hasContentHeight = false; - qreal contentWidth = 0; - qreal contentHeight = 0; QQmlComponent *delegate = nullptr; QPointer<QQuickMenuBarItem> currentItem; }; diff --git a/src/quicktemplates2/qquickmenubaritem.cpp b/src/quicktemplates2/qquickmenubaritem.cpp index cbf490b8..f32baff5 100644 --- a/src/quicktemplates2/qquickmenubaritem.cpp +++ b/src/quicktemplates2/qquickmenubaritem.cpp @@ -167,12 +167,12 @@ void QQuickMenuBarItem::geometryChanged(const QRectF &newGeometry, const QRectF QFont QQuickMenuBarItem::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::MenuBarFont); + return QQuickTheme::font(QQuickTheme::MenuBar); } QPalette QQuickMenuBarItem::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::MenuBarPalette); + return QQuickTheme::palette(QQuickTheme::MenuBar); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickmenuitem.cpp b/src/quicktemplates2/qquickmenuitem.cpp index 7a7b9b0b..b02b8e60 100644 --- a/src/quicktemplates2/qquickmenuitem.cpp +++ b/src/quicktemplates2/qquickmenuitem.cpp @@ -256,12 +256,12 @@ void QQuickMenuItem::componentComplete() QFont QQuickMenuItem::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::MenuItemFont); + return QQuickTheme::font(QQuickTheme::Menu); } QPalette QQuickMenuItem::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::MenuPalette); + return QQuickTheme::palette(QQuickTheme::Menu); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickmenuseparator.cpp b/src/quicktemplates2/qquickmenuseparator.cpp index dee5287a..0e2ed9e3 100644 --- a/src/quicktemplates2/qquickmenuseparator.cpp +++ b/src/quicktemplates2/qquickmenuseparator.cpp @@ -71,9 +71,14 @@ QQuickMenuSeparator::QQuickMenuSeparator(QQuickItem *parent) { } +QFont QQuickMenuSeparator::defaultFont() const +{ + return QQuickTheme::font(QQuickTheme::Menu); +} + QPalette QQuickMenuSeparator::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::MenuPalette); + return QQuickTheme::palette(QQuickTheme::Menu); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickmenuseparator_p.h b/src/quicktemplates2/qquickmenuseparator_p.h index 002b68ba..1e687fd0 100644 --- a/src/quicktemplates2/qquickmenuseparator_p.h +++ b/src/quicktemplates2/qquickmenuseparator_p.h @@ -60,6 +60,7 @@ public: explicit QQuickMenuSeparator(QQuickItem *parent = nullptr); protected: + QFont defaultFont() const override; QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp index eba31fe2..43dfa682 100644 --- a/src/quicktemplates2/qquickoverlay.cpp +++ b/src/quicktemplates2/qquickoverlay.cpp @@ -370,7 +370,7 @@ QQuickOverlay *QQuickOverlay::overlay(QQuickWindow *window) QQuickItem *content = window->contentItem(); // Do not re-create the overlay if the window is being destroyed // and thus, its content item no longer has a window associated. - if (content->window()) { + if (content && content->window()) { overlay = new QQuickOverlay(window->contentItem()); window->setProperty(name, QVariant::fromValue(overlay)); } diff --git a/src/quicktemplates2/qquickpage.cpp b/src/quicktemplates2/qquickpage.cpp index 25dce5e6..93196c4c 100644 --- a/src/quicktemplates2/qquickpage.cpp +++ b/src/quicktemplates2/qquickpage.cpp @@ -35,14 +35,16 @@ ****************************************************************************/ #include "qquickpage_p.h" -#include "qquickcontrol_p_p.h" -#include "qquickpagelayout_p_p.h" +#include "qquickpage_p_p.h" +#include "qquicktabbar_p.h" +#include "qquicktoolbar_p.h" +#include "qquickdialogbuttonbox_p.h" QT_BEGIN_NAMESPACE /*! \qmltype Page - \inherits Control + \inherits Pane \instantiates QQuickPage \inqmlmodule QtQuick.Controls \since 5.7 @@ -84,37 +86,142 @@ QT_BEGIN_NAMESPACE {Focus Management in Qt Quick Controls 2} */ -class QQuickPagePrivate : public QQuickControlPrivate +static const QQuickItemPrivate::ChangeTypes LayoutChanges = QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility | QQuickItemPrivate::Destroyed + | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight; + +namespace { + enum Position { + Header, + Footer + }; + + Q_STATIC_ASSERT(int(Header) == int(QQuickTabBar::Header)); + Q_STATIC_ASSERT(int(Footer) == int(QQuickTabBar::Footer)); + + Q_STATIC_ASSERT(int(Header) == int(QQuickToolBar::Header)); + Q_STATIC_ASSERT(int(Footer) == int(QQuickToolBar::Footer)); + + Q_STATIC_ASSERT(int(Header) == int(QQuickDialogButtonBox::Header)); + Q_STATIC_ASSERT(int(Footer) == int(QQuickDialogButtonBox::Footer)); + + static void setPos(QQuickItem *item, Position position) + { + if (QQuickToolBar *toolBar = qobject_cast<QQuickToolBar *>(item)) + toolBar->setPosition(static_cast<QQuickToolBar::Position>(position)); + else if (QQuickTabBar *tabBar = qobject_cast<QQuickTabBar *>(item)) + tabBar->setPosition(static_cast<QQuickTabBar::Position>(position)); + else if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(item)) + buttonBox->setPosition(static_cast<QQuickDialogButtonBox::Position>(position)); + } +} + +void QQuickPagePrivate::relayout() { - Q_DECLARE_PUBLIC(QQuickPage) + Q_Q(QQuickPage); + const qreal hh = header && header->isVisible() ? header->height() : 0; + const qreal fh = footer && footer->isVisible() ? footer->height() : 0; + const qreal hsp = hh > 0 ? spacing : 0; + const qreal fsp = fh > 0 ? spacing : 0; + + if (contentItem) { + contentItem->setY(q->topPadding() + hh + hsp); + contentItem->setX(q->leftPadding()); + contentItem->setWidth(q->availableWidth()); + contentItem->setHeight(q->availableHeight() - hh - fh - hsp - fsp); + } -public: - QQuickItem *getContentItem() override; + if (header) + header->setWidth(q->width()); - qreal contentWidth = 0; - qreal contentHeight = 0; - QString title; - QScopedPointer<QQuickPageLayout> layout; -}; + if (footer) { + footer->setY(q->height() - footer->height()); + footer->setWidth(q->width()); + } +} + +void QQuickPagePrivate::resizeContent() +{ + relayout(); +} -QQuickItem *QQuickPagePrivate::getContentItem() +void QQuickPagePrivate::itemVisibilityChanged(QQuickItem *item) { Q_Q(QQuickPage); - if (QQuickItem *item = QQuickControlPrivate::getContentItem()) - return item; - return new QQuickItem(q); + QQuickPanePrivate::itemVisibilityChanged(item); + if (item == header) { + emit q->implicitHeaderWidthChanged(); + emit q->implicitHeaderHeightChanged(); + relayout(); + } else if (item == footer) { + emit q->implicitFooterWidthChanged(); + emit q->implicitFooterHeightChanged(); + relayout(); + } +} + +void QQuickPagePrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickPage); + QQuickPanePrivate::itemImplicitWidthChanged(item); + if (item == header) + emit q->implicitHeaderWidthChanged(); + else if (item == footer) + emit q->implicitFooterWidthChanged(); +} + +void QQuickPagePrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickPage); + QQuickPanePrivate::itemImplicitHeightChanged(item); + if (item == header) + emit q->implicitHeaderHeightChanged(); + else if (item == footer) + emit q->implicitFooterHeightChanged(); +} + +void QQuickPagePrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF & diff) +{ + QQuickPanePrivate::itemGeometryChanged(item, change, diff); + if (item == header || item == footer) + relayout(); +} + +void QQuickPagePrivate::itemDestroyed(QQuickItem *item) +{ + Q_Q(QQuickPage); + QQuickPanePrivate::itemDestroyed(item); + if (item == header) { + header = nullptr; + relayout(); + emit q->implicitHeaderWidthChanged(); + emit q->implicitHeaderHeightChanged(); + emit q->headerChanged(); + } else if (item == footer) { + footer = nullptr; + relayout(); + emit q->implicitFooterWidthChanged(); + emit q->implicitFooterHeightChanged(); + emit q->footerChanged(); + } } QQuickPage::QQuickPage(QQuickItem *parent) - : QQuickControl(*(new QQuickPagePrivate), parent) + : QQuickPane(*(new QQuickPagePrivate), parent) +{ +} + +QQuickPage::QQuickPage(QQuickPagePrivate &dd, QQuickItem *parent) + : QQuickPane(dd, parent) +{ +} + +QQuickPage::~QQuickPage() { Q_D(QQuickPage); - setFlag(ItemIsFocusScope); - setAcceptedMouseButtons(Qt::AllButtons); -#if QT_CONFIG(cursor) - setCursor(Qt::ArrowCursor); -#endif - d->layout.reset(new QQuickPageLayout(this)); + if (d->header) + QQuickItemPrivate::get(d->header)->removeItemChangeListener(d, LayoutChanges); + if (d->footer) + QQuickItemPrivate::get(d->footer)->removeItemChangeListener(d, LayoutChanges); } /*! @@ -185,16 +292,29 @@ void QQuickPage::setTitle(const QString &title) QQuickItem *QQuickPage::header() const { Q_D(const QQuickPage); - return d->layout->header(); + return d->header; } void QQuickPage::setHeader(QQuickItem *header) { Q_D(QQuickPage); - if (!d->layout->setHeader(header)) + if (d->header == header) return; + + if (d->header) { + QQuickItemPrivate::get(d->header)->removeItemChangeListener(d, LayoutChanges); + d->header->setParentItem(nullptr); + } + d->header = header; + if (header) { + header->setParentItem(this); + QQuickItemPrivate::get(header)->addItemChangeListener(d, LayoutChanges); + if (qFuzzyIsNull(header->z())) + header->setZ(1); + setPos(header, Header); + } if (isComponentComplete()) - d->layout->update(); + d->relayout(); emit headerChanged(); } @@ -213,150 +333,120 @@ void QQuickPage::setHeader(QQuickItem *header) QQuickItem *QQuickPage::footer() const { Q_D(const QQuickPage); - return d->layout->footer(); + return d->footer; } void QQuickPage::setFooter(QQuickItem *footer) { Q_D(QQuickPage); - if (!d->layout->setFooter(footer)) + if (d->footer == footer) return; + + if (d->footer) { + QQuickItemPrivate::get(d->footer)->removeItemChangeListener(d, LayoutChanges); + footer->setParentItem(nullptr); + } + d->footer = footer; + if (footer) { + footer->setParentItem(this); + QQuickItemPrivate::get(footer)->addItemChangeListener(d, LayoutChanges); + if (qFuzzyIsNull(footer->z())) + footer->setZ(1); + setPos(footer, Footer); + } if (isComponentComplete()) - d->layout->update(); + d->relayout(); emit footerChanged(); } /*! - \qmlproperty list<Object> QtQuick.Controls::Page::contentData - \default + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Page::implicitHeaderWidth + \readonly - This property holds the list of content data. + This property holds the implicit header width. - The list contains all objects that have been declared in QML as children - of the container. + The value is equal to \c {header && header.visible ? header.implicitWidth : 0}. - \note Unlike \c contentChildren, \c contentData does include non-visual QML - objects. - - \sa Item::data, contentChildren + \sa implicitHeaderHeight, implicitFooterWidth */ -QQmlListProperty<QObject> QQuickPage::contentData() +qreal QQuickPage::implicitHeaderWidth() const { - return QQmlListProperty<QObject>(contentItem(), nullptr, - QQuickItemPrivate::data_append, - QQuickItemPrivate::data_count, - QQuickItemPrivate::data_at, - QQuickItemPrivate::data_clear); + Q_D(const QQuickPage); + if (!d->header || !d->header->isVisible()) + return 0; + return d->header->implicitWidth(); } /*! - \qmlproperty list<Item> QtQuick.Controls::Page::contentChildren + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Page::implicitHeaderHeight + \readonly - This property holds the list of content children. + This property holds the implicit header height. - The list contains all items that have been declared in QML as children - of the page. + The value is equal to \c {header && header.visible ? header.implicitHeight : 0}. - \note Unlike \c contentData, \c contentChildren does not include non-visual - QML objects. - - \sa Item::children, contentData + \sa implicitHeaderWidth, implicitFooterHeight */ -QQmlListProperty<QQuickItem> QQuickPage::contentChildren() +qreal QQuickPage::implicitHeaderHeight() const { - return QQmlListProperty<QQuickItem>(contentItem(), nullptr, - QQuickItemPrivate::children_append, - QQuickItemPrivate::children_count, - QQuickItemPrivate::children_at, - QQuickItemPrivate::children_clear); + Q_D(const QQuickPage); + if (!d->header || !d->header->isVisible()) + return 0; + return d->header->implicitHeight(); } /*! - \qmlproperty real QtQuick.Controls::Page::contentWidth - \since QtQuick.Controls 2.1 (Qt 5.8) + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Page::implicitFooterWidth + \readonly + + This property holds the implicit footer width. - This property holds the content width. It is used for calculating the total - implicit width of the page. + The value is equal to \c {footer && footer.visible ? footer.implicitWidth : 0}. - \sa contentHeight + \sa implicitFooterHeight, implicitHeaderWidth */ -qreal QQuickPage::contentWidth() const +qreal QQuickPage::implicitFooterWidth() const { Q_D(const QQuickPage); - return d->contentWidth; -} - -void QQuickPage::setContentWidth(qreal width) -{ - Q_D(QQuickPage); - if (qFuzzyCompare(d->contentWidth, width)) - return; - - d->contentWidth = width; - emit contentWidthChanged(); + if (!d->footer || !d->footer->isVisible()) + return 0; + return d->footer->implicitWidth(); } /*! - \qmlproperty real QtQuick.Controls::Page::contentHeight - \since QtQuick.Controls 2.1 (Qt 5.8) + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Page::implicitFooterHeight + \readonly - This property holds the content height. It is used for calculating the total - implicit height of the page. + This property holds the implicit footer height. - \sa contentWidth + The value is equal to \c {footer && footer.visible ? footer.implicitHeight : 0}. + + \sa implicitFooterWidth, implicitHeaderHeight */ -qreal QQuickPage::contentHeight() const +qreal QQuickPage::implicitFooterHeight() const { Q_D(const QQuickPage); - return d->contentHeight; -} - -void QQuickPage::setContentHeight(qreal height) -{ - Q_D(QQuickPage); - if (qFuzzyCompare(d->contentHeight, height)) - return; - - d->contentHeight = height; - emit contentHeightChanged(); + if (!d->footer || !d->footer->isVisible()) + return 0; + return d->footer->implicitHeight(); } void QQuickPage::componentComplete() { Q_D(QQuickPage); - QQuickControl::componentComplete(); - d->layout->update(); -} - -void QQuickPage::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) -{ - QQuickControl::contentItemChange(newItem, oldItem); - if (oldItem) - disconnect(oldItem, &QQuickItem::childrenChanged, this, &QQuickPage::contentChildrenChanged); - if (newItem) - connect(newItem, &QQuickItem::childrenChanged, this, &QQuickPage::contentChildrenChanged); - emit contentChildrenChanged(); -} - -void QQuickPage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) -{ - Q_D(QQuickPage); - QQuickControl::geometryChanged(newGeometry, oldGeometry); - d->layout->update(); -} - -void QQuickPage::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) -{ - Q_D(QQuickPage); - QQuickControl::paddingChange(newPadding, oldPadding); - d->layout->update(); + QQuickPane::componentComplete(); + d->relayout(); } void QQuickPage::spacingChange(qreal newSpacing, qreal oldSpacing) { Q_D(QQuickPage); - QQuickControl::spacingChange(newSpacing, oldSpacing); - d->layout->update(); + QQuickPane::spacingChange(newSpacing, oldSpacing); + d->relayout(); } #if QT_CONFIG(accessibility) @@ -368,7 +458,7 @@ QAccessible::Role QQuickPage::accessibleRole() const void QQuickPage::accessibilityActiveChanged(bool active) { Q_D(QQuickPage); - QQuickControl::accessibilityActiveChanged(active); + QQuickPane::accessibilityActiveChanged(active); if (active) setAccessibleName(d->title); diff --git a/src/quicktemplates2/qquickpage_p.h b/src/quicktemplates2/qquickpage_p.h index 0789e996..b7888ad6 100644 --- a/src/quicktemplates2/qquickpage_p.h +++ b/src/quicktemplates2/qquickpage_p.h @@ -48,28 +48,31 @@ // We mean it. // -#include <QtQuickTemplates2/private/qquickcontrol_p.h> +#include <QtQuickTemplates2/private/qquickpane_p.h> #include <QtQml/qqmllist.h> QT_BEGIN_NAMESPACE class QQuickPagePrivate; -class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPage : public QQuickControl +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPage : public QQuickPane { Q_OBJECT Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL) Q_PROPERTY(QQuickItem *header READ header WRITE setHeader NOTIFY headerChanged FINAL) Q_PROPERTY(QQuickItem *footer READ footer WRITE setFooter NOTIFY footerChanged FINAL) - Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) - Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL) // 2.1 (Qt 5.8) Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged FINAL REVISION 1) Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged FINAL REVISION 1) - Q_CLASSINFO("DefaultProperty", "contentData") + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal implicitHeaderWidth READ implicitHeaderWidth NOTIFY implicitHeaderWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitHeaderHeight READ implicitHeaderHeight NOTIFY implicitHeaderHeightChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitFooterWidth READ implicitFooterWidth NOTIFY implicitFooterWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitFooterHeight READ implicitFooterHeight NOTIFY implicitFooterHeightChanged FINAL REVISION 5) public: explicit QQuickPage(QQuickItem *parent = nullptr); + ~QQuickPage(); QString title() const; void setTitle(const QString &title); @@ -80,31 +83,28 @@ public: QQuickItem *footer() const; void setFooter(QQuickItem *footer); - QQmlListProperty<QObject> contentData(); - QQmlListProperty<QQuickItem> contentChildren(); + // 2.5 (Qt 5.12) + qreal implicitHeaderWidth() const; + qreal implicitHeaderHeight() const; - // 2.1 (Qt 5.8) - qreal contentWidth() const; - void setContentWidth(qreal width); - - qreal contentHeight() const; - void setContentHeight(qreal height); + qreal implicitFooterWidth() const; + qreal implicitFooterHeight() const; Q_SIGNALS: void titleChanged(); void headerChanged(); void footerChanged(); - void contentChildrenChanged(); - // 2.1 (Qt 5.8) - Q_REVISION(1) void contentWidthChanged(); - Q_REVISION(1) void contentHeightChanged(); + // 2.5 (Qt 5.12) + void implicitHeaderWidthChanged(); + void implicitHeaderHeightChanged(); + void implicitFooterWidthChanged(); + void implicitFooterHeightChanged(); protected: + QQuickPage(QQuickPagePrivate &dd, QQuickItem *parent); + void componentComplete() override; - void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override; - void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; - void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override; void spacingChange(qreal newSpacing, qreal oldSpacing) override; #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickpagelayout_p_p.h b/src/quicktemplates2/qquickpage_p_p.h index a3807b62..b7d89ac4 100644 --- a/src/quicktemplates2/qquickpagelayout_p_p.h +++ b/src/quicktemplates2/qquickpage_p_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#ifndef QQUICKPAGELAYOUT_P_P_H -#define QQUICKPAGELAYOUT_P_P_H +#ifndef QQUICKPAGE_P_P_H +#define QQUICKPAGE_P_P_H // // W A R N I N G @@ -48,39 +48,31 @@ // We mean it. // -#include <QtQuick/private/qquickitemchangelistener_p.h> +#include <QtQuickTemplates2/private/qquickpane_p_p.h> QT_BEGIN_NAMESPACE -class QQuickControl; +class QQuickPane; -class QQuickPageLayout : public QQuickItemChangeListener +class QQuickPagePrivate : public QQuickPanePrivate { -public: - explicit QQuickPageLayout(QQuickControl *control); - ~QQuickPageLayout(); - - QQuickItem *header() const; - bool setHeader(QQuickItem *header); + Q_DECLARE_PUBLIC(QQuickPage) - QQuickItem *footer() const; - bool setFooter(QQuickItem *footer); - - void update(); +public: + void relayout(); + void resizeContent() override; -protected: void itemVisibilityChanged(QQuickItem *item) override; void itemImplicitWidthChanged(QQuickItem *item) override; void itemImplicitHeightChanged(QQuickItem *item) override; - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF & diff) override; void itemDestroyed(QQuickItem *item) override; -private: - QQuickItem *m_header = nullptr; - QQuickItem *m_footer = nullptr; - QQuickControl *m_control = nullptr; + QString title; + QQuickItem *header = nullptr; + QQuickItem *footer = nullptr; }; QT_END_NAMESPACE -#endif // QQUICKPAGELAYOUT_P_P_H +#endif // QQUICKPAGE_P_P_H diff --git a/src/quicktemplates2/qquickpageindicator.cpp b/src/quicktemplates2/qquickpageindicator.cpp index dd90402e..d29158a8 100644 --- a/src/quicktemplates2/qquickpageindicator.cpp +++ b/src/quicktemplates2/qquickpageindicator.cpp @@ -39,7 +39,6 @@ #include <QtCore/qmath.h> #include <QtQuick/private/qquickitem_p.h> -#include <QtQuick/private/qquickitemchangelistener_p.h> QT_BEGIN_NAMESPACE @@ -84,7 +83,7 @@ QT_BEGIN_NAMESPACE \sa SwipeView, {Customizing PageIndicator}, {Indicator Controls} */ -class QQuickPageIndicatorPrivate : public QQuickControlPrivate, public QQuickItemChangeListener +class QQuickPageIndicatorPrivate : public QQuickControlPrivate { Q_DECLARE_PUBLIC(QQuickPageIndicator) diff --git a/src/quicktemplates2/qquickpagelayout.cpp b/src/quicktemplates2/qquickpagelayout.cpp deleted file mode 100644 index 6312cc97..00000000 --- a/src/quicktemplates2/qquickpagelayout.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickpagelayout_p_p.h" -#include "qquickcontrol_p.h" -#include "qquickcontrol_p_p.h" -#include "qquicktoolbar_p.h" -#include "qquicktabbar_p.h" -#include "qquickdialogbuttonbox_p.h" - -#include <QtQuick/private/qquickitem_p.h> - -QT_BEGIN_NAMESPACE - -static const QQuickItemPrivate::ChangeTypes ItemChanges = QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility | QQuickItemPrivate::Destroyed - | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight; - -namespace { - enum Position { - Header, - Footer - }; - - Q_STATIC_ASSERT(int(Header) == int(QQuickTabBar::Header)); - Q_STATIC_ASSERT(int(Footer) == int(QQuickTabBar::Footer)); - - Q_STATIC_ASSERT(int(Header) == int(QQuickToolBar::Header)); - Q_STATIC_ASSERT(int(Footer) == int(QQuickToolBar::Footer)); - - Q_STATIC_ASSERT(int(Header) == int(QQuickDialogButtonBox::Header)); - Q_STATIC_ASSERT(int(Footer) == int(QQuickDialogButtonBox::Footer)); -} - -static void setPosition(QQuickItem *item, Position position) -{ - if (QQuickToolBar *toolBar = qobject_cast<QQuickToolBar *>(item)) - toolBar->setPosition(static_cast<QQuickToolBar::Position>(position)); - else if (QQuickTabBar *tabBar = qobject_cast<QQuickTabBar *>(item)) - tabBar->setPosition(static_cast<QQuickTabBar::Position>(position)); - else if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(item)) - buttonBox->setPosition(static_cast<QQuickDialogButtonBox::Position>(position)); -} - -QQuickPageLayout::QQuickPageLayout(QQuickControl *control) - : m_control(control) -{ -} - -QQuickPageLayout::~QQuickPageLayout() -{ - if (m_header) - QQuickItemPrivate::get(m_header)->removeItemChangeListener(this, ItemChanges); - if (m_footer) - QQuickItemPrivate::get(m_footer)->removeItemChangeListener(this, ItemChanges); -} - -QQuickItem *QQuickPageLayout::header() const -{ - return m_header; -} - -bool QQuickPageLayout::setHeader(QQuickItem *header) -{ - if (m_header == header) - return false; - - if (m_header) { - QQuickItemPrivate::get(m_header)->removeItemChangeListener(this, ItemChanges); - m_header->setParentItem(nullptr); - } - m_header = header; - if (header) { - header->setParentItem(m_control); - QQuickItemPrivate::get(header)->addItemChangeListener(this, ItemChanges); - if (qFuzzyIsNull(header->z())) - header->setZ(1); - setPosition(header, Header); - } - return true; -} - -QQuickItem *QQuickPageLayout::footer() const -{ - return m_footer; -} - -bool QQuickPageLayout::setFooter(QQuickItem *footer) -{ - if (m_footer == footer) - return false; - - if (m_footer) { - QQuickItemPrivate::get(m_footer)->removeItemChangeListener(this, ItemChanges); - m_footer->setParentItem(nullptr); - } - m_footer = footer; - if (footer) { - footer->setParentItem(m_control); - QQuickItemPrivate::get(footer)->addItemChangeListener(this, ItemChanges); - if (qFuzzyIsNull(footer->z())) - footer->setZ(1); - setPosition(footer, Footer); - } - return true; -} - -void QQuickPageLayout::update() -{ - QQuickItem *content = QQuickControlPrivate::get(m_control)->contentItem; - - const qreal hh = m_header && m_header->isVisible() ? m_header->height() : 0; - const qreal fh = m_footer && m_footer->isVisible() ? m_footer->height() : 0; - const qreal hsp = hh > 0 ? m_control->spacing() : 0; - const qreal fsp = fh > 0 ? m_control->spacing() : 0; - - if (content) { - content->setY(m_control->topPadding() + hh + hsp); - content->setX(m_control->leftPadding()); - content->setWidth(m_control->availableWidth()); - content->setHeight(m_control->availableHeight() - hh - fh - hsp - fsp); - } - - if (m_header) - m_header->setWidth(m_control->width()); - - if (m_footer) { - m_footer->setY(m_control->height() - m_footer->height()); - m_footer->setWidth(m_control->width()); - } -} - -void QQuickPageLayout::itemVisibilityChanged(QQuickItem *) -{ - update(); -} - -void QQuickPageLayout::itemImplicitWidthChanged(QQuickItem *) -{ - update(); -} - -void QQuickPageLayout::itemImplicitHeightChanged(QQuickItem *) -{ - update(); -} - -void QQuickPageLayout::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) -{ - update(); -} - -void QQuickPageLayout::itemDestroyed(QQuickItem *item) -{ - if (item == m_header) - m_header = nullptr; - else if (item == m_footer) - m_footer = nullptr; -} - -QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickpane.cpp b/src/quicktemplates2/qquickpane.cpp index 7d3754de..d923267f 100644 --- a/src/quicktemplates2/qquickpane.cpp +++ b/src/quicktemplates2/qquickpane.cpp @@ -36,6 +36,7 @@ #include "qquickpane_p.h" #include "qquickpane_p_p.h" +#include "qquickcontentitem_p.h" QT_BEGIN_NAMESPACE @@ -106,32 +107,142 @@ QT_BEGIN_NAMESPACE {Focus Management in Qt Quick Controls 2} */ +void QQuickPanePrivate::init() +{ + Q_Q(QQuickPane); + q->setFlag(QQuickItem::ItemIsFocusScope); + q->setAcceptedMouseButtons(Qt::AllButtons); +#if QT_CONFIG(cursor) + q->setCursor(Qt::ArrowCursor); +#endif + connect(q, &QQuickControl::implicitContentWidthChanged, this, &QQuickPanePrivate::updateContentWidth); + connect(q, &QQuickControl::implicitContentHeightChanged, this, &QQuickPanePrivate::updateContentHeight); +} + +QList<QQuickItem *> QQuickPanePrivate::contentChildItems() const +{ + if (!contentItem) + return QList<QQuickItem *>(); + + return contentItem->childItems(); +} + QQuickItem *QQuickPanePrivate::getContentItem() { Q_Q(QQuickPane); if (QQuickItem *item = QQuickControlPrivate::getContentItem()) return item; - return new QQuickItem(q); + + return new QQuickContentItem(q); +} + +void QQuickPanePrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + QQuickControlPrivate::itemImplicitWidthChanged(item); + + if (item == firstChild) + updateImplicitContentWidth(); +} + +void QQuickPanePrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + QQuickControlPrivate::itemImplicitHeightChanged(item); + + if (item == firstChild) + updateImplicitContentHeight(); +} + +void QQuickPanePrivate::contentChildrenChange() +{ + Q_Q(QQuickPane); + QQuickItem *newFirstChild = contentChildItems().value(0); + if (newFirstChild != firstChild) { + if (firstChild) + removeImplicitSizeListener(firstChild); + if (newFirstChild) + addImplicitSizeListener(newFirstChild); + firstChild = newFirstChild; + } + + updateImplicitContentSize(); + emit q->contentChildrenChanged(); +} + +qreal QQuickPanePrivate::getContentWidth() const +{ + if (!contentItem) + return 0; + + const qreal cw = contentItem->implicitWidth(); + if (!qFuzzyIsNull(cw)) + return cw; + + const auto contentChildren = contentChildItems(); + if (contentChildren.count() == 1) + return contentChildren.first()->implicitWidth(); + + return 0; +} + +qreal QQuickPanePrivate::getContentHeight() const +{ + if (!contentItem) + return 0; + + const qreal ch = contentItem->implicitHeight(); + if (!qFuzzyIsNull(ch)) + return ch; + + const auto contentChildren = contentChildItems(); + if (contentChildren.count() == 1) + return contentChildren.first()->implicitHeight(); + + return 0; +} + +void QQuickPanePrivate::updateContentWidth() +{ + Q_Q(QQuickPane); + if (hasContentWidth || qFuzzyCompare(contentWidth, implicitContentWidth)) + return; + + const qreal oldContentWidth = contentWidth; + contentWidth = implicitContentWidth; + q->contentSizeChange(QSizeF(contentWidth, contentHeight), QSizeF(oldContentWidth, contentHeight)); + emit q->contentWidthChanged(); +} + +void QQuickPanePrivate::updateContentHeight() +{ + Q_Q(QQuickPane); + if (hasContentHeight || qFuzzyCompare(contentHeight, implicitContentHeight)) + return; + + const qreal oldContentHeight = contentHeight; + contentHeight = implicitContentHeight; + q->contentSizeChange(QSizeF(contentWidth, contentHeight), QSizeF(contentWidth, oldContentHeight)); + emit q->contentHeightChanged(); } QQuickPane::QQuickPane(QQuickItem *parent) : QQuickControl(*(new QQuickPanePrivate), parent) { - setFlag(QQuickItem::ItemIsFocusScope); - setAcceptedMouseButtons(Qt::AllButtons); -#if QT_CONFIG(cursor) - setCursor(Qt::ArrowCursor); -#endif + Q_D(QQuickPane); + d->init(); +} + +QQuickPane::~QQuickPane() +{ + Q_D(QQuickPane); + d->removeImplicitSizeListener(d->contentItem); + d->removeImplicitSizeListener(d->firstChild); } QQuickPane::QQuickPane(QQuickPanePrivate &dd, QQuickItem *parent) : QQuickControl(dd, parent) { - setFlag(QQuickItem::ItemIsFocusScope); - setAcceptedMouseButtons(Qt::AllButtons); -#if QT_CONFIG(cursor) - setCursor(Qt::ArrowCursor); -#endif + Q_D(QQuickPane); + d->init(); } /*! @@ -153,13 +264,26 @@ qreal QQuickPane::contentWidth() const void QQuickPane::setContentWidth(qreal width) { Q_D(QQuickPane); + d->hasContentWidth = true; if (qFuzzyCompare(d->contentWidth, width)) return; + const qreal oldWidth = d->contentWidth; d->contentWidth = width; + contentSizeChange(QSizeF(width, d->contentHeight), QSizeF(oldWidth, d->contentHeight)); emit contentWidthChanged(); } +void QQuickPane::resetContentWidth() +{ + Q_D(QQuickPane); + if (!d->hasContentWidth) + return; + + d->hasContentHeight = false; + d->updateContentWidth(); +} + /*! \qmlproperty real QtQuick.Controls::Pane::contentHeight @@ -179,13 +303,26 @@ qreal QQuickPane::contentHeight() const void QQuickPane::setContentHeight(qreal height) { Q_D(QQuickPane); + d->hasContentHeight = true; if (qFuzzyCompare(d->contentHeight, height)) return; + const qreal oldHeight = d->contentHeight; d->contentHeight = height; + contentSizeChange(QSizeF(d->contentWidth, height), QSizeF(d->contentWidth, oldHeight)); emit contentHeightChanged(); } +void QQuickPane::resetContentHeight() +{ + Q_D(QQuickPane); + if (!d->hasContentHeight) + return; + + d->hasContentHeight = false; + d->updateContentHeight(); +} + /*! \qmlproperty list<Object> QtQuick.Controls::Pane::contentData \default @@ -200,9 +337,10 @@ void QQuickPane::setContentHeight(qreal height) \sa Item::data, contentChildren */ -QQmlListProperty<QObject> QQuickPane::contentData() +QQmlListProperty<QObject> QQuickPanePrivate::contentData() { - return QQmlListProperty<QObject>(contentItem(), nullptr, + Q_Q(QQuickPane); + return QQmlListProperty<QObject>(q->contentItem(), nullptr, QQuickItemPrivate::data_append, QQuickItemPrivate::data_count, QQuickItemPrivate::data_at, @@ -222,23 +360,42 @@ QQmlListProperty<QObject> QQuickPane::contentData() \sa Item::children, contentData */ -QQmlListProperty<QQuickItem> QQuickPane::contentChildren() +QQmlListProperty<QQuickItem> QQuickPanePrivate::contentChildren() { - return QQmlListProperty<QQuickItem>(contentItem(), nullptr, + Q_Q(QQuickPane); + return QQmlListProperty<QQuickItem>(q->contentItem(), nullptr, QQuickItemPrivate::children_append, QQuickItemPrivate::children_count, QQuickItemPrivate::children_at, QQuickItemPrivate::children_clear); } +void QQuickPane::componentComplete() +{ + Q_D(QQuickPane); + QQuickControl::componentComplete(); + d->updateImplicitContentSize(); +} + void QQuickPane::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) { + Q_D(QQuickPane); QQuickControl::contentItemChange(newItem, oldItem); - if (oldItem) - disconnect(oldItem, &QQuickItem::childrenChanged, this, &QQuickPane::contentChildrenChanged); - if (newItem) - connect(newItem, &QQuickItem::childrenChanged, this, &QQuickPane::contentChildrenChanged); - emit contentChildrenChanged(); + if (oldItem) { + d->removeImplicitSizeListener(oldItem); + QObjectPrivate::disconnect(oldItem, &QQuickItem::childrenChanged, d, &QQuickPanePrivate::contentChildrenChange); + } + if (newItem) { + d->addImplicitSizeListener(newItem); + QObjectPrivate::connect(newItem, &QQuickItem::childrenChanged, d, &QQuickPanePrivate::contentChildrenChange); + } + d->contentChildrenChange(); +} + +void QQuickPane::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize) +{ + Q_UNUSED(newSize) + Q_UNUSED(oldSize) } #if QT_CONFIG(accessibility) @@ -249,3 +406,5 @@ QAccessible::Role QQuickPane::accessibleRole() const #endif QT_END_NAMESPACE + +#include "moc_qquickpane_p.cpp" diff --git a/src/quicktemplates2/qquickpane_p.h b/src/quicktemplates2/qquickpane_p.h index 759c59d8..86b2c9f2 100644 --- a/src/quicktemplates2/qquickpane_p.h +++ b/src/quicktemplates2/qquickpane_p.h @@ -58,23 +58,23 @@ class QQuickPanePrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPane : public QQuickControl { Q_OBJECT - Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged FINAL) - Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged FINAL) - Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) - Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL) + Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL) + Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL) + Q_PRIVATE_PROPERTY(QQuickPane::d_func(), QQmlListProperty<QObject> contentData READ contentData FINAL) + Q_PRIVATE_PROPERTY(QQuickPane::d_func(), QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL) Q_CLASSINFO("DefaultProperty", "contentData") public: explicit QQuickPane(QQuickItem *parent = nullptr); + ~QQuickPane(); qreal contentWidth() const; void setContentWidth(qreal width); + void resetContentWidth(); qreal contentHeight() const; void setContentHeight(qreal height); - - QQmlListProperty<QObject> contentData(); - QQmlListProperty<QQuickItem> contentChildren(); + void resetContentHeight(); Q_SIGNALS: void contentWidthChanged(); @@ -84,7 +84,10 @@ Q_SIGNALS: protected: QQuickPane(QQuickPanePrivate &dd, QQuickItem *parent); + void componentComplete() override; + void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override; + virtual void contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize); #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickpane_p_p.h b/src/quicktemplates2/qquickpane_p_p.h index c811c487..bd89aee2 100644 --- a/src/quicktemplates2/qquickpane_p_p.h +++ b/src/quicktemplates2/qquickpane_p_p.h @@ -59,10 +59,30 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPanePrivate : public QQuickControlP Q_DECLARE_PUBLIC(QQuickPane) public: + void init(); + + virtual QQmlListProperty<QObject> contentData(); + virtual QQmlListProperty<QQuickItem> contentChildren(); + virtual QList<QQuickItem *> contentChildItems() const; + QQuickItem *getContentItem() override; + qreal getContentWidth() const override; + qreal getContentHeight() const override; + + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + + void contentChildrenChange(); + + void updateContentWidth(); + void updateContentHeight(); + + bool hasContentWidth = false; + bool hasContentHeight = false; qreal contentWidth = 0; qreal contentHeight = 0; + QQuickItem *firstChild = nullptr; }; QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index b69dab64..d5e2c940 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -36,6 +36,7 @@ #include "qquickpopup_p.h" #include "qquickpopup_p_p.h" +#include "qquickpopupanchors_p.h" #include "qquickpopupitem_p_p.h" #include "qquickpopuppositioner_p_p.h" #include "qquickapplicationwindow_p.h" @@ -109,14 +110,42 @@ QT_BEGIN_NAMESPACE \image qtquickcontrols2-popup.png The \l implicitWidth and \l implicitHeight of a popup are typically based - on the implicit sizes of the background and the content item plus any - \l padding. These properties determine how large the popup will be when no + on the implicit sizes of the background and the content item plus any insets + and paddings. These properties determine how large the popup will be when no explicit \l width or \l height is specified. + The geometry of the \l contentItem is determined by the padding. The following + example reserves 10px padding between the boundaries of the popup and its content: + + \code + Popup { + padding: 10 + + contentItem: Text { + text: "Content" + } + } + \endcode + The \l background item fills the entire width and height of the popup, - unless an explicit size has been given for it. + unless insets or an explicit size have been given for it. + + Negative insets can be used to make the background larger than the popup. + The following example uses negative insets to place a shadow outside the + popup's boundaries: - The geometry of the \l contentItem is determined by the \l padding. + \code + Popup { + topInset: -2 + leftInset: -2 + rightInset: -6 + bottomInset: -6 + + background: BorderImage { + source: ":/images/shadowed-background.png" + } + } + \endcode \section1 Popup Sizing @@ -178,6 +207,11 @@ QT_BEGIN_NAMESPACE \include qquickoverlay-popup-parent.qdocinc + Another way to center a popup in the window regardless of its parent item + is to use \l {anchors.centerIn}: + + \snippet qtquickcontrols2-popup.qml centerIn + \sa {Popup Controls}, {Customizing Popup}, ApplicationWindow */ @@ -230,7 +264,10 @@ void QQuickPopupPrivate::init() QObject::connect(popupItem, &QQuickControl::paddingChanged, q, &QQuickPopup::paddingChanged); QObject::connect(popupItem, &QQuickControl::backgroundChanged, q, &QQuickPopup::backgroundChanged); QObject::connect(popupItem, &QQuickControl::contentItemChanged, q, &QQuickPopup::contentItemChanged); - positioner = new QQuickPopupPositioner(q); + QObject::connect(popupItem, &QQuickControl::implicitContentWidthChanged, q, &QQuickPopup::implicitContentWidthChanged); + QObject::connect(popupItem, &QQuickControl::implicitContentHeightChanged, q, &QQuickPopup::implicitContentHeightChanged); + QObject::connect(popupItem, &QQuickControl::implicitBackgroundWidthChanged, q, &QQuickPopup::implicitBackgroundWidthChanged); + QObject::connect(popupItem, &QQuickControl::implicitBackgroundHeightChanged, q, &QQuickPopup::implicitBackgroundHeightChanged); } void QQuickPopupPrivate::closeOrReject() @@ -400,7 +437,7 @@ bool QQuickPopupPrivate::prepareEnterTransition() visible = true; transitionState = EnterTransition; popupItem->setVisible(true); - positioner->setParentItem(parentItem); + getPositioner()->setParentItem(parentItem); emit q->visibleChanged(); } return true; @@ -439,7 +476,7 @@ void QQuickPopupPrivate::finalizeEnterTransition() void QQuickPopupPrivate::finalizeExitTransition() { Q_Q(QQuickPopup); - positioner->setParentItem(nullptr); + getPositioner()->setParentItem(nullptr); popupItem->setParentItem(nullptr); popupItem->setVisible(false); destroyOverlay(); @@ -525,6 +562,55 @@ void QQuickPopupPrivate::setBottomMargin(qreal value, bool reset) } } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlpropertygroup QtQuick.Controls::Popup::anchors + \qmlproperty Object QtQuick.Controls::Popup::anchors.centerIn + + Anchors provide a way to position an item by specifying its + relationship with other items. + + A common use case is to center a popup within its parent. One way to do + this is with the \l {Item::}{x} and \l {Item::}{y} properties. Anchors offer + a more convenient approach: + + \qml + Pane { + // ... + + Popup { + anchors.centerIn: parent + } + } + \endqml + + It is also possible to center the popup in the window by using \l Overlay: + + \snippet qtquickcontrols2-popup.qml centerIn + + This makes it easy to center a popup in the window from any component. + + \note Popups can only be centered within their immediate parent or + the window overlay; trying to center in other items will produce a warning. + + \sa {Popup Positioning}, {Item::anchors} +*/ +QQuickPopupAnchors *QQuickPopupPrivate::getAnchors() +{ + Q_Q(QQuickPopup); + if (!anchors) + anchors = new QQuickPopupAnchors(q); + return anchors; +} + +QQuickPopupPositioner *QQuickPopupPrivate::getPositioner() +{ + Q_Q(QQuickPopup); + if (!positioner) + positioner = new QQuickPopupPositioner(q); + return positioner; +} + void QQuickPopupPrivate::setWindow(QQuickWindow *newWindow) { Q_Q(QQuickPopup); @@ -566,7 +652,7 @@ void QQuickPopupPrivate::itemDestroyed(QQuickItem *item) void QQuickPopupPrivate::reposition() { - positioner->reposition(); + getPositioner()->reposition(); } static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQuickItem *parent) @@ -955,17 +1041,13 @@ void QQuickPopup::setImplicitHeight(qreal height) qreal QQuickPopup::contentWidth() const { Q_D(const QQuickPopup); - return d->contentWidth; + return d->popupItem->contentWidth(); } void QQuickPopup::setContentWidth(qreal width) { Q_D(QQuickPopup); - if (qFuzzyCompare(d->contentWidth, width)) - return; - - d->contentWidth = width; - emit contentWidthChanged(); + d->popupItem->setContentWidth(width); } /*! @@ -981,17 +1063,13 @@ void QQuickPopup::setContentWidth(qreal width) qreal QQuickPopup::contentHeight() const { Q_D(const QQuickPopup); - return d->contentHeight; + return d->popupItem->contentHeight(); } void QQuickPopup::setContentHeight(qreal height) { Q_D(QQuickPopup); - if (qFuzzyCompare(d->contentHeight, height)) - return; - - d->contentHeight = height; - emit contentHeightChanged(); + d->popupItem->setContentHeight(height); } /*! @@ -1249,11 +1327,12 @@ void QQuickPopup::resetPadding() /*! \qmlproperty real QtQuick.Controls::Popup::topPadding - This property holds the top padding. + This property holds the top padding. Unless explicitly set, the value + is equal to \c verticalPadding. \include qquickpopup-padding.qdocinc - \sa padding, bottomPadding, availableHeight + \sa padding, bottomPadding, verticalPadding, availableHeight */ qreal QQuickPopup::topPadding() const { @@ -1276,11 +1355,12 @@ void QQuickPopup::resetTopPadding() /*! \qmlproperty real QtQuick.Controls::Popup::leftPadding - This property holds the left padding. + This property holds the left padding. Unless explicitly set, the value + is equal to \c horizontalPadding. \include qquickpopup-padding.qdocinc - \sa padding, rightPadding, availableWidth + \sa padding, rightPadding, horizontalPadding, availableWidth */ qreal QQuickPopup::leftPadding() const { @@ -1303,11 +1383,12 @@ void QQuickPopup::resetLeftPadding() /*! \qmlproperty real QtQuick.Controls::Popup::rightPadding - This property holds the right padding. + This property holds the right padding. Unless explicitly set, the value + is equal to \c horizontalPadding. \include qquickpopup-padding.qdocinc - \sa padding, leftPadding, availableWidth + \sa padding, leftPadding, horizontalPadding, availableWidth */ qreal QQuickPopup::rightPadding() const { @@ -1330,11 +1411,12 @@ void QQuickPopup::resetRightPadding() /*! \qmlproperty real QtQuick.Controls::Popup::bottomPadding - This property holds the bottom padding. + This property holds the bottom padding. Unless explicitly set, the value + is equal to \c verticalPadding. \include qquickpopup-padding.qdocinc - \sa padding, topPadding, availableHeight + \sa padding, topPadding, verticalPadding, availableHeight */ qreal QQuickPopup::bottomPadding() const { @@ -1524,8 +1606,9 @@ void QQuickPopup::setParentItem(QQuickItem *parent) QQuickItemPrivate::get(d->parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Destroyed); } d->parentItem = parent; - if (d->positioner->parentItem()) - d->positioner->setParentItem(parent); + QQuickPopupPositioner *positioner = d->getPositioner(); + if (positioner->parentItem()) + positioner->setParentItem(parent); if (parent) { QObjectPrivate::connect(parent, &QQuickItem::windowChanged, d, &QQuickPopupPrivate::setWindow); QQuickItemPrivate::get(d->parentItem)->addItemChangeListener(d, QQuickItemPrivate::Destroyed); @@ -1620,13 +1703,12 @@ void QQuickPopup::setContentItem(QQuickItem *item) \sa Item::data, contentChildren */ -QQmlListProperty<QObject> QQuickPopup::contentData() +QQmlListProperty<QObject> QQuickPopupPrivate::contentData() { - Q_D(QQuickPopup); - QQuickControlPrivate *p = QQuickControlPrivate::get(d->popupItem); + QQuickControlPrivate *p = QQuickControlPrivate::get(popupItem); if (!p->contentItem) p->executeContentItem(); - return QQmlListProperty<QObject>(d->popupItem->contentItem(), nullptr, + return QQmlListProperty<QObject>(popupItem->contentItem(), nullptr, QQuickItemPrivate::data_append, QQuickItemPrivate::data_count, QQuickItemPrivate::data_at, @@ -1646,10 +1728,9 @@ QQmlListProperty<QObject> QQuickPopup::contentData() \sa Item::children, contentData */ -QQmlListProperty<QQuickItem> QQuickPopup::contentChildren() +QQmlListProperty<QQuickItem> QQuickPopupPrivate::contentChildren() { - Q_D(QQuickPopup); - return QQmlListProperty<QQuickItem>(d->popupItem->contentItem(), nullptr, + return QQmlListProperty<QQuickItem>(popupItem->contentItem(), nullptr, QQuickItemPrivate::children_append, QQuickItemPrivate::children_count, QQuickItemPrivate::children_at, @@ -2042,6 +2123,236 @@ void QQuickPopup::setExit(QQuickTransition *transition) emit exitChanged(); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::horizontalPadding + + This property holds the horizontal padding. Unless explicitly set, the value + is equal to \c padding. + + \include qquickpopup-padding.qdocinc + + \sa padding, leftPadding, rightPadding, verticalPadding +*/ +qreal QQuickPopup::horizontalPadding() const +{ + Q_D(const QQuickPopup); + return d->popupItem->horizontalPadding(); +} + +void QQuickPopup::setHorizontalPadding(qreal padding) +{ + Q_D(QQuickPopup); + d->popupItem->setHorizontalPadding(padding); +} + +void QQuickPopup::resetHorizontalPadding() +{ + Q_D(QQuickPopup); + d->popupItem->resetHorizontalPadding(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::verticalPadding + + This property holds the vertical padding. Unless explicitly set, the value + is equal to \c padding. + + \include qquickpopup-padding.qdocinc + + \sa padding, topPadding, bottomPadding, horizontalPadding +*/ +qreal QQuickPopup::verticalPadding() const +{ + Q_D(const QQuickPopup); + return d->popupItem->verticalPadding(); +} + +void QQuickPopup::setVerticalPadding(qreal padding) +{ + Q_D(QQuickPopup); + d->popupItem->setVerticalPadding(padding); +} + +void QQuickPopup::resetVerticalPadding() +{ + Q_D(QQuickPopup); + d->popupItem->resetVerticalPadding(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::implicitContentWidth + \readonly + + This property holds the implicit content width. + + The value is calculated based on the content children. + + \sa implicitContentHeight, implicitBackgroundWidth +*/ +qreal QQuickPopup::implicitContentWidth() const +{ + Q_D(const QQuickPopup); + return d->popupItem->implicitContentWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::implicitContentHeight + \readonly + + This property holds the implicit content height. + + The value is calculated based on the content children. + + \sa implicitContentWidth, implicitBackgroundHeight +*/ +qreal QQuickPopup::implicitContentHeight() const +{ + Q_D(const QQuickPopup); + return d->popupItem->implicitContentHeight(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::implicitBackgroundWidth + \readonly + + This property holds the implicit background width. + + The value is equal to \c {background ? background.implicitWidth : 0}. + + \sa implicitBackgroundHeight, implicitContentWidth +*/ +qreal QQuickPopup::implicitBackgroundWidth() const +{ + Q_D(const QQuickPopup); + return d->popupItem->implicitBackgroundWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::implicitBackgroundHeight + \readonly + + This property holds the implicit background height. + + The value is equal to \c {background ? background.implicitHeight : 0}. + + \sa implicitBackgroundWidth, implicitContentHeight +*/ +qreal QQuickPopup::implicitBackgroundHeight() const +{ + Q_D(const QQuickPopup); + return d->popupItem->implicitBackgroundHeight(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::topInset + + This property holds the top inset for the background. + + \sa {Popup Layout}, bottomInset +*/ +qreal QQuickPopup::topInset() const +{ + Q_D(const QQuickPopup); + return d->popupItem->topInset(); +} + +void QQuickPopup::setTopInset(qreal inset) +{ + Q_D(QQuickPopup); + d->popupItem->setTopInset(inset); +} + +void QQuickPopup::resetTopInset() +{ + Q_D(QQuickPopup); + d->popupItem->resetTopInset(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::leftInset + + This property holds the left inset for the background. + + \sa {Popup Layout}, rightInset +*/ +qreal QQuickPopup::leftInset() const +{ + Q_D(const QQuickPopup); + return d->popupItem->leftInset(); +} + +void QQuickPopup::setLeftInset(qreal inset) +{ + Q_D(QQuickPopup); + d->popupItem->setLeftInset(inset); +} + +void QQuickPopup::resetLeftInset() +{ + Q_D(QQuickPopup); + d->popupItem->resetLeftInset(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::rightInset + + This property holds the right inset for the background. + + \sa {Popup Layout}, leftInset +*/ +qreal QQuickPopup::rightInset() const +{ + Q_D(const QQuickPopup); + return d->popupItem->rightInset(); +} + +void QQuickPopup::setRightInset(qreal inset) +{ + Q_D(QQuickPopup); + d->popupItem->setRightInset(inset); +} + +void QQuickPopup::resetRightInset() +{ + Q_D(QQuickPopup); + d->popupItem->resetRightInset(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Popup::bottomInset + + This property holds the bottom inset for the background. + + \sa {Popup Layout}, topInset +*/ +qreal QQuickPopup::bottomInset() const +{ + Q_D(const QQuickPopup); + return d->popupItem->bottomInset(); +} + +void QQuickPopup::setBottomInset(qreal inset) +{ + Q_D(QQuickPopup); + d->popupItem->setBottomInset(inset); +} + +void QQuickPopup::resetBottomInset() +{ + Q_D(QQuickPopup); + d->popupItem->resetBottomInset(); +} + bool QQuickPopup::filtersChildMouseEvents() const { Q_D(const QQuickPopup); @@ -2217,6 +2528,14 @@ void QQuickPopup::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) Q_UNUSED(oldItem); } +void QQuickPopup::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize) +{ + if (!qFuzzyCompare(newSize.width(), oldSize.width())) + emit contentWidthChanged(); + if (!qFuzzyCompare(newSize.height(), oldSize.height())) + emit contentHeightChanged(); +} + void QQuickPopup::fontChange(const QFont &newFont, const QFont &oldFont) { Q_UNUSED(newFont); @@ -2292,10 +2611,14 @@ void QQuickPopup::paddingChange(const QMarginsF &newPadding, const QMarginsF &ol if (bp) emit bottomPaddingChanged(); - if (lp || rp) + if (lp || rp) { + emit horizontalPaddingChanged(); emit availableWidthChanged(); - if (tp || bp) + } + if (tp || bp) { + emit verticalPaddingChanged(); emit availableHeightChanged(); + } } void QQuickPopup::paletteChange(const QPalette &newPalette, const QPalette &oldPalette) @@ -2312,14 +2635,26 @@ void QQuickPopup::spacingChange(qreal newSpacing, qreal oldSpacing) emit spacingChanged(); } +void QQuickPopup::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset) +{ + if (!qFuzzyCompare(newInset.top(), oldInset.top())) + emit topInsetChanged(); + if (!qFuzzyCompare(newInset.left(), oldInset.left())) + emit leftInsetChanged(); + if (!qFuzzyCompare(newInset.right(), oldInset.right())) + emit rightInsetChanged(); + if (!qFuzzyCompare(newInset.bottom(), oldInset.bottom())) + emit bottomInsetChanged(); +} + QFont QQuickPopup::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont); + return QQuickTheme::font(QQuickTheme::System); } QPalette QQuickPopup::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette); + return QQuickTheme::palette(QQuickTheme::System); } #if QT_CONFIG(accessibility) @@ -2359,3 +2694,5 @@ bool QQuickPopup::setAccessibleProperty(const char *propertyName, const QVariant } QT_END_NAMESPACE + +#include "moc_qquickpopup_p.cpp" diff --git a/src/quicktemplates2/qquickpopup_p.h b/src/quicktemplates2/qquickpopup_p.h index 2a42ff27..12dbd247 100644 --- a/src/quicktemplates2/qquickpopup_p.h +++ b/src/quicktemplates2/qquickpopup_p.h @@ -67,6 +67,7 @@ QT_BEGIN_NAMESPACE class QQuickWindow; +class QQuickPopupAnchors; class QQuickPopupPrivate; class QQuickTransition; @@ -100,8 +101,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPopup : public QObject, public QQml Q_PROPERTY(QQuickItem *parent READ parentItem WRITE setParentItem RESET resetParentItem NOTIFY parentChanged FINAL) Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL) Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged FINAL) - Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) - Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL) + Q_PRIVATE_PROPERTY(QQuickPopup::d_func(), QQmlListProperty<QObject> contentData READ contentData FINAL) + Q_PRIVATE_PROPERTY(QQuickPopup::d_func(), QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL) Q_PROPERTY(bool clip READ clip WRITE setClip NOTIFY clipChanged FINAL) Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL) Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged FINAL) @@ -121,6 +122,18 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPopup : public QObject, public QQml Q_PROPERTY(bool mirrored READ isMirrored NOTIFY mirroredChanged FINAL REVISION 3) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL REVISION 3) Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal horizontalPadding READ horizontalPadding WRITE setHorizontalPadding RESET resetHorizontalPadding NOTIFY horizontalPaddingChanged FINAL) + Q_PROPERTY(qreal verticalPadding READ verticalPadding WRITE setVerticalPadding RESET resetVerticalPadding NOTIFY verticalPaddingChanged FINAL) + Q_PRIVATE_PROPERTY(QQuickPopup::d_func(), QQuickPopupAnchors *anchors READ getAnchors DESIGNABLE false CONSTANT FINAL REVISION 5) + Q_PROPERTY(qreal implicitContentWidth READ implicitContentWidth NOTIFY implicitContentWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitContentHeight READ implicitContentHeight NOTIFY implicitContentHeightChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitBackgroundWidth READ implicitBackgroundWidth NOTIFY implicitBackgroundWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitBackgroundHeight READ implicitBackgroundHeight NOTIFY implicitBackgroundHeightChanged FINAL REVISION 5) + Q_PROPERTY(qreal topInset READ topInset WRITE setTopInset RESET resetTopInset NOTIFY topInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal leftInset READ leftInset WRITE setLeftInset RESET resetLeftInset NOTIFY leftInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal rightInset READ rightInset WRITE setRightInset RESET resetRightInset NOTIFY rightInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal bottomInset READ bottomInset WRITE setBottomInset RESET resetBottomInset NOTIFY bottomInsetChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background,contentItem") Q_CLASSINFO("DefaultProperty", "contentData") @@ -224,9 +237,6 @@ public: QQuickItem *contentItem() const; void setContentItem(QQuickItem *item); - QQmlListProperty<QObject> contentData(); - QQmlListProperty<QQuickItem> contentChildren(); - bool clip() const; void setClip(bool clip); @@ -304,6 +314,37 @@ public: void setPalette(const QPalette &palette); void resetPalette(); + // 2.5 (Qt 5.12) + qreal horizontalPadding() const; + void setHorizontalPadding(qreal padding); + void resetHorizontalPadding(); + + qreal verticalPadding() const; + void setVerticalPadding(qreal padding); + void resetVerticalPadding(); + + qreal implicitContentWidth() const; + qreal implicitContentHeight() const; + + qreal implicitBackgroundWidth() const; + qreal implicitBackgroundHeight() const; + + qreal topInset() const; + void setTopInset(qreal inset); + void resetTopInset(); + + qreal leftInset() const; + void setLeftInset(qreal inset); + void resetLeftInset(); + + qreal rightInset() const; + void setRightInset(qreal inset); + void resetRightInset(); + + qreal bottomInset() const; + void setBottomInset(qreal inset); + void resetBottomInset(); + public Q_SLOTS: void open(); void close(); @@ -359,6 +400,17 @@ Q_SIGNALS: Q_REVISION(3) void mirroredChanged(); Q_REVISION(3) void enabledChanged(); Q_REVISION(3) void paletteChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void horizontalPaddingChanged(); + Q_REVISION(5) void verticalPaddingChanged(); + Q_REVISION(5) void implicitContentWidthChanged(); + Q_REVISION(5) void implicitContentHeightChanged(); + Q_REVISION(5) void implicitBackgroundWidthChanged(); + Q_REVISION(5) void implicitBackgroundHeightChanged(); + Q_REVISION(5) void topInsetChanged(); + Q_REVISION(5) void leftInsetChanged(); + Q_REVISION(5) void rightInsetChanged(); + Q_REVISION(5) void bottomInsetChanged(); protected: QQuickPopup(QQuickPopupPrivate &dd, QObject *parent); @@ -387,6 +439,7 @@ protected: #endif virtual void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem); + virtual void contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize); virtual void fontChange(const QFont &newFont, const QFont &oldFont); virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); virtual void localeChange(const QLocale &newLocale, const QLocale &oldLocale); @@ -395,6 +448,7 @@ protected: virtual void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding); virtual void paletteChange(const QPalette &newPalette, const QPalette &oldPalette); virtual void spacingChange(qreal newSpacing, qreal oldSpacing); + virtual void insetChange(const QMarginsF &newInset, const QMarginsF &oldInset); virtual QFont defaultFont() const; virtual QPalette defaultPalette() const; diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index 318ae598..e32fdb28 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QQuickTransition; class QQuickTransitionManager; class QQuickPopup; +class QQuickPopupAnchors; class QQuickPopupItem; class QQuickPopupPrivate; class QQuickPopupPositioner; @@ -92,6 +93,9 @@ public: return popup->d_func(); } + QQmlListProperty<QObject> contentData(); + QQmlListProperty<QQuickItem> contentChildren(); + void init(); void closeOrReject(); bool tryClose(const QPointF &pos, QQuickPopup::ClosePolicy flags); @@ -113,7 +117,7 @@ public: bool handleTouchEvent(QQuickItem *item, QTouchEvent *event); #endif - virtual void reposition(); + void reposition(); void createOverlay(); void destroyOverlay(); @@ -134,6 +138,9 @@ public: void setRightMargin(qreal value, bool reset = false); void setBottomMargin(qreal value, bool reset = false); + QQuickPopupAnchors *getAnchors(); + virtual QQuickPopupPositioner *getPositioner(); + void setWindow(QQuickWindow *window); void itemDestroyed(QQuickItem *item) override; @@ -175,8 +182,6 @@ public: qreal leftMargin = 0; qreal rightMargin = 0; qreal bottomMargin = 0; - qreal contentWidth = 0; - qreal contentHeight = 0; QPointF pressPoint; TransitionState transitionState = NoTransition; QQuickPopup::ClosePolicy closePolicy = DefaultClosePolicy; @@ -190,6 +195,7 @@ public: QList<QQuickStateAction> enterActions; QList<QQuickStateAction> exitActions; QQuickPopupTransitionManager transitionManager; + QQuickPopupAnchors *anchors = nullptr; friend class QQuickPopupTransitionManager; }; diff --git a/src/quicktemplates2/qquickpopupanchors.cpp b/src/quicktemplates2/qquickpopupanchors.cpp new file mode 100644 index 00000000..5acc2934 --- /dev/null +++ b/src/quicktemplates2/qquickpopupanchors.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickpopupanchors_p.h" +#include "qquickpopupanchors_p_p.h" +#include "qquickpopup_p_p.h" + +QT_BEGIN_NAMESPACE + +QQuickPopupAnchors::QQuickPopupAnchors(QQuickPopup *popup) + : QObject(*(new QQuickPopupAnchorsPrivate), popup) +{ + Q_D(QQuickPopupAnchors); + d->popup = popup; +} + +QQuickItem *QQuickPopupAnchors::centerIn() const +{ + Q_D(const QQuickPopupAnchors); + return d->centerIn; +} + +void QQuickPopupAnchors::setCenterIn(QQuickItem *item) +{ + Q_D(QQuickPopupAnchors); + if (item == d->centerIn) + return; + + d->centerIn = item; + QQuickPopupPrivate::get(d->popup)->reposition(); + emit centerInChanged(); +} + +void QQuickPopupAnchors::resetCenterIn() +{ + setCenterIn(nullptr); +} + +QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickpopupanchors_p.h b/src/quicktemplates2/qquickpopupanchors_p.h new file mode 100644 index 00000000..531c494e --- /dev/null +++ b/src/quicktemplates2/qquickpopupanchors_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPOPUPANCHORS_P_H +#define QQUICKPOPUPANCHORS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobject.h> +#include <QtQml/qqml.h> +#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickItem; +class QQuickPopupAnchorsPrivate; +class QQuickPopup; + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPopupAnchors : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQuickItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged) + +public: + explicit QQuickPopupAnchors(QQuickPopup *popup); + + QQuickItem *centerIn() const; + void setCenterIn(QQuickItem *item); + void resetCenterIn(); + +Q_SIGNALS: + void centerInChanged(); + +private: + Q_DISABLE_COPY(QQuickPopupAnchors) + Q_DECLARE_PRIVATE(QQuickPopupAnchors) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickPopupAnchors) + +#endif // QQUICKPOPUPANCHORS_P_H diff --git a/src/quicktemplates2/qquickpopupanchors_p_p.h b/src/quicktemplates2/qquickpopupanchors_p_p.h new file mode 100644 index 00000000..989dc6df --- /dev/null +++ b/src/quicktemplates2/qquickpopupanchors_p_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPOPUPANCHORS_P_P_H +#define QQUICKPOPUPANCHORS_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/private/qobject_p.h> +#include <QtQuickTemplates2/private/qquickpopup_p_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickItem; +class QQuickPopup; + +class QQuickPopupAnchorsPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickPopupAnchors) + +public: + static QQuickPopupAnchorsPrivate *get(QQuickPopupAnchors *popupAnchors) + { + return popupAnchors->d_func(); + } + + QQuickPopup *popup = nullptr; + QQuickItem *centerIn = nullptr; +}; + +QT_END_NAMESPACE + +#endif // QQUICKPOPUPANCHORS_P_P_H diff --git a/src/quicktemplates2/qquickpopupitem.cpp b/src/quicktemplates2/qquickpopupitem.cpp index f835aef4..cf2fec41 100644 --- a/src/quicktemplates2/qquickpopupitem.cpp +++ b/src/quicktemplates2/qquickpopupitem.cpp @@ -37,7 +37,8 @@ #include "qquickpopupitem_p_p.h" #include "qquickapplicationwindow_p.h" #include "qquickshortcutcontext_p_p.h" -#include "qquickcontrol_p_p.h" +#include "qquickpage_p_p.h" +#include "qquickcontentitem_p.h" #include "qquickpopup_p_p.h" #include "qquickdeferredexecute_p_p.h" @@ -46,7 +47,7 @@ QT_BEGIN_NAMESPACE -class QQuickPopupItemPrivate : public QQuickControlPrivate +class QQuickPopupItemPrivate : public QQuickPagePrivate { Q_DECLARE_PUBLIC(QQuickPopupItem) @@ -80,13 +81,13 @@ QQuickPopupItemPrivate::QQuickPopupItemPrivate(QQuickPopup *popup) void QQuickPopupItemPrivate::implicitWidthChanged() { - QQuickControlPrivate::implicitWidthChanged(); + QQuickPagePrivate::implicitWidthChanged(); emit popup->implicitWidthChanged(); } void QQuickPopupItemPrivate::implicitHeightChanged() { - QQuickControlPrivate::implicitHeightChanged(); + QQuickPagePrivate::implicitHeightChanged(); emit popup->implicitHeightChanged(); } @@ -95,7 +96,7 @@ void QQuickPopupItemPrivate::resolveFont() if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(popup->window())) inheritFont(window->font()); else - inheritFont(themeFont(QPlatformTheme::SystemFont)); + inheritFont(QQuickTheme::font(QQuickTheme::System)); } void QQuickPopupItemPrivate::resolvePalette() @@ -103,15 +104,16 @@ void QQuickPopupItemPrivate::resolvePalette() if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(popup->window())) inheritPalette(window->palette()); else - inheritPalette(themePalette(QPlatformTheme::SystemPalette)); + inheritPalette(QQuickTheme::palette(QQuickTheme::System)); } QQuickItem *QQuickPopupItemPrivate::getContentItem() { Q_Q(QQuickPopupItem); - if (QQuickItem *item = QQuickControlPrivate::getContentItem()) + if (QQuickItem *item = QQuickPagePrivate::getContentItem()) return item; - return new QQuickItem(q); + + return new QQuickContentItem(popup, q); } static inline QString contentItemName() { return QStringLiteral("contentItem"); } @@ -151,7 +153,7 @@ void QQuickPopupItemPrivate::executeBackground(bool complete) } QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) - : QQuickControl(*(new QQuickPopupItemPrivate(popup)), nullptr) + : QQuickPage(*(new QQuickPopupItemPrivate(popup)), nullptr) { setParent(popup); setFlag(ItemIsFocusScope); @@ -305,28 +307,35 @@ void QQuickPopupItem::wheelEvent(QWheelEvent *event) void QQuickPopupItem::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) { Q_D(QQuickPopupItem); - QQuickControl::contentItemChange(newItem, oldItem); + QQuickPage::contentItemChange(newItem, oldItem); d->popup->contentItemChange(newItem, oldItem); } +void QQuickPopupItem::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize) +{ + Q_D(QQuickPopupItem); + QQuickPage::contentSizeChange(newSize, oldSize); + d->popup->contentSizeChange(newSize, oldSize); +} + void QQuickPopupItem::fontChange(const QFont &newFont, const QFont &oldFont) { Q_D(QQuickPopupItem); - QQuickControl::fontChange(newFont, oldFont); + QQuickPage::fontChange(newFont, oldFont); d->popup->fontChange(newFont, oldFont); } void QQuickPopupItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QQuickPopupItem); - QQuickControl::geometryChanged(newGeometry, oldGeometry); + QQuickPage::geometryChanged(newGeometry, oldGeometry); d->popup->geometryChanged(newGeometry, oldGeometry); } void QQuickPopupItem::localeChange(const QLocale &newLocale, const QLocale &oldLocale) { Q_D(QQuickPopupItem); - QQuickControl::localeChange(newLocale, oldLocale); + QQuickPage::localeChange(newLocale, oldLocale); d->popup->localeChange(newLocale, oldLocale); } @@ -339,21 +348,21 @@ void QQuickPopupItem::mirrorChange() void QQuickPopupItem::itemChange(ItemChange change, const ItemChangeData &data) { Q_D(QQuickPopupItem); - QQuickControl::itemChange(change, data); + QQuickPage::itemChange(change, data); d->popup->itemChange(change, data); } void QQuickPopupItem::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) { Q_D(QQuickPopupItem); - QQuickControl::paddingChange(newPadding, oldPadding); + QQuickPage::paddingChange(newPadding, oldPadding); d->popup->paddingChange(newPadding, oldPadding); } void QQuickPopupItem::paletteChange(const QPalette &newPalette, const QPalette &oldPalette) { Q_D(QQuickPopupItem); - QQuickControl::paletteChange(newPalette, oldPalette); + QQuickPage::paletteChange(newPalette, oldPalette); d->popup->paletteChange(newPalette, oldPalette); } @@ -379,7 +388,7 @@ QAccessible::Role QQuickPopupItem::accessibleRole() const void QQuickPopupItem::accessibilityActiveChanged(bool active) { Q_D(const QQuickPopupItem); - QQuickControl::accessibilityActiveChanged(active); + QQuickPage::accessibilityActiveChanged(active); d->popup->accessibilityActiveChanged(active); } #endif diff --git a/src/quicktemplates2/qquickpopupitem_p_p.h b/src/quicktemplates2/qquickpopupitem_p_p.h index 0187b77a..a15aeb17 100644 --- a/src/quicktemplates2/qquickpopupitem_p_p.h +++ b/src/quicktemplates2/qquickpopupitem_p_p.h @@ -48,14 +48,13 @@ // We mean it. // -#include <QtQuickTemplates2/private/qquickcontrol_p.h> +#include <QtQuickTemplates2/private/qquickpage_p.h> QT_BEGIN_NAMESPACE class QQuickPopup; class QQuickPopupItemPrivate; - -class QQuickPopupItem : public QQuickControl +class QQuickPopupItem : public QQuickPage { Q_OBJECT @@ -88,6 +87,7 @@ protected: #endif void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override; + void contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize) override; void fontChange(const QFont &newFont, const QFont &oldFont) override; void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override; diff --git a/src/quicktemplates2/qquickpopuppositioner.cpp b/src/quicktemplates2/qquickpopuppositioner.cpp index 841eac9c..69a57674 100644 --- a/src/quicktemplates2/qquickpopuppositioner.cpp +++ b/src/quicktemplates2/qquickpopuppositioner.cpp @@ -34,10 +34,13 @@ ** ****************************************************************************/ +#include "qquickoverlay_p.h" #include "qquickpopuppositioner_p_p.h" +#include "qquickpopupanchors_p.h" #include "qquickpopupitem_p_p.h" #include "qquickpopup_p_p.h" +#include <QtQml/qqmlinfo.h> #include <QtQuick/private/qquickitem_p.h> QT_BEGIN_NAMESPACE @@ -62,6 +65,11 @@ QQuickPopupPositioner::~QQuickPopupPositioner() } } +QQuickPopup *QQuickPopupPositioner::popup() const +{ + return m_popup; +} + QQuickItem *QQuickPopupPositioner::parentItem() const { return m_parentItem; @@ -109,12 +117,31 @@ void QQuickPopupPositioner::reposition() bool heightAdjusted = false; QQuickPopupPrivate *p = QQuickPopupPrivate::get(m_popup); - QRectF rect(p->allowHorizontalMove ? p->x : popupItem->x(), - p->allowVerticalMove ? p->y : popupItem->y(), + const QQuickItem *centerInParent = p->anchors ? p->getAnchors()->centerIn() : nullptr; + const QQuickOverlay *centerInOverlay = qobject_cast<const QQuickOverlay*>(centerInParent); + QRectF rect(!centerInParent ? p->allowHorizontalMove ? p->x : popupItem->x() : 0, + !centerInParent ? p->allowVerticalMove ? p->y : popupItem->y() : 0, !p->hasWidth && iw > 0 ? iw : w, !p->hasHeight && ih > 0 ? ih : h); if (m_parentItem) { - rect.moveTopLeft(m_parentItem->mapToItem(popupItem->parentItem(), rect.topLeft())); + // m_parentItem is the parent that the popup should open in, + // and popupItem()->parentItem() is the overlay, so the mapToItem() calls below + // effectively map the rect to scene coordinates. + if (centerInParent) { + if (centerInParent != parentItem() && !centerInOverlay) { + qmlWarning(m_popup) << "Popup can only be centered within its immediate parent or Overlay.overlay"; + return; + } + + if (centerInOverlay) { + rect.moveCenter(QPointF(qRound(centerInOverlay->width() / 2.0), qRound(centerInOverlay->height() / 2.0))); + } else { + const QPointF parentItemCenter = QPointF(qRound(m_parentItem->width() / 2), qRound(m_parentItem->height() / 2)); + rect.moveCenter(m_parentItem->mapToItem(popupItem->parentItem(), parentItemCenter)); + } + } else { + rect.moveTopLeft(m_parentItem->mapToItem(popupItem->parentItem(), rect.topLeft())); + } if (p->window) { const QMarginsF margins = p->getMargins(); @@ -215,7 +242,11 @@ void QQuickPopupPositioner::reposition() popupItem->setPosition(rect.topLeft()); - const QPointF effectivePos = m_parentItem ? m_parentItem->mapFromScene(rect.topLeft()) : rect.topLeft(); + // If the popup was assigned a parent, rect will be in scene coordinates, + // so we need to map its top left back to item coordinates. + // However, if centering within the overlay, the coordinates will be relative + // to the window, so we don't need to do anything. + const QPointF effectivePos = m_parentItem && !centerInOverlay ? m_parentItem->mapFromScene(rect.topLeft()) : rect.topLeft(); if (!qFuzzyCompare(p->effectiveX, effectivePos.x())) { p->effectiveX = effectivePos.x(); emit m_popup->xChanged(); diff --git a/src/quicktemplates2/qquickpopuppositioner_p_p.h b/src/quicktemplates2/qquickpopuppositioner_p_p.h index db1f9b17..6eb990a7 100644 --- a/src/quicktemplates2/qquickpopuppositioner_p_p.h +++ b/src/quicktemplates2/qquickpopuppositioner_p_p.h @@ -61,6 +61,8 @@ public: explicit QQuickPopupPositioner(QQuickPopup *popup); ~QQuickPopupPositioner(); + QQuickPopup *popup() const; + QQuickItem *parentItem() const; void setParentItem(QQuickItem *parent); diff --git a/src/quicktemplates2/qquickradiobutton.cpp b/src/quicktemplates2/qquickradiobutton.cpp index 86be3ed6..bf0c414c 100644 --- a/src/quicktemplates2/qquickradiobutton.cpp +++ b/src/quicktemplates2/qquickradiobutton.cpp @@ -99,12 +99,12 @@ QQuickRadioButton::QQuickRadioButton(QQuickItem *parent) QFont QQuickRadioButton::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::RadioButtonFont); + return QQuickTheme::font(QQuickTheme::RadioButton); } QPalette QQuickRadioButton::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::RadioButtonPalette); + return QQuickTheme::palette(QQuickTheme::RadioButton); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickradiodelegate.cpp b/src/quicktemplates2/qquickradiodelegate.cpp index fe603d36..12a1ffb7 100644 --- a/src/quicktemplates2/qquickradiodelegate.cpp +++ b/src/quicktemplates2/qquickradiodelegate.cpp @@ -100,7 +100,12 @@ QQuickRadioDelegate::QQuickRadioDelegate(QQuickItem *parent) QFont QQuickRadioDelegate::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::ListViewFont); + return QQuickTheme::font(QQuickTheme::ListView); +} + +QPalette QQuickRadioDelegate::defaultPalette() const +{ + return QQuickTheme::palette(QQuickTheme::ListView); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickradiodelegate_p.h b/src/quicktemplates2/qquickradiodelegate_p.h index 4db9959d..453856e4 100644 --- a/src/quicktemplates2/qquickradiodelegate_p.h +++ b/src/quicktemplates2/qquickradiodelegate_p.h @@ -63,6 +63,7 @@ public: protected: QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp index 569d7645..ff488dac 100644 --- a/src/quicktemplates2/qquickrangeslider.cpp +++ b/src/quicktemplates2/qquickrangeslider.cpp @@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE use the following syntax: \code - first.onValueChanged: console.log("first.value changed to " + first.value) + first.onMoved: console.log("first.value changed to " + first.value) \endcode The \l {first.position} and \l {second.position} properties are expressed as @@ -263,8 +263,13 @@ void QQuickRangeSliderNode::setHandle(QQuickItem *handle) if (!d->handle.isExecuting()) d->cancelHandle(); + const qreal oldImplicitHandleWidth = implicitHandleWidth(); + const qreal oldImplicitHandleHeight = implicitHandleHeight(); + + QQuickControlPrivate::get(d->slider)->removeImplicitSizeListener(d->handle); delete d->handle; d->handle = handle; + if (handle) { if (!handle->parentItem()) handle->setParentItem(d->slider); @@ -288,7 +293,13 @@ void QQuickRangeSliderNode::setHandle(QQuickItem *handle) } handle->setActiveFocusOnTab(true); + QQuickControlPrivate::get(d->slider)->addImplicitSizeListener(handle); } + + if (!qFuzzyCompare(oldImplicitHandleWidth, implicitHandleWidth())) + emit implicitHandleWidthChanged(); + if (!qFuzzyCompare(oldImplicitHandleHeight, implicitHandleHeight())) + emit implicitHandleHeightChanged(); if (!d->handle.isExecuting()) emit handleChanged(); } @@ -326,6 +337,22 @@ void QQuickRangeSliderNode::setHovered(bool hovered) emit hoveredChanged(); } +qreal QQuickRangeSliderNode::implicitHandleWidth() const +{ + Q_D(const QQuickRangeSliderNode); + if (!d->handle) + return 0; + return d->handle->implicitWidth(); +} + +qreal QQuickRangeSliderNode::implicitHandleHeight() const +{ + Q_D(const QQuickRangeSliderNode); + if (!d->handle) + return 0; + return d->handle->implicitHeight(); +} + void QQuickRangeSliderNode::increase() { Q_D(QQuickRangeSliderNode); @@ -360,10 +387,14 @@ public: void updateHover(const QPointF &pos); + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + bool live = true; qreal from = defaultFrom; qreal to = defaultTo; qreal stepSize = 0; + qreal touchDragThreshold = -1; QQuickRangeSliderNode *first = nullptr; QQuickRangeSliderNode *second = nullptr; QPointF pressPoint; @@ -503,6 +534,7 @@ void QQuickRangeSliderPrivate::handleMove(const QPointF &point) QQuickControlPrivate::handleMove(point); QQuickRangeSliderNode *pressedNode = QQuickRangeSliderPrivate::pressedNode(touchId); if (pressedNode) { + const qreal oldPos = pressedNode->position(); qreal pos = positionAt(q, pressedNode->handle(), point); if (snapMode == QQuickRangeSlider::SnapAlways) pos = snapPosition(q, pos); @@ -510,6 +542,9 @@ void QQuickRangeSliderPrivate::handleMove(const QPointF &point) pressedNode->setValue(valueAt(q, pos)); else QQuickRangeSliderNodePrivate::get(pressedNode)->setPosition(pos); + + if (!qFuzzyCompare(pressedNode->position(), oldPos)) + emit pressedNode->moved(); } } @@ -525,6 +560,7 @@ void QQuickRangeSliderPrivate::handleRelease(const QPointF &point) QQuickRangeSliderNodePrivate *pressedNodePrivate = QQuickRangeSliderNodePrivate::get(pressedNode); if (q->keepMouseGrab() || q->keepTouchGrab()) { + const qreal oldPos = pressedNode->position(); qreal pos = positionAt(q, pressedNode->handle(), point); if (snapMode != QQuickRangeSlider::NoSnap) pos = snapPosition(q, pos); @@ -535,6 +571,9 @@ void QQuickRangeSliderPrivate::handleRelease(const QPointF &point) pressedNodePrivate->setPosition(pos); q->setKeepMouseGrab(false); q->setKeepTouchGrab(false); + + if (!qFuzzyCompare(pressedNode->position(), oldPos)) + emit pressedNode->moved(); } pressedNode->setPressed(false); pressedNodePrivate->touchId = -1; @@ -559,6 +598,24 @@ void QQuickRangeSliderPrivate::updateHover(const QPointF &pos) second->setHovered(secondHandle && secondHandle->isEnabled() && secondHandle->contains(q->mapToItem(secondHandle, pos))); } +void QQuickRangeSliderPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + QQuickControlPrivate::itemImplicitWidthChanged(item); + if (item == first->handle()) + emit first->implicitHandleWidthChanged(); + else if (item == second->handle()) + emit second->implicitHandleWidthChanged(); +} + +void QQuickRangeSliderPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + QQuickControlPrivate::itemImplicitHeightChanged(item); + if (item == first->handle()) + emit first->implicitHandleHeightChanged(); + else if (item == second->handle()) + emit second->implicitHandleHeightChanged(); +} + QQuickRangeSlider::QQuickRangeSlider(QQuickItem *parent) : QQuickControl(*(new QQuickRangeSliderPrivate), parent) { @@ -573,6 +630,13 @@ QQuickRangeSlider::QQuickRangeSlider(QQuickItem *parent) #endif } +QQuickRangeSlider::~QQuickRangeSlider() +{ + Q_D(QQuickRangeSlider); + d->removeImplicitSizeListener(d->first->handle()); + d->removeImplicitSizeListener(d->second->handle()); +} + /*! \qmlproperty real QtQuick.Controls::RangeSlider::from @@ -630,6 +694,55 @@ void QQuickRangeSlider::setTo(qreal to) } /*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty qreal QtQuick.Controls::RangeSlider::touchDragThreshold + + This property holds the threshold (in logical pixels) at which a touch drag event will be initiated. + The mouse drag threshold won't be affected. + The default value is \c Qt.styleHints.startDragDistance. + + \sa QStyleHints + +*/ +qreal QQuickRangeSlider::touchDragThreshold() const +{ + Q_D(const QQuickRangeSlider); + return d->touchDragThreshold; +} + +void QQuickRangeSlider::setTouchDragThreshold(qreal touchDragThreshold) +{ + Q_D(QQuickRangeSlider); + if (d->touchDragThreshold == touchDragThreshold) + return; + + d->touchDragThreshold = touchDragThreshold; + emit touchDragThresholdChanged(); +} + +void QQuickRangeSlider::resetTouchDragThreshold() +{ + setTouchDragThreshold(-1); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlmethod real QtQuick.Controls::RangeSlider::valueAt(real position) + + Returns the value for the given \a position. + + \sa first.value, second.value, first.position, second.position, live +*/ +qreal QQuickRangeSlider::valueAt(qreal position) const +{ + Q_D(const QQuickRangeSlider); + const qreal value = (d->to - d->from) * position; + if (qFuzzyIsNull(d->stepSize)) + return d->from + value; + return d->from + qRound(value / d->stepSize) * d->stepSize; +} + +/*! \qmlpropertygroup QtQuick.Controls::RangeSlider::first \qmlproperty real QtQuick.Controls::RangeSlider::first.value \qmlproperty real QtQuick.Controls::RangeSlider::first.position @@ -637,6 +750,9 @@ void QQuickRangeSlider::setTo(qreal to) \qmlproperty Item QtQuick.Controls::RangeSlider::first.handle \qmlproperty bool QtQuick.Controls::RangeSlider::first.pressed \qmlproperty bool QtQuick.Controls::RangeSlider::first.hovered + \qmlproperty real QtQuick.Controls::RangeSlider::first.implicitHandleWidth + \qmlproperty real QtQuick.Controls::RangeSlider::first.implicitHandleHeight + \qmlsignal void QtQuick.Controls::RangeSlider::moved() \table \header @@ -677,6 +793,20 @@ void QQuickRangeSlider::setTo(qreal to) \li hovered \li This property holds whether the first handle is hovered. This property was introduced in QtQuick.Controls 2.1. + \row + \li implicitHandleWidth + \li This property holds the implicit width of the first handle. + This property was introduced in QtQuick.Controls 2.5. + \row + \li implicitHandleHeight + \li This property holds the implicit height of the first handle. + This property was introduced in QtQuick.Controls 2.5. + \row + \li moved() + \li This signal is emitted when the first handle has been interactively moved + by the user by either touch, mouse, or keys. + + This signal was introduced in QtQuick.Controls 2.5. \endtable \sa first.increase(), first.decrease() @@ -695,6 +825,9 @@ QQuickRangeSliderNode *QQuickRangeSlider::first() const \qmlproperty Item QtQuick.Controls::RangeSlider::second.handle \qmlproperty bool QtQuick.Controls::RangeSlider::second.pressed \qmlproperty bool QtQuick.Controls::RangeSlider::second.hovered + \qmlproperty real QtQuick.Controls::RangeSlider::second.implicitHandleWidth + \qmlproperty real QtQuick.Controls::RangeSlider::second.implicitHandleHeight + \qmlsignal void QtQuick.Controls::RangeSlider::moved() \table \header @@ -735,6 +868,20 @@ QQuickRangeSliderNode *QQuickRangeSlider::first() const \li hovered \li This property holds whether the second handle is hovered. This property was introduced in QtQuick.Controls 2.1. + \row + \li implicitHandleWidth + \li This property holds the implicit width of the second handle. + This property was introduced in QtQuick.Controls 2.5. + \row + \li implicitHandleHeight + \li This property holds the implicit height of the second handle. + This property was introduced in QtQuick.Controls 2.5. + \row + \li moved() + \li This signal is emitted when the second handle has been interactively moved + by the user by either touch, mouse, or keys. + + This signal was introduced in QtQuick.Controls 2.5. \endtable \sa second.increase(), second.decrease() @@ -971,6 +1118,7 @@ void QQuickRangeSlider::keyPressEvent(QKeyEvent *event) if (!focusNode) return; + const qreal oldValue = focusNode->value(); if (d->orientation == Qt::Horizontal) { if (event->key() == Qt::Key_Left) { focusNode->setPressed(true); @@ -998,6 +1146,8 @@ void QQuickRangeSlider::keyPressEvent(QKeyEvent *event) event->accept(); } } + if (!qFuzzyCompare(focusNode->value(), oldValue)) + emit focusNode->moved(); } void QQuickRangeSlider::hoverEnterEvent(QHoverEvent *event) @@ -1055,9 +1205,9 @@ void QQuickRangeSlider::touchEvent(QTouchEvent *event) case Qt::TouchPointMoved: if (!keepTouchGrab()) { if (d->orientation == Qt::Horizontal) - setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - point.startPos().x(), Qt::XAxis, &point)); + setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - point.startPos().x(), Qt::XAxis, &point, qRound(d->touchDragThreshold))); else - setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - point.startPos().y(), Qt::YAxis, &point)); + setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - point.startPos().y(), Qt::YAxis, &point, qRound(d->touchDragThreshold))); } if (keepTouchGrab()) d->handleMove(point.pos()); diff --git a/src/quicktemplates2/qquickrangeslider_p.h b/src/quicktemplates2/qquickrangeslider_p.h index 45de6bbb..a42245a1 100644 --- a/src/quicktemplates2/qquickrangeslider_p.h +++ b/src/quicktemplates2/qquickrangeslider_p.h @@ -70,9 +70,12 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickRangeSlider : public QQuickControl Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3) // 2.3 (Qt 5.10) Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal touchDragThreshold READ touchDragThreshold WRITE setTouchDragThreshold RESET resetTouchDragThreshold NOTIFY touchDragThresholdChanged FINAL REVISION 5) public: explicit QQuickRangeSlider(QQuickItem *parent = nullptr); + ~QQuickRangeSlider(); qreal from() const; void setFrom(qreal from); @@ -109,6 +112,12 @@ public: bool isHorizontal() const; bool isVertical() const; + // 2.5 (Qt 5.12) + qreal touchDragThreshold() const; + void setTouchDragThreshold(qreal touchDragThreshold); + void resetTouchDragThreshold(); + Q_REVISION(5) Q_INVOKABLE qreal valueAt(qreal position) const; + Q_SIGNALS: void fromChanged(); void toChanged(); @@ -117,6 +126,8 @@ Q_SIGNALS: void orientationChanged(); // 2.2 (Qt 5.9) Q_REVISION(2) void liveChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void touchDragThresholdChanged(); protected: void focusInEvent(QFocusEvent *event) override; @@ -156,6 +167,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickRangeSliderNode : public QObject Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL) // 2.1 (Qt 5.8) Q_PROPERTY(bool hovered READ isHovered WRITE setHovered NOTIFY hoveredChanged FINAL REVISION 1) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal implicitHandleWidth READ implicitHandleWidth NOTIFY implicitHandleWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitHandleHeight READ implicitHandleHeight NOTIFY implicitHandleHeightChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "handle") public: @@ -178,6 +192,10 @@ public: bool isHovered() const; void setHovered(bool hovered); + // 2.5 (Qt 5.12) + qreal implicitHandleWidth() const; + qreal implicitHandleHeight() const; + public Q_SLOTS: void increase(); void decrease(); @@ -190,6 +208,10 @@ Q_SIGNALS: void pressedChanged(); // 2.1 (Qt 5.8) Q_REVISION(1) void hoveredChanged(); + // 2.5 (Qt 5.12) + /*Q_REVISION(5)*/ void moved(); + /*Q_REVISION(5)*/ void implicitHandleWidthChanged(); + /*Q_REVISION(5)*/ void implicitHandleHeightChanged(); private: Q_DISABLE_COPY(QQuickRangeSliderNode) diff --git a/src/quicktemplates2/qquickscrollview.cpp b/src/quicktemplates2/qquickscrollview.cpp index dba0d95c..1d7ecfad 100644 --- a/src/quicktemplates2/qquickscrollview.cpp +++ b/src/quicktemplates2/qquickscrollview.cpp @@ -35,7 +35,7 @@ ****************************************************************************/ #include "qquickscrollview_p.h" -#include "qquickcontrol_p_p.h" +#include "qquickpane_p_p.h" #include "qquickscrollbar_p_p.h" #include <QtQuick/private/qquickflickable_p.h> @@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE /*! \qmltype ScrollView - \inherits Control + \inherits Pane \instantiates QQuickScrollView \inqmlmodule QtQuick.Controls \since 5.9 @@ -101,11 +101,15 @@ QT_BEGIN_NAMESPACE {Focus Management in Qt Quick Controls 2} */ -class QQuickScrollViewPrivate : public QQuickControlPrivate +class QQuickScrollViewPrivate : public QQuickPanePrivate { Q_DECLARE_PUBLIC(QQuickScrollView) public: + QQmlListProperty<QObject> contentData() override; + QQmlListProperty<QQuickItem> contentChildren() override; + QList<QQuickItem *> contentChildItems() const override; + QQuickItem *getContentItem() override; QQuickFlickable *ensureFlickable(bool content); @@ -129,12 +133,20 @@ public: static QQuickItem *contentChildren_at(QQmlListProperty<QQuickItem> *prop, int index); static void contentChildren_clear(QQmlListProperty<QQuickItem> *prop); + void itemImplicitWidthChanged(QQuickItem *item) override; + bool wasTouched = false; - qreal contentWidth = -1; - qreal contentHeight = -1; QQuickFlickable *flickable = nullptr; }; +QList<QQuickItem *> QQuickScrollViewPrivate::contentChildItems() const +{ + if (!flickable) + return QList<QQuickItem *>(); + + return flickable->contentItem()->childItems(); +} + QQuickItem *QQuickScrollViewPrivate::getContentItem() { if (!contentItem) @@ -164,7 +176,7 @@ bool QQuickScrollViewPrivate::setFlickable(QQuickFlickable *item, bool content) if (attached) QQuickScrollBarAttachedPrivate::get(attached)->setFlickable(nullptr); - QObject::disconnect(flickable->contentItem(), &QQuickItem::childrenChanged, q, &QQuickScrollView::contentChildrenChanged); + QObjectPrivate::disconnect(flickable->contentItem(), &QQuickItem::childrenChanged, this, &QQuickPanePrivate::contentChildrenChange); QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickScrollViewPrivate::updateContentWidth); QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickScrollViewPrivate::updateContentHeight); } @@ -175,19 +187,19 @@ bool QQuickScrollViewPrivate::setFlickable(QQuickFlickable *item, bool content) if (flickable) { flickable->installEventFilter(q); - if (contentWidth > 0) - item->setContentWidth(contentWidth); + if (hasContentWidth) + flickable->setContentWidth(contentWidth); else updateContentWidth(); - if (contentHeight > 0) - item->setContentHeight(contentHeight); + if (hasContentHeight) + flickable->setContentHeight(contentHeight); else updateContentHeight(); if (attached) QQuickScrollBarAttachedPrivate::get(attached)->setFlickable(flickable); - QObject::connect(flickable->contentItem(), &QQuickItem::childrenChanged, q, &QQuickScrollView::contentChildrenChanged); + QObjectPrivate::connect(flickable->contentItem(), &QQuickItem::childrenChanged, this, &QQuickPanePrivate::contentChildrenChange); QObjectPrivate::connect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickScrollViewPrivate::updateContentWidth); QObjectPrivate::connect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickScrollViewPrivate::updateContentHeight); } @@ -202,11 +214,11 @@ void QQuickScrollViewPrivate::updateContentWidth() return; const qreal cw = flickable->contentWidth(); - if (qFuzzyCompare(cw, contentWidth)) + if (qFuzzyCompare(cw, implicitContentWidth)) return; - contentWidth = cw; - emit q->contentWidthChanged(); + implicitContentWidth = cw; + emit q->implicitContentWidthChanged(); } void QQuickScrollViewPrivate::updateContentHeight() @@ -216,11 +228,11 @@ void QQuickScrollViewPrivate::updateContentHeight() return; const qreal ch = flickable->contentHeight(); - if (qFuzzyCompare(ch, contentHeight)) + if (qFuzzyCompare(ch, implicitContentHeight)) return; - contentHeight = ch; - emit q->contentHeightChanged(); + implicitContentHeight = ch; + emit q->implicitContentHeightChanged(); } QQuickScrollBar *QQuickScrollViewPrivate::verticalScrollBar() const @@ -342,73 +354,24 @@ void QQuickScrollViewPrivate::contentChildren_clear(QQmlListProperty<QQuickItem> children.clear(&children); } -QQuickScrollView::QQuickScrollView(QQuickItem *parent) - : QQuickControl(*(new QQuickScrollViewPrivate), parent) +void QQuickScrollViewPrivate::itemImplicitWidthChanged(QQuickItem *item) { - setFlag(ItemIsFocusScope); - setActiveFocusOnTab(true); - setFiltersChildMouseEvents(true); - setWheelEnabled(true); -} - -/*! - \qmlproperty real QtQuick.Controls::ScrollView::contentWidth - - This property holds the width of the scrollable content. - - If only a single item is used within a ScrollView, the content size is - automatically calculated based on the implicit size of its contained item. - - \sa contentHeight -*/ -qreal QQuickScrollView::contentWidth() const -{ - Q_D(const QQuickScrollView); - return d->contentWidth; -} - -void QQuickScrollView::setContentWidth(qreal width) -{ - Q_D(QQuickScrollView); - if (qFuzzyCompare(d->contentWidth, width)) + // a special case for width<->height dependent content (wrapping text) in ScrollView + if (contentWidth < 0 && !componentComplete) return; - if (d->flickable) { - d->flickable->setContentWidth(width); - } else { - d->contentWidth = width; - emit contentWidthChanged(); - } -} - -/*! - \qmlproperty real QtQuick.Controls::ScrollView::contentHeight - - This property holds the height of the scrollable content. - - If only a single item is used within a ScrollView, the content size is - automatically calculated based on the implicit size of its contained item. - - \sa contentWidth -*/ -qreal QQuickScrollView::contentHeight() const -{ - Q_D(const QQuickScrollView); - return d->contentHeight; + QQuickPanePrivate::itemImplicitWidthChanged(item); } -void QQuickScrollView::setContentHeight(qreal height) +QQuickScrollView::QQuickScrollView(QQuickItem *parent) + : QQuickPane(*(new QQuickScrollViewPrivate), parent) { Q_D(QQuickScrollView); - if (qFuzzyCompare(d->contentHeight, height)) - return; + d->contentWidth = -1; + d->contentHeight = -1; - if (d->flickable) { - d->flickable->setContentHeight(height); - } else { - d->contentHeight = height; - emit contentHeightChanged(); - } + setFiltersChildMouseEvents(true); + setWheelEnabled(true); } /*! @@ -423,10 +386,10 @@ void QQuickScrollView::setContentHeight(qreal height) \sa Item::data, contentChildren */ -QQmlListProperty<QObject> QQuickScrollView::contentData() +QQmlListProperty<QObject> QQuickScrollViewPrivate::contentData() { - Q_D(QQuickScrollView); - return QQmlListProperty<QObject>(this, d, + Q_Q(QQuickScrollView); + return QQmlListProperty<QObject>(q, this, QQuickScrollViewPrivate::contentData_append, QQuickScrollViewPrivate::contentData_count, QQuickScrollViewPrivate::contentData_at, @@ -444,10 +407,10 @@ QQmlListProperty<QObject> QQuickScrollView::contentData() \sa Item::children, contentData */ -QQmlListProperty<QQuickItem> QQuickScrollView::contentChildren() +QQmlListProperty<QQuickItem> QQuickScrollViewPrivate::contentChildren() { - Q_D(QQuickScrollView); - return QQmlListProperty<QQuickItem>(this, d, + Q_Q(QQuickScrollView); + return QQmlListProperty<QQuickItem>(q, this, QQuickScrollViewPrivate::contentChildren_append, QQuickScrollViewPrivate::contentChildren_count, QQuickScrollViewPrivate::contentChildren_at, @@ -503,13 +466,13 @@ bool QQuickScrollView::eventFilter(QObject *object, QEvent *event) if (!d->wheelEnabled) return true; } - return QQuickControl::eventFilter(object, event); + return QQuickPane::eventFilter(object, event); } void QQuickScrollView::keyPressEvent(QKeyEvent *event) { Q_D(QQuickScrollView); - QQuickControl::keyPressEvent(event); + QQuickPane::keyPressEvent(event); switch (event->key()) { case Qt::Key_Up: if (QQuickScrollBar *vbar = d->verticalScrollBar()) { @@ -544,22 +507,26 @@ void QQuickScrollView::keyPressEvent(QKeyEvent *event) void QQuickScrollView::componentComplete() { Q_D(QQuickScrollView); - QQuickControl::componentComplete(); - if (!d->contentItem) { + QQuickPane::componentComplete(); + if (!d->contentItem) d->ensureFlickable(true); - } else { - if (d->contentWidth <= 0) - d->updateContentWidth(); - if (d->contentHeight <= 0) - d->updateContentHeight(); - } } void QQuickScrollView::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) { Q_D(QQuickScrollView); - QQuickControl::contentItemChange(newItem, oldItem); d->setFlickable(qobject_cast<QQuickFlickable *>(newItem), false); + QQuickPane::contentItemChange(newItem, oldItem); +} + +void QQuickScrollView::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize) +{ + Q_D(QQuickScrollView); + QQuickPane::contentSizeChange(newSize, oldSize); + if (d->flickable) { + d->flickable->setContentWidth(newSize.width()); + d->flickable->setContentHeight(newSize.height()); + } } #if QT_CONFIG(accessibility) @@ -570,3 +537,5 @@ QAccessible::Role QQuickScrollView::accessibleRole() const #endif QT_END_NAMESPACE + +#include "moc_qquickscrollview_p.cpp" diff --git a/src/quicktemplates2/qquickscrollview_p.h b/src/quicktemplates2/qquickscrollview_p.h index 136260c2..2b8d260e 100644 --- a/src/quicktemplates2/qquickscrollview_p.h +++ b/src/quicktemplates2/qquickscrollview_p.h @@ -48,39 +48,20 @@ // We mean it. // -#include <QtQuickTemplates2/private/qquickcontrol_p.h> +#include <QtQuickTemplates2/private/qquickpane_p.h> #include <QtQml/qqmllist.h> QT_BEGIN_NAMESPACE class QQuickScrollViewPrivate; -class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollView : public QQuickControl +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollView : public QQuickPane { Q_OBJECT - Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged FINAL) - Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged FINAL) - Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) - Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL) - Q_CLASSINFO("DefaultProperty", "contentData") public: explicit QQuickScrollView(QQuickItem *parent = nullptr); - qreal contentWidth() const; - void setContentWidth(qreal width); - - qreal contentHeight() const; - void setContentHeight(qreal height); - - QQmlListProperty<QObject> contentData(); - QQmlListProperty<QQuickItem> contentChildren(); - -Q_SIGNALS: - void contentWidthChanged(); - void contentHeightChanged(); - void contentChildrenChanged(); - protected: bool childMouseEventFilter(QQuickItem *item, QEvent *event) override; bool eventFilter(QObject *object, QEvent *event) override; @@ -88,6 +69,7 @@ protected: void componentComplete() override; void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override; + void contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize) override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp index 5806aad5..179dcb64 100644 --- a/src/quicktemplates2/qquickslider.cpp +++ b/src/quicktemplates2/qquickslider.cpp @@ -105,11 +105,15 @@ public: void cancelHandle(); void executeHandle(bool complete = false); + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + qreal from = 0; qreal to = 1; qreal value = 0; qreal position = 0; qreal stepSize = 0; + qreal touchDragThreshold = -1; // in QQuickWindowPrivate::dragOverThreshold, '-1' implies using styleHints::startDragDistance() bool live = true; bool pressed = false; QPointF pressPoint; @@ -248,6 +252,22 @@ void QQuickSliderPrivate::executeHandle(bool complete) quickCompleteDeferred(q, handleName(), handle); } +void QQuickSliderPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickSlider); + QQuickControlPrivate::itemImplicitWidthChanged(item); + if (item == handle) + emit q->implicitHandleWidthChanged(); +} + +void QQuickSliderPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickSlider); + QQuickControlPrivate::itemImplicitHeightChanged(item); + if (item == handle) + emit q->implicitHandleHeightChanged(); +} + QQuickSlider::QQuickSlider(QQuickItem *parent) : QQuickControl(*(new QQuickSliderPrivate), parent) { @@ -259,6 +279,12 @@ QQuickSlider::QQuickSlider(QQuickItem *parent) #endif } +QQuickSlider::~QQuickSlider() +{ + Q_D(QQuickSlider); + d->removeImplicitSizeListener(d->handle); +} + /*! \qmlproperty real QtQuick.Controls::Slider::from @@ -549,10 +575,23 @@ void QQuickSlider::setHandle(QQuickItem *handle) if (!d->handle.isExecuting()) d->cancelHandle(); + const qreal oldImplicitHandleWidth = implicitHandleWidth(); + const qreal oldImplicitHandleHeight = implicitHandleHeight(); + + d->removeImplicitSizeListener(d->handle); delete d->handle; d->handle = handle; - if (handle && !handle->parentItem()) - handle->setParentItem(this); + + if (handle) { + if (!handle->parentItem()) + handle->setParentItem(this); + d->addImplicitSizeListener(handle); + } + + if (!qFuzzyCompare(oldImplicitHandleWidth, implicitHandleWidth())) + emit implicitHandleWidthChanged(); + if (!qFuzzyCompare(oldImplicitHandleHeight, implicitHandleHeight())) + emit implicitHandleHeightChanged(); if (!d->handle.isExecuting()) emit handleChanged(); } @@ -629,6 +668,81 @@ void QQuickSlider::decrease() setValue(d->value - step); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty qreal QtQuick.Controls::Slider::touchDragThreshold + + This property holds the threshold (in logical pixels) at which a touch drag event will be initiated. + The mouse drag threshold won't be affected. + The default value is \c Qt.styleHints.startDragDistance. + + \sa QStyleHints +*/ +qreal QQuickSlider::touchDragThreshold() const +{ + Q_D(const QQuickSlider); + return d->touchDragThreshold; +} + +void QQuickSlider::setTouchDragThreshold(qreal touchDragThreshold) +{ + Q_D(QQuickSlider); + if (d->touchDragThreshold == touchDragThreshold) + return; + + d->touchDragThreshold = touchDragThreshold; + emit touchDragThresholdChanged(); +} + +void QQuickSlider::resetTouchDragThreshold() +{ + setTouchDragThreshold(-1); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Slider::implicitHandleWidth + \readonly + + This property holds the implicit handle width. + + The value is equal to \c {handle ? handle.implicitWidth : 0}. + + This is typically used, together with \l {Control::}{implicitContentWidth} and + \l {Control::}{implicitBackgroundWidth}, to calculate the \l {Item::}{implicitWidth}. + + \sa implicitHandleHeight +*/ +qreal QQuickSlider::implicitHandleWidth() const +{ + Q_D(const QQuickSlider); + if (!d->handle) + return 0; + return d->handle->implicitWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::Slider::implicitHandleHeight + \readonly + + This property holds the implicit handle height. + + The value is equal to \c {handle ? handle.implicitHeight : 0}. + + This is typically used, together with \l {Control::}{implicitContentHeight} and + \l {Control::}{implicitBackgroundHeight}, to calculate the \l {Item::}{implicitHeight}. + + \sa implicitHandleWidth +*/ +qreal QQuickSlider::implicitHandleHeight() const +{ + Q_D(const QQuickSlider); + if (!d->handle) + return 0; + return d->handle->implicitHeight(); +} + void QQuickSlider::keyPressEvent(QKeyEvent *event) { Q_D(QQuickSlider); @@ -697,9 +811,9 @@ void QQuickSlider::touchEvent(QTouchEvent *event) case Qt::TouchPointMoved: if (!keepTouchGrab()) { if (d->orientation == Qt::Horizontal) - setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point)); + setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point, qRound(d->touchDragThreshold))); else - setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point)); + setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point, qRound(d->touchDragThreshold))); } if (keepTouchGrab()) d->handleMove(point.pos()); diff --git a/src/quicktemplates2/qquickslider_p.h b/src/quicktemplates2/qquickslider_p.h index ee6bcffa..c65733dc 100644 --- a/src/quicktemplates2/qquickslider_p.h +++ b/src/quicktemplates2/qquickslider_p.h @@ -71,10 +71,15 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSlider : public QQuickControl // 2.3 (Qt 5.10) Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3) Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal touchDragThreshold READ touchDragThreshold WRITE setTouchDragThreshold RESET resetTouchDragThreshold NOTIFY touchDragThresholdChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitHandleWidth READ implicitHandleWidth NOTIFY implicitHandleWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitHandleHeight READ implicitHandleHeight NOTIFY implicitHandleHeightChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background,handle") public: explicit QQuickSlider(QQuickItem *parent = nullptr); + ~QQuickSlider(); qreal from() const; void setFrom(qreal from); @@ -121,6 +126,14 @@ public: bool isHorizontal() const; bool isVertical() const; + // 2.5 (Qt 5.12) + qreal touchDragThreshold() const; + void setTouchDragThreshold(qreal touchDragThreshold); + void resetTouchDragThreshold(); + + qreal implicitHandleWidth() const; + qreal implicitHandleHeight() const; + public Q_SLOTS: void increase(); void decrease(); @@ -139,6 +152,10 @@ Q_SIGNALS: // 2.2 (Qt 5.9) Q_REVISION(2) void moved(); Q_REVISION(2) void liveChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void touchDragThresholdChanged(); + Q_REVISION(5) void implicitHandleWidthChanged(); + Q_REVISION(5) void implicitHandleHeightChanged(); protected: void keyPressEvent(QKeyEvent *event) override; diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp index f1361330..7f4f59fa 100644 --- a/src/quicktemplates2/qquickspinbox.cpp +++ b/src/quicktemplates2/qquickspinbox.cpp @@ -135,6 +135,9 @@ public: void handleRelease(const QPointF &point) override; void handleUngrab() override; + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + bool editable = false; bool wrap = false; int from = 0; @@ -403,6 +406,24 @@ void QQuickSpinBoxPrivate::handleUngrab() stopPressRepeat(); } +void QQuickSpinBoxPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + QQuickControlPrivate::itemImplicitWidthChanged(item); + if (item == up->indicator()) + emit up->implicitIndicatorWidthChanged(); + else if (item == down->indicator()) + emit down->implicitIndicatorWidthChanged(); +} + +void QQuickSpinBoxPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + QQuickControlPrivate::itemImplicitHeightChanged(item); + if (item == up->indicator()) + emit up->implicitIndicatorHeightChanged(); + else if (item == down->indicator()) + emit down->implicitIndicatorHeightChanged(); +} + QQuickSpinBox::QQuickSpinBox(QQuickItem *parent) : QQuickControl(*(new QQuickSpinBoxPrivate), parent) { @@ -418,6 +439,13 @@ QQuickSpinBox::QQuickSpinBox(QQuickItem *parent) #endif } +QQuickSpinBox::~QQuickSpinBox() +{ + Q_D(QQuickSpinBox); + d->removeImplicitSizeListener(d->up->indicator()); + d->removeImplicitSizeListener(d->down->indicator()); +} + /*! \qmlproperty int QtQuick.Controls::SpinBox::from @@ -688,9 +716,13 @@ void QQuickSpinBox::setValueFromText(const QJSValue &callback) \qmlproperty bool QtQuick.Controls::SpinBox::up.pressed \qmlproperty Item QtQuick.Controls::SpinBox::up.indicator \qmlproperty bool QtQuick.Controls::SpinBox::up.hovered + \qmlproperty real QtQuick.Controls::SpinBox::up.implicitIndicatorWidth + \qmlproperty real QtQuick.Controls::SpinBox::up.implicitIndicatorHeight These properties hold the up indicator item and whether it is pressed or - hovered. The \c up.hovered property was introduced in QtQuick.Controls 2.1. + hovered. The \c up.hovered property was introduced in QtQuick.Controls 2.1, + and the \c up.implicitIndicatorWidth and \c up.implicitIndicatorHeight + properties were introduced in QtQuick.Controls 2.5. \sa increase() */ @@ -705,9 +737,13 @@ QQuickSpinButton *QQuickSpinBox::up() const \qmlproperty bool QtQuick.Controls::SpinBox::down.pressed \qmlproperty Item QtQuick.Controls::SpinBox::down.indicator \qmlproperty bool QtQuick.Controls::SpinBox::down.hovered + \qmlproperty real QtQuick.Controls::SpinBox::down.implicitIndicatorWidth + \qmlproperty real QtQuick.Controls::SpinBox::down.implicitIndicatorHeight These properties hold the down indicator item and whether it is pressed or - hovered. The \c down.hovered property was introduced in QtQuick.Controls 2.1. + hovered. The \c down.hovered property was introduced in QtQuick.Controls 2.1, + and the \c down.implicitIndicatorWidth and \c down.implicitIndicatorHeight + properties were introduced in QtQuick.Controls 2.5. \sa decrease() */ @@ -1000,12 +1036,12 @@ void QQuickSpinBox::localeChange(const QLocale &newLocale, const QLocale &oldLoc QFont QQuickSpinBox::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont); + return QQuickTheme::font(QQuickTheme::SpinBox); } QPalette QQuickSpinBox::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::TextLineEditPalette); + return QQuickTheme::palette(QQuickTheme::SpinBox); } #if QT_CONFIG(accessibility) @@ -1082,13 +1118,24 @@ void QQuickSpinButton::setIndicator(QQuickItem *indicator) if (!d->indicator.isExecuting()) d->cancelIndicator(); + const qreal oldImplicitIndicatorWidth = implicitIndicatorWidth(); + const qreal oldImplicitIndicatorHeight = implicitIndicatorHeight(); + + QQuickSpinBox *spinBox = static_cast<QQuickSpinBox *>(parent()); + QQuickSpinBoxPrivate::get(spinBox)->removeImplicitSizeListener(d->indicator); delete d->indicator; d->indicator = indicator; if (indicator) { if (!indicator->parentItem()) - indicator->setParentItem(static_cast<QQuickItem *>(parent())); + indicator->setParentItem(spinBox); + QQuickSpinBoxPrivate::get(spinBox)->addImplicitSizeListener(indicator); } + + if (!qFuzzyCompare(oldImplicitIndicatorWidth, implicitIndicatorWidth())) + emit implicitIndicatorWidthChanged(); + if (!qFuzzyCompare(oldImplicitIndicatorHeight, implicitIndicatorHeight())) + emit implicitIndicatorHeightChanged(); if (!d->indicator.isExecuting()) emit indicatorChanged(); } @@ -1109,4 +1156,20 @@ void QQuickSpinButton::setHovered(bool hovered) emit hoveredChanged(); } +qreal QQuickSpinButton::implicitIndicatorWidth() const +{ + Q_D(const QQuickSpinButton); + if (!d->indicator) + return 0; + return d->indicator->implicitWidth(); +} + +qreal QQuickSpinButton::implicitIndicatorHeight() const +{ + Q_D(const QQuickSpinButton); + if (!d->indicator) + return 0; + return d->indicator->implicitHeight(); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickspinbox_p.h b/src/quicktemplates2/qquickspinbox_p.h index f5370331..4a339b76 100644 --- a/src/quicktemplates2/qquickspinbox_p.h +++ b/src/quicktemplates2/qquickspinbox_p.h @@ -81,6 +81,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSpinBox : public QQuickControl public: explicit QQuickSpinBox(QQuickItem *parent = nullptr); + ~QQuickSpinBox(); int from() const; void setFrom(int from); @@ -182,6 +183,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSpinButton : public QObject Q_PROPERTY(QQuickItem *indicator READ indicator WRITE setIndicator NOTIFY indicatorChanged FINAL) // 2.1 (Qt 5.8) Q_PROPERTY(bool hovered READ isHovered WRITE setHovered NOTIFY hoveredChanged FINAL REVISION 1) + // 2.5 (Qt 5.12) + Q_PROPERTY(qreal implicitIndicatorWidth READ implicitIndicatorWidth NOTIFY implicitIndicatorWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitIndicatorHeight READ implicitIndicatorHeight NOTIFY implicitIndicatorHeightChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "indicator") public: @@ -197,11 +201,18 @@ public: bool isHovered() const; void setHovered(bool hovered); + // 2.5 (Qt 5.12) + qreal implicitIndicatorWidth() const; + qreal implicitIndicatorHeight() const; + Q_SIGNALS: void pressedChanged(); void indicatorChanged(); // 2.1 (Qt 5.8) Q_REVISION(1) void hoveredChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void implicitIndicatorWidthChanged(); + Q_REVISION(5) void implicitIndicatorHeightChanged(); private: Q_DISABLE_COPY(QQuickSpinButton) diff --git a/src/quicktemplates2/qquickswipedelegate.cpp b/src/quicktemplates2/qquickswipedelegate.cpp index fab50116..97c17a6b 100644 --- a/src/quicktemplates2/qquickswipedelegate.cpp +++ b/src/quicktemplates2/qquickswipedelegate.cpp @@ -1201,12 +1201,19 @@ void QQuickSwipeDelegate::touchEvent(QTouchEvent *event) event->ignore(); } +void QQuickSwipeDelegate::componentComplete() +{ + Q_D(QQuickSwipeDelegate); + QQuickItemDelegate::componentComplete(); + QQuickSwipePrivate::get(&d->swipe)->reposition(DontAnimatePosition); +} + void QQuickSwipeDelegate::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QQuickSwipeDelegate); QQuickControl::geometryChanged(newGeometry, oldGeometry); - if (!qFuzzyCompare(newGeometry.width(), oldGeometry.width())) { + if (isComponentComplete() && !qFuzzyCompare(newGeometry.width(), oldGeometry.width())) { QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&d->swipe); swipePrivate->reposition(DontAnimatePosition); } @@ -1214,7 +1221,12 @@ void QQuickSwipeDelegate::geometryChanged(const QRectF &newGeometry, const QRect QFont QQuickSwipeDelegate::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::ListViewFont); + return QQuickTheme::font(QQuickTheme::ListView); +} + +QPalette QQuickSwipeDelegate::defaultPalette() const +{ + return QQuickTheme::palette(QQuickTheme::ListView); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquickswipedelegate_p.h b/src/quicktemplates2/qquickswipedelegate_p.h index a9900eb8..53211ccb 100644 --- a/src/quicktemplates2/qquickswipedelegate_p.h +++ b/src/quicktemplates2/qquickswipedelegate_p.h @@ -79,9 +79,11 @@ protected: void mouseReleaseEvent(QMouseEvent *event) override; void touchEvent(QTouchEvent *event) override; + void componentComplete() override; void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; QFont defaultFont() const override; + QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) QAccessible::Role accessibleRole() const override; diff --git a/src/quicktemplates2/qquickswipeview.cpp b/src/quicktemplates2/qquickswipeview.cpp index d3026597..f887be7b 100644 --- a/src/quicktemplates2/qquickswipeview.cpp +++ b/src/quicktemplates2/qquickswipeview.cpp @@ -113,6 +113,12 @@ public: static QQuickSwipeViewPrivate *get(QQuickSwipeView *view); + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + + qreal getContentWidth() const override; + qreal getContentHeight() const override; + bool interactive = true; Qt::Orientation orientation = Qt::Horizontal; }; @@ -164,11 +170,44 @@ QQuickSwipeViewPrivate *QQuickSwipeViewPrivate::get(QQuickSwipeView *view) return view->d_func(); } +void QQuickSwipeViewPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickSwipeView); + QQuickContainerPrivate::itemImplicitWidthChanged(item); + if (item == q->currentItem()) + updateImplicitContentWidth(); +} + +void QQuickSwipeViewPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickSwipeView); + QQuickContainerPrivate::itemImplicitHeightChanged(item); + if (item == q->currentItem()) + updateImplicitContentHeight(); +} + +qreal QQuickSwipeViewPrivate::getContentWidth() const +{ + Q_Q(const QQuickSwipeView); + QQuickItem *currentItem = q->currentItem(); + return currentItem ? currentItem->implicitWidth() : 0; +} + +qreal QQuickSwipeViewPrivate::getContentHeight() const +{ + Q_Q(const QQuickSwipeView); + QQuickItem *currentItem = q->currentItem(); + return currentItem ? currentItem->implicitHeight() : 0; +} + QQuickSwipeView::QQuickSwipeView(QQuickItem *parent) : QQuickContainer(*(new QQuickSwipeViewPrivate), parent) { + Q_D(QQuickSwipeView); + d->changeTypes |= QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight; setFlag(ItemIsFocusScope); setActiveFocusOnTab(true); + QObjectPrivate::connect(this, &QQuickContainer::currentItemChanged, d, &QQuickControlPrivate::updateImplicitContentSize); } /*! diff --git a/src/quicktemplates2/qquickswitch.cpp b/src/quicktemplates2/qquickswitch.cpp index 3c84bbc7..675cb6ae 100644 --- a/src/quicktemplates2/qquickswitch.cpp +++ b/src/quicktemplates2/qquickswitch.cpp @@ -229,10 +229,14 @@ void QQuickSwitch::buttonChange(ButtonChange change) QQuickAbstractButton::buttonChange(change); } +QFont QQuickSwitch::defaultFont() const +{ + return QQuickTheme::font(QQuickTheme::Switch); +} + QPalette QQuickSwitch::defaultPalette() const { - // ### TODO: add QPlatformTheme::SwitchPalette - return QQuickControlPrivate::themePalette(QPlatformTheme::CheckBoxPalette); + return QQuickTheme::palette(QQuickTheme::Switch); } QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickswitch_p.h b/src/quicktemplates2/qquickswitch_p.h index 0faaf114..ddc32395 100644 --- a/src/quicktemplates2/qquickswitch_p.h +++ b/src/quicktemplates2/qquickswitch_p.h @@ -83,6 +83,7 @@ protected: void nextCheckState() override; void buttonChange(ButtonChange change) override; + QFont defaultFont() const override; QPalette defaultPalette() const override; private: diff --git a/src/quicktemplates2/qquickswitchdelegate.cpp b/src/quicktemplates2/qquickswitchdelegate.cpp index 9257a5fd..3a849be0 100644 --- a/src/quicktemplates2/qquickswitchdelegate.cpp +++ b/src/quicktemplates2/qquickswitchdelegate.cpp @@ -200,7 +200,12 @@ void QQuickSwitchDelegate::touchEvent(QTouchEvent *event) QFont QQuickSwitchDelegate::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::ListViewFont); + return QQuickTheme::font(QQuickTheme::ListView); +} + +QPalette QQuickSwitchDelegate::defaultPalette() const +{ + return QQuickTheme::palette(QQuickTheme::ListView); } void QQuickSwitchDelegate::mirrorChange() diff --git a/src/quicktemplates2/qquickswitchdelegate_p.h b/src/quicktemplates2/qquickswitchdelegate_p.h index 973ec21d..1fb35aea 100644 --- a/src/quicktemplates2/qquickswitchdelegate_p.h +++ b/src/quicktemplates2/qquickswitchdelegate_p.h @@ -79,6 +79,8 @@ protected: #endif QFont defaultFont() const override; + QPalette defaultPalette() const override; + void mirrorChange() override; void nextCheckState() override; diff --git a/src/quicktemplates2/qquicktabbar.cpp b/src/quicktemplates2/qquicktabbar.cpp index 2d732152..745023c3 100644 --- a/src/quicktemplates2/qquicktabbar.cpp +++ b/src/quicktemplates2/qquicktabbar.cpp @@ -104,15 +104,14 @@ public: void updateCurrentIndex(); void updateLayout(); + qreal getContentWidth() const override; + qreal getContentHeight() const override; + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; void itemImplicitWidthChanged(QQuickItem *item) override; void itemImplicitHeightChanged(QQuickItem *item) override; bool updatingLayout = false; - bool hasContentWidth = false; - bool hasContentHeight = false; - qreal contentWidth = 0; - qreal contentHeight = 0; QQuickTabBar::Position position = QQuickTabBar::Header; }; @@ -154,8 +153,6 @@ void QQuickTabBarPrivate::updateLayout() if (count <= 0 || !contentItem) return; - qreal maxHeight = 0; - qreal totalWidth = 0; qreal reservedWidth = 0; int resizableCount = 0; @@ -166,21 +163,15 @@ void QQuickTabBarPrivate::updateLayout() QQuickItem *item = q->itemAt(i); if (item) { QQuickItemPrivate *p = QQuickItemPrivate::get(item); - if (!p->widthValid) { + if (!p->widthValid) ++resizableCount; - totalWidth += item->implicitWidth(); - } else { + else reservedWidth += item->width(); - totalWidth += item->width(); - } - maxHeight = qMax(maxHeight, item->implicitHeight()); allItems += item; } } const qreal totalSpacing = qMax(0, count - 1) * spacing; - totalWidth += totalSpacing; - const qreal itemWidth = (contentItem->width() - reservedWidth - totalSpacing) / qMax(1, resizableCount); updatingLayout = true; @@ -191,48 +182,68 @@ void QQuickTabBarPrivate::updateLayout() p->widthValid = false; } if (!p->heightValid) { - item->setHeight(hasContentHeight ? contentHeight : maxHeight); + item->setHeight(contentHeight); p->heightValid = false; } else { - item->setY((maxHeight - item->height()) / 2); + item->setY((contentHeight - item->height()) / 2); } } updatingLayout = false; +} - bool contentWidthChange = false; - if (!hasContentWidth && !qFuzzyCompare(contentWidth, totalWidth)) { - contentWidth = totalWidth; - contentWidthChange = true; +qreal QQuickTabBarPrivate::getContentWidth() const +{ + Q_Q(const QQuickTabBar); + const int count = contentModel->count(); + qreal totalWidth = qMax(0, count - 1) * spacing; + for (int i = 0; i < count; ++i) { + QQuickItem *item = q->itemAt(i); + if (item) { + QQuickItemPrivate *p = QQuickItemPrivate::get(item); + if (!p->widthValid) + totalWidth += item->implicitWidth(); + else + totalWidth += item->width(); + } } + return totalWidth; +} - bool contentHeightChange = false; - if (!hasContentHeight && !qFuzzyCompare(contentHeight, maxHeight)) { - contentHeight = maxHeight; - contentHeightChange = true; +qreal QQuickTabBarPrivate::getContentHeight() const +{ + Q_Q(const QQuickTabBar); + const int count = contentModel->count(); + qreal maxHeight = 0; + for (int i = 0; i < count; ++i) { + QQuickItem *item = q->itemAt(i); + if (item) + maxHeight = qMax(maxHeight, item->implicitHeight()); } - - if (contentWidthChange) - emit q->contentWidthChanged(); - if (contentHeightChange) - emit q->contentHeightChanged(); + return maxHeight; } -void QQuickTabBarPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) +void QQuickTabBarPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) { - if (!updatingLayout) + QQuickContainerPrivate::itemGeometryChanged(item, change, diff); + if (!updatingLayout) { + if (change.sizeChange()) + updateImplicitContentSize(); updateLayout(); + } } -void QQuickTabBarPrivate::itemImplicitWidthChanged(QQuickItem *) +void QQuickTabBarPrivate::itemImplicitWidthChanged(QQuickItem *item) { - if (!updatingLayout && !hasContentWidth) - updateLayout(); + QQuickContainerPrivate::itemImplicitWidthChanged(item); + if (item != contentItem) + updateImplicitContentWidth(); } -void QQuickTabBarPrivate::itemImplicitHeightChanged(QQuickItem *) +void QQuickTabBarPrivate::itemImplicitHeightChanged(QQuickItem *item) { - if (!updatingLayout && !hasContentHeight) - updateLayout(); + QQuickContainerPrivate::itemImplicitHeightChanged(item); + if (item != contentItem) + updateImplicitContentHeight(); } QQuickTabBar::QQuickTabBar(QQuickItem *parent) @@ -283,39 +294,11 @@ void QQuickTabBar::setPosition(Position position) This property holds the content width. It is used for calculating the total implicit width of the tab bar. - Unless explicitly overridden, the content width is automatically calculated - based on the total implicit width of the tabs and the \l {Control::}{spacing} - of the tab bar. + \note This property is available in TabBar since QtQuick.Controls 2.2 (Qt 5.9), + but it was promoted to the Container base type in QtQuick.Controls 2.5 (Qt 5.12). - \sa contentHeight + \sa Container::contentWidth */ -qreal QQuickTabBar::contentWidth() const -{ - Q_D(const QQuickTabBar); - return d->contentWidth; -} - -void QQuickTabBar::setContentWidth(qreal width) -{ - Q_D(QQuickTabBar); - d->hasContentWidth = true; - if (qFuzzyCompare(d->contentWidth, width)) - return; - - d->contentWidth = width; - emit contentWidthChanged(); -} - -void QQuickTabBar::resetContentWidth() -{ - Q_D(QQuickTabBar); - if (!d->hasContentWidth) - return; - - d->hasContentWidth = false; - if (isComponentComplete()) - d->updateLayout(); -} /*! \since QtQuick.Controls 2.2 (Qt 5.9) @@ -324,38 +307,11 @@ void QQuickTabBar::resetContentWidth() This property holds the content height. It is used for calculating the total implicit height of the tab bar. - Unless explicitly overridden, the content height is automatically calculated - based on the maximum implicit height of the tabs. + \note This property is available in TabBar since QtQuick.Controls 2.2 (Qt 5.9), + but it was promoted to the Container base type in QtQuick.Controls 2.5 (Qt 5.12). - \sa contentWidth + \sa Container::contentHeight */ -qreal QQuickTabBar::contentHeight() const -{ - Q_D(const QQuickTabBar); - return d->contentHeight; -} - -void QQuickTabBar::setContentHeight(qreal height) -{ - Q_D(QQuickTabBar); - d->hasContentHeight = true; - if (qFuzzyCompare(d->contentHeight, height)) - return; - - d->contentHeight = height; - emit contentHeightChanged(); -} - -void QQuickTabBar::resetContentHeight() -{ - Q_D(QQuickTabBar); - if (!d->hasContentHeight) - return; - - d->hasContentHeight = false; - if (isComponentComplete()) - d->updateLayout(); -} QQuickTabBarAttached *QQuickTabBar::qmlAttachedProperties(QObject *object) { @@ -399,6 +355,7 @@ void QQuickTabBar::itemAdded(int index, QQuickItem *item) QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item)); if (attached) QQuickTabBarAttachedPrivate::get(attached)->update(this, index); + d->updateImplicitContentSize(); if (isComponentComplete()) polish(); } @@ -419,13 +376,19 @@ void QQuickTabBar::itemRemoved(int index, QQuickItem *item) QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item)); if (attached) QQuickTabBarAttachedPrivate::get(attached)->update(nullptr, -1); + d->updateImplicitContentSize(); if (isComponentComplete()) polish(); } +QFont QQuickTabBar::defaultFont() const +{ + return QQuickTheme::font(QQuickTheme::TabBar); +} + QPalette QQuickTabBar::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::TabBarPalette); + return QQuickTheme::palette(QQuickTheme::TabBar); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquicktabbar_p.h b/src/quicktemplates2/qquicktabbar_p.h index f0299bd5..5367118c 100644 --- a/src/quicktemplates2/qquicktabbar_p.h +++ b/src/quicktemplates2/qquicktabbar_p.h @@ -61,8 +61,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTabBar : public QQuickContainer Q_OBJECT Q_PROPERTY(Position position READ position WRITE setPosition NOTIFY positionChanged FINAL) // 2.2 (Qt 5.9) - Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL REVISION 2) - Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL REVISION 2) + Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL REVISION 2) // re-declare QQuickContainer::contentWidth (REV 5) + Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL REVISION 2) // re-declare QQuickContainer::contentHeight (REV 5) public: explicit QQuickTabBar(QQuickItem *parent = nullptr); @@ -76,22 +76,10 @@ public: Position position() const; void setPosition(Position position); - // 2.2 (Qt 5.9) - qreal contentWidth() const; - void setContentWidth(qreal width); - void resetContentWidth(); - - qreal contentHeight() const; - void setContentHeight(qreal height); - void resetContentHeight(); - static QQuickTabBarAttached *qmlAttachedProperties(QObject *object); Q_SIGNALS: void positionChanged(); - // 2.2 (Qt 5.9) - Q_REVISION(2) void contentWidthChanged(); - Q_REVISION(2) void contentHeightChanged(); protected: void updatePolish() override; @@ -102,6 +90,7 @@ protected: void itemMoved(int index, QQuickItem *item) override; void itemRemoved(int index, QQuickItem *item) override; + QFont defaultFont() const override; QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquicktabbutton.cpp b/src/quicktemplates2/qquicktabbutton.cpp index 617d4aea..6e20b0da 100644 --- a/src/quicktemplates2/qquicktabbutton.cpp +++ b/src/quicktemplates2/qquicktabbutton.cpp @@ -72,12 +72,12 @@ QQuickTabButton::QQuickTabButton(QQuickItem *parent) QFont QQuickTabButton::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::TabButtonFont); + return QQuickTheme::font(QQuickTheme::TabBar); } QPalette QQuickTabButton::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::TabBarPalette); + return QQuickTheme::palette(QQuickTheme::TabBar); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp index db6d9283..ee7d0ae3 100644 --- a/src/quicktemplates2/qquicktextarea.cpp +++ b/src/quicktemplates2/qquicktextarea.cpp @@ -145,28 +145,76 @@ QQuickTextAreaPrivate::~QQuickTextAreaPrivate() #endif } -void QQuickTextAreaPrivate::resizeBackground() +void QQuickTextAreaPrivate::setTopInset(qreal value, bool reset) { Q_Q(QQuickTextArea); - if (background) { - QQuickItemPrivate *p = QQuickItemPrivate::get(background); - if (!p->widthValid && qFuzzyIsNull(background->x())) { - if (flickable) - background->setWidth(flickable->width()); - else - background->setWidth(q->width()); - p->widthValid = false; - } - if (!p->heightValid && qFuzzyIsNull(background->y())) { - if (flickable) - background->setHeight(flickable->height()); - else - background->setHeight(q->height()); - p->heightValid = false; - } + 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 QQuickTextAreaPrivate::setLeftInset(qreal value, bool reset) +{ + Q_Q(QQuickTextArea); + 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 QQuickTextAreaPrivate::setRightInset(qreal value, bool reset) +{ + Q_Q(QQuickTextArea); + 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 QQuickTextAreaPrivate::setBottomInset(qreal value, bool reset) +{ + Q_Q(QQuickTextArea); + 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 QQuickTextAreaPrivate::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 @@ -186,7 +234,7 @@ void QQuickTextAreaPrivate::inheritFont(const QFont &font) QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font; parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve()); - const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont); + const QFont defaultFont = QQuickTheme::font(QQuickTheme::TextArea); const QFont resolvedFont = parentFont.resolve(defaultFont); setFont_helper(resolvedFont); @@ -228,7 +276,7 @@ void QQuickTextAreaPrivate::inheritPalette(const QPalette &palette) QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette; parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve()); - const QPalette defaultPalette = QQuickControlPrivate::themePalette(QPlatformTheme::TextEditPalette); + const QPalette defaultPalette = QQuickTheme::palette(QQuickTheme::TextArea); const QPalette resolvedPalette = parentPalette.resolve(defaultPalette); setPalette_helper(resolvedPalette); @@ -450,6 +498,30 @@ void QQuickTextAreaPrivate::executeBackground(bool complete) quickCompleteDeferred(q, backgroundName(), background); } +void QQuickTextAreaPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickTextArea); + if (item == background) + emit q->implicitBackgroundWidthChanged(); +} + +void QQuickTextAreaPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickTextArea); + if (item == background) + emit q->implicitBackgroundHeightChanged(); +} + +void QQuickTextAreaPrivate::itemDestroyed(QQuickItem *item) +{ + Q_Q(QQuickTextArea); + if (item == background) { + background = nullptr; + emit q->implicitBackgroundWidthChanged(); + emit q->implicitBackgroundHeightChanged(); + } +} + QQuickTextArea::QQuickTextArea(QQuickItem *parent) : QQuickTextEdit(*(new QQuickTextAreaPrivate), parent) { @@ -470,6 +542,7 @@ QQuickTextArea::~QQuickTextArea() Q_D(QQuickTextArea); if (d->flickable) d->detachFlickable(); + QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry); } QQuickTextAreaAttached *QQuickTextArea::qmlAttachedProperties(QObject *object) @@ -518,8 +591,18 @@ void QQuickTextArea::setBackground(QQuickItem *background) 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); delete d->background; d->background = background; + if (background) { if (d->flickable) background->setParentItem(d->flickable); @@ -527,9 +610,20 @@ void QQuickTextArea::setBackground(QQuickItem *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(); } @@ -561,6 +655,30 @@ void QQuickTextArea::setPlaceholderText(const QString &text) } /*! + \qmlproperty color QtQuick.Controls::TextArea::placeholderTextColor + \since QtQuick.Controls 2.5 (Qt 5.12) + + This property holds the color of placeholderText. + + \sa placeholderText +*/ +QColor QQuickTextArea::placeholderTextColor() const +{ + Q_D(const QQuickTextArea); + return d->placeholderColor; +} + +void QQuickTextArea::setPlaceholderTextColor(const QColor &color) +{ + Q_D(QQuickTextArea); + if (d->placeholderColor == color) + return; + + d->placeholderColor = color; + emit placeholderTextColorChanged(); +} + +/*! \qmlproperty enumeration QtQuick.Controls::TextArea::focusReason \include qquickcontrol-focusreason.qdocinc @@ -697,6 +815,148 @@ void QQuickTextArea::resetPalette() setPalette(QPalette()); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextArea::implicitBackgroundWidth + \readonly + + This property holds the implicit background width. + + The value is equal to \c {background ? background.implicitWidth : 0}. + + \sa implicitBackgroundHeight +*/ +qreal QQuickTextArea::implicitBackgroundWidth() const +{ + Q_D(const QQuickTextArea); + if (!d->background) + return 0; + return d->background->implicitWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextArea::implicitBackgroundHeight + \readonly + + This property holds the implicit background height. + + The value is equal to \c {background ? background.implicitHeight : 0}. + + \sa implicitBackgroundWidth +*/ +qreal QQuickTextArea::implicitBackgroundHeight() const +{ + Q_D(const QQuickTextArea); + if (!d->background) + return 0; + return d->background->implicitHeight(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextArea::topInset + + This property holds the top inset for the background. + + \sa {Control Layout}, bottomInset +*/ +qreal QQuickTextArea::topInset() const +{ + Q_D(const QQuickTextArea); + return d->getTopInset(); +} + +void QQuickTextArea::setTopInset(qreal inset) +{ + Q_D(QQuickTextArea); + d->setTopInset(inset); +} + +void QQuickTextArea::resetTopInset() +{ + Q_D(QQuickTextArea); + d->setTopInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextArea::leftInset + + This property holds the left inset for the background. + + \sa {Control Layout}, rightInset +*/ +qreal QQuickTextArea::leftInset() const +{ + Q_D(const QQuickTextArea); + return d->getLeftInset(); +} + +void QQuickTextArea::setLeftInset(qreal inset) +{ + Q_D(QQuickTextArea); + d->setLeftInset(inset); +} + +void QQuickTextArea::resetLeftInset() +{ + Q_D(QQuickTextArea); + d->setLeftInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextArea::rightInset + + This property holds the right inset for the background. + + \sa {Control Layout}, leftInset +*/ +qreal QQuickTextArea::rightInset() const +{ + Q_D(const QQuickTextArea); + return d->getRightInset(); +} + +void QQuickTextArea::setRightInset(qreal inset) +{ + Q_D(QQuickTextArea); + d->setRightInset(inset); +} + +void QQuickTextArea::resetRightInset() +{ + Q_D(QQuickTextArea); + d->setRightInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextArea::bottomInset + + This property holds the bottom inset for the background. + + \sa {Control Layout}, topInset +*/ +qreal QQuickTextArea::bottomInset() const +{ + Q_D(const QQuickTextArea); + return d->getBottomInset(); +} + +void QQuickTextArea::setBottomInset(qreal inset) +{ + Q_D(QQuickTextArea); + d->setBottomInset(inset); +} + +void QQuickTextArea::resetBottomInset() +{ + Q_D(QQuickTextArea); + d->setBottomInset(0, true); +} + void QQuickTextArea::classBegin() { Q_D(QQuickTextArea); @@ -760,6 +1020,14 @@ void QQuickTextArea::geometryChanged(const QRectF &newGeometry, const QRectF &ol d->resizeBackground(); } +void QQuickTextArea::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset) +{ + Q_D(QQuickTextArea); + Q_UNUSED(newInset); + Q_UNUSED(oldInset); + d->resizeBackground(); +} + QSGNode *QQuickTextArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) { Q_D(QQuickTextArea); diff --git a/src/quicktemplates2/qquicktextarea_p.h b/src/quicktemplates2/qquicktextarea_p.h index 5482ceae..3c38dabf 100644 --- a/src/quicktemplates2/qquicktextarea_p.h +++ b/src/quicktemplates2/qquicktextarea_p.h @@ -73,6 +73,14 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTextArea : public QQuickTextEdit Q_PROPERTY(bool hoverEnabled READ isHoverEnabled WRITE setHoverEnabled RESET resetHoverEnabled NOTIFY hoverEnabledChanged FINAL REVISION 1) // 2.3 (Qt 5.10) Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) + // 2.5 (Qt 5.12) + Q_PROPERTY(QColor placeholderTextColor READ placeholderTextColor WRITE setPlaceholderTextColor NOTIFY placeholderTextColorChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitBackgroundWidth READ implicitBackgroundWidth NOTIFY implicitBackgroundWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitBackgroundHeight READ implicitBackgroundHeight NOTIFY implicitBackgroundHeightChanged FINAL REVISION 5) + Q_PROPERTY(qreal topInset READ topInset WRITE setTopInset RESET resetTopInset NOTIFY topInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal leftInset READ leftInset WRITE setLeftInset RESET resetLeftInset NOTIFY leftInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal rightInset READ rightInset WRITE setRightInset RESET resetRightInset NOTIFY rightInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal bottomInset READ bottomInset WRITE setBottomInset RESET resetBottomInset NOTIFY bottomInsetChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background") public: @@ -108,6 +116,29 @@ public: void setPalette(const QPalette &palette); void resetPalette(); + // 2.5 (Qt 5.12) + QColor placeholderTextColor() const; + void setPlaceholderTextColor(const QColor &color); + + qreal implicitBackgroundWidth() const; + qreal implicitBackgroundHeight() const; + + qreal topInset() const; + void setTopInset(qreal inset); + void resetTopInset(); + + qreal leftInset() const; + void setLeftInset(qreal inset); + void resetLeftInset(); + + qreal rightInset() const; + void setRightInset(qreal inset); + void resetRightInset(); + + qreal bottomInset() const; + void setBottomInset(qreal inset); + void resetBottomInset(); + Q_SIGNALS: void fontChanged(); void implicitWidthChanged3(); @@ -123,6 +154,14 @@ Q_SIGNALS: Q_REVISION(1) void hoverEnabledChanged(); // 2.3 (Qt 5.10) Q_REVISION(3) void paletteChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void placeholderTextColorChanged(); + Q_REVISION(5) void implicitBackgroundWidthChanged(); + Q_REVISION(5) void implicitBackgroundHeightChanged(); + Q_REVISION(5) void topInsetChanged(); + Q_REVISION(5) void leftInsetChanged(); + Q_REVISION(5) void rightInsetChanged(); + Q_REVISION(5) void bottomInsetChanged(); protected: void classBegin() override; @@ -130,6 +169,8 @@ protected: void itemChange(ItemChange change, const ItemChangeData &value) override; void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + virtual void insetChange(const QMarginsF &newInset, const QMarginsF &oldInset); + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) override; void focusInEvent(QFocusEvent *event) override; diff --git a/src/quicktemplates2/qquicktextarea_p_p.h b/src/quicktemplates2/qquicktextarea_p_p.h index 9120c61c..613551e4 100644 --- a/src/quicktemplates2/qquicktextarea_p_p.h +++ b/src/quicktemplates2/qquicktextarea_p_p.h @@ -80,6 +80,17 @@ public: return static_cast<QQuickTextAreaPrivate *>(QObjectPrivate::get(item)); } + inline QMarginsF getInset() const { return QMarginsF(getLeftInset(), getTopInset(), getRightInset(), getBottomInset()); } + inline qreal getTopInset() const { return extra.isAllocated() ? extra->topInset : 0; } + inline qreal getLeftInset() const { return extra.isAllocated() ? extra->leftInset : 0; } + inline qreal getRightInset() const { return extra.isAllocated() ? extra->rightInset : 0; } + inline qreal getBottomInset() const { return extra.isAllocated() ? extra->bottomInset : 0; } + + void setTopInset(qreal value, bool reset = false); + void setLeftInset(qreal value, bool reset = false); + void setRightInset(qreal value, bool reset = false); + void setBottomInset(qreal value, bool reset = false); + void resizeBackground(); void resolveFont(); @@ -128,20 +139,36 @@ public: void cancelBackground(); void executeBackground(bool complete = false); + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + void itemDestroyed(QQuickItem *item) override; + #if QT_CONFIG(quicktemplates2_hover) bool hovered = false; bool explicitHoverEnabled = false; #endif struct ExtraData { + bool hasTopInset = false; + bool hasLeftInset = false; + bool hasRightInset = false; + bool hasBottomInset = false; + bool hasBackgroundWidth = false; + bool hasBackgroundHeight = false; + qreal topInset = 0; + qreal leftInset = 0; + qreal rightInset = 0; + qreal bottomInset = 0; QFont requestedFont; QPalette requestedPalette; }; QLazilyAllocated<ExtraData> extra; + bool resizingBackground = false; QPalette resolvedPalette; QQuickDeferredPointer<QQuickItem> background; QString placeholder; + QColor placeholderColor; Qt::FocusReason focusReason = Qt::OtherFocusReason; QQuickPressHandler pressHandler; QQuickFlickable *flickable = nullptr; diff --git a/src/quicktemplates2/qquicktextfield.cpp b/src/quicktemplates2/qquicktextfield.cpp index e7c66f84..15acfeb6 100644 --- a/src/quicktemplates2/qquicktextfield.cpp +++ b/src/quicktemplates2/qquicktextfield.cpp @@ -126,22 +126,76 @@ QQuickTextFieldPrivate::~QQuickTextFieldPrivate() #endif } -void QQuickTextFieldPrivate::resizeBackground() +void QQuickTextFieldPrivate::setTopInset(qreal value, bool reset) { Q_Q(QQuickTextField); - if (background) { - QQuickItemPrivate *p = QQuickItemPrivate::get(background); - if (!p->widthValid && qFuzzyIsNull(background->x())) { - background->setWidth(q->width()); - p->widthValid = false; - } - if (!p->heightValid && qFuzzyIsNull(background->y())) { - background->setHeight(q->height()); - p->heightValid = false; - } + 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 QQuickTextFieldPrivate::setLeftInset(qreal value, bool reset) +{ + Q_Q(QQuickTextField); + 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 QQuickTextFieldPrivate::setRightInset(qreal value, bool reset) +{ + Q_Q(QQuickTextField); + 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 QQuickTextFieldPrivate::setBottomInset(qreal value, bool reset) +{ + Q_Q(QQuickTextField); + 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 QQuickTextFieldPrivate::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 @@ -161,7 +215,7 @@ void QQuickTextFieldPrivate::inheritFont(const QFont &font) QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font; parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve()); - const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont); + const QFont defaultFont = QQuickTheme::font(QQuickTheme::TextField); const QFont resolvedFont = parentFont.resolve(defaultFont); setFont_helper(resolvedFont); @@ -203,7 +257,7 @@ void QQuickTextFieldPrivate::inheritPalette(const QPalette &palette) QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette; parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve()); - const QPalette defaultPalette = QQuickControlPrivate::themePalette(QPlatformTheme::TextLineEditPalette); + const QPalette defaultPalette = QQuickTheme::palette(QQuickTheme::TextField); const QPalette resolvedPalette = parentPalette.resolve(defaultPalette); setPalette_helper(resolvedPalette); @@ -325,6 +379,42 @@ void QQuickTextFieldPrivate::executeBackground(bool complete) quickCompleteDeferred(q, backgroundName(), background); } +void QQuickTextFieldPrivate::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 QQuickTextFieldPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + Q_Q(QQuickTextField); + if (item == background) + emit q->implicitBackgroundWidthChanged(); +} + +void QQuickTextFieldPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + Q_Q(QQuickTextField); + if (item == background) + emit q->implicitBackgroundHeightChanged(); +} + +void QQuickTextFieldPrivate::itemDestroyed(QQuickItem *item) +{ + Q_Q(QQuickTextField); + if (item == background) { + background = nullptr; + emit q->implicitBackgroundWidthChanged(); + emit q->implicitBackgroundHeightChanged(); + } +} + QQuickTextField::QQuickTextField(QQuickItem *parent) : QQuickTextInput(*(new QQuickTextFieldPrivate), parent) { @@ -340,6 +430,12 @@ QQuickTextField::QQuickTextField(QQuickItem *parent) QObjectPrivate::connect(this, &QQuickTextInput::echoModeChanged, d, &QQuickTextFieldPrivate::echoModeChanged); } +QQuickTextField::~QQuickTextField() +{ + Q_D(QQuickTextField); + QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry); +} + QFont QQuickTextField::font() const { return QQuickTextInput::font(); @@ -381,15 +477,36 @@ void QQuickTextField::setBackground(QQuickItem *background) 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); delete 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(); } @@ -421,6 +538,30 @@ void QQuickTextField::setPlaceholderText(const QString &text) } /*! + \qmlproperty color QtQuick.Controls::TextField::placeholderTextColor + \since QtQuick.Controls 2.5 (Qt 5.12) + + This property holds the color of placeholderText. + + \sa placeholderText +*/ +QColor QQuickTextField::placeholderTextColor() const +{ + Q_D(const QQuickTextField); + return d->placeholderColor; +} + +void QQuickTextField::setPlaceholderTextColor(const QColor &color) +{ + Q_D(QQuickTextField); + if (d->placeholderColor == color) + return; + + d->placeholderColor = color; + emit placeholderTextColorChanged(); +} + +/*! \qmlproperty enumeration QtQuick.Controls::TextField::focusReason \include qquickcontrol-focusreason.qdocinc @@ -557,6 +698,148 @@ void QQuickTextField::classBegin() d->resolvePalette(); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextField::implicitBackgroundWidth + \readonly + + This property holds the implicit background width. + + The value is equal to \c {background ? background.implicitWidth : 0}. + + \sa implicitBackgroundHeight +*/ +qreal QQuickTextField::implicitBackgroundWidth() const +{ + Q_D(const QQuickTextField); + if (!d->background) + return 0; + return d->background->implicitWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextField::implicitBackgroundHeight + \readonly + + This property holds the implicit background height. + + The value is equal to \c {background ? background.implicitHeight : 0}. + + \sa implicitBackgroundWidth +*/ +qreal QQuickTextField::implicitBackgroundHeight() const +{ + Q_D(const QQuickTextField); + if (!d->background) + return 0; + return d->background->implicitHeight(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextField::topInset + + This property holds the top inset for the background. + + \sa {Control Layout}, bottomInset +*/ +qreal QQuickTextField::topInset() const +{ + Q_D(const QQuickTextField); + return d->getTopInset(); +} + +void QQuickTextField::setTopInset(qreal inset) +{ + Q_D(QQuickTextField); + d->setTopInset(inset); +} + +void QQuickTextField::resetTopInset() +{ + Q_D(QQuickTextField); + d->setTopInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextField::leftInset + + This property holds the left inset for the background. + + \sa {Control Layout}, rightInset +*/ +qreal QQuickTextField::leftInset() const +{ + Q_D(const QQuickTextField); + return d->getLeftInset(); +} + +void QQuickTextField::setLeftInset(qreal inset) +{ + Q_D(QQuickTextField); + d->setLeftInset(inset); +} + +void QQuickTextField::resetLeftInset() +{ + Q_D(QQuickTextField); + d->setLeftInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextField::rightInset + + This property holds the right inset for the background. + + \sa {Control Layout}, leftInset +*/ +qreal QQuickTextField::rightInset() const +{ + Q_D(const QQuickTextField); + return d->getRightInset(); +} + +void QQuickTextField::setRightInset(qreal inset) +{ + Q_D(QQuickTextField); + d->setRightInset(inset); +} + +void QQuickTextField::resetRightInset() +{ + Q_D(QQuickTextField); + d->setRightInset(0, true); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::TextField::bottomInset + + This property holds the bottom inset for the background. + + \sa {Control Layout}, topInset +*/ +qreal QQuickTextField::bottomInset() const +{ + Q_D(const QQuickTextField); + return d->getBottomInset(); +} + +void QQuickTextField::setBottomInset(qreal inset) +{ + Q_D(QQuickTextField); + d->setBottomInset(inset); +} + +void QQuickTextField::resetBottomInset() +{ + Q_D(QQuickTextField); + d->setBottomInset(0, true); +} + void QQuickTextField::componentComplete() { Q_D(QQuickTextField); @@ -604,6 +887,13 @@ void QQuickTextField::geometryChanged(const QRectF &newGeometry, const QRectF &o d->resizeBackground(); } +void QQuickTextField::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset) +{ + Q_D(QQuickTextField); + Q_UNUSED(newInset); + Q_UNUSED(oldInset); + d->resizeBackground(); +} QSGNode *QQuickTextField::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) { QQuickDefaultClipNode *clipNode = static_cast<QQuickDefaultClipNode *>(oldNode); diff --git a/src/quicktemplates2/qquicktextfield_p.h b/src/quicktemplates2/qquicktextfield_p.h index 4757bd2d..d0d25d70 100644 --- a/src/quicktemplates2/qquicktextfield_p.h +++ b/src/quicktemplates2/qquicktextfield_p.h @@ -72,10 +72,19 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTextField : public QQuickTextInput Q_PROPERTY(bool hoverEnabled READ isHoverEnabled WRITE setHoverEnabled RESET resetHoverEnabled NOTIFY hoverEnabledChanged FINAL REVISION 1) // 2.3 (Qt 5.10) Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3) + // 2.5 (Qt 5.12) + Q_PROPERTY(QColor placeholderTextColor READ placeholderTextColor WRITE setPlaceholderTextColor NOTIFY placeholderTextColorChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitBackgroundWidth READ implicitBackgroundWidth NOTIFY implicitBackgroundWidthChanged FINAL REVISION 5) + Q_PROPERTY(qreal implicitBackgroundHeight READ implicitBackgroundHeight NOTIFY implicitBackgroundHeightChanged FINAL REVISION 5) + Q_PROPERTY(qreal topInset READ topInset WRITE setTopInset RESET resetTopInset NOTIFY topInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal leftInset READ leftInset WRITE setLeftInset RESET resetLeftInset NOTIFY leftInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal rightInset READ rightInset WRITE setRightInset RESET resetRightInset NOTIFY rightInsetChanged FINAL REVISION 5) + Q_PROPERTY(qreal bottomInset READ bottomInset WRITE setBottomInset RESET resetBottomInset NOTIFY bottomInsetChanged FINAL REVISION 5) Q_CLASSINFO("DeferredPropertyNames", "background") public: explicit QQuickTextField(QQuickItem *parent = nullptr); + ~QQuickTextField(); QFont font() const; void setFont(const QFont &font); @@ -102,6 +111,29 @@ public: void setPalette(const QPalette &palette); void resetPalette(); + // 2.5 (Qt 5.12) + QColor placeholderTextColor() const; + void setPlaceholderTextColor(const QColor &color); + + qreal implicitBackgroundWidth() const; + qreal implicitBackgroundHeight() const; + + qreal topInset() const; + void setTopInset(qreal inset); + void resetTopInset(); + + qreal leftInset() const; + void setLeftInset(qreal inset); + void resetLeftInset(); + + qreal rightInset() const; + void setRightInset(qreal inset); + void resetRightInset(); + + qreal bottomInset() const; + void setBottomInset(qreal inset); + void resetBottomInset(); + Q_SIGNALS: void fontChanged(); void implicitWidthChanged3(); @@ -117,6 +149,14 @@ Q_SIGNALS: Q_REVISION(1) void hoverEnabledChanged(); // 2.3 (Qt 5.10) Q_REVISION(3) void paletteChanged(); + // 2.5 (Qt 5.12) + Q_REVISION(5) void placeholderTextColorChanged(); + Q_REVISION(5) void implicitBackgroundWidthChanged(); + Q_REVISION(5) void implicitBackgroundHeightChanged(); + Q_REVISION(5) void topInsetChanged(); + Q_REVISION(5) void leftInsetChanged(); + Q_REVISION(5) void rightInsetChanged(); + Q_REVISION(5) void bottomInsetChanged(); protected: void classBegin() override; @@ -124,6 +164,8 @@ protected: void itemChange(ItemChange change, const ItemChangeData &value) override; void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + virtual void insetChange(const QMarginsF &newInset, const QMarginsF &oldInset); + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) override; void focusInEvent(QFocusEvent *event) override; diff --git a/src/quicktemplates2/qquicktextfield_p_p.h b/src/quicktemplates2/qquicktextfield_p_p.h index e863a92d..3389d3dc 100644 --- a/src/quicktemplates2/qquicktextfield_p_p.h +++ b/src/quicktemplates2/qquicktextfield_p_p.h @@ -50,6 +50,7 @@ #include <QtQml/private/qlazilyallocated_p.h> #include <QtQuick/private/qquicktextinput_p_p.h> +#include <QtQuick/private/qquickitemchangelistener_p.h> #include <QtQuickTemplates2/private/qquickpresshandler_p_p.h> #include <QtQuickTemplates2/private/qquickdeferredpointer_p_p.h> @@ -61,7 +62,7 @@ QT_BEGIN_NAMESPACE -class QQuickTextFieldPrivate : public QQuickTextInputPrivate +class QQuickTextFieldPrivate : public QQuickTextInputPrivate, public QQuickItemChangeListener #if QT_CONFIG(accessibility) , public QAccessible::ActivationObserver #endif @@ -75,6 +76,17 @@ public: static QQuickTextFieldPrivate *get(QQuickTextField *item) { return static_cast<QQuickTextFieldPrivate *>(QObjectPrivate::get(item)); } + inline QMarginsF getInset() const { return QMarginsF(getLeftInset(), getTopInset(), getRightInset(), getBottomInset()); } + inline qreal getTopInset() const { return extra.isAllocated() ? extra->topInset : 0; } + inline qreal getLeftInset() const { return extra.isAllocated() ? extra->leftInset : 0; } + inline qreal getRightInset() const { return extra.isAllocated() ? extra->rightInset : 0; } + inline qreal getBottomInset() const { return extra.isAllocated() ? extra->bottomInset : 0; } + + void setTopInset(qreal value, bool reset = false); + void setLeftInset(qreal value, bool reset = false); + void setRightInset(qreal value, bool reset = false); + void setBottomInset(qreal value, bool reset = false); + void resizeBackground(); void resolveFont(); @@ -116,20 +128,37 @@ public: void cancelBackground(); void executeBackground(bool complete = false); + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + void itemDestroyed(QQuickItem *item) override; + #if QT_CONFIG(quicktemplates2_hover) bool hovered = false; bool explicitHoverEnabled = false; #endif struct ExtraData { + bool hasTopInset = false; + bool hasLeftInset = false; + bool hasRightInset = false; + bool hasBottomInset = false; + bool hasBackgroundWidth = false; + bool hasBackgroundHeight = false; + qreal topInset = 0; + qreal leftInset = 0; + qreal rightInset = 0; + qreal bottomInset = 0; QFont requestedFont; QPalette requestedPalette; }; QLazilyAllocated<ExtraData> extra; + bool resizingBackground = false; QPalette resolvedPalette; QQuickDeferredPointer<QQuickItem> background; QString placeholder; + QColor placeholderColor; Qt::FocusReason focusReason = Qt::OtherFocusReason; QQuickPressHandler pressHandler; }; diff --git a/src/quicktemplates2/qquicktheme.cpp b/src/quicktemplates2/qquicktheme.cpp new file mode 100644 index 00000000..1ea0cef2 --- /dev/null +++ b/src/quicktemplates2/qquicktheme.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquicktheme_p.h" +#include "qquicktheme_p_p.h" + +#include <QtGui/qpa/qplatformtheme.h> +#include <QtGui/private/qguiapplication_p.h> + +QT_BEGIN_NAMESPACE + +QScopedPointer<QQuickTheme> QQuickThemePrivate::instance; + +static QPlatformTheme::Font platformFont(QQuickTheme::Scope scope) +{ + switch (scope) { + case QQuickTheme::Button: return QPlatformTheme::PushButtonFont; + case QQuickTheme::CheckBox: return QPlatformTheme::CheckBoxFont; + case QQuickTheme::ComboBox: return QPlatformTheme::ComboMenuItemFont; + case QQuickTheme::GroupBox: return QPlatformTheme::GroupBoxTitleFont; + case QQuickTheme::ItemView: return QPlatformTheme::ItemViewFont; + case QQuickTheme::Label: return QPlatformTheme::LabelFont; + case QQuickTheme::ListView: return QPlatformTheme::ListViewFont; + case QQuickTheme::Menu: return QPlatformTheme::MenuFont; + case QQuickTheme::MenuBar: return QPlatformTheme::MenuBarFont; + case QQuickTheme::RadioButton: return QPlatformTheme::RadioButtonFont; + case QQuickTheme::SpinBox: return QPlatformTheme::EditorFont; + case QQuickTheme::Switch: return QPlatformTheme::CheckBoxFont; + case QQuickTheme::TabBar: return QPlatformTheme::TabButtonFont; + case QQuickTheme::TextArea: return QPlatformTheme::EditorFont; + case QQuickTheme::TextField: return QPlatformTheme::EditorFont; + case QQuickTheme::ToolBar: return QPlatformTheme::ToolButtonFont; + case QQuickTheme::ToolTip: return QPlatformTheme::TipLabelFont; + case QQuickTheme::Tumbler: return QPlatformTheme::ItemViewFont; + default: return QPlatformTheme::SystemFont; + } +} + +static QPlatformTheme::Palette platformPalette(QQuickTheme::Scope scope) +{ + switch (scope) { + case QQuickTheme::Button: return QPlatformTheme::ButtonPalette; + case QQuickTheme::CheckBox: return QPlatformTheme::CheckBoxPalette; + case QQuickTheme::ComboBox: return QPlatformTheme::ComboBoxPalette; + case QQuickTheme::GroupBox: return QPlatformTheme::GroupBoxPalette; + case QQuickTheme::ItemView: return QPlatformTheme::ItemViewPalette; + case QQuickTheme::Label: return QPlatformTheme::LabelPalette; + case QQuickTheme::ListView: return QPlatformTheme::ItemViewPalette; + case QQuickTheme::Menu: return QPlatformTheme::MenuPalette; + case QQuickTheme::MenuBar: return QPlatformTheme::MenuBarPalette; + case QQuickTheme::RadioButton: return QPlatformTheme::RadioButtonPalette; + case QQuickTheme::SpinBox: return QPlatformTheme::TextLineEditPalette; + case QQuickTheme::Switch: return QPlatformTheme::CheckBoxPalette; + case QQuickTheme::TabBar: return QPlatformTheme::TabBarPalette; + case QQuickTheme::TextArea: return QPlatformTheme::TextEditPalette; + case QQuickTheme::TextField: return QPlatformTheme::TextLineEditPalette; + case QQuickTheme::ToolBar: return QPlatformTheme::ToolButtonPalette; + case QQuickTheme::ToolTip: return QPlatformTheme::ToolTipPalette; + case QQuickTheme::Tumbler: return QPlatformTheme::ItemViewPalette; + default: return QPlatformTheme::SystemPalette; + } +} + +QQuickTheme::QQuickTheme() + : d_ptr(new QQuickThemePrivate) +{ + d_ptr->q_ptr = this; +} + +QQuickTheme::~QQuickTheme() +{ +} + +QQuickTheme *QQuickTheme::instance() +{ + return QQuickThemePrivate::instance.data(); +} + +QFont QQuickTheme::font(Scope scope) +{ + const QFont *font = nullptr; + if (QQuickTheme *theme = instance()) + font = QQuickThemePrivate::get(theme)->fonts[scope].data(); + else if (QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) + font = theme->font(platformFont(scope)); + + if (font) { + QFont f = *font; + if (scope == System) + f.resolve(0); + return f; + } + + if (scope != System) + return QQuickTheme::font(System); + + return QFont(); +} + +QPalette QQuickTheme::palette(Scope scope) +{ + const QPalette *palette = nullptr; + if (QQuickTheme *theme = instance()) + palette = QQuickThemePrivate::get(theme)->palettes[scope].data(); + else if (QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) + palette = theme->palette(platformPalette(scope)); + + if (palette) { + QPalette f = *palette; + if (scope == System) + f.resolve(0); + return f; + } + + if (scope != System) + return QQuickTheme::palette(System); + + return QPalette(); +} + +void QQuickTheme::setFont(Scope scope, const QFont &font) +{ + Q_D(QQuickTheme); + d->fonts[scope] = QSharedPointer<QFont>::create(d->defaultFont ? d->defaultFont->resolve(font) : font); +} + +void QQuickTheme::setPalette(Scope scope, const QPalette &palette) +{ + Q_D(QQuickTheme); + d->palettes[scope] = QSharedPointer<QPalette>::create(d->defaultPalette ? d->defaultPalette->resolve(palette) : palette); +} + +QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquicktheme_p.h b/src/quicktemplates2/qquicktheme_p.h new file mode 100644 index 00000000..d51cc5b6 --- /dev/null +++ b/src/quicktemplates2/qquicktheme_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKTHEME_P_H +#define QQUICKTHEME_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h> +#include <QtCore/qscopedpointer.h> +#include <QtGui/qfont.h> +#include <QtGui/qpalette.h> + +QT_BEGIN_NAMESPACE + +class QQuickThemePrivate; + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTheme +{ +public: + QQuickTheme(); + ~QQuickTheme(); + + static QQuickTheme *instance(); + + enum Scope { + System, + Button, + CheckBox, + ComboBox, + GroupBox, + ItemView, + Label, + ListView, + Menu, + MenuBar, + RadioButton, + SpinBox, + Switch, + TabBar, + TextArea, + TextField, + ToolBar, + ToolTip, + Tumbler + }; + + static QFont font(Scope scope); + static QPalette palette(Scope scope); + + void setFont(Scope scope, const QFont &font); + void setPalette(Scope scope, const QPalette &palette); + +private: + Q_DISABLE_COPY(QQuickTheme) + Q_DECLARE_PRIVATE(QQuickTheme) + QScopedPointer<QQuickThemePrivate> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QQUICKTHEME_P_H diff --git a/src/quicktemplates2/qquicktheme_p_p.h b/src/quicktemplates2/qquicktheme_p_p.h new file mode 100644 index 00000000..c7421677 --- /dev/null +++ b/src/quicktemplates2/qquicktheme_p_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKTHEME_P_P_H +#define QQUICKTHEME_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuickTemplates2/private/qquicktheme_p.h> + +QT_BEGIN_NAMESPACE + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickThemePrivate +{ + Q_DECLARE_PUBLIC(QQuickTheme) + +public: + static QQuickThemePrivate *get(QQuickTheme *theme) + { + return theme->d_func(); + } + + static QScopedPointer<QQuickTheme> instance; + + static const int NScopes = QQuickTheme::Tumbler + 1; + + QScopedPointer<const QFont> defaultFont; + QScopedPointer<const QPalette> defaultPalette; + QSharedPointer<QFont> fonts[NScopes]; + QSharedPointer<QPalette> palettes[NScopes]; + QQuickTheme *q_ptr = nullptr; +}; + +QT_END_NAMESPACE + +#endif // QQUICKTHEME_P_P_H diff --git a/src/quicktemplates2/qquicktoolbar.cpp b/src/quicktemplates2/qquicktoolbar.cpp index a2f129fa..0abf0364 100644 --- a/src/quicktemplates2/qquicktoolbar.cpp +++ b/src/quicktemplates2/qquicktoolbar.cpp @@ -139,9 +139,14 @@ void QQuickToolBar::setPosition(Position position) emit positionChanged(); } +QFont QQuickToolBar::defaultFont() const +{ + return QQuickTheme::font(QQuickTheme::ToolBar); +} + QPalette QQuickToolBar::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::ToolButtonPalette); + return QQuickTheme::palette(QQuickTheme::ToolBar); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquicktoolbar_p.h b/src/quicktemplates2/qquicktoolbar_p.h index b919c615..ef2ceb7e 100644 --- a/src/quicktemplates2/qquicktoolbar_p.h +++ b/src/quicktemplates2/qquicktoolbar_p.h @@ -75,6 +75,7 @@ Q_SIGNALS: void positionChanged(); protected: + QFont defaultFont() const override; QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquicktoolbutton.cpp b/src/quicktemplates2/qquicktoolbutton.cpp index f87a58b2..eb70fbc4 100644 --- a/src/quicktemplates2/qquicktoolbutton.cpp +++ b/src/quicktemplates2/qquicktoolbutton.cpp @@ -71,12 +71,12 @@ QQuickToolButton::QQuickToolButton(QQuickItem *parent) QFont QQuickToolButton::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::ToolButtonFont); + return QQuickTheme::font(QQuickTheme::ToolBar); } QPalette QQuickToolButton::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::ToolButtonPalette); + return QQuickTheme::palette(QQuickTheme::ToolBar); } QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquicktoolseparator.cpp b/src/quicktemplates2/qquicktoolseparator.cpp index a6fdfc5b..625e85e9 100644 --- a/src/quicktemplates2/qquicktoolseparator.cpp +++ b/src/quicktemplates2/qquicktoolseparator.cpp @@ -131,9 +131,14 @@ bool QQuickToolSeparator::isVertical() const return d->orientation == Qt::Vertical; } +QFont QQuickToolSeparator::defaultFont() const +{ + return QQuickTheme::font(QQuickTheme::ToolBar); +} + QPalette QQuickToolSeparator::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::ToolButtonPalette); + return QQuickTheme::palette(QQuickTheme::ToolBar); } #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquicktoolseparator_p.h b/src/quicktemplates2/qquicktoolseparator_p.h index 2108cc5b..c3c14b82 100644 --- a/src/quicktemplates2/qquicktoolseparator_p.h +++ b/src/quicktemplates2/qquicktoolseparator_p.h @@ -74,6 +74,7 @@ Q_SIGNALS: void orientationChanged(); protected: + QFont defaultFont() const override; QPalette defaultPalette() const override; #if QT_CONFIG(accessibility) diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp index 282b093d..00090f66 100644 --- a/src/quicktemplates2/qquicktooltip.cpp +++ b/src/quicktemplates2/qquicktooltip.cpp @@ -270,14 +270,39 @@ QQuickToolTipAttached *QQuickToolTip::qmlAttachedProperties(QObject *object) return new QQuickToolTipAttached(object); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlmethod void QtQuick.Controls::ToolTip::show(string text, int timeout = -1) + + This method shows the tooltip with \a text and \a timeout (milliseconds). +*/ +void QQuickToolTip::show(const QString &text, int ms) +{ + if (ms >= 0) + setTimeout(ms); + setText(text); + open(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlmethod void QtQuick.Controls::ToolTip::hide() + + This method hides the tooltip. +*/ +void QQuickToolTip::hide() +{ + close(); +} + QFont QQuickToolTip::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::TipLabelFont); + return QQuickTheme::font(QQuickTheme::ToolTip); } QPalette QQuickToolTip::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::ToolTipPalette); + return QQuickTheme::palette(QQuickTheme::ToolTip); } void QQuickToolTip::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) @@ -508,10 +533,8 @@ void QQuickToolTipAttached::show(const QString &text, int ms) tip->resetWidth(); tip->resetHeight(); tip->setParentItem(qobject_cast<QQuickItem *>(parent())); - tip->setTimeout(ms >= 0 ? ms : d->timeout); tip->setDelay(d->delay); - tip->setText(text); - tip->open(); + tip->show(text, ms >= 0 ? ms : d->timeout); } /*! diff --git a/src/quicktemplates2/qquicktooltip_p.h b/src/quicktemplates2/qquicktooltip_p.h index 60b02502..432bdd8e 100644 --- a/src/quicktemplates2/qquicktooltip_p.h +++ b/src/quicktemplates2/qquicktooltip_p.h @@ -84,6 +84,10 @@ Q_SIGNALS: void delayChanged(); void timeoutChanged(); +public Q_SLOTS: + Q_REVISION(5) void show(const QString &text, int ms = -1); + Q_REVISION(5) void hide(); + protected: QFont defaultFont() const override; QPalette defaultPalette() const override; diff --git a/src/quicktemplates2/qquicktumbler.cpp b/src/quicktemplates2/qquicktumbler.cpp index 65e9ec4f..75520375 100644 --- a/src/quicktemplates2/qquicktumbler.cpp +++ b/src/quicktemplates2/qquicktumbler.cpp @@ -70,7 +70,8 @@ QT_BEGIN_NAMESPACE The API is similar to that of views like \l ListView and \l PathView; a \l model and \l delegate can be set, and the \l count and \l currentItem - properties provide read-only access to information about the view. + properties provide read-only access to information about the view. To + position the view at a certain index, use \l positionViewAtIndex(). Unlike views like \l PathView and \l ListView, however, there is always a current item (when the model isn't empty). This means that when \l count is @@ -261,8 +262,9 @@ void QQuickTumblerPrivate::itemChildRemoved(QQuickItem *, QQuickItem *) _q_updateItemHeights(); } -void QQuickTumblerPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &) +void QQuickTumblerPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) { + QQuickControlPrivate::itemGeometryChanged(item, change, diff); if (change.sizeChange()) calculateDisplacements(); } @@ -336,6 +338,8 @@ int QQuickTumbler::count() const The value of this property is \c -1 when \l count is equal to \c 0. In all other cases, it will be greater than or equal to \c 0. + + \sa currentItem, positionViewAtIndex() */ int QQuickTumbler::currentIndex() const { @@ -356,6 +360,8 @@ void QQuickTumbler::setCurrentIndex(int currentIndex) \readonly This property holds the item at the current index. + + \sa currentIndex, positionViewAtIndex() */ QQuickItem *QQuickTumbler::currentItem() const { @@ -457,6 +463,41 @@ bool QQuickTumbler::isMoving() const return d->view && d->view->property("moving").toBool(); } +/*! + \qmlmethod void QtQuick.Controls::Tumbler::positionViewAtIndex(int index, PositionMode mode) + \since QtQuick.Controls 2.5 (Qt 5.12) + + Positions the view so that the \a index is at the position specified by \a mode. + + For example: + + \code + positionViewAtIndex(10, Tumbler.Center) + \endcode + + If \l wrap is true (the default), the modes available to \l {PathView}'s + \l {PathView::}{positionViewAtIndex()} function + are available, otherwise the modes available to \l {ListView}'s + \l {ListView::}{positionViewAtIndex()} function + are available. + + \note There is a known limitation that using \c Tumbler.Beginning when \l + wrap is \c true will result in the wrong item being positioned at the top + of view. As a workaround, pass \c {index - 1}. + + \sa currentIndex +*/ +void QQuickTumbler::positionViewAtIndex(int index, QQuickTumbler::PositionMode mode) +{ + Q_D(QQuickTumbler); + if (!d->view) { + d->warnAboutIncorrectContentItem(); + return; + } + + QMetaObject::invokeMethod(d->view, "positionViewAtIndex", Q_ARG(int, index), Q_ARG(int, mode)); +} + void QQuickTumbler::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QQuickTumbler); @@ -555,7 +596,7 @@ void QQuickTumblerPrivate::setupViewData(QQuickItem *newControlContentItem) return; if (viewContentItemType == QQuickTumblerPrivate::UnsupportedContentItemType) { - qWarning() << "Tumbler: contentItem must contain either a PathView or a ListView"; + warnAboutIncorrectContentItem(); return; } @@ -582,6 +623,12 @@ void QQuickTumblerPrivate::setupViewData(QQuickItem *newControlContentItem) calculateDisplacements(); } +void QQuickTumblerPrivate::warnAboutIncorrectContentItem() +{ + Q_Q(QQuickTumbler); + qmlWarning(q) << "Tumbler: contentItem must contain either a PathView or a ListView"; +} + void QQuickTumblerPrivate::syncCurrentIndex() { const int actualViewIndex = view->property("currentIndex").toInt(); @@ -788,12 +835,12 @@ void QQuickTumbler::updatePolish() QFont QQuickTumbler::defaultFont() const { - return QQuickControlPrivate::themeFont(QPlatformTheme::ItemViewFont); + return QQuickTheme::font(QQuickTheme::Tumbler); } QPalette QQuickTumbler::defaultPalette() const { - return QQuickControlPrivate::themePalette(QPlatformTheme::ItemViewPalette); + return QQuickTheme::palette(QQuickTheme::Tumbler); } void QQuickTumblerAttachedPrivate::init(QQuickItem *delegateItem) diff --git a/src/quicktemplates2/qquicktumbler_p.h b/src/quicktemplates2/qquicktumbler_p.h index 5d4df4a7..3f7c06db 100644 --- a/src/quicktemplates2/qquicktumbler_p.h +++ b/src/quicktemplates2/qquicktumbler_p.h @@ -100,6 +100,19 @@ public: // 2.2 (Qt 5.9) bool isMoving() const; + enum PositionMode { + Beginning, + Center, + End, + Visible, // ListView-only + Contain, + SnapPosition + }; + Q_ENUM(PositionMode) + + // 2.5 (Qt 5.12) + Q_REVISION(5) Q_INVOKABLE void positionViewAtIndex(int index, PositionMode mode); + Q_SIGNALS: void modelChanged(); void countChanged(); diff --git a/src/quicktemplates2/qquicktumbler_p_p.h b/src/quicktemplates2/qquicktumbler_p_p.h index a7e5f2ac..2f8b1207 100644 --- a/src/quicktemplates2/qquicktumbler_p_p.h +++ b/src/quicktemplates2/qquicktumbler_p_p.h @@ -48,13 +48,12 @@ // We mean it. // -#include <QtQuick/private/qquickitemchangelistener_p.h> #include <QtQuickTemplates2/private/qquickcontrol_p_p.h> #include <QtQuickTemplates2/private/qquicktumbler_p.h> QT_BEGIN_NAMESPACE -class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTumblerPrivate : public QQuickControlPrivate, public QQuickItemChangeListener +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTumblerPrivate : public QQuickControlPrivate { Q_DECLARE_PUBLIC(QQuickTumbler) @@ -103,6 +102,7 @@ public: void disconnectFromView(); void setupViewData(QQuickItem *newControlContentItem); + void warnAboutIncorrectContentItem(); void syncCurrentIndex(); enum PropertyChangeReason { diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri index b2193ec0..33bc47ca 100644 --- a/src/quicktemplates2/quicktemplates2.pri +++ b/src/quicktemplates2/quicktemplates2.pri @@ -15,6 +15,7 @@ HEADERS += \ $$PWD/qquickcombobox_p.h \ $$PWD/qquickcontainer_p.h \ $$PWD/qquickcontainer_p_p.h \ + $$PWD/qquickcontentitem_p.h \ $$PWD/qquickcontrol_p.h \ $$PWD/qquickcontrol_p_p.h \ $$PWD/qquickdeferredexecute_p_p.h \ @@ -47,14 +48,16 @@ HEADERS += \ $$PWD/qquickoverlay_p.h \ $$PWD/qquickoverlay_p_p.h \ $$PWD/qquickpage_p.h \ + $$PWD/qquickpage_p_p.h \ $$PWD/qquickpageindicator_p.h \ - $$PWD/qquickpagelayout_p_p.h \ $$PWD/qquickpalette_p.h \ $$PWD/qquickpaletteprovider_p.h \ $$PWD/qquickpane_p.h \ $$PWD/qquickpane_p_p.h \ $$PWD/qquickpopup_p.h \ $$PWD/qquickpopup_p_p.h \ + $$PWD/qquickpopupanchors_p.h \ + $$PWD/qquickpopupanchors_p_p.h \ $$PWD/qquickpopupitem_p_p.h \ $$PWD/qquickpopuppositioner_p_p.h \ $$PWD/qquickpresshandler_p_p.h \ @@ -86,6 +89,8 @@ HEADERS += \ $$PWD/qquicktextarea_p_p.h \ $$PWD/qquicktextfield_p.h \ $$PWD/qquicktextfield_p_p.h \ + $$PWD/qquicktheme_p.h \ + $$PWD/qquicktheme_p_p.h \ $$PWD/qquicktoolbar_p.h \ $$PWD/qquicktoolbutton_p.h \ $$PWD/qquicktoolseparator_p.h \ @@ -104,6 +109,7 @@ SOURCES += \ $$PWD/qquickcheckdelegate.cpp \ $$PWD/qquickcombobox.cpp \ $$PWD/qquickcontainer.cpp \ + $$PWD/qquickcontentitem.cpp \ $$PWD/qquickcontrol.cpp \ $$PWD/qquickdeferredexecute.cpp \ $$PWD/qquickdelaybutton.cpp \ @@ -124,11 +130,11 @@ SOURCES += \ $$PWD/qquickoverlay.cpp \ $$PWD/qquickpage.cpp \ $$PWD/qquickpageindicator.cpp \ - $$PWD/qquickpagelayout.cpp \ $$PWD/qquickpalette.cpp \ $$PWD/qquickpaletteprovider.cpp \ $$PWD/qquickpane.cpp \ $$PWD/qquickpopup.cpp \ + $$PWD/qquickpopupanchors.cpp \ $$PWD/qquickpopupitem.cpp \ $$PWD/qquickpopuppositioner.cpp \ $$PWD/qquickpresshandler.cpp \ @@ -155,6 +161,7 @@ SOURCES += \ $$PWD/qquicktabbutton.cpp \ $$PWD/qquicktextarea.cpp \ $$PWD/qquicktextfield.cpp \ + $$PWD/qquicktheme.cpp \ $$PWD/qquicktoolbar.cpp \ $$PWD/qquicktoolbutton.cpp \ $$PWD/qquicktoolseparator.cpp \ |