diff --git a/examples/tabview/main.cpp b/examples/tabview/main.cpp index 7afab28f..2db5fe31 100644 --- a/examples/tabview/main.cpp +++ b/examples/tabview/main.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,7 @@ class TabView : public QskTabView buttonAt( 2 )->setEnabled( false ); setCurrentIndex( 4 ); + setAutoFitTabs(false); } void appendTab() @@ -80,6 +82,39 @@ class TabView : public QskTabView } } } + + void updateAlignment( const QString& hAlignment, const QString& vAlignment ) + { + Qt::Alignment alignment; + + if( hAlignment == QStringLiteral( "align left" ) ) + { + alignment |= Qt::AlignLeft; + } + else if( hAlignment == QStringLiteral( "align center" ) ) + { + alignment |= Qt::AlignHCenter; + } + else if( hAlignment == QStringLiteral( "align right" ) ) + { + alignment |= Qt::AlignRight; + } + + if( vAlignment == QStringLiteral( "align top" ) ) + { + alignment |= Qt::AlignTop; + } + else if( vAlignment == QStringLiteral( "align middle" ) ) + { + alignment |= Qt::AlignVCenter; + } + else if( vAlignment == QStringLiteral( "align bottom" ) ) + { + alignment |= Qt::AlignBottom; + } + + setTabAlignment( alignment ); + } }; int main( int argc, char* argv[] ) @@ -113,12 +148,35 @@ int main( int argc, char* argv[] ) QObject::connect( removeButton, &QskPushButton::clicked, tabView, &TabView::removeLastTab ); + auto hAlignmentBox = new QskSimpleListBox(); + hAlignmentBox->append( "align left" ); + hAlignmentBox->append( "align center" ); + hAlignmentBox->append( "align right" ); + + auto vAlignmentBox = new QskSimpleListBox(); + vAlignmentBox->append( "align top" ); + vAlignmentBox->append( "align middle" ); + vAlignmentBox->append( "align bottom" ); + + auto alignmentLambda = [ tabView, hAlignmentBox, vAlignmentBox ]() + { + tabView->updateAlignment( hAlignmentBox->selectedEntry(), + vAlignmentBox->selectedEntry() ); + }; + + QObject::connect( hAlignmentBox, &QskSimpleListBox::selectedEntryChanged, + alignmentLambda ); + QObject::connect( vAlignmentBox, &QskSimpleListBox::selectedEntryChanged, + alignmentLambda ); + auto buttonBox = new QskLinearBox( Qt::Horizontal ); buttonBox->addItem( rotateButton ); buttonBox->addItem( autoFitButton ); buttonBox->addItem( addButton ); buttonBox->addItem( removeButton ); - buttonBox->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); + buttonBox->addItem( hAlignmentBox ); + buttonBox->addItem( vAlignmentBox ); + buttonBox->setSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Fixed ); auto layoutBox = new QskLinearBox( Qt::Vertical ); layoutBox->setDefaultAlignment( Qt::AlignLeft ); diff --git a/src/controls/QskTabBar.cpp b/src/controls/QskTabBar.cpp index 677d3acf..11a08ffe 100644 --- a/src/controls/QskTabBar.cpp +++ b/src/controls/QskTabBar.cpp @@ -40,7 +40,6 @@ namespace : QskLinearBox( orientation, parent ) { setObjectName( QStringLiteral( "QskTabBarLayoutBox" ) ); - setExtraSpacingAt( Qt::RightEdge | Qt::BottomEdge ); } void restack( int currentIndex ) @@ -270,11 +269,13 @@ class QskTabBar::PrivateData } ScrollBox* scrollBox = nullptr; + QskLinearBox* alignmentBox = nullptr; ButtonBox* buttonBox = nullptr; int currentIndex = -1; QskTextOptions textOptions; uint position : 2; + Qt::Alignment alignment; }; QskTabBar::QskTabBar( QQuickItem* parent ) @@ -298,10 +299,17 @@ QskTabBar::QskTabBar( Qsk::Position position, QQuickItem* parent ) m_data->scrollBox = new ScrollBox( this ); m_data->scrollBox->setOrientation( orientation ); - m_data->buttonBox = new ButtonBox( orientation, m_data->scrollBox ); + m_data->alignmentBox = new QskLinearBox( Qt::Horizontal, m_data->scrollBox ); + + m_data->buttonBox = new ButtonBox( orientation, m_data->alignmentBox ); m_data->buttonBox->setSpacing( spacingHint( QskTabBar::Panel ) ); m_data->buttonBox->setSizePolicy( QskSizePolicy::Maximum, QskSizePolicy::Maximum ); + m_data->alignmentBox->setStretchFactor( m_data->buttonBox, 5 ); + + Qt::Alignment alignment = alignmentHint( Panel, Qt::AlignLeft | Qt::AlignTop ); + setTabAlignment( alignment ); + connect( this, &QskTabBar::currentIndexChanged, m_data->buttonBox, &ButtonBox::restack, Qt::QueuedConnection ); } @@ -323,6 +331,9 @@ void QskTabBar::setTabPosition( Qsk::Position position ) { qskTransposeSizePolicy( this ); + m_data->alignmentBox->setOrientation( orientation ); + qskTransposeSizePolicy( m_data->alignmentBox ); + m_data->buttonBox->setOrientation( orientation ); qskTransposeSizePolicy( m_data->buttonBox ); @@ -342,6 +353,42 @@ Qsk::Position QskTabBar::tabPosition() const return static_cast< Qsk::Position >( m_data->position ); } +void QskTabBar::setTabAlignment( Qt::Alignment alignment ) +{ + // we don't check for m_data->alignment, because fit tabs could have changed + if ( autoFitTabs() ) + return; + + m_data->alignment = alignment; + m_data->alignmentBox->setSizePolicy( orientation(), QskSizePolicy::Preferred ); + + if( ( orientation() == Qt::Horizontal && alignment & Qt::AlignLeft ) + || ( orientation() == Qt::Vertical && alignment & Qt::AlignTop ) ) + { + removeSpacer( Qsk::Left ); + ensureSpacer( Qsk::Right ); + } + else if( ( orientation() == Qt::Horizontal && alignment & Qt::AlignHCenter ) + || ( orientation() == Qt::Vertical && alignment & Qt::AlignVCenter ) ) + { + ensureSpacer( Qsk::Left ); + ensureSpacer( Qsk::Right ); + } + else if( ( orientation() == Qt::Horizontal && alignment & Qt::AlignRight ) + || ( orientation() == Qt::Vertical && alignment & Qt::AlignBottom ) ) + { + removeSpacer( Qsk::Right ); + ensureSpacer( Qsk::Left ); + } + + Q_EMIT tabAlignmentChanged( alignment ); +} + +Qt::Alignment QskTabBar::tabAlignment() const +{ + return m_data->alignment; +} + Qt::Orientation QskTabBar::orientation() const { return qskOrientation( m_data->position ); @@ -365,20 +412,35 @@ void QskTabBar::setAutoFitTabs( bool on ) { const auto orientation = qskOrientation( m_data->position ); int policy = m_data->buttonBox->sizePolicy( orientation ); + int boxPolicy = m_data->alignmentBox->sizePolicy( orientation ); if ( ( policy & QskSizePolicy::GrowFlag ) != on ) { if ( on ) + { policy |= QskSizePolicy::GrowFlag; + boxPolicy |= QskSizePolicy::GrowFlag; + removeSpacer( Qsk::Left ); + removeSpacer( Qsk::Right ); + } else + { policy &= ~QskSizePolicy::GrowFlag; + boxPolicy &= ~QskSizePolicy::GrowFlag; + } // we need operators for QskSizePolicy::Policy: TODO ... m_data->buttonBox->setSizePolicy( orientation, static_cast< QskSizePolicy::Policy >( policy ) ); + m_data->alignmentBox->setSizePolicy( + orientation, static_cast< QskSizePolicy::Policy >( boxPolicy ) ); + polish(); + if( !on ) + setTabAlignment( m_data->alignment ); + Q_EMIT autoFitTabsChanged( on ); } } @@ -671,6 +733,33 @@ void QskTabBar::handleButtonClick() } } +void QskTabBar::ensureSpacer( Qsk::Position position ) +{ + int boxPos = m_data->alignmentBox->indexOf( m_data->buttonBox ); + int pos = ( position == Qsk::Left ) ? 0 : -1; + + if( ( boxPos > 0 && position == Qsk::Left ) + || ( boxPos < m_data->alignmentBox->elementCount() - 1 && position == Qsk::Right ) ) + { + return; // nothing to do, spacer is already there + } + + m_data->alignmentBox->insertSpacer( pos, 0, 10 ); +} + +void QskTabBar::removeSpacer( Qsk::Position position ) +{ + int boxPos = m_data->alignmentBox->indexOf( m_data->buttonBox ); + int pos = ( position == Qsk::Left ) ? boxPos - 1 : boxPos + 1; + + if( pos < 0 || pos >= m_data->alignmentBox->elementCount() ) + { + return; // nothing to do, no spacer there + } + + m_data->alignmentBox->removeAt( pos ); +} + QskAspect::Subcontrol QskTabBar::substitutedSubcontrol( QskAspect::Subcontrol subControl ) const { diff --git a/src/controls/QskTabBar.h b/src/controls/QskTabBar.h index 12978bb3..0a7391cb 100644 --- a/src/controls/QskTabBar.h +++ b/src/controls/QskTabBar.h @@ -19,6 +19,9 @@ class QSK_EXPORT QskTabBar : public QskBox Q_PROPERTY( Qsk::Position tabPosition READ tabPosition WRITE setTabPosition NOTIFY tabPositionChanged FINAL ) + Q_PROPERTY( Qt::Alignment tabAlignment READ tabAlignment + WRITE setTabAlignment NOTIFY tabAlignmentChanged FINAL ) + Q_PROPERTY( Qt::Orientation orientation READ orientation ) Q_PROPERTY( bool autoScrollFocusButton READ autoScrollFocusButton @@ -48,6 +51,9 @@ class QSK_EXPORT QskTabBar : public QskBox void setTabPosition( Qsk::Position ); Qsk::Position tabPosition() const; + void setTabAlignment( Qt::Alignment ); + Qt::Alignment tabAlignment() const; + Qt::Orientation orientation() const; void setAutoScrollFocusedButton( bool ); @@ -99,6 +105,7 @@ class QSK_EXPORT QskTabBar : public QskBox void countChanged( int ); void textOptionsChanged( const QskTextOptions& ); void tabPositionChanged( Qsk::Position ); + void tabAlignmentChanged( Qt::Alignment ); void autoScrollFocusedButtonChanged( bool ); void autoFitTabsChanged( bool ); @@ -111,6 +118,8 @@ class QSK_EXPORT QskTabBar : public QskBox private: void adjustCurrentIndex(); void handleButtonClick(); + void ensureSpacer( Qsk::Position position ); + void removeSpacer( Qsk::Position position ); class PrivateData; std::unique_ptr< PrivateData > m_data; diff --git a/src/controls/QskTabView.cpp b/src/controls/QskTabView.cpp index 567586c6..1c7bc511 100644 --- a/src/controls/QskTabView.cpp +++ b/src/controls/QskTabView.cpp @@ -70,6 +70,9 @@ QskTabView::QskTabView( Qsk::Position tabPosition, QQuickItem* parent ) connect( m_data->tabBar, &QskTabBar::tabPositionChanged, this, &QskTabView::tabPositionChanged ); + connect( m_data->tabBar, &QskTabBar::tabAlignmentChanged, + this, &QskTabView::tabAlignmentChanged ); + connect( m_data->tabBar, &QskTabBar::autoFitTabsChanged, this, &QskTabView::autoFitTabsChanged ); } @@ -104,6 +107,22 @@ Qsk::Position QskTabView::tabPosition() const return m_data->tabBar->tabPosition(); } +void QskTabView::setTabAlignment( Qt::Alignment alignment ) +{ + if ( alignment == tabAlignment() ) + return; + + m_data->tabBar->setTabAlignment( alignment ); + + polish(); + update(); +} + +Qt::Alignment QskTabView::tabAlignment() const +{ + return m_data->tabBar->tabAlignment(); +} + void QskTabView::setAutoFitTabs( bool on ) { m_data->tabBar->setAutoFitTabs( on ); diff --git a/src/controls/QskTabView.h b/src/controls/QskTabView.h index 04568497..dc3c0892 100644 --- a/src/controls/QskTabView.h +++ b/src/controls/QskTabView.h @@ -21,6 +21,9 @@ class QSK_EXPORT QskTabView : public QskControl Q_PROPERTY( Qsk::Position tabPosition READ tabPosition WRITE setTabPosition NOTIFY tabPositionChanged FINAL ) + Q_PROPERTY( Qt::Alignment tabAlignment READ tabAlignment + WRITE setTabAlignment NOTIFY tabAlignmentChanged FINAL ) + Q_PROPERTY( bool autoFitTabs READ autoFitTabs WRITE setAutoFitTabs NOTIFY autoFitTabsChanged FINAL ) @@ -47,6 +50,9 @@ class QSK_EXPORT QskTabView : public QskControl void setTabPosition( Qsk::Position ); Qsk::Position tabPosition() const; + void setTabAlignment( Qt::Alignment ); + Qt::Alignment tabAlignment() const; + void setAutoFitTabs( bool ); bool autoFitTabs() const; @@ -84,6 +90,7 @@ class QSK_EXPORT QskTabView : public QskControl void currentIndexChanged( int index ); void countChanged( int ); void tabPositionChanged( Qsk::Position ); + void tabAlignmentChanged( Qt::Alignment ); void autoFitTabsChanged( bool ); protected: