QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskDialogSubWindow.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskDialogSubWindow.h"
7#include "QskDialogButtonBox.h"
8#include "QskTextLabel.h"
9#include "QskPushButton.h"
10#include "QskLinearBox.h"
11#include "QskQuick.h"
12#include "QskEvent.h"
13
14#include <qquickwindow.h>
15#include <qpointer.h>
16
17QSK_SUBCONTROL( QskDialogSubWindow, DialogTitle )
18
19static inline void qskSetRejectOnClose( QskDialogSubWindow* subWindow, bool on )
20{
21 if ( on )
22 {
23 QObject::connect( subWindow, &QskPopup::closed,
24 subWindow, &QskDialogSubWindow::reject );
25 }
26 else
27 {
28 QObject::disconnect( subWindow, &QskPopup::closed,
29 subWindow, &QskDialogSubWindow::reject );
30 }
31}
32
33namespace
34{
35 class TitleLabel final : public QskTextLabel
36 {
37 protected:
38 QskAspect::Subcontrol substitutedSubcontrol(
39 QskAspect::Subcontrol subControl ) const override
40 {
41 if ( subControl == QskTextLabel::Text )
42 return QskDialogSubWindow::DialogTitle;
43
44 return QskTextLabel::substitutedSubcontrol( subControl );
45 }
46 };
47}
48
49class QskDialogSubWindow::PrivateData
50{
51 public:
52 QskDialog::Actions actions = QskDialog::NoAction;
53
54 QskTextLabel* titleLabel = nullptr;
55 QskDialogButtonBox* buttonBox = nullptr;
56
57 QPointer< QQuickItem > contentItem;
58
59 QskLinearBox* layout = nullptr;
60
61 QskDialog::DialogCode result = QskDialog::Rejected;
62};
63
64QskDialogSubWindow::QskDialogSubWindow( QQuickItem* parent )
65 : Inherited( parent )
66 , m_data( new PrivateData() )
67{
68 qskSetRejectOnClose( this, true );
69
70 m_data->layout = new QskLinearBox( Qt::Vertical, this );
71 m_data->layout->setSizePolicy(
72 QskSizePolicy::MinimumExpanding, QskSizePolicy::Constrained );
73
74 setPolishOnResize( true );
75 setPolishOnParentResize( true );
76}
77
78QskDialogSubWindow::~QskDialogSubWindow()
79{
80}
81
82void QskDialogSubWindow::addDialogAction( QskDialog::Action action )
83{
84 if ( action != QskDialog::NoAction )
85 {
86 if ( m_data->buttonBox == nullptr )
87 initButtonBox();
88
89 m_data->buttonBox->addAction( action );
90 }
91}
92
93void QskDialogSubWindow::addDialogButton(
94 QskPushButton* button, QskDialog::ActionRole actionRole )
95{
96 if ( button )
97 {
98 if ( m_data->buttonBox == nullptr )
99 initButtonBox();
100
101 m_data->buttonBox->addButton( button, actionRole );
102 }
103}
104
105void QskDialogSubWindow::setDialogActions( QskDialog::Actions actions )
106{
107 if ( m_data->actions == actions )
108 return;
109
110 m_data->actions = actions;
111
112 if ( actions == QskDialog::NoAction )
113 {
114 delete m_data->buttonBox;
115 m_data->buttonBox = nullptr;
116 }
117 else
118 {
119 if ( m_data->buttonBox == nullptr )
120 initButtonBox();
121
122 if ( m_data->buttonBox )
123 m_data->buttonBox->setActions( actions );
124 }
125}
126
127QskDialog::Actions QskDialogSubWindow::dialogActions() const
128{
129 if ( m_data->buttonBox )
130 return m_data->buttonBox->actions();
131
132 return QskDialog::NoAction;
133}
134
135void QskDialogSubWindow::setTitle( const QString& title )
136{
137 bool changed = false;
138 auto& titleLabel = m_data->titleLabel;
139
140 if ( title.isEmpty() )
141 {
142 changed = ( titleLabel != nullptr );
143
144 delete titleLabel;
145 titleLabel = nullptr;
146 }
147 else
148 {
149 if ( titleLabel == nullptr )
150 {
151 titleLabel = new TitleLabel();
152 m_data->layout->insertItem( 0, titleLabel );
153 changed = true;
154 }
155 else
156 {
157 changed = ( titleLabel->text() != title );
158 }
159
160 if ( changed )
161 titleLabel->setText( title );
162 }
163
164 if ( changed )
165 {
167 polish();
168
169 Q_EMIT titleChanged( title );
170 }
171}
172
173QString QskDialogSubWindow::title() const
174{
175 if ( auto label = m_data->titleLabel )
176 return label->text();
177
178 return QString();
179}
180
181QskTextLabel* QskDialogSubWindow::titleLabel()
182{
183 return m_data->titleLabel;
184}
185
186const QskTextLabel* QskDialogSubWindow::titleLabel() const
187{
188 return m_data->titleLabel;
189}
190
191void QskDialogSubWindow::setContentItem( QQuickItem* item )
192{
193 if ( item == m_data->contentItem )
194 return;
195
196 if ( m_data->contentItem )
197 {
198 if ( m_data->contentItem->parent() == m_data->layout )
199 delete m_data->contentItem;
200 else
201 m_data->layout->removeItem( m_data->contentItem );
202 }
203
204 m_data->contentItem = item;
205
206 if ( item )
207 {
208 const int index = m_data->titleLabel ? 1 : 0;
209 m_data->layout->insertItem( index, m_data->contentItem );
210 }
211}
212
213QQuickItem* QskDialogSubWindow::contentItem() const
214{
215 return m_data->contentItem;
216}
217
218void QskDialogSubWindow::setContentPadding( const QMarginsF& padding )
219{
220 // should be a skin hint ???
221 m_data->layout->setMargins( padding );
222}
223
224QMarginsF QskDialogSubWindow::contentPadding() const
225{
226 return m_data->layout->margins();
227}
228
229void QskDialogSubWindow::setDefaultDialogAction( QskDialog::Action action )
230{
231 QskPushButton* button = nullptr;
232
233 if ( m_data->buttonBox )
234 button = m_data->buttonBox->button( action );
235
236 setDefaultButton( button );
237}
238
239void QskDialogSubWindow::setDefaultButton( QskPushButton* button )
240{
241 if ( !qskIsAncestorOf( m_data->buttonBox, button ) )
242 {
243#if defined( QT_DEBUG )
244 qWarning( "Only buttons of the QskDialogButtonBox can be the default button." );
245#endif
246 return;
247 }
248
249 m_data->buttonBox->setDefaultButton( button );
250}
251
252QskPushButton* QskDialogSubWindow::defaultButton() const
253{
254 if ( m_data->buttonBox == nullptr )
255 return nullptr;
256
257 return m_data->buttonBox->defaultButton();
258}
259
260QskDialogButtonBox* QskDialogSubWindow::buttonBox()
261{
262 return m_data->buttonBox;
263}
264
265const QskDialogButtonBox* QskDialogSubWindow::buttonBox() const
266{
267 return m_data->buttonBox;
268}
269
270QskDialog::Action QskDialogSubWindow::clickedAction() const
271{
272 if ( m_data->buttonBox )
273 return m_data->buttonBox->clickedAction();
274
275 return QskDialog::NoAction;
276}
277
278void QskDialogSubWindow::setResult( QskDialog::DialogCode result )
279{
280 m_data->result = result;
281}
282
283QskDialog::DialogCode QskDialogSubWindow::result() const
284{
285 return m_data->result;
286}
287
288QskDialog::DialogCode QskDialogSubWindow::exec()
289{
290 m_data->result = QskDialog::Rejected;
291 ( void ) execPopup();
292 return m_data->result;
293}
294
295void QskDialogSubWindow::done( QskDialog::DialogCode result )
296{
297 m_data->result = result;
298
299 if ( isOpen() )
300 {
301 qskSetRejectOnClose( this, false );
302 close();
303 qskSetRejectOnClose( this, true );
304 }
305
306 Q_EMIT finished( result );
307
308 if ( result == QskDialog::Accepted )
309 Q_EMIT accepted();
310 else
311 Q_EMIT rejected();
312}
313
314void QskDialogSubWindow::accept()
315{
316 done( QskDialog::Accepted );
317}
318
319void QskDialogSubWindow::reject()
320{
321 done( QskDialog::Rejected );
322}
323
324void QskDialogSubWindow::keyPressEvent( QKeyEvent* event )
325{
326 if ( m_data->buttonBox &&
327 QskDialogButtonBox::isDefaultButtonKeyEvent( event ) )
328 {
329 auto button = m_data->buttonBox->defaultButton();
330 if ( button && button->isEnabled() )
331 {
332 button->click();
333 return;
334 }
335 }
336
337 Inherited::keyPressEvent( event );
338}
339
340void QskDialogSubWindow::initButtonBox()
341{
342 auto buttonBox = new QskDialogButtonBox();
343 m_data->layout->addItem( buttonBox );
344
345 connect( buttonBox, &QskDialogButtonBox::accepted,
346 this, &QskDialogSubWindow::accept );
347
348 connect( buttonBox, &QskDialogButtonBox::rejected,
349 this, &QskDialogSubWindow::reject );
350
351 m_data->buttonBox = buttonBox;
352}
353
354void QskDialogSubWindow::updateLayout()
355{
356 updateGeometry();
357 m_data->layout->setGeometry( layoutRect() );
358}
359
360void QskDialogSubWindow::updateGeometry()
361{
362 /*
363 This code is for Preferred/Constrained without checking
364 the actual sizePolicy. TODO ...
365 */
366 const auto minSize = minimumSize();
367 const auto maxSize = maximumSize();
368
369 auto width = sizeHint().width();
370 width = qMin( width, maxSize.width() );
371 width = qMax( width, minSize.width() );
372
373 auto height = heightForWidth( width );
374 height = qMin( height, maxSize.height() );
375 height = qMax( height, minSize.height() );
376
377 QRectF rect( 0.0, 0.0, width, height );
378 rect.moveCenter( qskItemRect( parentItem() ).center() );
379
380 setGeometry( rect );
381}
382
383QSizeF QskDialogSubWindow::layoutSizeHint(
384 Qt::SizeHint which, const QSizeF& constraint ) const
385{
386 if ( which == Qt::MaximumSize && polishOnParentResize() )
387 return 0.9 * parentItem()->size();
388
389 auto size = m_data->layout->effectiveSizeHint( which, constraint );
390
391 if ( which == Qt::MinimumSize )
392 {
393 const auto w = qMax( 300.0, size.width() );
394 size.setWidth( w );
395 }
396
397 return size;
398}
399
400#include "moc_QskDialogSubWindow.cpp"
Subcontrol
For use within the rendering or lay-outing of a specific QskSkinnable.
Definition QskAspect.h:104
QSizeF maximumSize
Definition QskControl.h:48
QSizeF minimumSize
Definition QskControl.h:47
qreal heightForWidth(qreal width) const
QRectF layoutRect() const
QSizeF sizeHint() const
Definition QskControl.h:214
QRectF rect
Definition QskItem.h:21
void resetImplicitSize()
Definition QskItem.cpp:721
void setGeometry(qreal x, qreal y, qreal width, qreal height)
Definition QskItem.cpp:330
Layout stringing items in rows and columns.