QTabBar mit einigen beweglichen Tabs?

Alles rund um die Programmierung mit Qt
Antworten
hilefoks
Beiträge: 144
Registriert: 13. März 2008 16:09

QTabBar mit einigen beweglichen Tabs?

Beitrag von hilefoks »

Moin,

Ich habe mal wieder einen Knoten im Kopf!? ;-)

Ich brauche ein TabWidget bei dem die Tabs beweglich/verschiebbar sind und zwei Buttons zum Hinzufügen beziehungsweise Entfernen von Tabs besitzt. Soweit alles mit normalem QTabWidget machbar.

Aber: Unter MacOS sieht das ziemlich bescheiden aus.

Deshalb möchte ich vor den normalen Tabs einen Tab haben, der bei einem Klick einen neuen Tab erzeugt und am Ende einen Tab, der den zuletzt selektierten Tab löscht. Auch hier ist die Implementierung noch kein Problem.

Das Problem ist aber, das zudem alle "normalen" Tabs beweglich sein sollen, nicht aber der erste und letzte Tab.

Ich habe versucht, dies mittels tabMoved Signal abzufangen, aber das funktioniert nicht korrekt. Zwar kann ich die Position der Tabs damit wieder korrigieren, aber gelegentlich ist danach ein Tab A selektiert, aber der Inhalt von Tab B gerendert.

Ausserdem kann ich natürlich nicht vernünftig von QTabWidget ableiten, da diese Klasse nicht genügend virtuelle Methoden bietet. Aber das ist ein anderes Thema, mit dem ich so auch leben könnte.

Code: Alles auswählen

class CORE_WIDGET_EXPORT TabWidget : public QTabWidget
{
Q_OBJECT

public:
    TabWidget(QWidget *parent = 0);

public slots:
    void testAddTabRequested();
    void testRemoveTabRequested(int index);

signals:
    void addTabRequested();
    void removeTabRequested(int index);

protected:
    virtual void tabInserted(int index);
    virtual void tabRemoved(int index);

private slots:
    void updateTabPosition();

private:
    QWidget* m_addWidget;
    QWidget* m_removeWidget;
    int m_lastSelectedTab;
};

Code: Alles auswählen


TabWidget::TabWidget(QWidget *parent)
  : QTabWidget( parent ),
    m_lastSelectedTab( -1 )
{
    m_addWidget = new QLabel( "Initial Add Widget", this );
    m_removeWidget = new QLabel( "Initial Remove Widget", this );

    addTab( m_addWidget, tr( "+" ) );
    addTab( m_removeWidget, tr( "-" ) );
    setTabEnabled( 1, false );

    connect( m_addWidget, SIGNAL( destroyed() ), this, SLOT( updateTabPosition() ) );
    connect( m_removeWidget, SIGNAL( destroyed() ), this, SLOT( updateTabPosition() ) );

    connect( tabBar(), &QTabBar::currentChanged, [=](int index) {
        if( currentWidget() == m_addWidget ) {
            emit addTabRequested();
        }
        else if( currentWidget() == m_removeWidget ) {
            setCurrentIndex( m_lastSelectedTab > 1 ? m_lastSelectedTab - 1 : m_lastSelectedTab + 1 );
            emit removeTabRequested( m_lastSelectedTab );
        }
        else {
            m_lastSelectedTab = index;
        }
    } );

    connect( tabBar(), &QTabBar::tabMoved, [=]() {
        if( indexOf( m_addWidget ) != 0 ) {
            tabBar()->moveTab( indexOf( m_addWidget ), 0 );
        }

        if( indexOf( m_removeWidget ) != count() -1 ) {
            tabBar()->moveTab( indexOf( m_removeWidget ), count() -1 );
        }

        setCurrentIndex( m_lastSelectedTab );
    } );

    connect( this, SIGNAL( addTabRequested() ), this, SLOT( testAddTabRequested() ) );
    connect( this, SIGNAL( removeTabRequested(int) ), this, SLOT( testRemoveTabRequested(int) ) );

    testAddTabRequested();
}

void TabWidget::testAddTabRequested()
{
    QString str = QString( "Tab %1" ).arg( count() - 2 );
    addTab( new QLabel( str, this ), str );
}

void TabWidget::testRemoveTabRequested(int index)
{
    removeTab( index );
}

void TabWidget::tabInserted(int index)
{
    QTabWidget::tabInserted( index );
    setTabEnabled( indexOf( m_removeWidget ), count() > 3 );
    updateTabPosition();
}

void TabWidget::tabRemoved(int index)
{
    QTabWidget::tabRemoved( index );
    setTabEnabled( indexOf( m_removeWidget ), count() > 3 );
}

void TabWidget::updateTabPosition()
{
    if( !m_addWidget ) {
        m_addWidget = new QLabel( "New Add Widget", this );
    }

    if( indexOf( m_addWidget ) < 0 ) {
        insertTab( 0, m_addWidget, tr( "+" ) );
    }
    else if( indexOf( m_addWidget ) != 0 ) {
        tabBar()->moveTab( indexOf( m_addWidget ), 0 );
    }

    if( !m_removeWidget ) {
        m_addWidget = new QLabel( "New Remove Widget", this );
    }

    if( indexOf( m_removeWidget ) < 0 ) {
        addTab( m_removeWidget, tr( "-" ) );
    }
    else if( indexOf( m_removeWidget ) != count() -1 ) {
        tabBar()->moveTab( indexOf( m_removeWidget ), count() -1 );
    }

    setCurrentIndex( m_lastSelectedTab > 0 ? m_lastSelectedTab : 1 );
}
So sieht das ganze bisher übrigens aus:Bild

Hat jemand eine Idee, wie ich das Problem mit dem falsch gerendertem Inhalt in den Griff bekomme? Jemand eine bessere Idee, das ganze zu implementieren?

MfG,
Hilefoks
Antworten