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

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