QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskDialog.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskDialog.h"
7#include "QskDialogButtonBox.h"
8
9#include "QskMessageSubWindow.h"
10#include "QskMessageWindow.h"
11
12#include "QskSelectionSubWindow.h"
13#include "QskSelectionWindow.h"
14
15#include "QskFocusIndicator.h"
16
17#include <qguiapplication.h>
18#include <qpointer.h>
19#include <qquickwindow.h>
20
21#include <qpa/qplatformdialoghelper.h>
22
23static QskDialog::Action qskActionCandidate( const QskDialogButtonBox* buttonBox )
24{
25 // not the fastest code ever, but usually we always
26 // have a AcceptRole or YesRole button
27
28 const QskDialog::ActionRole candidates[] =
29 {
30 QskDialog::AcceptRole, QskDialog::YesRole,
31 QskDialog::RejectRole, QskDialog::NoRole, QskDialog::DestructiveRole,
32 QskDialog::UserRole, QskDialog::ResetRole,
33 QskDialog::ApplyRole, QskDialog::HelpRole
34 };
35
36 for ( auto role : candidates )
37 {
38 const auto& buttons = buttonBox->buttons( role );
39 if ( !buttons.isEmpty() )
40 return buttonBox->action( buttons.first() );
41 }
42
43 return QskDialog::NoAction;
44}
45
46static QskDialog::DialogCode qskExec( QskDialogWindow* dialogWindow )
47{
48#if 1
49 auto focusIndicator = new QskFocusIndicator();
50 focusIndicator->setObjectName( QStringLiteral( "DialogFocusIndicator" ) );
51 dialogWindow->addItem( focusIndicator );
52#endif
53
54 return dialogWindow->exec();
55}
56
57static QQuickWindow* qskSomeQuickWindow()
58{
59 // not the best code ever, but as it is a fallback only
60 // maybe we should also add the stacking order
61
62 const auto windows = QGuiApplication::topLevelWindows();
63 for ( auto window : windows )
64 {
65 if ( window->isVisible() )
66 {
67 if ( auto quickWindow = qobject_cast< QQuickWindow* >( window ) )
68 return quickWindow;
69 }
70 }
71
72 return nullptr;
73}
74
75static void qskSetupSubWindow(
76 const QString& title, QskDialog::Actions actions,
77 QskDialog::Action defaultAction, QskDialogSubWindow* subWindow )
78{
79 subWindow->setPopupFlag( QskPopup::DeleteOnClose );
80 subWindow->setModal( true );
81#if 0
82 subWindow->setWindowTitle( ... );
83#endif
84 subWindow->setTitle( title );
85 subWindow->setDialogActions( actions );
86
87 if ( actions != QskDialog::NoAction && defaultAction == QskDialog::NoAction )
88 defaultAction = qskActionCandidate( subWindow->buttonBox() );
89
90 subWindow->setDefaultDialogAction( defaultAction );
91}
92
93static void qskSetupWindow(
94 QWindow* transientParent, const QString& title,
95 QskDialog::Actions actions, QskDialog::Action defaultAction,
96 QskDialogWindow* window )
97{
98 window->setTransientParent( transientParent );
99
100 window->setTitle( title );
101 window->setDialogActions( actions );
102
103 if ( actions != QskDialog::NoAction && defaultAction == QskDialog::NoAction )
104 defaultAction = qskActionCandidate( window->buttonBox() );
105
106 window->setDefaultDialogAction( defaultAction );
107
108 window->setModality( transientParent ? Qt::WindowModal : Qt::ApplicationModal );
109
110 const QSize size = window->sizeConstraint();
111
112 if ( window->parent() )
113 {
114 QRect r( QPoint(), size );
115 r.moveCenter( QRect( QPoint(), window->parent()->size() ).center() );
116
117 window->setGeometry( r );
118 }
119
120 if ( size.isValid() )
121 {
122 window->setFlags( window->flags() | Qt::MSWindowsFixedSizeDialogHint );
123 window->setFixedSize( size );
124 }
125
126 window->setModality( Qt::ApplicationModal );
127}
128
129static QskDialog::Action qskMessageSubWindow(
130 QQuickWindow* window, const QString& title,
131 const QString& text, uint priority, QskDialog::Actions actions,
132 QskDialog::Action defaultAction )
133{
134 auto subWindow = new QskMessageSubWindow( window->contentItem() );
135 subWindow->setPriority( priority );
136 subWindow->setText( text );
137
138 qskSetupSubWindow( title, actions, defaultAction, subWindow );
139 ( void ) subWindow->exec();
140
141 auto clickedAction = subWindow->clickedAction();
142 if ( clickedAction == QskDialog::NoAction )
143 {
144 // dialog might have been closed by the window menu
145 clickedAction = QskDialog::Cancel;
146 }
147
148 return clickedAction;
149}
150
151static QskDialog::Action qskMessageWindow(
152 QWindow* transientParent, const QString& title,
153 const QString& text, uint priority, QskDialog::Actions actions,
154 QskDialog::Action defaultAction )
155{
156 Q_UNUSED( priority ); // can we do something with it ?
157
158 QskMessageWindow messageWindow;
159 messageWindow.setText( text );
160
161 qskSetupWindow( transientParent, title, actions, defaultAction, &messageWindow );
162 ( void ) qskExec( &messageWindow );
163
164 auto clickedAction = messageWindow.clickedAction();
165 if ( clickedAction == QskDialog::NoAction )
166 {
167 // dialog might have been closed by the window menu
168 clickedAction = QskDialog::Cancel;
169 }
170
171 return clickedAction;
172}
173
174static QString qskSelectSubWindow(
175 QQuickWindow* window, const QString& title,
176 QskDialog::Actions actions, QskDialog::Action defaultAction,
177 const QStringList& entries, int selectedRow )
178{
179 auto subWindow = new QskSelectionSubWindow( window->contentItem() );
180 subWindow->setEntries( entries );
181 subWindow->setSelectedRow( selectedRow );
182
183 QString selectedEntry;
184
185 qskSetupSubWindow( title, actions, defaultAction, subWindow );
186 if ( subWindow->exec() == QskDialog::Accepted )
187 selectedEntry = subWindow->selectedEntry();
188
189 return selectedEntry;
190}
191
192static QString qskSelectWindow(
193 QWindow* transientParent, const QString& title,
194 QskDialog::Actions actions, QskDialog::Action defaultAction,
195 const QStringList& entries, int selectedRow )
196{
197 QskSelectionWindow window;
198 window.setEntries( entries );
199 window.setSelectedRow( selectedRow );
200
201 QString selectedEntry = window.selectedEntry();
202
203 qskSetupWindow( transientParent, title, actions, defaultAction, &window );
204 if ( qskExec( &window ) == QskDialog::Accepted )
205 selectedEntry = window.selectedEntry();
206
207 return selectedEntry;
208}
209
210class QskDialog::PrivateData
211{
212 public:
213 QPointer< QWindow > transientParent;
214 QskDialog::Policy policy = QskDialog::TopLevelWindow;
215};
216
217QskDialog::QskDialog()
218 : m_data( new PrivateData )
219{
220}
221
222QskDialog::~QskDialog()
223{
224}
225
226QskDialog* QskDialog::instance()
227{
228 static QskDialog instance;
229 return &instance;
230}
231
232void QskDialog::setPolicy( Policy policy )
233{
234 if ( policy != m_data->policy )
235 {
236 m_data->policy = policy;
237 Q_EMIT policyChanged();
238 }
239}
240
241QskDialog::Policy QskDialog::policy() const
242{
243 return m_data->policy;
244}
245
246void QskDialog::setTransientParent( QWindow* window )
247{
248 if ( m_data->transientParent != window )
249 {
250 m_data->transientParent = window;
251 Q_EMIT transientParentChanged();
252 }
253}
254
255QWindow* QskDialog::transientParent() const
256{
257 return m_data->transientParent;
258}
259
260QskDialog::Action QskDialog::message(
261 const QString& title, const QString& text, uint priority,
262 Actions actions, Action defaultAction ) const
263{
264 if ( m_data->policy == EmbeddedBox )
265 {
266 auto quickWindow = qobject_cast< QQuickWindow* >( m_data->transientParent );
267
268 if ( quickWindow == nullptr )
269 quickWindow = qskSomeQuickWindow();
270
271 if ( quickWindow )
272 {
273 return qskMessageSubWindow( quickWindow,
274 title, text, priority, actions, defaultAction );
275 }
276 }
277
278 return qskMessageWindow( m_data->transientParent,
279 title, text, priority, actions, defaultAction );
280}
281
282QskDialog::Action QskDialog::information(
283 const QString& title, const QString& text,
284 Actions actions, Action defaultAction ) const
285{
286 return QskDialog::message( title, text, 0, actions, defaultAction );
287}
288
289QskDialog::Action QskDialog::question(
290 const QString& title, const QString& text,
291 Actions actions, Action defaultAction ) const
292{
293 return QskDialog::message( title, text, 0, actions, defaultAction );
294}
295
296QString QskDialog::select( const QString& title,
297 const QStringList& entries, int selectedRow ) const
298{
299#if 1
300 // should be parameters
301 const auto actions = QskDialog::Ok | QskDialog::Cancel;
302 const auto defaultAction = QskDialog::Ok;
303#endif
304
305 if ( m_data->policy == EmbeddedBox )
306 {
307 auto quickWindow = qobject_cast< QQuickWindow* >( m_data->transientParent );
308
309 if ( quickWindow == nullptr )
310 quickWindow = qskSomeQuickWindow();
311
312 if ( quickWindow )
313 {
314 return qskSelectSubWindow( quickWindow,
315 title, actions, defaultAction, entries, selectedRow );
316 }
317 }
318
319 return qskSelectWindow( m_data->transientParent, title,
320 actions, defaultAction, entries, selectedRow );
321
322}
323
324QskDialog::ActionRole QskDialog::actionRole( Action action )
325{
326 using Q = QPlatformDialogHelper;
327
328 const auto role = Q::buttonRole( static_cast< Q::StandardButton >( action ) );
329 return static_cast< ActionRole >( role );
330}
331
332#include "moc_QskDialog.cpp"