QskTabBar: Respect alignment hint

This commit is contained in:
Peter Hartmann 2021-11-10 08:55:23 +01:00
parent 411e9832fd
commit c6fb4ee75a
5 changed files with 185 additions and 3 deletions

View File

@ -13,6 +13,7 @@
#include <QskObjectCounter.h> #include <QskObjectCounter.h>
#include <QskPushButton.h> #include <QskPushButton.h>
#include <QskSkin.h> #include <QskSkin.h>
#include <QskSimpleListBox.h>
#include <QskTabButton.h> #include <QskTabButton.h>
#include <QskTabBar.h> #include <QskTabBar.h>
#include <QskTabView.h> #include <QskTabView.h>
@ -53,6 +54,7 @@ class TabView : public QskTabView
buttonAt( 2 )->setEnabled( false ); buttonAt( 2 )->setEnabled( false );
setCurrentIndex( 4 ); setCurrentIndex( 4 );
setAutoFitTabs(false);
} }
void appendTab() 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[] ) int main( int argc, char* argv[] )
@ -113,12 +148,35 @@ int main( int argc, char* argv[] )
QObject::connect( removeButton, &QskPushButton::clicked, QObject::connect( removeButton, &QskPushButton::clicked,
tabView, &TabView::removeLastTab ); 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 ); auto buttonBox = new QskLinearBox( Qt::Horizontal );
buttonBox->addItem( rotateButton ); buttonBox->addItem( rotateButton );
buttonBox->addItem( autoFitButton ); buttonBox->addItem( autoFitButton );
buttonBox->addItem( addButton ); buttonBox->addItem( addButton );
buttonBox->addItem( removeButton ); 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 ); auto layoutBox = new QskLinearBox( Qt::Vertical );
layoutBox->setDefaultAlignment( Qt::AlignLeft ); layoutBox->setDefaultAlignment( Qt::AlignLeft );

View File

@ -40,7 +40,6 @@ namespace
: QskLinearBox( orientation, parent ) : QskLinearBox( orientation, parent )
{ {
setObjectName( QStringLiteral( "QskTabBarLayoutBox" ) ); setObjectName( QStringLiteral( "QskTabBarLayoutBox" ) );
setExtraSpacingAt( Qt::RightEdge | Qt::BottomEdge );
} }
void restack( int currentIndex ) void restack( int currentIndex )
@ -270,11 +269,13 @@ class QskTabBar::PrivateData
} }
ScrollBox* scrollBox = nullptr; ScrollBox* scrollBox = nullptr;
QskLinearBox* alignmentBox = nullptr;
ButtonBox* buttonBox = nullptr; ButtonBox* buttonBox = nullptr;
int currentIndex = -1; int currentIndex = -1;
QskTextOptions textOptions; QskTextOptions textOptions;
uint position : 2; uint position : 2;
Qt::Alignment alignment;
}; };
QskTabBar::QskTabBar( QQuickItem* parent ) QskTabBar::QskTabBar( QQuickItem* parent )
@ -298,10 +299,17 @@ QskTabBar::QskTabBar( Qsk::Position position, QQuickItem* parent )
m_data->scrollBox = new ScrollBox( this ); m_data->scrollBox = new ScrollBox( this );
m_data->scrollBox->setOrientation( orientation ); 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->setSpacing( spacingHint( QskTabBar::Panel ) );
m_data->buttonBox->setSizePolicy( QskSizePolicy::Maximum, QskSizePolicy::Maximum ); 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, connect( this, &QskTabBar::currentIndexChanged,
m_data->buttonBox, &ButtonBox::restack, Qt::QueuedConnection ); m_data->buttonBox, &ButtonBox::restack, Qt::QueuedConnection );
} }
@ -323,6 +331,9 @@ void QskTabBar::setTabPosition( Qsk::Position position )
{ {
qskTransposeSizePolicy( this ); qskTransposeSizePolicy( this );
m_data->alignmentBox->setOrientation( orientation );
qskTransposeSizePolicy( m_data->alignmentBox );
m_data->buttonBox->setOrientation( orientation ); m_data->buttonBox->setOrientation( orientation );
qskTransposeSizePolicy( m_data->buttonBox ); qskTransposeSizePolicy( m_data->buttonBox );
@ -342,6 +353,42 @@ Qsk::Position QskTabBar::tabPosition() const
return static_cast< Qsk::Position >( m_data->position ); 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 Qt::Orientation QskTabBar::orientation() const
{ {
return qskOrientation( m_data->position ); return qskOrientation( m_data->position );
@ -365,20 +412,35 @@ void QskTabBar::setAutoFitTabs( bool on )
{ {
const auto orientation = qskOrientation( m_data->position ); const auto orientation = qskOrientation( m_data->position );
int policy = m_data->buttonBox->sizePolicy( orientation ); int policy = m_data->buttonBox->sizePolicy( orientation );
int boxPolicy = m_data->alignmentBox->sizePolicy( orientation );
if ( ( policy & QskSizePolicy::GrowFlag ) != on ) if ( ( policy & QskSizePolicy::GrowFlag ) != on )
{ {
if ( on ) if ( on )
{
policy |= QskSizePolicy::GrowFlag; policy |= QskSizePolicy::GrowFlag;
boxPolicy |= QskSizePolicy::GrowFlag;
removeSpacer( Qsk::Left );
removeSpacer( Qsk::Right );
}
else else
{
policy &= ~QskSizePolicy::GrowFlag; policy &= ~QskSizePolicy::GrowFlag;
boxPolicy &= ~QskSizePolicy::GrowFlag;
}
// we need operators for QskSizePolicy::Policy: TODO ... // we need operators for QskSizePolicy::Policy: TODO ...
m_data->buttonBox->setSizePolicy( m_data->buttonBox->setSizePolicy(
orientation, static_cast< QskSizePolicy::Policy >( policy ) ); orientation, static_cast< QskSizePolicy::Policy >( policy ) );
m_data->alignmentBox->setSizePolicy(
orientation, static_cast< QskSizePolicy::Policy >( boxPolicy ) );
polish(); polish();
if( !on )
setTabAlignment( m_data->alignment );
Q_EMIT autoFitTabsChanged( on ); 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 QskTabBar::substitutedSubcontrol(
QskAspect::Subcontrol subControl ) const QskAspect::Subcontrol subControl ) const
{ {

View File

@ -19,6 +19,9 @@ class QSK_EXPORT QskTabBar : public QskBox
Q_PROPERTY( Qsk::Position tabPosition READ tabPosition Q_PROPERTY( Qsk::Position tabPosition READ tabPosition
WRITE setTabPosition NOTIFY tabPositionChanged FINAL ) 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( Qt::Orientation orientation READ orientation )
Q_PROPERTY( bool autoScrollFocusButton READ autoScrollFocusButton Q_PROPERTY( bool autoScrollFocusButton READ autoScrollFocusButton
@ -48,6 +51,9 @@ class QSK_EXPORT QskTabBar : public QskBox
void setTabPosition( Qsk::Position ); void setTabPosition( Qsk::Position );
Qsk::Position tabPosition() const; Qsk::Position tabPosition() const;
void setTabAlignment( Qt::Alignment );
Qt::Alignment tabAlignment() const;
Qt::Orientation orientation() const; Qt::Orientation orientation() const;
void setAutoScrollFocusedButton( bool ); void setAutoScrollFocusedButton( bool );
@ -99,6 +105,7 @@ class QSK_EXPORT QskTabBar : public QskBox
void countChanged( int ); void countChanged( int );
void textOptionsChanged( const QskTextOptions& ); void textOptionsChanged( const QskTextOptions& );
void tabPositionChanged( Qsk::Position ); void tabPositionChanged( Qsk::Position );
void tabAlignmentChanged( Qt::Alignment );
void autoScrollFocusedButtonChanged( bool ); void autoScrollFocusedButtonChanged( bool );
void autoFitTabsChanged( bool ); void autoFitTabsChanged( bool );
@ -111,6 +118,8 @@ class QSK_EXPORT QskTabBar : public QskBox
private: private:
void adjustCurrentIndex(); void adjustCurrentIndex();
void handleButtonClick(); void handleButtonClick();
void ensureSpacer( Qsk::Position position );
void removeSpacer( Qsk::Position position );
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;

View File

@ -70,6 +70,9 @@ QskTabView::QskTabView( Qsk::Position tabPosition, QQuickItem* parent )
connect( m_data->tabBar, &QskTabBar::tabPositionChanged, connect( m_data->tabBar, &QskTabBar::tabPositionChanged,
this, &QskTabView::tabPositionChanged ); this, &QskTabView::tabPositionChanged );
connect( m_data->tabBar, &QskTabBar::tabAlignmentChanged,
this, &QskTabView::tabAlignmentChanged );
connect( m_data->tabBar, &QskTabBar::autoFitTabsChanged, connect( m_data->tabBar, &QskTabBar::autoFitTabsChanged,
this, &QskTabView::autoFitTabsChanged ); this, &QskTabView::autoFitTabsChanged );
} }
@ -104,6 +107,22 @@ Qsk::Position QskTabView::tabPosition() const
return m_data->tabBar->tabPosition(); 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 ) void QskTabView::setAutoFitTabs( bool on )
{ {
m_data->tabBar->setAutoFitTabs( on ); m_data->tabBar->setAutoFitTabs( on );

View File

@ -21,6 +21,9 @@ class QSK_EXPORT QskTabView : public QskControl
Q_PROPERTY( Qsk::Position tabPosition READ tabPosition Q_PROPERTY( Qsk::Position tabPosition READ tabPosition
WRITE setTabPosition NOTIFY tabPositionChanged FINAL ) WRITE setTabPosition NOTIFY tabPositionChanged FINAL )
Q_PROPERTY( Qt::Alignment tabAlignment READ tabAlignment
WRITE setTabAlignment NOTIFY tabAlignmentChanged FINAL )
Q_PROPERTY( bool autoFitTabs READ autoFitTabs Q_PROPERTY( bool autoFitTabs READ autoFitTabs
WRITE setAutoFitTabs NOTIFY autoFitTabsChanged FINAL ) WRITE setAutoFitTabs NOTIFY autoFitTabsChanged FINAL )
@ -47,6 +50,9 @@ class QSK_EXPORT QskTabView : public QskControl
void setTabPosition( Qsk::Position ); void setTabPosition( Qsk::Position );
Qsk::Position tabPosition() const; Qsk::Position tabPosition() const;
void setTabAlignment( Qt::Alignment );
Qt::Alignment tabAlignment() const;
void setAutoFitTabs( bool ); void setAutoFitTabs( bool );
bool autoFitTabs() const; bool autoFitTabs() const;
@ -84,6 +90,7 @@ class QSK_EXPORT QskTabView : public QskControl
void currentIndexChanged( int index ); void currentIndexChanged( int index );
void countChanged( int ); void countChanged( int );
void tabPositionChanged( Qsk::Position ); void tabPositionChanged( Qsk::Position );
void tabAlignmentChanged( Qt::Alignment );
void autoFitTabsChanged( bool ); void autoFitTabsChanged( bool );
protected: protected: