/****************************************************************************** * QSkinny - Copyright (C) 2016 Uwe Rathmann * This file may be used under the terms of the QSkinny License, Version 1.0 *****************************************************************************/ #include "QskTabBar.h" #include "QskLinearBox.h" #include "QskTabButton.h" #include "QskTextOptions.h" #include "QskAspect.h" QSK_SUBCONTROL( QskTabBar, Panel ) class QskTabBar::PrivateData { public: PrivateData(): currentIndex( -1 ), layoutBox( nullptr ) { } int currentIndex; QskTextOptions textOptions; QskLinearBox* layoutBox; }; QskTabBar::QskTabBar( QQuickItem* parent ): QskTabBar( Qt::Horizontal, parent ) { } QskTabBar::QskTabBar( Qt::Orientation orientation, QQuickItem* parent ): Inherited( parent ), m_data( new PrivateData() ) { #if 0 setFlag( QQuickItem::ItemHasContents, false ); setFlag( QQuickItem::ItemIsFocusScope ); #endif m_data->layoutBox = new QskLinearBox( orientation, this ); m_data->layoutBox->setObjectName( QStringLiteral( "QskTabBarLayoutBox" ) ); m_data->layoutBox->setSpacing( 0 ); m_data->layoutBox->setMargins( 0 ); m_data->layoutBox->setExtraSpacingAt( Qt::RightEdge | Qt::BottomEdge ); if ( orientation == Qt::Horizontal ) setSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Fixed ); else setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Preferred ); setAutoLayoutChildren( true ); QObject::connect( this, &QskTabBar::currentIndexChanged, this, &QskTabBar::restack, Qt::QueuedConnection ); } QskTabBar::~QskTabBar() { } void QskTabBar::setOrientation( Qt::Orientation orientation ) { if ( orientation == m_data->layoutBox->orientation() ) return; setSizePolicy( sizePolicy( Qt::Vertical ), sizePolicy( Qt::Horizontal ) ); m_data->layoutBox->setOrientation( orientation ); resetImplicitSize(); for ( int i = 0; i < count(); i++ ) buttonAt( i )->update(); Q_EMIT orientationChanged(); } Qt::Orientation QskTabBar::orientation() const { return m_data->layoutBox->orientation(); } void QskTabBar::setTextOptions( const QskTextOptions& options ) { if ( options != m_data->textOptions ) { // we should consider text options being something for // QskControl - maybe added to the propagation system ??? m_data->textOptions = options; Q_EMIT textOptionsChanged(); for ( int i = 0; i < count(); i++ ) buttonAt( i )->setTextOptions( options ); } } QskTextOptions QskTabBar::textOptions() const { return m_data->textOptions; } int QskTabBar::addTab( const QString& text ) { return insertTab( -1, text ); } int QskTabBar::insertTab( int index, const QString& text ) { return insertTab( index, new QskTabButton( text ) ); } int QskTabBar::addTab( QskTabButton* button ) { return insertTab( -1, button ); } int QskTabBar::insertTab( int index, QskTabButton* button ) { if ( index < 0 || index >= m_data->layoutBox->itemCount() ) index = m_data->layoutBox->itemCount(); if ( isComponentComplete() ) { if ( count() == 0 ) { m_data->currentIndex = 0; button->setChecked( true ); } } m_data->layoutBox->insertItem( index, button ); restack(); if ( button->textOptions() != m_data->textOptions ) button->setTextOptions( m_data->textOptions ); auto onTabSelected = [ = ] ( bool on ) { if ( on ) { int pos = indexOf( button ); if ( pos >= 0 && pos != m_data->currentIndex ) { m_data->currentIndex = pos; Q_EMIT currentIndexChanged( pos ); } } }; connect( button, &QskTabButton::toggled, this, onTabSelected ); Q_EMIT countChanged(); return index; } void QskTabBar::removeTab( int index ) { QQuickItem* item = m_data->layoutBox->itemAtIndex( index ); if ( item ) { delete m_data->layoutBox->itemAtIndex( index ); Q_EMIT countChanged(); if ( index == m_data->currentIndex ) { QskTabButton* nextButton = nullptr; for ( int i = m_data->currentIndex; i >= 0; i-- ) { QskTabButton* btn = buttonAt( index ); if ( btn && btn->isEnabled() ) { nextButton = btn; break; } } if ( nextButton == nullptr ) { for ( int i = m_data->currentIndex; i < count(); i++ ) { QskTabButton* btn = buttonAt( index ); if ( btn && btn->isEnabled() ) { nextButton = btn; break; } } } if ( nextButton && !nextButton->isChecked() ) nextButton->setChecked( true ); } } restack(); } void QskTabBar::clear() { if ( count() == 0 ) return; const int idx = currentIndex(); m_data->layoutBox->clear(); Q_EMIT countChanged(); if ( idx >= 0 ) Q_EMIT currentIndexChanged( -1 ); } bool QskTabBar::isTabEnabled( int index ) const { const QskTabButton* btn = buttonAt( index ); return btn ? btn->isEnabled() : false; } void QskTabBar::setTabEnabled( int index, bool enabled ) { QskTabButton* btn = buttonAt( index ); if ( btn ) { // what happens, when it is the current button ??? btn->setEnabled( enabled ); } } void QskTabBar::setCurrentIndex( int index ) { if ( index != m_data->currentIndex ) { if ( isComponentComplete() ) { QskTabButton* btn = buttonAt( index ); if ( btn && btn->isEnabled() && !btn->isChecked() ) btn->setChecked( true ); } else { m_data->currentIndex = index; Q_EMIT currentIndexChanged( m_data->currentIndex ); } } } int QskTabBar::currentIndex() const { return m_data->currentIndex; } int QskTabBar::count() const { return m_data->layoutBox->itemCount(); } QskTabButton* QskTabBar::buttonAt( int position ) { return qobject_cast< QskTabButton* >( m_data->layoutBox->itemAtIndex( position ) ); } const QskTabButton* QskTabBar::buttonAt( int position ) const { QskTabBar* that = const_cast< QskTabBar* >( this ); return that->buttonAt( position ); } QskTabButton* QskTabBar::currentButton() { return buttonAt( currentIndex() ); } const QskTabButton* QskTabBar::currentButton() const { return buttonAt( currentIndex() ); } QString QskTabBar::currentButtonText() const { return buttonTextAt( currentIndex() ); } QString QskTabBar::buttonTextAt( int index ) const { if ( const QskTabButton* btn = buttonAt( index ) ) return btn->text(); return QString::null; } int QskTabBar::indexOf( QskTabButton* button ) const { return m_data->layoutBox->indexOf( button ); } void QskTabBar::componentComplete() { Inherited::componentComplete(); if ( m_data->currentIndex < 0 && count() >= 0 ) m_data->currentIndex = 0; QskTabButton* btn = buttonAt( m_data->currentIndex ); if ( btn && btn->isEnabled() && !btn->isChecked() ) btn->setChecked( true ); } void QskTabBar::restack() { const int c = currentIndex(); for ( int i = count() - 1; i >= 0; --i ) { auto button = buttonAt( i ); button->setZ( c == i ? count() : ( count() - i ) ); } } QskAspect::Subcontrol QskTabBar::effectiveSubcontrol( QskAspect::Subcontrol subControl ) const { if ( subControl == QskBox::Panel ) return QskTabBar::Panel; return Inherited::effectiveSubcontrol( subControl ); } #include "moc_QskTabBar.cpp"