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 | |
13 | QT_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 | |
55 | Q_LOGGING_CATEGORY(qtLabsPlatformDialogs, "qt.labs.platform.dialogs" ) |
56 | |
57 | QQuickLabsPlatformDialog::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 | |
70 | QQuickLabsPlatformDialog::~QQuickLabsPlatformDialog() |
71 | { |
72 | destroy(); |
73 | } |
74 | |
75 | QPlatformDialogHelper *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 | */ |
87 | QQmlListProperty<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 | */ |
101 | QWindow *QQuickLabsPlatformDialog::parentWindow() const |
102 | { |
103 | return m_parentWindow; |
104 | } |
105 | |
106 | void 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 | */ |
120 | QString QQuickLabsPlatformDialog::title() const |
121 | { |
122 | return m_title; |
123 | } |
124 | |
125 | void 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 | */ |
139 | Qt::WindowFlags QQuickLabsPlatformDialog::flags() const |
140 | { |
141 | return m_flags; |
142 | } |
143 | |
144 | void 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 | */ |
163 | Qt::WindowModality QQuickLabsPlatformDialog::modality() const |
164 | { |
165 | return m_modality; |
166 | } |
167 | |
168 | void 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 | */ |
184 | bool QQuickLabsPlatformDialog::isVisible() const |
185 | { |
186 | return m_handle && m_visible; |
187 | } |
188 | |
189 | void 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 | */ |
209 | int QQuickLabsPlatformDialog::result() const |
210 | { |
211 | return m_result; |
212 | } |
213 | |
214 | void 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 | */ |
230 | void 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 | */ |
248 | void 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 | */ |
266 | void 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 | */ |
278 | void 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 | */ |
290 | void 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 | |
301 | void QQuickLabsPlatformDialog::classBegin() |
302 | { |
303 | } |
304 | |
305 | void QQuickLabsPlatformDialog::componentComplete() |
306 | { |
307 | m_complete = true; |
308 | if (!m_parentWindow) |
309 | setParentWindow(findParentWindow()); |
310 | } |
311 | |
312 | static const char *qmlTypeName(const QObject *object) |
313 | { |
314 | return object->metaObject()->className() + qstrlen(str: "QQuickLabsPlatform" ); |
315 | } |
316 | |
317 | bool 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 | |
334 | void QQuickLabsPlatformDialog::destroy() |
335 | { |
336 | delete m_handle; |
337 | m_handle = nullptr; |
338 | } |
339 | |
340 | bool QQuickLabsPlatformDialog::useNativeDialog() const |
341 | { |
342 | return !QCoreApplication::testAttribute(attribute: Qt::AA_DontUseNativeDialogs) |
343 | && QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(type: m_type); |
344 | } |
345 | |
346 | void QQuickLabsPlatformDialog::onCreate(QPlatformDialogHelper *dialog) |
347 | { |
348 | Q_UNUSED(dialog); |
349 | } |
350 | |
351 | void QQuickLabsPlatformDialog::onShow(QPlatformDialogHelper *dialog) |
352 | { |
353 | Q_UNUSED(dialog); |
354 | } |
355 | |
356 | void QQuickLabsPlatformDialog::onHide(QPlatformDialogHelper *dialog) |
357 | { |
358 | Q_UNUSED(dialog); |
359 | } |
360 | |
361 | QWindow *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 | |
376 | QT_END_NAMESPACE |
377 | |
378 | #include "moc_qquicklabsplatformdialog_p.cpp" |
379 | |