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
174Qt::WindowFlags QQuickDialogPrivate::popupWindowType() const
175{
176 return Qt::Dialog;
177}
178
179QQuickDialog::QQuickDialog(QObject *parent)
180 : QQuickDialog(*(new QQuickDialogPrivate), parent)
181{
182}
183
184QQuickDialog::QQuickDialog(QQuickDialogPrivate &dd, QObject *parent)
185 : QQuickPopup(dd, parent)
186{
187 Q_D(QQuickDialog);
188
189 // Dialogs should get active focus when opened so that e.g. Cancel closes them.
190 setFocus(true);
191 QObject::connect(d->popupItem, &QQuickPopupItem::headerChanged, this, &QQuickDialog::headerChanged);
192 QObject::connect(d->popupItem, &QQuickPopupItem::footerChanged, this, &QQuickDialog::footerChanged);
193 QObject::connect(d->popupItem, &QQuickPopupItem::implicitHeaderWidthChanged, this, &QQuickDialog::implicitHeaderWidthChanged);
194 QObject::connect(d->popupItem, &QQuickPopupItem::implicitHeaderHeightChanged, this, &QQuickDialog::implicitHeaderHeightChanged);
195 QObject::connect(d->popupItem, &QQuickPopupItem::implicitFooterWidthChanged, this, &QQuickDialog::implicitFooterWidthChanged);
196 QObject::connect(d->popupItem, &QQuickPopupItem::implicitFooterHeightChanged, this, &QQuickDialog::implicitFooterHeightChanged);
197}
198
199QQuickDialog::~QQuickDialog()
200{
201 Q_D(QQuickDialog);
202 QObject::disconnect(d->popupItem, &QQuickPopupItem::headerChanged, this, &QQuickDialog::headerChanged);
203 QObject::disconnect(d->popupItem, &QQuickPopupItem::footerChanged, this, &QQuickDialog::footerChanged);
204 QObject::disconnect(d->popupItem, &QQuickPopupItem::implicitHeaderWidthChanged, this, &QQuickDialog::implicitHeaderWidthChanged);
205 QObject::disconnect(d->popupItem, &QQuickPopupItem::implicitHeaderHeightChanged, this, &QQuickDialog::implicitHeaderHeightChanged);
206 QObject::disconnect(d->popupItem, &QQuickPopupItem::implicitFooterWidthChanged, this, &QQuickDialog::implicitFooterWidthChanged);
207 QObject::disconnect(d->popupItem, &QQuickPopupItem::implicitFooterHeightChanged, this, &QQuickDialog::implicitFooterHeightChanged);
208}
209
210/*!
211 \qmlproperty string QtQuick.Controls::Dialog::title
212
213 This property holds the dialog title.
214
215 The title is displayed in the dialog header.
216
217 \code
218 Dialog {
219 title: qsTr("About")
220
221 Label {
222 text: "Lorem ipsum..."
223 }
224 }
225 \endcode
226*/
227QString QQuickDialog::title() const
228{
229 Q_D(const QQuickDialog);
230 return d->title;
231}
232
233void QQuickDialog::setTitle(const QString &title)
234{
235 Q_D(QQuickDialog);
236 if (d->title == title)
237 return;
238 d->title = title;
239
240 if (d->popupWindow)
241 d->popupWindow->setTitle(title);
242 else
243 d->popupItem->setTitle(title);
244
245 emit titleChanged();
246}
247
248/*!
249 \qmlproperty Item QtQuick.Controls::Dialog::header
250
251 This property holds the dialog header item. The header item is positioned to
252 the top, and resized to the width of the dialog. The default value is \c null.
253
254 \note Assigning a \l DialogButtonBox as a dialog header automatically connects
255 its \l {DialogButtonBox::}{accepted()} and \l {DialogButtonBox::}{rejected()}
256 signals to the respective signals in Dialog.
257
258 \note Assigning a \l DialogButtonBox, \l ToolBar, or \l TabBar as a dialog
259 header automatically sets the respective \l DialogButtonBox::position,
260 \l ToolBar::position, or \l TabBar::position property to \c Header.
261
262 \sa footer
263*/
264QQuickItem *QQuickDialog::header() const
265{
266 Q_D(const QQuickDialog);
267 return d->popupItem->header();
268}
269
270void QQuickDialog::setHeader(QQuickItem *header)
271{
272 Q_D(QQuickDialog);
273 QQuickItem *oldHeader = d->popupItem->header();
274 if (oldHeader == header)
275 return;
276
277 QQuickControlPrivate::warnIfCustomizationNotSupported(this, header, QStringLiteral("header"));
278
279 if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldHeader)) {
280 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::accepted, d, &QQuickDialogPrivate::handleAccept);
281 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::rejected, d, &QQuickDialogPrivate::handleReject);
282 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
283 if (d->buttonBox == buttonBox)
284 d->buttonBox = nullptr;
285 }
286
287 if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(header)) {
288 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::accepted, d, &QQuickDialogPrivate::handleAccept);
289 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::rejected, d, &QQuickDialogPrivate::handleReject);
290 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
291 d->buttonBox = buttonBox;
292 buttonBox->setStandardButtons(d->standardButtons);
293 }
294
295 d->popupItem->setHeader(header);
296}
297
298/*!
299 \qmlproperty Item QtQuick.Controls::Dialog::footer
300
301 This property holds the dialog footer item. The footer item is positioned to
302 the bottom, and resized to the width of the dialog. The default value is \c null.
303
304 \note Assigning a \l DialogButtonBox as a dialog footer automatically connects
305 its \l {DialogButtonBox::}{accepted()} and \l {DialogButtonBox::}{rejected()}
306 signals to the respective signals in Dialog.
307
308 \note Assigning a \l DialogButtonBox, \l ToolBar, or \l TabBar as a dialog
309 footer automatically sets the respective \l DialogButtonBox::position,
310 \l ToolBar::position, or \l TabBar::position property to \c Footer.
311
312 \sa header
313*/
314QQuickItem *QQuickDialog::footer() const
315{
316 Q_D(const QQuickDialog);
317 return d->popupItem->footer();
318}
319
320void QQuickDialog::setFooter(QQuickItem *footer)
321{
322 Q_D(QQuickDialog);
323 QQuickItem *oldFooter = d->popupItem->footer();
324 if (oldFooter == footer)
325 return;
326
327 QQuickControlPrivate::warnIfCustomizationNotSupported(this, footer, QStringLiteral("footer"));
328
329 if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldFooter)) {
330 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::accepted, d, &QQuickDialogPrivate::handleAccept);
331 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::rejected, d, &QQuickDialogPrivate::handleReject);
332 QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
333 if (d->buttonBox == buttonBox)
334 d->buttonBox = nullptr;
335 }
336 if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(footer)) {
337 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::accepted, d, &QQuickDialogPrivate::handleAccept);
338 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::rejected, d, &QQuickDialogPrivate::handleReject);
339 QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
340 d->buttonBox = buttonBox;
341 buttonBox->setStandardButtons(d->standardButtons);
342 }
343
344 d->popupItem->setFooter(footer);
345}
346
347/*!
348 \qmlproperty enumeration QtQuick.Controls::Dialog::standardButtons
349
350 This property holds a combination of standard buttons that are used by the dialog.
351
352 \snippet qtquickcontrols-dialog.qml 1
353
354 The buttons will be positioned in the appropriate order for the user's platform.
355
356 Possible flags:
357 \value Dialog.Ok An "OK" button defined with the \c AcceptRole.
358 \value Dialog.Open An "Open" button defined with the \c AcceptRole.
359 \value Dialog.Save A "Save" button defined with the \c AcceptRole.
360 \value Dialog.Cancel A "Cancel" button defined with the \c RejectRole.
361 \value Dialog.Close A "Close" button defined with the \c RejectRole.
362 \value Dialog.Discard A "Discard" or "Don't Save" button, depending on the platform, defined with the \c DestructiveRole.
363 \value Dialog.Apply An "Apply" button defined with the \c ApplyRole.
364 \value Dialog.Reset A "Reset" button defined with the \c ResetRole.
365 \value Dialog.RestoreDefaults A "Restore Defaults" button defined with the \c ResetRole.
366 \value Dialog.Help A "Help" button defined with the \c HelpRole.
367 \value Dialog.SaveAll A "Save All" button defined with the \c AcceptRole.
368 \value Dialog.Yes A "Yes" button defined with the \c YesRole.
369 \value Dialog.YesToAll A "Yes to All" button defined with the \c YesRole.
370 \value Dialog.No A "No" button defined with the \c NoRole.
371 \value Dialog.NoToAll A "No to All" button defined with the \c NoRole.
372 \value Dialog.Abort An "Abort" button defined with the \c RejectRole.
373 \value Dialog.Retry A "Retry" button defined with the \c AcceptRole.
374 \value Dialog.Ignore An "Ignore" button defined with the \c AcceptRole.
375 \value Dialog.NoButton An invalid button.
376
377 \sa DialogButtonBox
378*/
379QPlatformDialogHelper::StandardButtons QQuickDialog::standardButtons() const
380{
381 Q_D(const QQuickDialog);
382 return d->standardButtons;
383}
384
385void QQuickDialog::setStandardButtons(QPlatformDialogHelper::StandardButtons buttons)
386{
387 Q_D(QQuickDialog);
388 if (d->standardButtons == buttons)
389 return;
390
391 d->standardButtons = buttons;
392 if (d->buttonBox)
393 d->buttonBox->setStandardButtons(buttons);
394 emit standardButtonsChanged();
395}
396
397/*!
398 \since QtQuick.Controls 2.3 (Qt 5.10)
399 \qmlmethod AbstractButton QtQuick.Controls::Dialog::standardButton(StandardButton button)
400
401 Returns the specified standard \a button, or \c null if it does not exist.
402
403 \sa standardButtons
404*/
405QQuickAbstractButton *QQuickDialog::standardButton(QPlatformDialogHelper::StandardButton button) const
406{
407 Q_D(const QQuickDialog);
408 if (!d->buttonBox)
409 return nullptr;
410 return d->buttonBox->standardButton(button);
411}
412
413/*!
414 \since QtQuick.Controls 2.3 (Qt 5.10)
415 \qmlproperty int QtQuick.Controls::Dialog::result
416
417 This property holds the result code.
418
419 Standard result codes:
420 \value Dialog.Accepted The dialog was accepted.
421 \value Dialog.Rejected The dialog was rejected.
422
423 \sa accept(), reject(), done()
424*/
425int QQuickDialog::result() const
426{
427 Q_D(const QQuickDialog);
428 return d->result;
429}
430
431void QQuickDialog::setResult(int result)
432{
433 Q_D(QQuickDialog);
434 if (d->result == result)
435 return;
436
437 d->result = result;
438 emit resultChanged();
439}
440
441/*!
442 \since QtQuick.Controls 2.5 (Qt 5.12)
443 \qmlproperty real QtQuick.Controls::Dialog::implicitHeaderWidth
444 \readonly
445
446 This property holds the implicit header width.
447
448 The value is equal to \c {header && header.visible ? header.implicitWidth : 0}.
449
450 \sa implicitHeaderHeight, implicitFooterWidth
451*/
452qreal QQuickDialog::implicitHeaderWidth() const
453{
454 Q_D(const QQuickDialog);
455 return d->popupItem->implicitHeaderWidth();
456}
457
458/*!
459 \since QtQuick.Controls 2.5 (Qt 5.12)
460 \qmlproperty real QtQuick.Controls::Dialog::implicitHeaderHeight
461 \readonly
462
463 This property holds the implicit header height.
464
465 The value is equal to \c {header && header.visible ? header.implicitHeight : 0}.
466
467 \sa implicitHeaderWidth, implicitFooterHeight
468*/
469qreal QQuickDialog::implicitHeaderHeight() const
470{
471 Q_D(const QQuickDialog);
472 return d->popupItem->implicitHeaderHeight();
473}
474
475/*!
476 \since QtQuick.Controls 2.5 (Qt 5.12)
477 \qmlproperty real QtQuick.Controls::Dialog::implicitFooterWidth
478 \readonly
479
480 This property holds the implicit footer width.
481
482 The value is equal to \c {footer && footer.visible ? footer.implicitWidth : 0}.
483
484 \sa implicitFooterHeight, implicitHeaderWidth
485*/
486qreal QQuickDialog::implicitFooterWidth() const
487{
488 Q_D(const QQuickDialog);
489 return d->popupItem->implicitFooterWidth();
490}
491
492/*!
493 \since QtQuick.Controls 2.5 (Qt 5.12)
494 \qmlproperty real QtQuick.Controls::Dialog::implicitFooterHeight
495 \readonly
496
497 This property holds the implicit footer height.
498
499 The value is equal to \c {footer && footer.visible ? footer.implicitHeight : 0}.
500
501 \sa implicitFooterWidth, implicitHeaderHeight
502*/
503qreal QQuickDialog::implicitFooterHeight() const
504{
505 Q_D(const QQuickDialog);
506 return d->popupItem->implicitFooterHeight();
507}
508
509void QQuickDialog::setOpacity(qreal opacity)
510{
511 Q_D(QQuickDialog);
512 QQuickPopup::setOpacity(d->popupWindow ? qreal(!qFuzzyIsNull(opacity)) : opacity);
513}
514
515/*!
516 \qmlmethod void QtQuick.Controls::Dialog::accept()
517
518 Emits the \l accepted() signal and closes the dialog.
519
520 \sa reject(), done()
521*/
522void QQuickDialog::accept()
523{
524 done(Accepted);
525}
526
527/*!
528 \qmlmethod void QtQuick.Controls::Dialog::reject()
529
530 Emits the \l rejected() signal and closes the dialog.
531
532 \sa accept(), done()
533*/
534void QQuickDialog::reject()
535{
536 done(Rejected);
537}
538
539/*!
540 \since QtQuick.Controls 2.3 (Qt 5.10)
541 \qmlmethod void QtQuick.Controls::Dialog::done(int result)
542
543 \list 1
544 \li Sets the \a result.
545 \li Emits \l accepted() or \l rejected() depending on
546 whether the result is \c Dialog.Accepted or \c Dialog.Rejected,
547 respectively.
548 \li Emits \l{Popup::}{closed()}.
549 \endlist
550
551 \sa accept(), reject(), result
552*/
553void QQuickDialog::done(int result)
554{
555 setResult(result);
556
557 if (result == Accepted)
558 emit accepted();
559 else if (result == Rejected)
560 emit rejected();
561
562 close();
563}
564
565void QQuickDialog::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
566{
567 QQuickPopup::itemChange(change, data);
568
569 if (change != QQuickItem::ItemVisibleHasChanged || !isComponentComplete() || !data.boolValue)
570 return;
571
572 Q_D(QQuickDialog);
573 if (d->buttonBox && QQuickItemPrivate::get(d->popupItem)->subFocusItem == nullptr) {
574 for (int i = 0; i < d->buttonBox->count(); ++i) {
575 QQuickItem *item = qobject_cast<QQuickItem *>(d->buttonBox->itemAt(i));
576 if (item && item->isEnabled()) {
577 d->buttonBox->setFocus(true, Qt::OtherFocusReason);
578 break;
579 }
580 }
581 }
582}
583
584#if QT_CONFIG(accessibility)
585QAccessible::Role QQuickDialog::accessibleRole() const
586{
587 return QAccessible::Dialog;
588}
589
590void QQuickDialog::accessibilityActiveChanged(bool active)
591{
592 Q_D(QQuickDialog);
593 QQuickPopup::accessibilityActiveChanged(active);
594
595 if (active)
596 maybeSetAccessibleName(d->popupItem->title());
597}
598#endif
599
600QT_END_NAMESPACE
601
602#include "moc_qquickdialog_p.cpp"
Combined button and popup list for selecting options.