6#include "QskDialogButtonBox.h"
7#include "QskDialogButton.h"
8#include "QskLinearBox.h"
11#include "QskLinearLayoutEngine.h"
17#include <qpa/qplatformdialoghelper.h>
23static void qskSendEventTo( QObject*
object, QEvent::Type type )
26 QCoreApplication::sendEvent(
object, &event );
34 LayoutEngine( Qt::Orientation orientation )
41 const auto index = insertSpacerAt( count(), 0 );
42 setStretchFactorAt( index, 1 );
45 void addButtons(
const QVector< QskPushButton* >& buttons,
bool reverse )
49 for (
int i = buttons.count() - 1; i >= 0; i-- )
50 addItem( buttons[ i ] );
54 for (
int i = 0; i < buttons.count(); i++ )
55 addItem( buttons[ i ] );
61class QskDialogButtonBox::PrivateData
64 PrivateData( Qt::Orientation orientation )
65 : layoutEngine( orientation )
74 connect( button, &QskPushButton::clicked,
75 box, &QskDialogButtonBox::onButtonClicked,
76 Qt::UniqueConnection );
78 connect( button, &QskPushButton::visibleChanged,
79 box, &QskDialogButtonBox::invalidateLayout,
80 Qt::UniqueConnection );
84 disconnect( button, &QskPushButton::clicked,
85 box, &QskDialogButtonBox::onButtonClicked );
87 disconnect( button, &QskPushButton::visibleChanged,
88 box, &QskDialogButtonBox::invalidateLayout );
91 LayoutEngine layoutEngine;
93 QVector< QskPushButton* > buttons[ QskDialog::NActionRoles ];
94 QPointer< QskPushButton > defaultButton;
96 QskDialog::Action clickedAction = QskDialog::NoAction;
97 bool centeredButtons =
false;
100QskDialogButtonBox::QskDialogButtonBox( QQuickItem* parent )
105QskDialogButtonBox::QskDialogButtonBox( Qt::Orientation orientation, QQuickItem* parent )
106 : Inherited( parent )
107 , m_data( new PrivateData( orientation ) )
109 setPolishOnResize(
true );
111 if ( orientation == Qt::Horizontal )
112 initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Fixed );
114 initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Preferred );
117QskDialogButtonBox::~QskDialogButtonBox()
119 for (
int i = 0; i < QskDialog::NActionRoles; i++ )
121 for (
auto button : std::as_const( m_data->buttons[ i ] ) )
128 PrivateData::connectButton(
this, button,
false );
133void QskDialogButtonBox::setOrientation( Qt::Orientation orientation )
135 if ( m_data->layoutEngine.orientation() == orientation )
138 m_data->layoutEngine.setOrientation( orientation );
140 if ( orientation == Qt::Horizontal )
141 setSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Fixed );
143 setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Preferred );
147 Q_EMIT orientationChanged();
150Qt::Orientation QskDialogButtonBox::orientation()
const
152 return m_data->layoutEngine.orientation();
158 if ( subControl == QskBox::Panel )
159 return QskDialogButtonBox::Panel;
161 return Inherited::substitutedSubcontrol( subControl );
164QSizeF QskDialogButtonBox::layoutSizeHint(
165 Qt::SizeHint which,
const QSizeF& constraint )
const
167 if ( which == Qt::MaximumSize )
170 if ( ( m_data->layoutEngine.count() == 0 ) &&
hasChildItems() )
175 return m_data->layoutEngine.sizeHint( which, constraint );
178void QskDialogButtonBox::invalidateLayout()
180 m_data->layoutEngine.clear();
185void QskDialogButtonBox::updateLayout()
187 auto& layoutEngine = m_data->layoutEngine;
193 if ( parentItem() && ( layoutEngine.count() > 0 ) )
194 qskSendEventTo( parentItem(), QEvent::LayoutRequest );
201void QskDialogButtonBox::rearrangeButtons()
206 auto& layoutEngine = m_data->layoutEngine;
207 layoutEngine.clear();
209 const int* currentLayout =
effectiveSkin()->dialogButtonLayout( orientation() );
211 if ( m_data->centeredButtons )
212 layoutEngine.addStretch();
214 while ( *currentLayout != QPlatformDialogHelper::EOL )
216 const int role = ( *currentLayout & ~QPlatformDialogHelper::Reverse );
217 const bool reverse = ( *currentLayout & QPlatformDialogHelper::Reverse );
221 case QPlatformDialogHelper::Stretch:
223 if ( !m_data->centeredButtons )
224 layoutEngine.addStretch();
228 case QPlatformDialogHelper::AcceptRole:
230 const auto& buttons = m_data->buttons[ role ];
232 if ( !buttons.isEmpty() )
233 layoutEngine.addItem( buttons.first() );
237 case QPlatformDialogHelper::AlternateRole:
239 const auto& buttons = m_data->buttons[ QskDialog::AcceptRole ];
241 if ( buttons.size() > 1 )
242 layoutEngine.addButtons( buttons.mid( 1 ), reverse );
246 case QPlatformDialogHelper::DestructiveRole:
247 case QPlatformDialogHelper::RejectRole:
248 case QPlatformDialogHelper::ActionRole:
249 case QPlatformDialogHelper::HelpRole:
250 case QPlatformDialogHelper::YesRole:
251 case QPlatformDialogHelper::NoRole:
252 case QPlatformDialogHelper::ApplyRole:
253 case QPlatformDialogHelper::ResetRole:
255 const auto& buttons = m_data->buttons[ role ];
257 if ( !buttons.isEmpty() )
258 layoutEngine.addButtons( buttons, reverse );
267 if ( m_data->centeredButtons )
268 layoutEngine.addStretch();
270 updateTabFocusChain();
273void QskDialogButtonBox::updateTabFocusChain()
275 if ( childItems().count() <= 1 )
278 QQuickItem* lastItem =
nullptr;
280 const auto& layoutEngine = m_data->layoutEngine;
281 for (
int i = 0; i < layoutEngine.count(); i++ )
283 if (
auto item = layoutEngine.itemAt( i ) )
286 item->stackAfter( lastItem );
293void QskDialogButtonBox::setCenteredButtons(
bool centered )
295 if ( centered != m_data->centeredButtons )
297 m_data->centeredButtons = centered;
300 Q_EMIT centeredButtonsChanged();
304bool QskDialogButtonBox::centeredButtons()
const
306 return m_data->centeredButtons;
309void QskDialogButtonBox::addButton(
312 if ( role < 0 || role >= QskDialog::NActionRoles )
317 if ( button->parent() ==
nullptr )
318 button->setParent(
this );
324 button->setParentItem(
this );
326 PrivateData::connectButton(
this, button,
true );
328 m_data->buttons[ role ].removeOne( button );
329 m_data->buttons[ role ] += button;
334void QskDialogButtonBox::addAction( QskDialog::Action action )
336 if (
auto button = createButton( action ) )
337 addButton( button, QskDialog::actionRole( action ) );
340void QskDialogButtonBox::removeButton(
QskPushButton* button )
342 if ( button ==
nullptr )
345 for (
int i = 0; i < QskDialog::NActionRoles; i++ )
347 if ( m_data->buttons[ i ].removeOne( button ) )
349 PrivateData::connectButton(
this, button,
false );
359 QskDialog::Action action )
const
364void QskDialogButtonBox::clear()
366 for (
int i = 0; i < QskDialog::NActionRoles; i++ )
368 qDeleteAll( m_data->buttons[ i ] );
369 m_data->buttons[ i ].clear();
375void QskDialogButtonBox::setDefaultButton(
QskPushButton* button )
377 m_data->defaultButton = button;
382 return m_data->defaultButton;
385void QskDialogButtonBox::setActions( QskDialog::Actions actions )
387 for (
int i = 0; i < QskDialog::NActionRoles; i++ )
389 qDeleteAll( m_data->buttons[ i ] );
390 m_data->buttons[ i ].clear();
393 for (
int i = QskDialog::Ok; i <= QskDialog::RestoreDefaults; i <<= 1 )
395 const auto action =
static_cast< QskDialog::Action
>( i );
396 if ( action & actions )
403QVector< QskPushButton* > QskDialogButtonBox::buttons()
const
405 QVector< QskPushButton* > buttons;
407 for (
int i = 0; i < QskDialog::NActionRoles; i++ )
408 buttons += m_data->buttons[ i ];
413QVector< QskPushButton* > QskDialogButtonBox::buttons(
414 QskDialog::ActionRole role )
const
416 if ( role < 0 || role >= QskDialog::NActionRoles )
417 return QVector< QskPushButton* >();
419 return m_data->buttons[ role ];
423QskDialog::ActionRole QskDialogButtonBox::actionRole(
426 for (
int i = 0; i < QskDialog::NActionRoles; i++ )
428 const auto& buttons = m_data->buttons[ i ];
430 for (
const auto btn : buttons )
433 return static_cast< QskDialog::ActionRole
>( i );
437 return QskDialog::InvalidRole;
440void QskDialogButtonBox::onButtonClicked()
442 auto button = qobject_cast< QskPushButton* >( sender() );
443 if ( button ==
nullptr )
446 switch ( actionRole( button ) )
448 case QskDialog::AcceptRole:
449 case QskDialog::YesRole:
451 m_data->clickedAction = action( button );
453 Q_EMIT clicked( button );
457 case QskDialog::RejectRole:
458 case QskDialog::NoRole:
459 case QskDialog::DestructiveRole:
461 m_data->clickedAction = action( button );
463 Q_EMIT clicked( button );
469 m_data->clickedAction = QskDialog::NoAction;
470 Q_EMIT clicked( button );
477QskDialog::Actions QskDialogButtonBox::actions()
const
479 QskDialog::Actions actions;
481 for (
int i = 0; i < QskDialog::NActionRoles; i++ )
483 const auto& buttons = m_data->buttons[ i ];
485 for (
const auto btn : buttons )
486 actions |= action( btn );
492QskDialog::Action QskDialogButtonBox::action(
const QskPushButton* button )
const
496 if (
auto dialogButton = qobject_cast< const QskDialogButton* >( button ) )
497 return dialogButton->action();
499 const QVariant value = button->property(
"standardButton" );
500 if ( value.canConvert<
int >() )
501 return static_cast< QskDialog::Action
>( value.toInt() );
504 return QskDialog::NoAction;
507QskPushButton* QskDialogButtonBox::button( QskDialog::Action action )
const
509 for (
int i = 0; i < QskDialog::NActionRoles; i++ )
511 const auto& buttons = m_data->buttons[ i ];
512 for (
auto btn : buttons )
514 if ( this->action( btn ) == action )
522QskDialog::Action QskDialogButtonBox::clickedAction()
const
524 return m_data->clickedAction;
527bool QskDialogButtonBox::event( QEvent* event )
529 switch (
static_cast< int >( event->type() ) )
531 case QEvent::LayoutRequest:
537 case QEvent::LayoutDirectionChange:
539 m_data->layoutEngine.setVisualDirection(
544 case QEvent::ContentsRectChange:
551 return Inherited::event( event );
554void QskDialogButtonBox::itemChange(
555 QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData& value )
559 if ( change == ItemChildRemovedChange )
561 if (
auto button = qobject_cast< QskPushButton* >( value.item ) )
562 removeButton( button );
566bool QskDialogButtonBox::isDefaultButtonKeyEvent(
const QKeyEvent* event )
568 if ( !event->modifiers() )
569 return ( event->key() == Qt::Key_Enter ) || (
event->key() == Qt::Key_Return );
571 return ( event->modifiers() & Qt::KeypadModifier ) && ( event->key() == Qt::Key_Enter );
574#include "moc_QskDialogButtonBox.cpp"
Subcontrol
For use within the rendering or lay-outing of a specific QskSkinnable.
void setSizePolicy(QskSizePolicy)
void itemChange(ItemChange, const ItemChangeData &) override
QRectF layoutRect() const
bool maybeUnresized() const
bool layoutMirroring() const
QskSkin * effectiveSkin() const