192static QRectF alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment,
const QSizeF &size,
const QRectF &rectangle)
194 alignment = QGuiApplicationPrivate::visualAlignment(direction, alignment);
195 qreal x = rectangle.x();
196 qreal y = rectangle.y();
197 qreal w = size.width();
198 qreal h = size.height();
200 if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter || (alignment & Qt::AlignVertical_Mask) == 0)
201 y += qMax<qreal>(0, (rectangle.size().height() - h) / 2);
202 else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom)
203 y += qMax<qreal>(0, rectangle.size().height() - h);
204 if ((alignment & Qt::AlignRight) == Qt::AlignRight)
205 x += qMax<qreal>(0, rectangle.size().width() - w);
206 else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter)
207 x += qMax<qreal>(0, (rectangle.size().width() - w) / 2);
208 return QRectF(x, y, w, h);
211void QQuickDialogButtonBoxPrivate::resizeContent()
213 Q_Q(QQuickDialogButtonBox);
214 if (!contentItem || !contentModel)
217 QRectF geometry = q->boundingRect().adjusted(q->leftPadding(), q->topPadding(), -q->rightPadding(), -q->bottomPadding());
219 geometry = alignedRect(q->isMirrored() ? Qt::RightToLeft : Qt::LeftToRight, alignment, QSizeF(contentWidth, contentHeight), geometry);
221 contentItem->setPosition(geometry.topLeft());
222 contentItem->setSize(geometry.size());
225void QQuickDialogButtonBoxPrivate::updateLayout()
227 Q_Q(QQuickDialogButtonBox);
228 const int count = contentModel->count();
232 const int halign = alignment & Qt::AlignHorizontal_Mask;
233 const int valign = alignment & Qt::AlignVertical_Mask;
235 QList<QQuickAbstractButton *> buttons;
236 const qreal cw = (alignment & Qt::AlignHorizontal_Mask) == 0 ? q->availableWidth() : contentWidth;
237 const qreal itemWidth = (cw - qMax(0, count - 1) * spacing) / count;
239 for (
int i = 0; i < count; ++i) {
240 QQuickItem *item = q->itemAt(i);
242 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
243 if (!p->widthValid()) {
245 item->setWidth(itemWidth);
249 item->setHeight(contentHeight);
252 p->widthValidFlag =
false;
255 buttons +=
static_cast<QQuickAbstractButton *>(item);
258 struct ButtonLayout {
259 ButtonLayout(QPlatformDialogHelper::ButtonLayout layout)
260 : m_layout(QPlatformDialogHelper::buttonLayout(Qt::Horizontal, layout))
264 bool operator()(QQuickAbstractButton *first, QQuickAbstractButton *second)
266 const QPlatformDialogHelper::ButtonRole firstRole = QQuickDialogPrivate::buttonRole(first);
267 const QPlatformDialogHelper::ButtonRole secondRole = QQuickDialogPrivate::buttonRole(second);
269 if (firstRole != secondRole && firstRole != QPlatformDialogHelper::InvalidRole && secondRole != QPlatformDialogHelper::InvalidRole) {
270 const int *l = m_layout;
271 while (*l != QPlatformDialogHelper::EOL) {
273 const int role = (*l & ~QPlatformDialogHelper::Reverse);
274 if (role == firstRole)
276 if (role == secondRole)
282 if (firstRole == secondRole)
285 return firstRole != QPlatformDialogHelper::InvalidRole;
290 std::stable_sort(buttons.begin(), buttons.end(), ButtonLayout(
static_cast<QPlatformDialogHelper::ButtonLayout>(buttonLayout)));
292 for (
int i = 0; i < buttons.size() - 1; ++i)
293 q->insertItem(i, buttons.at(i));
296void QQuickDialogButtonBoxPrivate::updateFocus()
298 Q_Q(QQuickDialogButtonBox);
299 const int count = contentModel->count();
304 int indexOfFocusButton = -1;
305 QQuickButton *buttonToHighlight =
nullptr;
306 for (
int i = 0; i < count; ++i) {
307 QQuickItem *item = q->itemAt(i);
308 if (
auto *button = qobject_cast<QQuickButton *>(item)) {
309 const auto stdButton = standardButton(button);
310 const bool isDefaultStdbutton = defaultStandardButton != QPlatformDialogHelper::NoButton && stdButton == defaultStandardButton;
311 const bool isDefaultButton = defaultButton == button;
312 if (isDefaultButton || isDefaultStdbutton) {
313 buttonToHighlight = button;
314 indexOfFocusButton = i;
320 if (indexOfFocusButton < 0) {
321 for (
int i = 0; i < count; ++i) {
322 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->itemAt(i));
323 if (button && QQuickDialogPrivate::buttonRole(button) == QPlatformDialogHelper::ButtonRole::AcceptRole) {
324 indexOfFocusButton = i;
330 if (QQuickItemView *itemView = qobject_cast<QQuickItemView *>(contentItem)) {
333 itemView->setCurrentIndex(indexOfFocusButton);
334 itemView->setFocus(indexOfFocusButton >= 0);
337 for (
int i = 0; i < count; ++i) {
338 if (
auto *button = qobject_cast<QQuickButton *>(contentModel->get(i))) {
339 button->setFocus(i == indexOfFocusButton);
340 button->setHighlighted(button == buttonToHighlight);
341#if QT_CONFIG(accessibility)
342 if (
auto *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(button,
true)))
343 accessibleAttached->set_defaultButton(button == buttonToHighlight);
349qreal QQuickDialogButtonBoxPrivate::getContentWidth()
const
351 Q_Q(
const QQuickDialogButtonBox);
355 const int count = contentModel->count();
356 const qreal totalSpacing = qMax(0, count - 1) * spacing;
357 qreal totalWidth = totalSpacing;
359 for (
int i = 0; i < count; ++i) {
360 QQuickItem *item = q->itemAt(i);
362 totalWidth += item->implicitWidth();
363 maxWidth = qMax(maxWidth, item->implicitWidth());
366 if ((alignment & Qt::AlignHorizontal_Mask) == 0)
367 totalWidth = qMax(totalWidth, count * maxWidth + totalSpacing);
371qreal QQuickDialogButtonBoxPrivate::getContentHeight()
const
373 Q_Q(
const QQuickDialogButtonBox);
377 const int count = contentModel->count();
379 for (
int i = 0; i < count; ++i) {
380 QQuickItem *item = q->itemAt(i);
382 maxHeight = qMax(maxHeight, item->implicitHeight());
387void QQuickDialogButtonBoxPrivate::handleClick()
389 Q_Q(QQuickDialogButtonBox);
390 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->sender());
398 const QPlatformDialogHelper::ButtonRole role = QQuickDialogPrivate::buttonRole(button);
399 QPointer<QQuickDialogButtonBox> guard(q);
401 emit q->clicked(button);
407 case QPlatformDialogHelper::AcceptRole:
408 case QPlatformDialogHelper::YesRole:
411 case QPlatformDialogHelper::RejectRole:
412 case QPlatformDialogHelper::NoRole:
415 case QPlatformDialogHelper::ApplyRole:
418 case QPlatformDialogHelper::ResetRole:
421 case QPlatformDialogHelper::DestructiveRole:
424 case QPlatformDialogHelper::HelpRole:
425 emit q->helpRequested();
437QQuickAbstractButton *QQuickDialogButtonBoxPrivate::createStandardButton(QPlatformDialogHelper::StandardButton standardButton)
439 Q_Q(QQuickDialogButtonBox);
443 QQmlContext *creationContext = delegate->creationContext();
444 if (!creationContext)
445 creationContext = qmlContext(q);
447 QObject *object = delegate->beginCreate(creationContext);
448 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(object);
450 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button,
true));
451 QQuickDialogButtonBoxAttachedPrivate::get(attached)->standardButton = standardButton;
452 attached->setButtonRole(QPlatformDialogHelper::buttonRole(standardButton));
453 button->setText(buttonText(standardButton));
454 delegate->completeCreate();
455 button->setParent(q);
463void QQuickDialogButtonBoxPrivate::removeStandardButtons()
465 Q_Q(QQuickDialogButtonBox);
466 int i = q->count() - 1;
468 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->itemAt(i));
470 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(
471 qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button,
false));
473 QQuickDialogButtonBoxAttachedPrivate *p = QQuickDialogButtonBoxAttachedPrivate::get(attached);
474 if (p->standardButton != QPlatformDialogHelper::NoButton) {
475 q->removeItem(button);
476 button->deleteLater();
484void QQuickDialogButtonBoxPrivate::updateLanguage()
486 Q_Q(QQuickDialogButtonBox);
487 int i = q->count() - 1;
489 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(itemAt(i));
491 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(
492 qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button,
true));
493 const auto boxAttachedPrivate = QQuickDialogButtonBoxAttachedPrivate::get(attached);
494 const QPlatformDialogHelper::StandardButton standardButton = boxAttachedPrivate->standardButton;
496 if (standardButton != QPlatformDialogHelper::NoButton) {
497 button->setText(buttonText(standardButton));
504QPlatformDialogHelper::StandardButton QQuickDialogButtonBoxPrivate::standardButton(QQuickAbstractButton *button)
const {
505 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button,
false));
507 return QQuickDialogButtonBoxAttachedPrivate::get(attached)->standardButton;
509 return QPlatformDialogHelper::NoButton;
512QQuickDialogButtonBox::QQuickDialogButtonBox(QQuickItem *parent)
513 : QQuickContainer(*(
new QQuickDialogButtonBoxPrivate), parent)
515 Q_D(QQuickDialogButtonBox);
516 setFlag(ItemIsFocusScope);
517 d->changeTypes |= QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
518 d->buttonLayout = platformButtonLayout();
519 d->setSizePolicy(QLayoutPolicy::Preferred, QLayoutPolicy::Fixed);
595void QQuickDialogButtonBox::setAlignment(Qt::Alignment alignment)
597 Q_D(QQuickDialogButtonBox);
598 if (d->alignment == alignment)
601 d->alignment = alignment;
602 if (isComponentComplete()) {
606 emit alignmentChanged();
652void QQuickDialogButtonBox::setStandardButtons(QPlatformDialogHelper::StandardButtons buttons)
654 Q_D(QQuickDialogButtonBox);
655 if (d->standardButtons == buttons)
658 d->removeStandardButtons();
660 for (
int i = QPlatformDialogHelper::FirstButton; i <= QPlatformDialogHelper::LastButton; i<<=1) {
661 QPlatformDialogHelper::StandardButton standardButton =
static_cast<QPlatformDialogHelper::StandardButton>(i);
662 if (standardButton & buttons) {
663 QQuickAbstractButton *button = d->createStandardButton(standardButton);
669 if (isComponentComplete())
672 d->standardButtons = buttons;
673 emit standardButtonsChanged();
683QQuickAbstractButton *QQuickDialogButtonBox::standardButton(QPlatformDialogHelper::StandardButton button)
const
685 Q_D(
const QQuickDialogButtonBox);
686 if (Q_UNLIKELY(!(d->standardButtons & button)))
688 for (
int i = 0, n = count(); i < n; ++i) {
689 QQuickAbstractButton *btn = qobject_cast<QQuickAbstractButton *>(d->itemAt(i));
691 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(btn,
false));
692 if (attached && QQuickDialogButtonBoxAttachedPrivate::get(attached)->standardButton == button)
721void QQuickDialogButtonBox::setDefaultStandardButton(QPlatformDialogHelper::StandardButton button)
723 Q_D(QQuickDialogButtonBox);
724 if (d->defaultStandardButton == button)
727 d->defaultStandardButton = button;
729 if (isComponentComplete())
732 emit defaultStandardButtonChanged();
757void QQuickDialogButtonBox::setDefaultButton(QQuickAbstractButton *button)
759 Q_D(QQuickDialogButtonBox);
760 if (d->defaultButton == button)
763 if (d->defaultButton)
764 removeItem(d->defaultButton);
766 d->defaultButton = button;
768 if (d->defaultButton)
769 addItem(d->defaultButton);
771 if (isComponentComplete())
774 emit defaultButtonChanged();
827void QQuickDialogButtonBox::setButtonLayout(QPlatformDialogHelper::ButtonLayout layout)
829 Q_D(QQuickDialogButtonBox);
830 if (d->buttonLayout == layout)
833 d->buttonLayout = layout;
834 if (isComponentComplete())
836 emit buttonLayoutChanged();
875void QQuickDialogButtonBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
877 Q_D(QQuickDialogButtonBox);
878 QQuickContainer::contentItemChange(newItem, oldItem);
880 QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
882 QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
890void QQuickDialogButtonBox::itemAdded(
int index, QQuickItem *item)
892 Q_D(QQuickDialogButtonBox);
894 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
895 QObjectPrivate::connect(button, &QQuickAbstractButton::clicked, d, &QQuickDialogButtonBoxPrivate::handleClick);
896 if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(item,
false)))
897 QQuickDialogButtonBoxAttachedPrivate::get(attached)->setButtonBox(
this);
898 d->updateImplicitContentSize();
899 if (isComponentComplete())
903void QQuickDialogButtonBox::itemRemoved(
int index, QQuickItem *item)
905 Q_D(QQuickDialogButtonBox);
907 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
908 QObjectPrivate::disconnect(button, &QQuickAbstractButton::clicked, d, &QQuickDialogButtonBoxPrivate::handleClick);
909 if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(item,
false)))
910 QQuickDialogButtonBoxAttachedPrivate::get(attached)->setButtonBox(
nullptr);
911 d->updateImplicitContentSize();
912 if (isComponentComplete())
916void QQuickDialogButtonBox::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &data)
918 QQuickContainer::itemChange(change, data);
919 if (change != QQuickItem::ItemVisibleHasChanged || !isComponentComplete() || !data.boolValue)
922 Q_D(QQuickDialogButtonBox);
943QQuickDialogButtonBoxAttached::QQuickDialogButtonBoxAttached(QObject *parent)
944 : QObject(*(
new QQuickDialogButtonBoxAttachedPrivate), parent)
946 Q_D(QQuickDialogButtonBoxAttached);
947 QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent);
948 while (parentItem && !d->buttonBox) {
949 d->buttonBox = qobject_cast<QQuickDialogButtonBox *>(parentItem);
950 parentItem = parentItem->parentItem();