diff options
Diffstat (limited to 'src/widgets/widgets/qtabbar.cpp')
-rw-r--r-- | src/widgets/widgets/qtabbar.cpp | 91 |
1 files changed, 57 insertions, 34 deletions
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 1b64301fa6..0b463840ae 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -71,14 +71,6 @@ void QMovableTabWidget::paintEvent(QPaintEvent *e) p.drawPixmap(0, 0, m_pixmap); } -inline static bool verticalTabs(QTabBar::Shape shape) -{ - return shape == QTabBar::RoundedWest - || shape == QTabBar::RoundedEast - || shape == QTabBar::TriangularWest - || shape == QTabBar::TriangularEast; -} - void QTabBarPrivate::updateMacBorderMetrics() { #if defined(Q_OS_MACOS) @@ -283,9 +275,9 @@ void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const returns the visual geometry of a single tab. \table 100% - \row \li \inlineimage fusion-tabbar.png Screenshot of a Fusion style tab bar + \row \li \inlineimage {fusion-tabbar.png} {Screenshot of a Fusion style tab bar} \li A tab bar shown in the \l{Qt Widget Gallery}{Fusion widget style}. - \row \li \inlineimage fusion-tabbar-truncated.png Screenshot of a truncated Fusion tab bar + \row \li \inlineimage {fusion-tabbar-truncated.png} {Screenshot of a truncated Fusion tab bar} \li A truncated tab bar shown in the Fusion widget style. \endtable @@ -374,12 +366,14 @@ void QTabBarPrivate::init() leftB = new QToolButton(q); leftB->setObjectName(u"ScrollLeftButton"_s); leftB->setAutoRepeat(true); - QObject::connect(leftB, SIGNAL(clicked()), q, SLOT(_q_scrollTabs())); + QObjectPrivate::connect(leftB, &QToolButton::clicked, + this, &QTabBarPrivate::scrollTabs); leftB->hide(); rightB = new QToolButton(q); rightB->setObjectName(u"ScrollRightButton"_s); rightB->setAutoRepeat(true); - QObject::connect(rightB, SIGNAL(clicked()), q, SLOT(_q_scrollTabs())); + QObjectPrivate::connect(rightB, &QToolButton::clicked, + this, &QTabBarPrivate::scrollTabs); rightB->hide(); #ifdef QT_KEYPAD_NAVIGATION if (QApplicationPrivate::keypadNavigationEnabled()) { @@ -534,7 +528,6 @@ void QTabBarPrivate::layoutTabs() if (useScrollButtons && tabList.size() && last > available) { const QRect scrollRect = normalizedScrollRect(0); - scrollOffset = -scrollRect.left(); Q_Q(QTabBar); QStyleOption opt; @@ -571,10 +564,9 @@ void QTabBarPrivate::layoutTabs() leftB->show(); rightB->setGeometry(scrollButtonRightRect); - rightB->setEnabled(last - scrollOffset > scrollRect.x() + scrollRect.width()); + rightB->setEnabled(last + scrollRect.left() > scrollRect.x() + scrollRect.width()); rightB->show(); } else { - scrollOffset = 0; rightB->hide(); leftB->hide(); } @@ -591,6 +583,11 @@ QRect QTabBarPrivate::normalizedScrollRect(int index) // tab bar itself is in a different orientation. Q_Q(QTabBar); + // If scrollbuttons are not visible, then there's no tear either, and + // the entire widget is the scroll rect. + if (leftB->isHidden()) + return verticalTabs(shape) ? q->rect().transposed() : q->rect(); + QStyleOptionTab opt; q->initStyleOption(&opt, currentIndex); opt.rect = q->rect(); @@ -670,25 +667,33 @@ int QTabBarPrivate::hoveredTabIndex() const void QTabBarPrivate::makeVisible(int index) { Q_Q(QTabBar); - if (!validIndex(index) || leftB->isHidden()) + if (!validIndex(index)) return; const QRect tabRect = tabList.at(index)->rect; const int oldScrollOffset = scrollOffset; const bool horiz = !verticalTabs(shape); + const int available = horiz ? q->width() : q->height(); const int tabStart = horiz ? tabRect.left() : tabRect.top(); const int tabEnd = horiz ? tabRect.right() : tabRect.bottom(); const int lastTabEnd = horiz ? tabList.constLast()->rect.right() : tabList.constLast()->rect.bottom(); const QRect scrollRect = normalizedScrollRect(index); + const QRect entireScrollRect = normalizedScrollRect(0); // ignore tears const int scrolledTabBarStart = qMax(1, scrollRect.left() + scrollOffset); const int scrolledTabBarEnd = qMin(lastTabEnd - 1, scrollRect.right() + scrollOffset); - if (tabStart < scrolledTabBarStart) { + if (available >= lastTabEnd) { + // the entire tabbar fits, reset scroll + scrollOffset = 0; + } else if (tabStart < scrolledTabBarStart) { // Tab is outside on the left, so scroll left. scrollOffset = tabStart - scrollRect.left(); } else if (tabEnd > scrolledTabBarEnd) { // Tab is outside on the right, so scroll right. - scrollOffset = tabEnd - scrollRect.right(); + scrollOffset = qMax(0, tabEnd - scrollRect.right()); + } else if (scrollOffset + entireScrollRect.width() > lastTabEnd + 1) { + // fill any free space on the right without overshooting + scrollOffset = qMax(0, lastTabEnd - entireScrollRect.width() + 1); } leftB->setEnabled(scrollOffset > -scrollRect.left()); @@ -762,7 +767,7 @@ void QTabBarPrivate::autoHideTabs() q->setVisible(q->count() > 1); } -void QTabBarPrivate::_q_closeTab() +void QTabBarPrivate::closeTab() { Q_Q(QTabBar); QObject *object = q->sender(); @@ -785,7 +790,7 @@ void QTabBarPrivate::_q_closeTab() emit q->tabCloseRequested(tabToClose); } -void QTabBarPrivate::_q_scrollTabs() +void QTabBarPrivate::scrollTabs() { Q_Q(QTabBar); const QObject *sender = q->sender(); @@ -975,7 +980,8 @@ int QTabBar::insertTab(int index, const QIcon& icon, const QString &text) initStyleOption(&opt, index); ButtonPosition closeSide = (ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, nullptr, this); QAbstractButton *closeButton = new CloseButton(this); - connect(closeButton, SIGNAL(clicked()), this, SLOT(_q_closeTab())); + QObjectPrivate::connect(closeButton, &CloseButton::clicked, + d, &QTabBarPrivate::closeTab); setTabButton(index, closeSide, closeButton); } @@ -1410,7 +1416,10 @@ void QTabBar::setCurrentIndex(int index) if (tabRect(index).size() != tabSizeHint(index)) d->layoutTabs(); update(); - d->makeVisible(index); + if (!isVisible()) + d->layoutDirty = true; + else + d->makeVisible(index); if (d->validIndex(oldIndex)) { tab->lastTab = oldIndex; d->layoutTab(oldIndex); @@ -1645,6 +1654,8 @@ void QTabBar::showEvent(QShowEvent *) d->refresh(); if (!d->validIndex(d->currentIndex)) setCurrentIndex(0); + else + d->makeVisible(d->currentIndex); d->updateMacBorderMetrics(); } @@ -1778,6 +1789,8 @@ void QTabBar::resizeEvent(QResizeEvent *) Q_D(QTabBar); if (d->layoutDirty) updateGeometry(); + + // when resizing, we want to keep the scroll offset as much as possible d->layoutTabs(); d->makeVisible(d->currentIndex); @@ -1873,21 +1886,30 @@ void QTabBar::paintEvent(QPaintEvent *) QStyleOptionTab tabOption; const auto tab = d->tabList.at(selected); initStyleOption(&tabOption, selected); + if (d->paintWithOffsets && tab->dragOffset != 0) { + // if the drag offset is != 0, a move is in progress (drag or animation) + // => set the tab position to Moving to preserve the rect + tabOption.position = QStyleOptionTab::TabPosition::Moving; + if (vertical) tabOption.rect.moveTop(tabOption.rect.y() + tab->dragOffset); else tabOption.rect.moveLeft(tabOption.rect.x() + tab->dragOffset); } - if (!d->dragInProgress) - p.drawControl(QStyle::CE_TabBarTab, tabOption); - else { - int taboverlap = style()->pixelMetric(QStyle::PM_TabBarTabOverlap, nullptr, this); - if (verticalTabs(d->shape)) - d->movingTab->setGeometry(tabOption.rect.adjusted(0, -taboverlap, 0, taboverlap)); - else - d->movingTab->setGeometry(tabOption.rect.adjusted(-taboverlap, 0, taboverlap, 0)); - } + + // Calculate the rect of a moving tab + const int taboverlap = style()->pixelMetric(QStyle::PM_TabBarTabOverlap, nullptr, this); + const QRect &movingRect = verticalTabs(d->shape) + ? tabOption.rect.adjusted(0, -taboverlap, 0, taboverlap) + : tabOption.rect.adjusted(-taboverlap, 0, taboverlap, 0); + + // If a drag is in process, set the moving tab's geometry here + // (in an animation, it is already set) + if (d->dragInProgress) + d->movingTab->setGeometry(movingRect); + + p.drawControl(QStyle::CE_TabBarTab, tabOption); } // Only draw the tear indicator if necessary. Most of the time we don't need too. @@ -2227,7 +2249,7 @@ void QTabBarPrivate::setupMovableTab() QStyleOptionTab tab; q->initStyleOption(&tab, pressedIndex); - tab.position = QStyleOptionTab::OnlyOneTab; + tab.position = QStyleOptionTab::Moving; if (verticalTabs(shape)) tab.rect.moveTopLeft(QPoint(0, taboverlap)); else @@ -2417,7 +2439,7 @@ void QTabBarPrivate::setCurrentNextEnabledIndex(int offset) { Q_Q(QTabBar); for (int index = currentIndex + offset; validIndex(index); index += offset) { - if (tabList.at(index)->enabled) { + if (tabList.at(index)->enabled && tabList.at(index)->visible) { q->setCurrentIndex(index); break; } @@ -2563,7 +2585,8 @@ void QTabBar::setTabsClosable(bool closable) continue; newButtons = true; QAbstractButton *closeButton = new CloseButton(this); - connect(closeButton, SIGNAL(clicked()), this, SLOT(_q_closeTab())); + QObjectPrivate::connect(closeButton, &CloseButton::clicked, + d, &QTabBarPrivate::closeTab); setTabButton(i, closeSide, closeButton); } if (newButtons) |