From c2fd8f7d00e2a47724765e289b828c36c98da29c Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 5 Apr 2017 19:53:01 +0200 Subject: DialogButtonBox: add contentWidth and contentHeight This is a follow-up to f1f884d3, which mentioned that: This can be fixed properly in dev by providing separate contentWidth and contentHeight properties that cleanly propagate the content size to QML. [ChangeLog][Controls][DialogButtonBox] Added contentWidth and contentHeight properties. Change-Id: I4b53702568c55d666bccb587af9fe8c8eba0b63d Reviewed-by: Mitch Curtis --- src/imports/controls/DialogButtonBox.qml | 7 +- src/imports/controls/fusion/DialogButtonBox.qml | 7 +- src/imports/controls/imagine/DialogButtonBox.qml | 7 +- src/imports/controls/material/DialogButtonBox.qml | 7 +- src/imports/controls/universal/DialogButtonBox.qml | 7 +- src/quicktemplates2/qquickdialogbuttonbox.cpp | 198 +++++++++++++++++++-- src/quicktemplates2/qquickdialogbuttonbox_p.h | 12 ++ src/quicktemplates2/qquickdialogbuttonbox_p_p.h | 13 ++ 8 files changed, 218 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/imports/controls/DialogButtonBox.qml b/src/imports/controls/DialogButtonBox.qml index feff1492..e66d41e7 100644 --- a/src/imports/controls/DialogButtonBox.qml +++ b/src/imports/controls/DialogButtonBox.qml @@ -41,9 +41,9 @@ T.DialogButtonBox { id: control implicitWidth: Math.max(background ? background.implicitWidth : 0, - contentItem.implicitWidth + leftPadding + rightPadding) + (control.count === 1 ? contentWidth * 2 : contentWidth) + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, - contentItem.implicitHeight + topPadding + bottomPadding) + contentHeight + topPadding + bottomPadding) spacing: 1 padding: 12 @@ -54,9 +54,6 @@ T.DialogButtonBox { } contentItem: ListView { - implicitWidth: control.count === 1 ? 200 : contentWidth - implicitHeight: 40 - model: control.contentModel spacing: control.spacing orientation: ListView.Horizontal diff --git a/src/imports/controls/fusion/DialogButtonBox.qml b/src/imports/controls/fusion/DialogButtonBox.qml index cfd4be3e..3cf842ff 100644 --- a/src/imports/controls/fusion/DialogButtonBox.qml +++ b/src/imports/controls/fusion/DialogButtonBox.qml @@ -45,9 +45,9 @@ T.DialogButtonBox { id: control implicitWidth: Math.max(background ? background.implicitWidth : 0, - contentItem.implicitWidth + leftPadding + rightPadding) + contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, - contentItem.implicitHeight + topPadding + bottomPadding) + contentHeight + topPadding + bottomPadding) spacing: 6 padding: 6 @@ -56,9 +56,6 @@ T.DialogButtonBox { delegate: Button { } contentItem: ListView { - implicitWidth: contentWidth - implicitHeight: 24 - model: control.contentModel spacing: control.spacing orientation: ListView.Horizontal diff --git a/src/imports/controls/imagine/DialogButtonBox.qml b/src/imports/controls/imagine/DialogButtonBox.qml index eb756548..e58d5645 100644 --- a/src/imports/controls/imagine/DialogButtonBox.qml +++ b/src/imports/controls/imagine/DialogButtonBox.qml @@ -44,9 +44,9 @@ T.DialogButtonBox { id: control implicitWidth: Math.max(background ? background.implicitWidth : 0, - contentItem.implicitWidth + leftPadding + rightPadding) + (control.count === 1 ? contentWidth * 2 : contentWidth) + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, - contentItem.implicitHeight + topPadding + bottomPadding) + contentHeight + topPadding + bottomPadding) topPadding: background ? background.topPadding : 0 leftPadding: background ? background.leftPadding : 0 @@ -60,9 +60,6 @@ T.DialogButtonBox { } contentItem: ListView { - implicitWidth: control.count === 1 ? 200 : contentWidth - implicitHeight: 32 - model: control.contentModel spacing: control.spacing orientation: ListView.Horizontal diff --git a/src/imports/controls/material/DialogButtonBox.qml b/src/imports/controls/material/DialogButtonBox.qml index 7c217f59..1eeb07c5 100644 --- a/src/imports/controls/material/DialogButtonBox.qml +++ b/src/imports/controls/material/DialogButtonBox.qml @@ -45,9 +45,9 @@ T.DialogButtonBox { id: control implicitWidth: Math.max(background ? background.implicitWidth : 0, - contentItem.implicitWidth + leftPadding + rightPadding) + contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, - contentItem.implicitHeight + topPadding + bottomPadding) + contentHeight + topPadding + bottomPadding) spacing: 8 padding: 8 @@ -60,9 +60,6 @@ T.DialogButtonBox { delegate: Button { flat: true } contentItem: ListView { - implicitWidth: contentWidth - implicitHeight: control.Material.buttonHeight - model: control.contentModel spacing: control.spacing orientation: ListView.Horizontal diff --git a/src/imports/controls/universal/DialogButtonBox.qml b/src/imports/controls/universal/DialogButtonBox.qml index 6dff51d1..26f6ea1f 100644 --- a/src/imports/controls/universal/DialogButtonBox.qml +++ b/src/imports/controls/universal/DialogButtonBox.qml @@ -43,9 +43,9 @@ T.DialogButtonBox { id: control implicitWidth: Math.max(background ? background.implicitWidth : 0, - contentItem.implicitWidth + leftPadding + rightPadding) + (control.count === 1 ? contentWidth * 2 : contentWidth) + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, - contentItem.implicitHeight + topPadding + bottomPadding) + contentHeight + topPadding + bottomPadding) spacing: 4 padding: 24 @@ -58,9 +58,6 @@ T.DialogButtonBox { } contentItem: ListView { - implicitWidth: control.count === 1 ? 200 : contentWidth - implicitHeight: 32 - model: control.contentModel spacing: control.spacing orientation: ListView.Horizontal diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp index 7e178f2a..fb07f587 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox.cpp +++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp @@ -198,7 +198,11 @@ static QQuickDialogButtonBox::ButtonLayout platformButtonLayout() } QQuickDialogButtonBoxPrivate::QQuickDialogButtonBoxPrivate() - : alignment(0), + : hasContentWidth(false), + hasContentHeight(false), + contentWidth(0), + contentHeight(0), + alignment(0), position(QQuickDialogButtonBox::Footer), standardButtons(QPlatformDialogHelper::NoButton), buttonLayout(platformButtonLayout()), @@ -208,14 +212,18 @@ QQuickDialogButtonBoxPrivate::QQuickDialogButtonBoxPrivate() void QQuickDialogButtonBoxPrivate::itemImplicitWidthChanged(QQuickItem *item) { - Q_UNUSED(item); - resizeContent(); + if (item == contentItem) + resizeContent(); + else + updateContentWidth(); } void QQuickDialogButtonBoxPrivate::itemImplicitHeightChanged(QQuickItem *item) { - Q_UNUSED(item); - resizeContent(); + if (item == contentItem) + resizeContent(); + else + updateContentHeight(); } // adapted from QStyle::alignedRect() @@ -226,7 +234,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; @@ -244,11 +252,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()); @@ -265,8 +270,7 @@ void QQuickDialogButtonBoxPrivate::updateLayout() const int valign = alignment & Qt::AlignVertical_Mask; QVector 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 itemWidth = (contentWidth - qMax(0, count - 1) * spacing) / count; for (int i = 0; i < count; ++i) { QQuickItem *item = q->itemAt(i); @@ -274,11 +278,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; @@ -324,6 +328,89 @@ void QQuickDialogButtonBoxPrivate::updateLayout() 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::updateContentWidth() +{ + Q_Q(QQuickDialogButtonBox); + if (hasContentWidth) + return; + + const qreal oldContentWidth = contentWidth; + contentWidth = getContentWidth(); + if (qFuzzyCompare(contentWidth, oldContentWidth)) + return; + + emit q->contentWidthChanged(); +} + +void QQuickDialogButtonBoxPrivate::updateContentHeight() +{ + Q_Q(QQuickDialogButtonBox); + if (hasContentHeight) + return; + + const qreal oldContentHeight = contentHeight; + contentHeight = getContentHeight(); + if (qFuzzyCompare(contentHeight, oldContentHeight)) + return; + + emit q->contentHeightChanged(); +} + +void QQuickDialogButtonBoxPrivate::updateContentSize() +{ + Q_Q(QQuickDialogButtonBox); + if (hasContentWidth && hasContentHeight) + return; + + const qreal oldContentWidth = contentWidth; + if (!hasContentWidth) + contentWidth = getContentWidth(); + + const qreal oldContentHeight = contentHeight; + if (!hasContentHeight) + contentHeight = getContentHeight(); + + const bool widthChanged = !qFuzzyCompare(contentWidth, oldContentWidth); + const bool heightChanged = !qFuzzyCompare(contentHeight, oldContentHeight); + + if (widthChanged) + emit q->contentWidthChanged(); + if (heightChanged) + emit q->contentHeightChanged(); +} + void QQuickDialogButtonBoxPrivate::handleClick() { Q_Q(QQuickDialogButtonBox); @@ -647,6 +734,85 @@ void QQuickDialogButtonBox::resetButtonLayout() setButtonLayout(platformButtonLayout()); } +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::DialogButtonBox::contentWidth + + This property holds the content width. It is used for calculating the total + implicit width of the button box. + + Unless explicitly overridden, the content width is automatically calculated + based on the total implicit width of the buttons and the \l {Control::}{spacing} + of the button box. + + \sa contentHeight +*/ +qreal QQuickDialogButtonBox::contentWidth() const +{ + Q_D(const QQuickDialogButtonBox); + return d->contentWidth; +} + +void QQuickDialogButtonBox::setContentWidth(qreal width) +{ + Q_D(QQuickDialogButtonBox); + d->hasContentWidth = true; + if (qFuzzyCompare(d->contentWidth, width)) + return; + + d->contentWidth = width; + emit contentWidthChanged(); +} + +void QQuickDialogButtonBox::resetContentWidth() +{ + Q_D(QQuickDialogButtonBox); + if (!d->hasContentWidth) + return; + + d->hasContentWidth = false; + d->updateContentWidth(); +} + +/*! + \since QtQuick.Controls 2.5 (Qt 5.12) + \qmlproperty real QtQuick.Controls::DialogButtonBox::contentHeight + + This property holds the content height. It is used for calculating the total + implicit height of the button box. + + Unless explicitly overridden, the content height is automatically calculated + based on the maximum implicit height of the buttons. + + \sa contentWidth +*/ +qreal QQuickDialogButtonBox::contentHeight() const +{ + Q_D(const QQuickDialogButtonBox); + return d->contentHeight; +} + +void QQuickDialogButtonBox::setContentHeight(qreal height) +{ + Q_D(QQuickDialogButtonBox); + d->hasContentHeight = true; + if (qFuzzyCompare(d->contentHeight, height)) + return; + + d->contentHeight = height; + emit contentHeightChanged(); +} + +void QQuickDialogButtonBox::resetContentHeight() +{ + Q_D(QQuickDialogButtonBox); + if (!d->hasContentHeight) + return; + + d->hasContentHeight = false; + d->updateContentHeight(); +} + void QQuickDialogButtonBox::updatePolish() { Q_D(QQuickDialogButtonBox); @@ -691,6 +857,7 @@ void QQuickDialogButtonBox::itemAdded(int index, QQuickItem *item) QObjectPrivate::connect(button, &QQuickAbstractButton::clicked, d, &QQuickDialogButtonBoxPrivate::handleClick); if (QQuickDialogButtonBoxAttached *attached = qobject_cast(qmlAttachedPropertiesObject(item, false))) QQuickDialogButtonBoxAttachedPrivate::get(attached)->setButtonBox(this); + d->updateContentSize(); if (isComponentComplete()) polish(); } @@ -703,6 +870,7 @@ void QQuickDialogButtonBox::itemRemoved(int index, QQuickItem *item) QObjectPrivate::disconnect(button, &QQuickAbstractButton::clicked, d, &QQuickDialogButtonBoxPrivate::handleClick); if (QQuickDialogButtonBoxAttached *attached = qobject_cast(qmlAttachedPropertiesObject(item, false))) QQuickDialogButtonBoxAttachedPrivate::get(attached)->setButtonBox(nullptr); + d->updateContentSize(); if (isComponentComplete()) polish(); } diff --git a/src/quicktemplates2/qquickdialogbuttonbox_p.h b/src/quicktemplates2/qquickdialogbuttonbox_p.h index df302e54..0edc671d 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox_p.h +++ b/src/quicktemplates2/qquickdialogbuttonbox_p.h @@ -68,6 +68,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDialogButtonBox : public QQuickCont 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_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_FLAGS(QPlatformDialogHelper::StandardButtons) public: @@ -114,6 +116,14 @@ public: void setButtonLayout(ButtonLayout layout); void resetButtonLayout(); + qreal contentWidth() const; + void setContentWidth(qreal width); + void resetContentWidth(); + + qreal contentHeight() const; + void setContentHeight(qreal height); + void resetContentHeight(); + Q_SIGNALS: void accepted(); void rejected(); @@ -129,6 +139,8 @@ Q_SIGNALS: Q_REVISION(3) void discarded(); // 2.5 (Qt 5.12) Q_REVISION(5) void buttonLayoutChanged(); + Q_REVISION(5) void contentWidthChanged(); + Q_REVISION(5) void contentHeightChanged(); protected: void updatePolish() override; diff --git a/src/quicktemplates2/qquickdialogbuttonbox_p_p.h b/src/quicktemplates2/qquickdialogbuttonbox_p_p.h index 3c761d6b..b9cbe5b7 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox_p_p.h +++ b/src/quicktemplates2/qquickdialogbuttonbox_p_p.h @@ -69,12 +69,25 @@ public: void itemImplicitHeightChanged(QQuickItem *item) override; void resizeContent() override; + void updateLayout(); + + qreal getContentWidth() const; + qreal getContentHeight() const; + + void updateContentWidth(); + void updateContentHeight(); + void updateContentSize(); + void handleClick(); QQuickAbstractButton *createStandardButton(QPlatformDialogHelper::StandardButton button); void removeStandardButtons(); + bool hasContentWidth; + bool hasContentHeight; + qreal contentWidth; + qreal contentHeight; Qt::Alignment alignment; QQuickDialogButtonBox::Position position; QPlatformDialogHelper::StandardButtons standardButtons; -- cgit v1.2.3