Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickdialog.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
12#include <qpa/qplatformintegration.h>
13#include <private/qguiapplication_p.h>
14
16
17/*!
18 \qmltype Dialog
19 \inherits Popup
20//! \nativetype QQuickDialog
21 \inqmlmodule QtQuick.Controls
22 \ingroup qtquickcontrols-dialogs
23 \ingroup qtquickcontrols-popups
24 \brief Popup dialog with standard buttons and a title, used for short-term interaction with the user.
25 \since 5.8
26
27 A dialog is a popup mostly used for short-term tasks and brief communications
28 with the user. Similarly to \l ApplicationWindow and \l Page, Dialog is organized
29 into three sections: \l header, \l {Popup::}{contentItem}, and \l footer.
30
31 \image qtquickcontrols-page-wireframe.webp
32 {Page wireframe with header, content area, and footer}
33
34 The \l {Popup::}{padding} properties only affect the contentItem. Use the
35 \l {Popup::}{spacing} property to affect the space between header,
36 contentItem and footer.
37
38 By default, Dialogs have \l {QQuickItem::}{focus}.
39
40 \section1 Dialog Title and Buttons
41
42 Dialog's \l title is displayed by a style-specific title bar that is assigned
43 as a dialog \l header by default.
44
45 Dialog's standard buttons are managed by a \l DialogButtonBox that is assigned
46 as a dialog \l footer by default. The dialog's \l standardButtons property is
47 forwarded to the respective property of the button box. Furthermore, the
48 \l {DialogButtonBox::}{accepted()} and \l {DialogButtonBox::}{rejected()}
49 signals of the button box are connected to the respective signals in Dialog.
50
51 \snippet qtquickcontrols-dialog.qml 1
52
53 \section1 Modal Dialogs
54
55 A \l {Popup::}{modal} dialog blocks input to other content beneath
56 the dialog. When a modal dialog is opened, the user must finish
57 interacting with the dialog and close it before they can access any
58 other content in the same window.
59
60 \snippet qtquickcontrols-dialog-modal.qml 1
61
62 \section1 Modeless Dialogs
63
64 A modeless dialog is a dialog that operates independently of other
65 content around the dialog. When a modeless dialog is opened, the user
66 is allowed to interact with both the dialog and the other content in
67 the same window.
68
69 \snippet qtquickcontrols-dialog-modeless.qml 1
70
71 \sa DialogButtonBox, {Popup Controls}
72*/
73
74/*!
75 \qmlsignal QtQuick.Controls::Dialog::accepted()
76
77 This signal is emitted when the dialog has been accepted either
78 interactively or by calling \l accept().
79
80 \note This signal is \e not emitted when closing the dialog with
81 \l {Popup::}{close()} or setting \l {Popup::}{visible} to \c false.
82
83 \sa rejected()
84*/
85
86/*!
87 \qmlsignal QtQuick.Controls::Dialog::rejected()
88
89 This signal is emitted when the dialog has been rejected either
90 interactively or by calling \l reject().
91
92 \note This signal is \e not emitted when closing the dialog with
93 \l {Popup::}{close()} or setting \l {Popup::}{visible} to \c false.
94
95 \sa accepted()
96*/
97
98/*!
99 \since QtQuick.Controls 2.3 (Qt 5.10)
100 \qmlsignal QtQuick.Controls::Dialog::applied()
101
102 This signal is emitted when the \c Dialog.Apply standard button is clicked.
103
104 \sa discarded(), reset()
105*/
106
107/*!
108 \since QtQuick.Controls 2.3 (Qt 5.10)
109 \qmlsignal QtQuick.Controls::Dialog::reset()
110
111 This signal is emitted when the \c Dialog.Reset standard button is clicked.
112
113 \sa discarded(), applied()
114*/
115
116/*!
117 \since QtQuick.Controls 2.3 (Qt 5.10)
118 \qmlsignal QtQuick.Controls::Dialog::discarded()
119
120 This signal is emitted when the \c Dialog.Discard standard button is clicked.
121
122 \sa reset(), applied()
123*/
124
125/*!
126 \since QtQuick.Controls 2.3 (Qt 5.10)
127 \qmlsignal QtQuick.Controls::Dialog::helpRequested()
128
129 This signal is emitted when the \c Dialog.Help standard button is clicked.
130
131 \sa accepted(), rejected()
132*/
133
134QPlatformDialogHelper::ButtonRole QQuickDialogPrivate::buttonRole(QQuickAbstractButton *button)
135{
136 const QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, false));
137 return attached ? attached->buttonRole() : QPlatformDialogHelper::InvalidRole;
138}
139
140void QQuickDialogPrivate::handleAccept()
141{
142 Q_Q(QQuickDialog);
143 q->accept();
144}
145
146void QQuickDialogPrivate::handleReject()
147{
148 Q_Q(QQuickDialog);
149 q->reject();
150}
151
152void QQuickDialogPrivate::handleClick(QQuickAbstractButton *button)
153{
154 Q_Q(QQuickDialog);
155 switch (buttonRole(button)) {
156 case QPlatformDialogHelper::ApplyRole:
157 emit q->applied();
158 break;
159 case QPlatformDialogHelper::ResetRole:
160 emit q->reset();
161 break;
162 case QPlatformDialogHelper::DestructiveRole:
163 emit q->discarded();
164 q->close();
165 break;
166 case QPlatformDialogHelper::HelpRole:
167 emit q->helpRequested();
168 break;
169 default:
170 break;
171 }
172}
173
174QQuickDialog::QQuickDialog(QObject *parent)
175 : QQuickDialog(*(new QQuickDialogPrivate), parent)
176{
177}
178
179QQuickDialog::QQuickDialog(QQuickDialogPrivate &dd, QObject *parent)
180 : QQuickPopup(dd, parent)
181{
182 Q_D(QQuickDialog);
183
184 // Dialogs should get active focus when opened so that e.g. Cancel closes them.
185 setFocus(true);
186 QObject::connect(d->popupItem, &QQuickPopupItem::headerChanged, this, &QQuickDialog::headerChanged);
187 QObject::connect(d->popupItem, &QQuickPopupItem::footerChanged, this, &QQuickDialog::footerChanged);
188 QObject::connect(d->popupItem, &QQuickPopupItem::implicitHeaderWidthChanged, this, &QQuickDialog::implicitHeaderWidthChanged);
189 QObject::connect(d->popupItem, &QQuickPopupItem::implicitHeaderHeightChanged, this, &QQuickDialog::implicitHeaderHeightChanged);
190 QObject::connect(d->popupItem, &QQuickPopupItem::implicitFooterWidthChanged, this, &QQuickDialog::implicitFooterWidthChanged);
191 QObject::connect(d->popupItem, &QQuickPopupItem::implicitFooterHeightChanged, this, &QQuickDialog::implicitFooterHeightChanged);
192}
193
194QQuickDialog::~QQuickDialog()
195{
196 Q_D(QQuickDialog);
197 QObject::disconnect(d->popupItem, &QQuickPopupItem::headerChanged, this, &QQuickDialog::headerChanged);
198 QObject::disconnect(d->popupItem, &QQuickPopupItem::footerChanged, this, &QQuickDialog::footerChanged);
199 QObject::disconnect(d->popupItem, &QQuickPopupItem::implicitHeaderWidthChanged, this, &QQuickDialog::implicitHeaderWidthChanged);
200 QObject::disconnect(d->popupItem, &QQuickPopupItem::implicitHeaderHeightChanged, this, &QQuickDialog::implicitHeaderHeightChanged);
201 QObject::disconnect(d->popupItem, &QQuickPopupItem::implicitFooterWidthChanged, this, &QQuickDialog::implicitFooterWidthChanged);
202 QObject::disconnect(d->popupItem, &QQuickPopupItem::implicitFooterHeightChanged, this, &QQuickDialog::implicitFooterHeightChanged);
203}
204
205/*!
206 \qmlproperty string QtQuick.Controls::Dialog::title
207
208 This property holds the dialog title.
209
210 The title is displayed in the dialog header.
211
212 \code
213 Dialog {
214 title: qsTr("About")
215
216 Label {
217 text: "Lorem ipsum..."
218 }
219 }
220 \endcode
221*/
222QString QQuickDialog::title() const
223{
224 Q_D(const QQuickDialog);
225 return d->title;
226}
227
228void QQuickDialog::setTitle(const QString &title)
229{
230 Q_D(QQuickDialog);
231 if (d->title == title)
232 return;
233 d->title = title;
234
235 if (d->popupWindow)
236 d->popupWindow->setTitle(title);
237 else
238 d->popupItem->setTitle(title);
239
240 emit titleChanged();
241}
242
243/*!
244 \qmlproperty Item QtQuick.Controls::Dialog::header
245
246 This property holds the dialog header item. The header item is positioned to
247 the top, and resized to the width of the dialog. The default value is \c null.
248
249 \note Assigning a \l DialogButtonBox as a dialog header automatically connects
250 its \l {DialogButtonBox::}{accepted()} and \l {DialogButtonBox::}{rejected()}
251 signals to the respective signals in Dialog.
252
253 \note Assigning a \l DialogButtonBox, \l ToolBar, or \l TabBar as a dialog
254 header automatically sets the respective \l DialogButtonBox::position,
255 \l ToolBar::position, or \l TabBar::position property to \c Header.
256
257 \sa footer
258*/
259QQuickItem *QQuickDialog::header() const
260{
261 Q_D(const QQuickDialog);
262 return d->popupItem->header();
263}
264
265void QQuickDialog::setHeader(QQuickItem *header)
266{
267 Q_D(QQuickDialog);
268 QQuickItem *oldHeader = d->popupItem->header();
269 if (oldHeader == header)
270 return;
271
272 QQuickControlPrivate::warnIfCustomizationNotSupported(this, header, QStringLiteral("header"));
273
274 if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldHeader)) {
275 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::accepted, d, &QQuickDialogPrivate::handleAccept);
276 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::rejected, d, &QQuickDialogPrivate::handleReject);
277 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
278 if (d->buttonBox == buttonBox)
279 d->buttonBox = nullptr;
280 }
281
282 if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(header)) {
283 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::accepted, d, &QQuickDialogPrivate::handleAccept);
284 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::rejected, d, &QQuickDialogPrivate::handleReject);
285 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
286 d->buttonBox = buttonBox;
287 buttonBox->setStandardButtons(d->standardButtons);
288 }
289
290 d->popupItem->setHeader(header);
291}
292
293/*!
294 \qmlproperty Item QtQuick.Controls::Dialog::footer
295
296 This property holds the dialog footer item. The footer item is positioned to
297 the bottom, and resized to the width of the dialog. The default value is \c null.
298
299 \note Assigning a \l DialogButtonBox as a dialog footer automatically connects
300 its \l {DialogButtonBox::}{accepted()} and \l {DialogButtonBox::}{rejected()}
301 signals to the respective signals in Dialog.
302
303 \note Assigning a \l DialogButtonBox, \l ToolBar, or \l TabBar as a dialog
304 footer automatically sets the respective \l DialogButtonBox::position,
305 \l ToolBar::position, or \l TabBar::position property to \c Footer.
306
307 \sa header
308*/
309QQuickItem *QQuickDialog::footer() const
310{
311 Q_D(const QQuickDialog);
312 return d->popupItem->footer();
313}
314
315void QQuickDialog::setFooter(QQuickItem *footer)
316{
317 Q_D(QQuickDialog);
318 QQuickItem *oldFooter = d->popupItem->footer();
319 if (oldFooter == footer)
320 return;
321
322 QQuickControlPrivate::warnIfCustomizationNotSupported(this, footer, QStringLiteral("footer"));
323
324 if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldFooter)) {
325 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::accepted, d, &QQuickDialogPrivate::handleAccept);
326 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::rejected, d, &QQuickDialogPrivate::handleReject);
327 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
328 if (d->buttonBox == buttonBox)
329 d->buttonBox = nullptr;
330 }
331 if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(footer)) {
332 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::accepted, d, &QQuickDialogPrivate::handleAccept);
333 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::rejected, d, &QQuickDialogPrivate::handleReject);
334 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
335 d->buttonBox = buttonBox;
336 buttonBox->setStandardButtons(d->standardButtons);
337 }
338
339 d->popupItem->setFooter(footer);
340}
341
342/*!
343 \qmlproperty enumeration QtQuick.Controls::Dialog::standardButtons
344
345 This property holds a combination of standard buttons that are used by the dialog.
346
347 \snippet qtquickcontrols-dialog.qml 1
348
349 The buttons will be positioned in the appropriate order for the user's platform.
350
351 Possible flags:
352 \value Dialog.Ok An "OK" button defined with the \c AcceptRole.
353 \value Dialog.Open An "Open" button defined with the \c AcceptRole.
354 \value Dialog.Save A "Save" button defined with the \c AcceptRole.
355 \value Dialog.Cancel A "Cancel" button defined with the \c RejectRole.
356 \value Dialog.Close A "Close" button defined with the \c RejectRole.
357 \value Dialog.Discard A "Discard" or "Don't Save" button, depending on the platform, defined with the \c DestructiveRole.
358 \value Dialog.Apply An "Apply" button defined with the \c ApplyRole.
359 \value Dialog.Reset A "Reset" button defined with the \c ResetRole.
360 \value Dialog.RestoreDefaults A "Restore Defaults" button defined with the \c ResetRole.
361 \value Dialog.Help A "Help" button defined with the \c HelpRole.
362 \value Dialog.SaveAll A "Save All" button defined with the \c AcceptRole.
363 \value Dialog.Yes A "Yes" button defined with the \c YesRole.
364 \value Dialog.YesToAll A "Yes to All" button defined with the \c YesRole.
365 \value Dialog.No A "No" button defined with the \c NoRole.
366 \value Dialog.NoToAll A "No to All" button defined with the \c NoRole.
367 \value Dialog.Abort An "Abort" button defined with the \c RejectRole.
368 \value Dialog.Retry A "Retry" button defined with the \c AcceptRole.
369 \value Dialog.Ignore An "Ignore" button defined with the \c AcceptRole.
370 \value Dialog.NoButton An invalid button.
371
372 \sa DialogButtonBox
373*/
374QPlatformDialogHelper::StandardButtons QQuickDialog::standardButtons() const
375{
376 Q_D(const QQuickDialog);
377 return d->standardButtons;
378}
379
380void QQuickDialog::setStandardButtons(QPlatformDialogHelper::StandardButtons buttons)
381{
382 Q_D(QQuickDialog);
383 if (d->standardButtons == buttons)
384 return;
385
386 d->standardButtons = buttons;
387 if (d->buttonBox)
388 d->buttonBox->setStandardButtons(buttons);
389 emit standardButtonsChanged();
390}
391
392/*!
393 \since QtQuick.Controls 2.3 (Qt 5.10)
394 \qmlmethod AbstractButton QtQuick.Controls::Dialog::standardButton(StandardButton button)
395
396 Returns the specified standard \a button, or \c null if it does not exist.
397
398 \sa standardButtons
399*/
400QQuickAbstractButton *QQuickDialog::standardButton(QPlatformDialogHelper::StandardButton button) const
401{
402 Q_D(const QQuickDialog);
403 if (!d->buttonBox)
404 return nullptr;
405 return d->buttonBox->standardButton(button);
406}
407
408/*!
409 \since QtQuick.Controls 2.3 (Qt 5.10)
410 \qmlproperty int QtQuick.Controls::Dialog::result
411
412 This property holds the result code.
413
414 Standard result codes:
415 \value Dialog.Accepted The dialog was accepted.
416 \value Dialog.Rejected The dialog was rejected.
417
418 \sa accept(), reject(), done()
419*/
420int QQuickDialog::result() const
421{
422 Q_D(const QQuickDialog);
423 return d->result;
424}
425
426void QQuickDialog::setResult(int result)
427{
428 Q_D(QQuickDialog);
429 if (d->result == result)
430 return;
431
432 d->result = result;
433 emit resultChanged();
434}
435
436/*!
437 \since QtQuick.Controls 2.5 (Qt 5.12)
438 \qmlproperty real QtQuick.Controls::Dialog::implicitHeaderWidth
439 \readonly
440
441 This property holds the implicit header width.
442
443 The value is equal to \c {header && header.visible ? header.implicitWidth : 0}.
444
445 \sa implicitHeaderHeight, implicitFooterWidth
446*/
447qreal QQuickDialog::implicitHeaderWidth() const
448{
449 Q_D(const QQuickDialog);
450 return d->popupItem->implicitHeaderWidth();
451}
452
453/*!
454 \since QtQuick.Controls 2.5 (Qt 5.12)
455 \qmlproperty real QtQuick.Controls::Dialog::implicitHeaderHeight
456 \readonly
457
458 This property holds the implicit header height.
459
460 The value is equal to \c {header && header.visible ? header.implicitHeight : 0}.
461
462 \sa implicitHeaderWidth, implicitFooterHeight
463*/
464qreal QQuickDialog::implicitHeaderHeight() const
465{
466 Q_D(const QQuickDialog);
467 return d->popupItem->implicitHeaderHeight();
468}
469
470/*!
471 \since QtQuick.Controls 2.5 (Qt 5.12)
472 \qmlproperty real QtQuick.Controls::Dialog::implicitFooterWidth
473 \readonly
474
475 This property holds the implicit footer width.
476
477 The value is equal to \c {footer && footer.visible ? footer.implicitWidth : 0}.
478
479 \sa implicitFooterHeight, implicitHeaderWidth
480*/
481qreal QQuickDialog::implicitFooterWidth() const
482{
483 Q_D(const QQuickDialog);
484 return d->popupItem->implicitFooterWidth();
485}
486
487/*!
488 \since QtQuick.Controls 2.5 (Qt 5.12)
489 \qmlproperty real QtQuick.Controls::Dialog::implicitFooterHeight
490 \readonly
491
492 This property holds the implicit footer height.
493
494 The value is equal to \c {footer && footer.visible ? footer.implicitHeight : 0}.
495
496 \sa implicitFooterWidth, implicitHeaderHeight
497*/
498qreal QQuickDialog::implicitFooterHeight() const
499{
500 Q_D(const QQuickDialog);
501 return d->popupItem->implicitFooterHeight();
502}
503
504void QQuickDialog::setOpacity(qreal opacity)
505{
506 Q_D(QQuickDialog);
507 QQuickPopup::setOpacity(d->popupWindow ? qreal(!qFuzzyIsNull(opacity)) : opacity);
508}
509
510/*!
511 \qmlmethod void QtQuick.Controls::Dialog::accept()
512
513 Emits the \l accepted() signal and closes the dialog.
514
515 \sa reject(), done()
516*/
517void QQuickDialog::accept()
518{
519 done(Accepted);
520}
521
522/*!
523 \qmlmethod void QtQuick.Controls::Dialog::reject()
524
525 Emits the \l rejected() signal and closes the dialog.
526
527 \sa accept(), done()
528*/
529void QQuickDialog::reject()
530{
531 done(Rejected);
532}
533
534/*!
535 \since QtQuick.Controls 2.3 (Qt 5.10)
536 \qmlmethod void QtQuick.Controls::Dialog::done(int result)
537
538 \list 1
539 \li Sets the \a result.
540 \li Emits \l accepted() or \l rejected() depending on
541 whether the result is \c Dialog.Accepted or \c Dialog.Rejected,
542 respectively.
543 \li Emits \l{Popup::}{closed()}.
544 \endlist
545
546 \sa accept(), reject(), result
547*/
548void QQuickDialog::done(int result)
549{
550 setResult(result);
551
552 if (result == Accepted)
553 emit accepted();
554 else if (result == Rejected)
555 emit rejected();
556
557 close();
558}
559
560void QQuickDialog::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
561{
562 QQuickPopup::itemChange(change, data);
563
564 if (change != QQuickItem::ItemVisibleHasChanged || !isComponentComplete() || !data.boolValue)
565 return;
566
567 Q_D(QQuickDialog);
568 if (d->buttonBox && QQuickItemPrivate::get(d->popupItem)->subFocusItem == nullptr) {
569 for (int i = 0; i < d->buttonBox->count(); ++i) {
570 QQuickItem *item = qobject_cast<QQuickItem *>(d->buttonBox->itemAt(i));
571 if (item && item->isEnabled()) {
572 d->buttonBox->setFocus(true, Qt::OtherFocusReason);
573 break;
574 }
575 }
576 }
577}
578
579#if QT_CONFIG(accessibility)
580QAccessible::Role QQuickDialog::accessibleRole() const
581{
582 return QAccessible::Dialog;
583}
584
585void QQuickDialog::accessibilityActiveChanged(bool active)
586{
587 Q_D(QQuickDialog);
588 QQuickPopup::accessibilityActiveChanged(active);
589
590 if (active)
591 maybeSetAccessibleName(d->popupItem->title());
592}
593#endif
594
595QT_END_NAMESPACE
596
597#include "moc_qquickdialog_p.cpp"
Combined button and popup list for selecting options.