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
4#include "qquicklabsplatformdialog_p.h"
5
6#include <QtCore/qloggingcategory.h>
7#include <QtGui/private/qguiapplication_p.h>
8#include <QtQuick/qquickitem.h>
9#include <QtQuick/qquickwindow.h>
10
11#include "widgets/qwidgetplatform_p.h"
12
13QT_BEGIN_NAMESPACE
14
15/*!
16 \qmltype Dialog
17 \inherits QtObject
18//! \instantiates QQuickLabsPlatformDialog
19 \inqmlmodule Qt.labs.platform
20 \since 5.8
21 \brief The base class of native dialogs.
22
23 The Dialog type provides common QML API for native platform dialogs.
24
25 To show a native dialog, construct an instance of one of the concrete
26 Dialog implementations, set the desired properties, and call \l open().
27 Dialog emits \l accepted() or \l rejected() when the user is done with
28 the dialog.
29
30 \labs
31*/
32
33/*!
34 \qmlsignal void Qt.labs.platform::Dialog::accepted()
35
36 This signal is emitted when the dialog has been accepted either
37 interactively or by calling \l accept().
38
39 \note This signal is \e not emitted when closing the dialog with \l close().
40
41 \sa rejected()
42*/
43
44/*!
45 \qmlsignal void Qt.labs.platform::Dialog::rejected()
46
47 This signal is emitted when the dialog has been rejected either
48 interactively or by calling \l reject().
49
50 \note This signal is \e not emitted when closing the dialog with \l close().
51
52 \sa accepted()
53*/
54
55Q_LOGGING_CATEGORY(qtLabsPlatformDialogs, "qt.labs.platform.dialogs")
56
57QQuickLabsPlatformDialog::QQuickLabsPlatformDialog(QPlatformTheme::DialogType type, QObject *parent)
58 : QObject(parent),
59 m_visible(false),
60 m_complete(false),
61 m_result(0),
62 m_parentWindow(nullptr),
63 m_flags(Qt::Dialog),
64 m_modality(Qt::WindowModal),
65 m_type(type),
66 m_handle(nullptr)
67{
68}
69
70QQuickLabsPlatformDialog::~QQuickLabsPlatformDialog()
71{
72 destroy();
73}
74
75QPlatformDialogHelper *QQuickLabsPlatformDialog::handle() const
76{
77 return m_handle;
78}
79
80/*!
81 \qmldefault
82 \qmlproperty list<QtObject> Qt.labs.platform::Dialog::data
83
84 This default property holds the list of all objects declared as children of
85 the dialog.
86*/
87QQmlListProperty<QObject> QQuickLabsPlatformDialog::data()
88{
89 return QQmlListProperty<QObject>(this, &m_data);
90}
91
92/*!
93 \qmlproperty Window Qt.labs.platform::Dialog::parentWindow
94
95 This property holds the parent window of the dialog.
96
97 Unless explicitly set, the window is automatically resolved by iterating
98 the QML parent objects until a \l Window or an \l Item that has a window
99 is found.
100*/
101QWindow *QQuickLabsPlatformDialog::parentWindow() const
102{
103 return m_parentWindow;
104}
105
106void QQuickLabsPlatformDialog::setParentWindow(QWindow *window)
107{
108 if (m_parentWindow == window)
109 return;
110
111 m_parentWindow = window;
112 emit parentWindowChanged();
113}
114
115/*!
116 \qmlproperty string Qt.labs.platform::Dialog::title
117
118 This property holds the title of the dialog.
119*/
120QString QQuickLabsPlatformDialog::title() const
121{
122 return m_title;
123}
124
125void QQuickLabsPlatformDialog::setTitle(const QString &title)
126{
127 if (m_title == title)
128 return;
129
130 m_title = title;
131 emit titleChanged();
132}
133
134/*!
135 \qmlproperty Qt::WindowFlags Qt.labs.platform::Dialog::flags
136
137 This property holds the window flags of the dialog. The default value is \c Qt.Dialog.
138*/
139Qt::WindowFlags QQuickLabsPlatformDialog::flags() const
140{
141 return m_flags;
142}
143
144void QQuickLabsPlatformDialog::setFlags(Qt::WindowFlags flags)
145{
146 if (m_flags == flags)
147 return;
148
149 m_flags = flags;
150 emit flagsChanged();
151}
152
153/*!
154 \qmlproperty Qt::WindowModality Qt.labs.platform::Dialog::modality
155
156 This property holds the modality of the dialog. The default value is \c Qt.WindowModal.
157
158 Available values:
159 \value Qt.NonModal The dialog is not modal and does not block input to other windows.
160 \value Qt.WindowModal The dialog is modal to a single window hierarchy and blocks input to its parent window, all grandparent windows, and all siblings of its parent and grandparent windows.
161 \value Qt.ApplicationModal The dialog is modal to the application and blocks input to all windows.
162*/
163Qt::WindowModality QQuickLabsPlatformDialog::modality() const
164{
165 return m_modality;
166}
167
168void QQuickLabsPlatformDialog::setModality(Qt::WindowModality modality)
169{
170 if (m_modality == modality)
171 return;
172
173 m_modality = modality;
174 emit modalityChanged();
175}
176
177/*!
178 \qmlproperty bool Qt.labs.platform::Dialog::visible
179
180 This property holds the visibility of the dialog. The default value is \c false.
181
182 \sa open(), close()
183*/
184bool QQuickLabsPlatformDialog::isVisible() const
185{
186 return m_handle && m_visible;
187}
188
189void QQuickLabsPlatformDialog::setVisible(bool visible)
190{
191 if (visible)
192 open();
193 else
194 close();
195}
196
197/*!
198 \qmlproperty int Qt.labs.platform::Dialog::result
199
200 This property holds the result code.
201
202 Standard result codes:
203 \value Dialog.Accepted
204 \value Dialog.Rejected
205
206 \note MessageDialog sets the result to the value of the clicked standard
207 button instead of using the standard result codes.
208*/
209int QQuickLabsPlatformDialog::result() const
210{
211 return m_result;
212}
213
214void QQuickLabsPlatformDialog::setResult(int result)
215{
216 if (m_result == result)
217 return;
218
219 m_result = result;
220 emit resultChanged();
221}
222
223/*!
224 \qmlmethod void Qt.labs.platform::Dialog::open()
225
226 Opens the dialog.
227
228 \sa visible, close()
229*/
230void QQuickLabsPlatformDialog::open()
231{
232 if (m_visible || !create())
233 return;
234
235 onShow(dialog: m_handle);
236 m_visible = m_handle->show(windowFlags: m_flags, windowModality: m_modality, parent: m_parentWindow);
237 if (m_visible)
238 emit visibleChanged();
239}
240
241/*!
242 \qmlmethod void Qt.labs.platform::Dialog::close()
243
244 Closes the dialog.
245
246 \sa visible, open()
247*/
248void QQuickLabsPlatformDialog::close()
249{
250 if (!m_handle || !m_visible)
251 return;
252
253 onHide(dialog: m_handle);
254 m_handle->hide();
255 m_visible = false;
256 emit visibleChanged();
257}
258
259/*!
260 \qmlmethod void Qt.labs.platform::Dialog::accept()
261
262 Closes the dialog and emits the \l accepted() signal.
263
264 \sa reject()
265*/
266void QQuickLabsPlatformDialog::accept()
267{
268 done(result: Accepted);
269}
270
271/*!
272 \qmlmethod void Qt.labs.platform::Dialog::reject()
273
274 Closes the dialog and emits the \l rejected() signal.
275
276 \sa accept()
277*/
278void QQuickLabsPlatformDialog::reject()
279{
280 done(result: Rejected);
281}
282
283/*!
284 \qmlmethod void Qt.labs.platform::Dialog::done(int result)
285
286 Closes the dialog and sets the \a result.
287
288 \sa accept(), reject(), result
289*/
290void QQuickLabsPlatformDialog::done(int result)
291{
292 close();
293 setResult(result);
294
295 if (result == Accepted)
296 emit accepted();
297 else if (result == Rejected)
298 emit rejected();
299}
300
301void QQuickLabsPlatformDialog::classBegin()
302{
303}
304
305void QQuickLabsPlatformDialog::componentComplete()
306{
307 m_complete = true;
308 if (!m_parentWindow)
309 setParentWindow(findParentWindow());
310}
311
312static const char *qmlTypeName(const QObject *object)
313{
314 return object->metaObject()->className() + qstrlen(str: "QQuickLabsPlatform");
315}
316
317bool QQuickLabsPlatformDialog::create()
318{
319 if (!m_handle) {
320 if (useNativeDialog())
321 m_handle = QGuiApplicationPrivate::platformTheme()->createPlatformDialogHelper(type: m_type);
322 if (!m_handle)
323 m_handle = QWidgetPlatform::createDialog(type: m_type, parent: this);
324 qCDebug(qtLabsPlatformDialogs) << qmlTypeName(object: this) << "->" << m_handle;
325 if (m_handle) {
326 onCreate(dialog: m_handle);
327 connect(sender: m_handle, signal: &QPlatformDialogHelper::accept, context: this, slot: &QQuickLabsPlatformDialog::accept);
328 connect(sender: m_handle, signal: &QPlatformDialogHelper::reject, context: this, slot: &QQuickLabsPlatformDialog::reject);
329 }
330 }
331 return m_handle;
332}
333
334void QQuickLabsPlatformDialog::destroy()
335{
336 delete m_handle;
337 m_handle = nullptr;
338}
339
340bool QQuickLabsPlatformDialog::useNativeDialog() const
341{
342 return !QCoreApplication::testAttribute(attribute: Qt::AA_DontUseNativeDialogs)
343 && QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(type: m_type);
344}
345
346void QQuickLabsPlatformDialog::onCreate(QPlatformDialogHelper *dialog)
347{
348 Q_UNUSED(dialog);
349}
350
351void QQuickLabsPlatformDialog::onShow(QPlatformDialogHelper *dialog)
352{
353 Q_UNUSED(dialog);
354}
355
356void QQuickLabsPlatformDialog::onHide(QPlatformDialogHelper *dialog)
357{
358 Q_UNUSED(dialog);
359}
360
361QWindow *QQuickLabsPlatformDialog::findParentWindow() const
362{
363 QObject *obj = parent();
364 while (obj) {
365 QWindow *window = qobject_cast<QWindow *>(o: obj);
366 if (window)
367 return window;
368 QQuickItem *item = qobject_cast<QQuickItem *>(o: obj);
369 if (item && item->window())
370 return item->window();
371 obj = obj->parent();
372 }
373 return nullptr;
374}
375
376QT_END_NAMESPACE
377
378#include "moc_qquicklabsplatformdialog_p.cpp"
379

source code of qtdeclarative/src/labs/platform/qquicklabsplatformdialog.cpp