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 ( uint 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