1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qquickdialogbuttonbox_p.h"
38#include "qquickdialogbuttonbox_p_p.h"
39#include "qquickabstractbutton_p.h"
40#include "qquickbutton_p.h"
41#include "qquickdialog_p_p.h"
42
43#include <QtCore/qpointer.h>
44#include <QtGui/private/qguiapplication_p.h>
45#include <QtGui/qpa/qplatformtheme.h>
46#include <QtQml/qqmlengine.h>
47#include <QtQml/qqmlcontext.h>
48#include <QtQml/qqmlcomponent.h>
49
50#include <algorithm>
51
52QT_BEGIN_NAMESPACE
53
54/*!
55 \qmltype DialogButtonBox
56 \inherits Container
57//! \instantiates QQuickDialogButtonBox
58 \inqmlmodule QtQuick.Controls
59 \ingroup qtquickcontrols2-dialogs
60 \brief A button box used in dialogs.
61 \since 5.8
62
63 Dialogs and message boxes typically present buttons in an order that
64 conforms to the interface guidelines for that platform. Invariably,
65 different platforms have their dialog buttons in different orders.
66 DialogButtonBox allows a developer to add buttons to it and will
67 automatically use the appropriate order for the user's platform.
68
69 Most buttons for a dialog follow certain roles. Such roles include:
70
71 \list
72 \li Accepting or rejecting the dialog.
73 \li Asking for help.
74 \li Performing actions on the dialog itself (such as resetting fields or
75 applying changes).
76 \endlist
77
78 There can also be alternate ways of dismissing the dialog which may cause
79 destructive results.
80
81 Most dialogs have buttons that can almost be considered standard (e.g.
82 \uicontrol OK and \uicontrol Cancel buttons). It is sometimes convenient
83 to create these buttons in a standard way.
84
85 There are a couple ways of using DialogButtonBox. One way is to specify
86 the standard buttons (e.g. \uicontrol OK, \uicontrol Cancel, \uicontrol Save)
87 and let the button box setup the buttons.
88
89 \image qtquickcontrols2-dialogbuttonbox.png
90
91 \snippet qtquickcontrols2-dialogbuttonbox.qml 1
92
93 Alternatively, buttons and their roles can be specified by hand:
94
95 \snippet qtquickcontrols2-dialogbuttonbox-attached.qml 1
96
97 You can also mix and match normal buttons and standard buttons.
98
99 When a button is clicked in the button box, the \l clicked() signal is
100 emitted for the actual button that is pressed. In addition, the
101 following signals are automatically emitted when a button with the
102 respective role(s) is pressed:
103
104 \table
105 \header
106 \li Role
107 \li Signal
108 \row
109 \li \c AcceptRole, \c YesRole
110 \li \l accepted()
111 \row
112 \li \c ApplyRole
113 \li \l applied()
114 \row
115 \li \c DiscardRole
116 \li \l discarded()
117 \row
118 \li \c HelpRole
119 \li \l helpRequested()
120 \row
121 \li \c RejectRole, \c NoRole
122 \li \l rejected()
123 \row
124 \li \c ResetRole
125 \li \l reset()
126 \endtable
127
128 \sa Dialog
129*/
130
131/*!
132 \qmlsignal QtQuick.Controls::DialogButtonBox::accepted()
133
134 This signal is emitted when a button defined with the \c AcceptRole or
135 \c YesRole is clicked.
136
137 \sa rejected(), clicked(), helpRequested()
138*/
139
140/*!
141 \qmlsignal QtQuick.Controls::DialogButtonBox::rejected()
142
143 This signal is emitted when a button defined with the \c RejectRole or
144 \c NoRole is clicked.
145
146 \sa accepted(), helpRequested(), clicked()
147*/
148
149/*!
150 \since QtQuick.Controls 2.3 (Qt 5.10)
151 \qmlsignal QtQuick.Controls::DialogButtonBox::applied()
152
153 This signal is emitted when a button defined with the \c ApplyRole is
154 clicked.
155
156 \sa discarded(), reset()
157*/
158
159/*!
160 \since QtQuick.Controls 2.3 (Qt 5.10)
161 \qmlsignal QtQuick.Controls::DialogButtonBox::reset()
162
163 This signal is emitted when a button defined with the \c ResetRole is
164 clicked.
165
166 \sa discarded(), applied()
167*/
168
169/*!
170 \since QtQuick.Controls 2.3 (Qt 5.10)
171 \qmlsignal QtQuick.Controls::DialogButtonBox::discarded()
172
173 This signal is emitted when a button defined with the \c DiscardRole is
174 clicked.
175
176 \sa reset(), applied()
177*/
178
179/*!
180 \qmlsignal QtQuick.Controls::DialogButtonBox::helpRequested()
181
182 This signal is emitted when a button defined with the \c HelpRole is clicked.
183
184 \sa accepted(), rejected(), clicked()
185*/
186
187/*!
188 \qmlsignal QtQuick.Controls::DialogButtonBox::clicked(AbstractButton button)
189
190 This signal is emitted when a \a button inside the button box is clicked.
191
192 \sa accepted(), rejected(), helpRequested()
193*/
194
195static QPlatformDialogHelper::ButtonLayout platformButtonLayout()
196{
197 return QGuiApplicationPrivate::platformTheme()->themeHint(hint: QPlatformTheme::DialogButtonBoxLayout).value<QPlatformDialogHelper::ButtonLayout>();
198}
199
200void QQuickDialogButtonBoxPrivate::itemImplicitWidthChanged(QQuickItem *item)
201{
202 QQuickContainerPrivate::itemImplicitWidthChanged(item);
203 if (item == contentItem)
204 resizeContent();
205 else
206 updateImplicitContentWidth();
207}
208
209void QQuickDialogButtonBoxPrivate::itemImplicitHeightChanged(QQuickItem *item)
210{
211 QQuickContainerPrivate::itemImplicitHeightChanged(item);
212 if (item == contentItem)
213 resizeContent();
214 else
215 updateImplicitContentHeight();
216}
217
218// adapted from QStyle::alignedRect()
219static QRectF alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSizeF &size, const QRectF &rectangle)
220{
221 alignment = QGuiApplicationPrivate::visualAlignment(direction, alignment);
222 qreal x = rectangle.x();
223 qreal y = rectangle.y();
224 qreal w = size.width();
225 qreal h = size.height();
226 if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter || (alignment & Qt::AlignVertical_Mask) == 0)
227 y += (rectangle.size().height() - h) / 2;
228 else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom)
229 y += rectangle.size().height() - h;
230 if ((alignment & Qt::AlignRight) == Qt::AlignRight)
231 x += rectangle.size().width() - w;
232 else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter)
233 x += (rectangle.size().width() - w) / 2;
234 return QRectF(x, y, w, h);
235}
236
237void QQuickDialogButtonBoxPrivate::resizeContent()
238{
239 Q_Q(QQuickDialogButtonBox);
240 if (!contentItem)
241 return;
242
243 QRectF geometry = q->boundingRect().adjusted(xp1: q->leftPadding(), yp1: q->topPadding(), xp2: -q->rightPadding(), yp2: -q->bottomPadding());
244 if (alignment != 0)
245 geometry = alignedRect(direction: q->isMirrored() ? Qt::RightToLeft : Qt::LeftToRight, alignment, size: QSizeF(contentWidth, contentHeight), rectangle: geometry);
246
247 contentItem->setPosition(geometry.topLeft());
248 contentItem->setSize(geometry.size());
249}
250
251void QQuickDialogButtonBoxPrivate::updateLayout()
252{
253 Q_Q(QQuickDialogButtonBox);
254 const int count = contentModel->count();
255 if (count <= 0)
256 return;
257
258 const int halign = alignment & Qt::AlignHorizontal_Mask;
259 const int valign = alignment & Qt::AlignVertical_Mask;
260
261 QVector<QQuickAbstractButton *> buttons;
262 const qreal cw = (alignment & Qt::AlignHorizontal_Mask) == 0 ? q->availableWidth() : contentWidth;
263 const qreal itemWidth = (cw - qMax(a: 0, b: count - 1) * spacing) / count;
264
265 for (int i = 0; i < count; ++i) {
266 QQuickItem *item = q->itemAt(index: i);
267 if (item) {
268 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
269 if (!p->widthValid) {
270 if (!halign)
271 item->setWidth(itemWidth);
272 else
273 item->resetWidth();
274 if (!valign)
275 item->setHeight(contentHeight);
276 else
277 item->resetHeight();
278 p->widthValid = false;
279 }
280 }
281 buttons += static_cast<QQuickAbstractButton *>(item);
282 }
283
284 struct ButtonLayout {
285 ButtonLayout(QPlatformDialogHelper::ButtonLayout layout)
286 : m_layout(QPlatformDialogHelper::buttonLayout(orientation: Qt::Horizontal, policy: layout))
287 {
288 }
289
290 bool operator()(QQuickAbstractButton *first, QQuickAbstractButton *second)
291 {
292 const QPlatformDialogHelper::ButtonRole firstRole = QQuickDialogPrivate::buttonRole(button: first);
293 const QPlatformDialogHelper::ButtonRole secondRole = QQuickDialogPrivate::buttonRole(button: second);
294
295 if (firstRole != secondRole && firstRole != QPlatformDialogHelper::InvalidRole && secondRole != QPlatformDialogHelper::InvalidRole) {
296 const int *l = m_layout;
297 while (*l != QPlatformDialogHelper::EOL) {
298 // Unset the Reverse flag.
299 const int role = (*l & ~QPlatformDialogHelper::Reverse);
300 if (role == firstRole)
301 return true;
302 if (role == secondRole)
303 return false;
304 ++l;
305 }
306 }
307
308 if (firstRole == secondRole)
309 return false;
310
311 return firstRole != QPlatformDialogHelper::InvalidRole;
312 }
313 const int *m_layout;
314 };
315
316 std::stable_sort(first: buttons.begin(), last: buttons.end(), comp: ButtonLayout(static_cast<QPlatformDialogHelper::ButtonLayout>(buttonLayout)));
317
318 for (int i = 0; i < buttons.count() - 1; ++i)
319 q->insertItem(index: i, item: buttons.at(i));
320}
321
322qreal QQuickDialogButtonBoxPrivate::getContentWidth() const
323{
324 Q_Q(const QQuickDialogButtonBox);
325 const int count = contentModel->count();
326 const qreal totalSpacing = qMax(a: 0, b: count - 1) * spacing;
327 qreal totalWidth = totalSpacing;
328 qreal maxWidth = 0;
329 for (int i = 0; i < count; ++i) {
330 QQuickItem *item = q->itemAt(index: i);
331 if (item) {
332 totalWidth += item->implicitWidth();
333 maxWidth = qMax(a: maxWidth, b: item->implicitWidth());
334 }
335 }
336 if ((alignment & Qt::AlignHorizontal_Mask) == 0)
337 totalWidth = qMax(a: totalWidth, b: count * maxWidth + totalSpacing);
338 return totalWidth;
339}
340
341qreal QQuickDialogButtonBoxPrivate::getContentHeight() const
342{
343 Q_Q(const QQuickDialogButtonBox);
344 const int count = contentModel->count();
345 qreal maxHeight = 0;
346 for (int i = 0; i < count; ++i) {
347 QQuickItem *item = q->itemAt(index: i);
348 if (item)
349 maxHeight = qMax(a: maxHeight, b: item->implicitHeight());
350 }
351 return maxHeight;
352}
353
354void QQuickDialogButtonBoxPrivate::handleClick()
355{
356 Q_Q(QQuickDialogButtonBox);
357 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object: q->sender());
358 if (!button)
359 return;
360
361 // Can't fetch this *after* emitting clicked, as clicked may destroy the button
362 // or change its role. Now changing the role is not possible yet, but arguably
363 // both clicked and accepted/rejected/etc. should be emitted "atomically"
364 // depending on whatever role the button had at the time of the click.
365 const QPlatformDialogHelper::ButtonRole role = QQuickDialogPrivate::buttonRole(button);
366 QPointer<QQuickDialogButtonBox> guard(q);
367
368 emit q->clicked(button);
369
370 if (!guard)
371 return;
372
373 switch (role) {
374 case QPlatformDialogHelper::AcceptRole:
375 case QPlatformDialogHelper::YesRole:
376 emit q->accepted();
377 break;
378 case QPlatformDialogHelper::RejectRole:
379 case QPlatformDialogHelper::NoRole:
380 emit q->rejected();
381 break;
382 case QPlatformDialogHelper::ApplyRole:
383 emit q->applied();
384 break;
385 case QPlatformDialogHelper::ResetRole:
386 emit q->reset();
387 break;
388 case QPlatformDialogHelper::DestructiveRole:
389 emit q->discarded();
390 break;
391 case QPlatformDialogHelper::HelpRole:
392 emit q->helpRequested();
393 break;
394 default:
395 break;
396 }
397}
398
399QQuickAbstractButton *QQuickDialogButtonBoxPrivate::createStandardButton(QPlatformDialogHelper::StandardButton standardButton)
400{
401 Q_Q(QQuickDialogButtonBox);
402 if (!delegate)
403 return nullptr;
404
405 QQmlContext *creationContext = delegate->creationContext();
406 if (!creationContext)
407 creationContext = qmlContext(q);
408 QQmlContext *context = new QQmlContext(creationContext, q);
409 context->setContextObject(q);
410
411 QObject *object = delegate->beginCreate(context);
412 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(object);
413 if (button) {
414 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(object: qmlAttachedPropertiesObject<QQuickDialogButtonBox>(obj: button, create: true));
415 QQuickDialogButtonBoxAttachedPrivate::get(q: attached)->standardButton = standardButton;
416 attached->setButtonRole(QPlatformDialogHelper::buttonRole(button: standardButton));
417 button->setText(QPlatformTheme::removeMnemonics(original: QGuiApplicationPrivate::platformTheme()->standardButtonText(button: standardButton)));
418 delegate->completeCreate();
419 return button;
420 }
421
422 delete object;
423 return nullptr;
424}
425
426void QQuickDialogButtonBoxPrivate::removeStandardButtons()
427{
428 Q_Q(QQuickDialogButtonBox);
429 int i = q->count() - 1;
430 while (i >= 0) {
431 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object: q->itemAt(index: i));
432 if (button) {
433 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(
434 object: qmlAttachedPropertiesObject<QQuickDialogButtonBox>(obj: button, create: false));
435 if (attached) {
436 QQuickDialogButtonBoxAttachedPrivate *p = QQuickDialogButtonBoxAttachedPrivate::get(q: attached);
437 if (p->standardButton != QPlatformDialogHelper::NoButton) {
438 q->removeItem(item: i);
439 button->deleteLater();
440 }
441 }
442 }
443 --i;
444 }
445}
446
447void QQuickDialogButtonBoxPrivate::updateLanguage()
448{
449 Q_Q(QQuickDialogButtonBox);
450 int i = q->count() - 1;
451 while (i >= 0) {
452 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object: itemAt(index: i));
453 if (button) {
454 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(
455 object: qmlAttachedPropertiesObject<QQuickDialogButtonBox>(obj: button, create: true));
456 const auto boxAttachedPrivate = QQuickDialogButtonBoxAttachedPrivate::get(q: attached);
457 const QPlatformDialogHelper::StandardButton standardButton = boxAttachedPrivate->standardButton;
458 // The button might be a custom one with explicitly specified text, so we shouldn't change it in that case.
459 if (standardButton != QPlatformDialogHelper::NoButton) {
460 const QString buttonText = QGuiApplicationPrivate::platformTheme()->standardButtonText(button: standardButton);
461 button->setText(QPlatformTheme::removeMnemonics(original: buttonText));
462 }
463 }
464 --i;
465 }
466}
467
468QQuickDialogButtonBox::QQuickDialogButtonBox(QQuickItem *parent)
469 : QQuickContainer(*(new QQuickDialogButtonBoxPrivate), parent)
470{
471 Q_D(QQuickDialogButtonBox);
472 d->changeTypes |= QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
473 d->buttonLayout = platformButtonLayout();
474}
475
476QQuickDialogButtonBox::~QQuickDialogButtonBox()
477{
478}
479
480/*!
481 \qmlproperty enumeration QtQuick.Controls::DialogButtonBox::position
482
483 This property holds the position of the button box.
484
485 \note If the button box is assigned as a header or footer of ApplicationWindow
486 or Page, the appropriate position is set automatically.
487
488 Possible values:
489 \value DialogButtonBox.Header The button box is at the top, as a window or page header.
490 \value DialogButtonBox.Footer The button box is at the bottom, as a window or page header.
491
492 The default value is \c Footer.
493
494 \sa Dialog::header, Dialog::footer
495*/
496QQuickDialogButtonBox::Position QQuickDialogButtonBox::position() const
497{
498 Q_D(const QQuickDialogButtonBox);
499 return d->position;
500}
501
502void QQuickDialogButtonBox::setPosition(Position position)
503{
504 Q_D(QQuickDialogButtonBox);
505 if (d->position == position)
506 return;
507
508 d->position = position;
509 emit positionChanged();
510}
511
512/*!
513 \qmlproperty flags QtQuick.Controls::DialogButtonBox::alignment
514
515 This property holds the alignment of the buttons.
516
517 Possible values:
518 \value undefined The buttons are resized to fill the available space.
519 \value Qt.AlignLeft The buttons are aligned to the left.
520 \value Qt.AlignHCenter The buttons are horizontally centered.
521 \value Qt.AlignRight The buttons are aligned to the right.
522 \value Qt.AlignTop The buttons are aligned to the top.
523 \value Qt.AlignVCenter The buttons are vertically centered.
524 \value Qt.AlignBottom The buttons are aligned to the bottom.
525*/
526Qt::Alignment QQuickDialogButtonBox::alignment() const
527{
528 Q_D(const QQuickDialogButtonBox);
529 return d->alignment;
530}
531
532void QQuickDialogButtonBox::setAlignment(Qt::Alignment alignment)
533{
534 Q_D(QQuickDialogButtonBox);
535 if (d->alignment == alignment)
536 return;
537
538 d->alignment = alignment;
539 if (isComponentComplete()) {
540 d->resizeContent();
541 polish();
542 }
543 emit alignmentChanged();
544}
545
546void QQuickDialogButtonBox::resetAlignment()
547{
548 setAlignment({});
549}
550
551/*!
552 \qmlproperty enumeration QtQuick.Controls::DialogButtonBox::standardButtons
553
554 This property holds a combination of standard buttons that are used by the button box.
555
556 \snippet qtquickcontrols2-dialogbuttonbox.qml 1
557
558 The buttons will be positioned in the appropriate order for the user's platform.
559
560 Possible flags:
561 \value DialogButtonBox.Ok An "OK" button defined with the \c AcceptRole.
562 \value DialogButtonBox.Open An "Open" button defined with the \c AcceptRole.
563 \value DialogButtonBox.Save A "Save" button defined with the \c AcceptRole.
564 \value DialogButtonBox.Cancel A "Cancel" button defined with the \c RejectRole.
565 \value DialogButtonBox.Close A "Close" button defined with the \c RejectRole.
566 \value DialogButtonBox.Discard A "Discard" or "Don't Save" button, depending on the platform, defined with the \c DestructiveRole.
567 \value DialogButtonBox.Apply An "Apply" button defined with the \c ApplyRole.
568 \value DialogButtonBox.Reset A "Reset" button defined with the \c ResetRole.
569 \value DialogButtonBox.RestoreDefaults A "Restore Defaults" button defined with the \c ResetRole.
570 \value DialogButtonBox.Help A "Help" button defined with the \c HelpRole.
571 \value DialogButtonBox.SaveAll A "Save All" button defined with the \c AcceptRole.
572 \value DialogButtonBox.Yes A "Yes" button defined with the \c YesRole.
573 \value DialogButtonBox.YesToAll A "Yes to All" button defined with the \c YesRole.
574 \value DialogButtonBox.No A "No" button defined with the \c NoRole.
575 \value DialogButtonBox.NoToAll A "No to All" button defined with the \c NoRole.
576 \value DialogButtonBox.Abort An "Abort" button defined with the \c RejectRole.
577 \value DialogButtonBox.Retry A "Retry" button defined with the \c AcceptRole.
578 \value DialogButtonBox.Ignore An "Ignore" button defined with the \c AcceptRole.
579 \value DialogButtonBox.NoButton An invalid button.
580
581 \sa standardButton()
582*/
583QPlatformDialogHelper::StandardButtons QQuickDialogButtonBox::standardButtons() const
584{
585 Q_D(const QQuickDialogButtonBox);
586 return d->standardButtons;
587}
588
589void QQuickDialogButtonBox::setStandardButtons(QPlatformDialogHelper::StandardButtons buttons)
590{
591 Q_D(QQuickDialogButtonBox);
592 if (d->standardButtons == buttons)
593 return;
594
595 d->removeStandardButtons();
596
597 for (int i = QPlatformDialogHelper::FirstButton; i <= QPlatformDialogHelper::LastButton; i<<=1) {
598 QPlatformDialogHelper::StandardButton standardButton = static_cast<QPlatformDialogHelper::StandardButton>(i);
599 if (standardButton & buttons) {
600 QQuickAbstractButton *button = d->createStandardButton(standardButton);
601 if (button)
602 addItem(item: button);
603 }
604 }
605
606 if (isComponentComplete())
607 polish();
608
609 d->standardButtons = buttons;
610 emit standardButtonsChanged();
611}
612
613/*!
614 \qmlmethod AbstractButton QtQuick.Controls::DialogButtonBox::standardButton(StandardButton button)
615
616 Returns the specified standard \a button, or \c null if it does not exist.
617
618 \sa standardButtons
619*/
620QQuickAbstractButton *QQuickDialogButtonBox::standardButton(QPlatformDialogHelper::StandardButton button) const
621{
622 Q_D(const QQuickDialogButtonBox);
623 if (Q_UNLIKELY(!(d->standardButtons & button)))
624 return nullptr;
625 for (int i = 0, n = count(); i < n; ++i) {
626 QQuickAbstractButton *btn = qobject_cast<QQuickAbstractButton *>(object: d->itemAt(index: i));
627 if (Q_LIKELY(btn)) {
628 QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(object: qmlAttachedPropertiesObject<QQuickDialogButtonBox>(obj: btn, create: false));
629 if (attached && QQuickDialogButtonBoxAttachedPrivate::get(q: attached)->standardButton == button)
630 return btn;
631 }
632 }
633 return nullptr;
634}
635
636/*!
637 \qmlproperty Component QtQuick.Controls::DialogButtonBox::delegate
638
639 This property holds a delegate for creating standard buttons.
640
641 \sa standardButtons
642*/
643QQmlComponent *QQuickDialogButtonBox::delegate() const
644{
645 Q_D(const QQuickDialogButtonBox);
646 return d->delegate;
647}
648
649void QQuickDialogButtonBox::setDelegate(QQmlComponent* delegate)
650{
651 Q_D(QQuickDialogButtonBox);
652 if (d->delegate == delegate)
653 return;
654
655 delete d->delegate;
656 d->delegate = delegate;
657 emit delegateChanged();
658}
659
660QQuickDialogButtonBoxAttached *QQuickDialogButtonBox::qmlAttachedProperties(QObject *object)
661{
662 return new QQuickDialogButtonBoxAttached(object);
663}
664
665/*!
666 \since QtQuick.Controls 2.5 (Qt 5.12)
667 \qmlproperty enumeration QtQuick.Controls::DialogButtonBox::buttonLayout
668
669 This property holds the button layout policy to be used when arranging the buttons contained in the button box.
670 The default value is platform-specific.
671
672 Available values:
673 \value DialogButtonBox.WinLayout Use a policy appropriate for applications on Windows.
674 \value DialogButtonBox.MacLayout Use a policy appropriate for applications on macOS.
675 \value DialogButtonBox.KdeLayout Use a policy appropriate for applications on KDE.
676 \value DialogButtonBox.GnomeLayout Use a policy appropriate for applications on GNOME.
677 \value DialogButtonBox.AndroidLayout Use a policy appropriate for applications on Android.
678*/
679QPlatformDialogHelper::ButtonLayout QQuickDialogButtonBox::buttonLayout() const
680{
681 Q_D(const QQuickDialogButtonBox);
682 return d->buttonLayout;
683}
684
685void QQuickDialogButtonBox::setButtonLayout(QPlatformDialogHelper::ButtonLayout layout)
686{
687 Q_D(QQuickDialogButtonBox);
688 if (d->buttonLayout == layout)
689 return;
690
691 d->buttonLayout = layout;
692 if (isComponentComplete())
693 d->updateLayout();
694 emit buttonLayoutChanged();
695}
696
697void QQuickDialogButtonBox::resetButtonLayout()
698{
699 setButtonLayout(platformButtonLayout());
700}
701
702void QQuickDialogButtonBox::updatePolish()
703{
704 Q_D(QQuickDialogButtonBox);
705 QQuickContainer::updatePolish();
706 d->updateLayout();
707}
708
709bool QQuickDialogButtonBox::event(QEvent *e)
710{
711 Q_D(QQuickDialogButtonBox);
712 if (e->type() == QEvent::LanguageChange)
713 d->updateLanguage();
714 return QQuickContainer::event(e);
715}
716
717void QQuickDialogButtonBox::componentComplete()
718{
719 Q_D(QQuickDialogButtonBox);
720 QQuickContainer::componentComplete();
721 d->updateLayout();
722}
723
724void QQuickDialogButtonBox::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
725{
726 Q_D(QQuickDialogButtonBox);
727 QQuickContainer::geometryChanged(newGeometry, oldGeometry);
728 d->updateLayout();
729}
730
731void QQuickDialogButtonBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
732{
733 Q_D(QQuickDialogButtonBox);
734 QQuickContainer::contentItemChange(newItem, oldItem);
735 if (oldItem)
736 QQuickItemPrivate::get(item: oldItem)->removeItemChangeListener(d, types: QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
737 if (newItem)
738 QQuickItemPrivate::get(item: newItem)->addItemChangeListener(listener: d, types: QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
739}
740
741bool QQuickDialogButtonBox::isContent(QQuickItem *item) const
742{
743 return qobject_cast<QQuickAbstractButton *>(object: item);
744}
745
746void QQuickDialogButtonBox::itemAdded(int index, QQuickItem *item)
747{
748 Q_D(QQuickDialogButtonBox);
749 Q_UNUSED(index);
750 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object: item))
751 QObjectPrivate::connect(sender: button, signal: &QQuickAbstractButton::clicked, receiverPrivate: d, slot: &QQuickDialogButtonBoxPrivate::handleClick);
752 if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(object: qmlAttachedPropertiesObject<QQuickDialogButtonBox>(obj: item, create: false)))
753 QQuickDialogButtonBoxAttachedPrivate::get(q: attached)->setButtonBox(this);
754 d->updateImplicitContentSize();
755 if (isComponentComplete())
756 polish();
757}
758
759void QQuickDialogButtonBox::itemRemoved(int index, QQuickItem *item)
760{
761 Q_D(QQuickDialogButtonBox);
762 Q_UNUSED(index);
763 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object: item))
764 QObjectPrivate::disconnect(sender: button, signal: &QQuickAbstractButton::clicked, receiverPrivate: d, slot: &QQuickDialogButtonBoxPrivate::handleClick);
765 if (QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(object: qmlAttachedPropertiesObject<QQuickDialogButtonBox>(obj: item, create: false)))
766 QQuickDialogButtonBoxAttachedPrivate::get(q: attached)->setButtonBox(nullptr);
767 d->updateImplicitContentSize();
768 if (isComponentComplete())
769 polish();
770}
771
772#if QT_CONFIG(accessibility)
773QAccessible::Role QQuickDialogButtonBox::accessibleRole() const
774{
775 return QAccessible::PageTabList;
776}
777#endif
778
779void QQuickDialogButtonBoxAttachedPrivate::setButtonBox(QQuickDialogButtonBox *box)
780{
781 Q_Q(QQuickDialogButtonBoxAttached);
782 if (buttonBox == box)
783 return;
784
785 buttonBox = box;
786 emit q->buttonBoxChanged();
787}
788
789QQuickDialogButtonBoxAttached::QQuickDialogButtonBoxAttached(QObject *parent)
790 : QObject(*(new QQuickDialogButtonBoxAttachedPrivate), parent)
791{
792 Q_D(QQuickDialogButtonBoxAttached);
793 QQuickItem *parentItem = qobject_cast<QQuickItem *>(object: parent);
794 while (parentItem && !d->buttonBox) {
795 d->buttonBox = qobject_cast<QQuickDialogButtonBox *>(object: parentItem);
796 parentItem = parentItem->parentItem();
797 }
798}
799
800/*!
801 \qmlattachedproperty DialogButtonBox QtQuick.Controls::DialogButtonBox::buttonBox
802 \readonly
803
804 This attached property holds the button box that manages this button, or
805 \c null if the button is not in a button box.
806*/
807QQuickDialogButtonBox *QQuickDialogButtonBoxAttached::buttonBox() const
808{
809 Q_D(const QQuickDialogButtonBoxAttached);
810 return d->buttonBox;
811}
812
813/*!
814 \qmlattachedproperty enumeration QtQuick.Controls::DialogButtonBox::buttonRole
815
816 This attached property holds the role of each button in a button box.
817
818 \snippet qtquickcontrols2-dialogbuttonbox-attached.qml 1
819
820 Available values:
821 \value DialogButtonBox.InvalidRole The button is invalid.
822 \value DialogButtonBox.AcceptRole Clicking the button causes the dialog to be accepted (e.g. \uicontrol OK).
823 \value DialogButtonBox.RejectRole Clicking the button causes the dialog to be rejected (e.g. \uicontrol Cancel).
824 \value DialogButtonBox.DestructiveRole Clicking the button causes a destructive change (e.g. for discarding changes) and closes the dialog.
825 \value DialogButtonBox.ActionRole Clicking the button causes changes to the elements within the dialog.
826 \value DialogButtonBox.HelpRole The button can be clicked to request help.
827 \value DialogButtonBox.YesRole The button is a "Yes"-like button.
828 \value DialogButtonBox.NoRole The button is a "No"-like button.
829 \value DialogButtonBox.ResetRole The button resets the dialog's fields to default values.
830 \value DialogButtonBox.ApplyRole The button applies current changes.
831*/
832QPlatformDialogHelper::ButtonRole QQuickDialogButtonBoxAttached::buttonRole() const
833{
834 Q_D(const QQuickDialogButtonBoxAttached);
835 return d->buttonRole;
836}
837
838void QQuickDialogButtonBoxAttached::setButtonRole(QPlatformDialogHelper::ButtonRole role)
839{
840 Q_D(QQuickDialogButtonBoxAttached);
841 if (d->buttonRole == role)
842 return;
843
844 d->buttonRole = role;
845 emit buttonRoleChanged();
846}
847
848QT_END_NAMESPACE
849

source code of qtquickcontrols2/src/quicktemplates2/qquickdialogbuttonbox.cpp