4#include "private/qlayoutengine_p.h"
5#if QT_CONFIG(itemviews)
14#if QT_CONFIG(tabwidget)
20#if QT_CONFIG(whatsthis)
23#include "private/qtextengine_p.h"
24#if QT_CONFIG(accessibility)
28#include <qpa/qplatformnativeinterface.h>
32#include "private/qapplication_p.h"
33#include "private/qtabbar_p.h"
45 explicit CloseButton(
QWidget *parent =
nullptr);
47 QSize sizeHint()
const override;
48 QSize minimumSizeHint()
const override
49 {
return sizeHint(); }
71 p.drawPixmap(0, 0, m_pixmap);
76#if defined(Q_OS_MACOS)
88 upper = windowPos.
y();
89 int tabStripHeight =
q->tabSizeHint(0).height();
91 lower = upper + tabStripHeight + pixelTweak;
108 (
reinterpret_cast<RegisterContentBorderAreaFunction
>(
function))(
q->window()->windowHandle(), identifier, upper, lower);
115 (
reinterpret_cast<SetContentBorderAreaEnabledFunction
>(
function))(
q->window()->windowHandle(), identifier,
q->isVisible());
128 const int totalTabs =
tabList.size();
130 if (!
option || (tabIndex < 0 || tabIndex >= totalTabs))
136 option->rect =
q->tabRect(tabIndex);
143 if (isCurrent &&
q->hasFocus())
147 if (
q->isActiveWindow())
157 option->iconSize =
q->iconSize();
164 option->selectedPosition = QStyleOptionTab::PreviousIsSelected;
165 else if (tabIndex + 1 < totalTabs && tabIndex + 1 ==
currentIndex)
166 option->selectedPosition = QStyleOptionTab::NextIsSelected;
168 option->selectedPosition = QStyleOptionTab::NotAdjacent;
172 if (paintBeginning) {
174 option->position = QStyleOptionTab::OnlyOneTab;
176 option->position = QStyleOptionTab::Beginning;
177 }
else if (paintEnd) {
178 option->position = QStyleOptionTab::End;
180 option->position = QStyleOptionTab::Middle;
183#if QT_CONFIG(tabwidget)
184 if (
const QTabWidget *tw = qobject_cast<const QTabWidget *>(
q->parentWidget())) {
185 option->features |= QStyleOptionTab::HasFrame;
187 option->cornerWidgets |= QStyleOptionTab::LeftCornerWidget;
189 option->cornerWidgets |= QStyleOptionTab::RightCornerWidget;
192 option->tabIndex = tabIndex;
205 d->initBasicStyleOption(
option, tabIndex);
378#ifdef QT_KEYPAD_NAVIGATION
379 if (QApplicationPrivate::keypadNavigationEnabled()) {
387#if QT_CONFIG(accessibility)
388 leftB->setAccessibleName(QTabBar::tr(
"Scroll Left"));
389 rightB->setAccessibleName(QTabBar::tr(
"Scroll Right"));
402 if (
tabList.at(
i)->enabled &&
q->tabRect(
i).contains(
p))
415 int tabChainIndex = 0;
419 QList<QLayoutStruct> tabChain(
tabList.size() + 2);
423 tabChain[tabChainIndex].init();
424 tabChain[tabChainIndex].expansive = (!
expanding)
427 tabChain[tabChainIndex].empty =
true;
452 sz =
q->minimumTabSizeHint(
i);
455 tabChain[tabChainIndex].init();
456 tabChain[tabChainIndex].sizeHint = tab->maxRect.width();
457 tabChain[tabChainIndex].minimumSize = sz.
width();
458 tabChain[tabChainIndex].empty =
false;
459 tabChain[tabChainIndex].expansive =
true;
462 tabChain[tabChainIndex].maximumSize = tabChain[tabChainIndex].sizeHint;
467 available =
size.width();
468 maxExtent = maxHeight;
483 sz =
q->minimumTabSizeHint(
i);
486 tabChain[tabChainIndex].init();
487 tabChain[tabChainIndex].sizeHint = tab->maxRect.height();
488 tabChain[tabChainIndex].minimumSize = sz.
height();
489 tabChain[tabChainIndex].empty =
false;
490 tabChain[tabChainIndex].expansive =
true;
493 tabChain[tabChainIndex].maximumSize = tabChain[tabChainIndex].sizeHint;
498 available =
size.height();
499 maxExtent = maxWidth;
503 tabChain[tabChainIndex].init();
504 tabChain[tabChainIndex].expansive = (!
expanding)
507 tabChain[tabChainIndex].empty =
true;
508 Q_ASSERT(tabChainIndex == tabChain.size() - 1 - hiddenTabs);
511 qGeomCalc(tabChain, 0, tabChain.size(), 0,
qMax(available, last), 0);
524 tab->rect.setRect(lstruct.pos, 0, lstruct.size, maxExtent);
526 tab->rect.setRect(0, lstruct.pos, maxExtent, lstruct.size);
543 scrollButtonLeftRect.
setHeight(scrollButtonWidth);
544 scrollButtonRightRect.setY(scrollButtonRightRect.bottom() + 1 - scrollButtonWidth);
545 scrollButtonRightRect.setHeight(scrollButtonWidth);
549 scrollButtonRightRect.setWidth(scrollButtonWidth);
550 scrollButtonLeftRect.setX(scrollButtonLeftRect.right() + 1 - scrollButtonWidth);
551 scrollButtonLeftRect.setWidth(scrollButtonWidth);
555 scrollButtonLeftRect.setWidth(scrollButtonWidth);
556 scrollButtonRightRect.setX(scrollButtonRightRect.right() + 1 - scrollButtonWidth);
557 scrollButtonRightRect.setWidth(scrollButtonWidth);
575 q->tabLayoutChange();
601 int topEdge, bottomEdge;
602 bool leftButtonIsOnTop = scrollButtonLeftRect.
y() <
q->height() / 2;
603 bool rightButtonIsOnTop = scrollButtonRightRect.y() <
q->height() / 2;
605 if (leftButtonIsOnTop && rightButtonIsOnTop) {
606 topEdge = scrollButtonRightRect.bottom() + 1;
607 bottomEdge =
q->height();
608 }
else if (!leftButtonIsOnTop && !rightButtonIsOnTop) {
610 bottomEdge = scrollButtonLeftRect.top();
612 topEdge = scrollButtonLeftRect.bottom() + 1;
613 bottomEdge = scrollButtonRightRect.top();
618 if (tearTopVisible && !tearLeftRect.isNull())
619 topEdge = tearLeftRect.bottom() + 1;
620 if (tearBottomVisible && !tearRightRect.isNull())
621 bottomEdge = tearRightRect.top();
623 return QRect(topEdge, 0, bottomEdge - topEdge,
q->height());
632 int leftEdge, rightEdge;
633 bool leftButtonIsOnLeftSide = scrollButtonLeftRect.x() <
q->width() / 2;
634 bool rightButtonIsOnLeftSide = scrollButtonRightRect.x() <
q->width() / 2;
636 if (leftButtonIsOnLeftSide && rightButtonIsOnLeftSide) {
637 leftEdge = scrollButtonRightRect.right() + 1;
638 rightEdge =
q->width();
639 }
else if (!leftButtonIsOnLeftSide && !rightButtonIsOnLeftSide) {
641 rightEdge = scrollButtonLeftRect.left();
643 leftEdge = scrollButtonLeftRect.right() + 1;
644 rightEdge = scrollButtonRightRect.left();
649 if (tearLeftVisible && !tearLeftRect.isNull())
650 leftEdge = tearLeftRect.right() + 1;
651 if (tearRightVisible && !tearRightRect.isNull())
652 rightEdge = tearRightRect.left();
654 return QRect(leftEdge, 0, rightEdge - leftEdge,
q->height());
676 const int available = horiz ?
q->width() :
q->height();
677 const int tabStart = horiz ? tabRect.
left() : tabRect.
top();
678 const int tabEnd = horiz ? tabRect.
right() : tabRect.
bottom();
679 const int lastTabEnd = horiz ?
tabList.constLast()->rect.right() :
tabList.constLast()->rect.bottom();
685 if (available >= lastTabEnd) {
688 }
else if (tabStart < scrolledTabBarStart) {
691 }
else if (tabEnd > scrolledTabBarEnd) {
694 }
else if (
scrollOffset + entireScrollRect.width() > lastTabEnd + 1) {
757 for (
int i =
start;
i <
q->count(); ++
i) {
767 q->setVisible(
q->count() > 1);
789 if (tabToClose != -1)
790 emit q->tabCloseRequested(tabToClose);
802 if (sender ==
leftB) {
810 }
else if (sender ==
rightB) {
812 const auto tabRect =
tabList.at(
i)->rect;
813 int start = horizontal ? tabRect.left() : tabRect.top();
814 int end = horizontal ? tabRect.right() : tabRect.bottom();
836 if (!
q->isVisible()) {
957 if (!
d->validIndex(
index)) {
958 index =
d->tabList.size();
963#ifndef QT_NO_SHORTCUT
968 if (
d->tabList.size() == 1)
973 if (index <= d->lastVisible)
978 if (
d->closeButtonOnTabs) {
988 for (
const auto tab : std::as_const(
d->tabList)) {
989 if (tab->lastTab >=
index)
1012 if (
d->validIndex(
index)) {
1013 auto removedTab =
d->tabList.at(
index);
1014 if (
d->dragInProgress)
1015 d->moveTabFinished(
d->pressedIndex);
1017#ifndef QT_NO_SHORTCUT
1020 if (removedTab->leftWidget) {
1021 removedTab->leftWidget->hide();
1022 removedTab->leftWidget->deleteLater();
1023 removedTab->leftWidget =
nullptr;
1025 if (removedTab->rightWidget) {
1026 removedTab->rightWidget->hide();
1027 removedTab->rightWidget->deleteLater();
1028 removedTab->rightWidget =
nullptr;
1031 int newIndex = removedTab->lastTab;
1032 d->tabList.removeAt(
index);
1034 for (
auto tab : std::as_const(
d->tabList)) {
1035 if (tab->lastTab ==
index)
1037 if (tab->lastTab >
index)
1041 d->calculateFirstLastVisible(
index,
false,
true);
1043 if (
index ==
d->currentIndex) {
1047 d->currentIndex = -1;
1048 if (
d->tabList.size() > 0) {
1049 switch(
d->selectionBehaviorOnRemove) {
1051 if (newIndex >
index)
1053 if (
d->validIndex(newIndex) &&
d->tabList.at(newIndex)->visible)
1060 newIndex =
qBound(
d->firstVisible,
index-1,
d->lastVisible);
1066 if (
d->validIndex(newIndex)) {
1068 int bump =
d->tabList.at(newIndex)->lastTab;
1070 d->tabList.at(newIndex)->lastTab = bump;
1083 if (
d->hoverRect.isValid()) {
1085 d->hoverIndex =
tabAt(
d->mousePosition);
1086 if (
d->validIndex(
d->hoverIndex)) {
1106 return tab->enabled;
1119#ifndef QT_NO_SHORTCUT
1139 if (
d->validIndex(
index))
1140 return d->tabList.at(
index)->visible;
1153 d->layoutDirty = (
visible != tab->visible);
1154 if (!
d->layoutDirty)
1157 if (tab->leftWidget)
1158 tab->leftWidget->setVisible(
visible);
1159 if (tab->rightWidget)
1160 tab->rightWidget->setVisible(
visible);
1161#ifndef QT_NO_SHORTCUT
1166 const int newindex =
d->selectNewCurrentIndexFrom(
index+1);
1193 d->textSizes.remove(tab->text);
1195#ifndef QT_NO_SHORTCUT
1214 return tab->textColor;
1229 tab->textColor =
color;
1253 bool simpleIconChange = (!
icon.
isNull() && !tab->icon.isNull());
1255 if (simpleIconChange)
1262#if QT_CONFIG(tooltip)
1266void QTabBar::setTabToolTip(
int index,
const QString & tip)
1281 return tab->toolTip;
1286#if QT_CONFIG(whatsthis)
1297 tab->whatsThis =
text;
1310 return tab->whatsThis;
1354 r.translate(-
d->scrollOffset, 0);
1371 if (
d->validIndex(
d->currentIndex)
1373 return d->currentIndex;
1375 const int max =
d->tabList.size();
1376 for (
int i = 0;
i < max; ++
i) {
1394 if (
d->validIndex(
d->currentIndex))
1395 return d->currentIndex;
1403 if (
d->dragInProgress &&
d->pressedIndex != -1)
1405 if (
d->currentIndex ==
index)
1408 int oldIndex =
d->currentIndex;
1409 if (
auto tab =
d->at(
index)) {
1420 d->layoutDirty =
true;
1423 if (
d->validIndex(oldIndex)) {
1424 tab->lastTab = oldIndex;
1425 d->layoutTab(oldIndex);
1428#if QT_CONFIG(accessibility)
1429 if (QAccessible::isActive()) {
1431 QAccessibleEvent focusEvent(
this, QAccessible::Focus);
1432 focusEvent.setChild(
index);
1433 QAccessible::updateAccessibility(&focusEvent);
1435 QAccessibleEvent selectionEvent(
this, QAccessible::Selection);
1436 selectionEvent.setChild(
index);
1437 QAccessible::updateAccessibility(&selectionEvent);
1457 if (
d->iconSize.isValid())
1460 return QSize(iconExtent, iconExtent);
1468 d->layoutDirty =
true;
1481 return d->tabList.size();
1493 for (
const auto tab :
d->tabList) {
1507 if (!
d->useScrollButtons) {
1509 for (
const auto tab :
d->tabList) {
1527 static const auto Ellipses =
"..."_L1;
1558 tab->
text = oldText;
1570 QStyleOptionTab
opt;
1578 int maxWidgetHeight =
qMax(
opt.leftButtonSize.height(),
opt.rightButtonSize.height());
1579 int maxWidgetWidth =
qMax(
opt.leftButtonSize.width(),
opt.rightButtonSize.width());
1581 int widgetWidth = 0;
1582 int widgetHeight = 0;
1584 if (!
opt.leftButtonSize.isEmpty()) {
1586 widgetWidth +=
opt.leftButtonSize.width();
1587 widgetHeight +=
opt.leftButtonSize.height();
1589 if (!
opt.rightButtonSize.isEmpty()) {
1591 widgetWidth +=
opt.rightButtonSize.width();
1592 widgetHeight +=
opt.rightButtonSize.height();
1598 if (
it ==
d->textSizes.
end())
1600 const int textWidth =
it.value().width();
1604 textWidth +
iconSize.
width() + hframe + widgetHeight + padding);
1655 if (!
d->validIndex(
d->currentIndex))
1658 d->makeVisible(
d->currentIndex);
1659 d->updateMacBorderMetrics();
1667 d->updateMacBorderMetrics();
1675 switch (
event->type()) {
1680 if (!
d->hoverRect.contains(
d->mousePosition)) {
1681 if (
d->hoverRect.isValid())
1683 d->hoverIndex =
tabAt(
d->mousePosition);
1684 if (
d->validIndex(
d->hoverIndex)) {
1694 d->mousePosition = {-1, -1};
1695 if (
d->hoverRect.isValid())
1699#if QT_CONFIG(wheelevent)
1700 d->accumulatedAngleDelta =
QPoint();
1704#if QT_CONFIG(tooltip)
1707 if (!tab->toolTip.isEmpty()) {
1714#if QT_CONFIG(whatsthis)
1715 case QEvent::QEvent::QueryWhatsThis: {
1717 if (!tab || tab->whatsThis.isEmpty())
1723 if (!tab->whatsThis.isEmpty()) {
1725 tab->whatsThis,
this);
1731#ifndef QT_NO_SHORTCUT
1735 for (
int i = 0;
i <
d->tabList.size(); ++
i) {
1746 d->updateMacBorderMetrics();
1748#if QT_CONFIG(draganddrop)
1751 if (
d->changeCurrentOnDrag)
1755 if (
d->changeCurrentOnDrag) {
1756 const int tabIndex =
tabAt(
static_cast<QDragMoveEvent *
>(
event)->
position().toPoint());
1757 if (
isTabEnabled(tabIndex) &&
d->switchTabCurrentIndex != tabIndex) {
1758 d->switchTabCurrentIndex = tabIndex;
1759 if (
d->switchTabTimerId)
1768 d->killSwitchTabTimer();
1796 d->makeVisible(
d->currentIndex);
1805 QStyleOptionTabBarBase optTabBase;
1813 QStyleOptionTab cutTabLeft;
1814 QStyleOptionTab cutTabRight;
1815 selected =
d->currentIndex;
1816 if (
d->dragInProgress)
1817 selected =
d->pressedIndex;
1818 const QRect scrollRect =
d->normalizedScrollRect();
1820 for (
int i = 0;
i <
d->tabList.size(); ++
i)
1821 optTabBase.tabBarRect |=
tabRect(
i);
1823 optTabBase.selectedTabRect =
tabRect(selected);
1830 if (
d->leftB->isVisible() ||
d->rightB->isVisible()) {
1834 if (
d->leftB->isVisible())
1836 if (
d->rightB->isVisible())
1838 if (!buttonRegion.isEmpty())
1842 for (
int i = 0;
i <
d->tabList.size(); ++
i) {
1843 const auto tab =
d->tabList.at(
i);
1846 QStyleOptionTab tabOption;
1848 if (
d->paintWithOffsets && tab->dragOffset != 0) {
1850 tabOption.rect.moveTop(tabOption.rect.y() + tab->dragOffset);
1852 tabOption.rect.moveLeft(tabOption.rect.x() + tab->dragOffset);
1864 if (tabStart < scrollRect.
left() +
d->scrollOffset) {
1866 cutTabLeft = tabOption;
1867 }
else if (tabEnd > scrollRect.
right() +
d->scrollOffset) {
1869 cutTabRight = tabOption;
1873 if ((!vertical && (tabOption.rect.right() < 0 || tabOption.rect.left() >
width()))
1874 || (vertical && (tabOption.rect.bottom() < 0 || tabOption.rect.top() >
height())))
1877 optTabBase.tabBarRect |= tabOption.rect;
1885 if (selected >= 0) {
1886 QStyleOptionTab tabOption;
1887 const auto tab =
d->tabList.at(selected);
1890 if (
d->paintWithOffsets && tab->dragOffset != 0) {
1893 tabOption.position = QStyleOptionTab::TabPosition::Moving;
1896 tabOption.rect.moveTop(tabOption.rect.y() + tab->dragOffset);
1898 tabOption.rect.moveLeft(tabOption.rect.x() + tab->dragOffset);
1904 ? tabOption.rect.adjusted(0, -taboverlap, 0, taboverlap)
1905 : tabOption.rect.adjusted(-taboverlap, 0, taboverlap, 0);
1909 if (
d->dragInProgress)
1910 d->movingTab->setGeometry(movingRect);
1916 if (
d->leftB->isVisible() && cutLeft >= 0) {
1917 cutTabLeft.rect =
rect();
1922 if (
d->rightB->isVisible() && cutRight >= 0) {
1923 cutTabRight.rect =
rect();
1950 for (
int i =
tabList.size() - 1;
i >= 0; --
i) {
1968 for (
int i = fromIndex;
i <
tabList.size(); ++
i) {
1975 for (
int i = fromIndex-1;
i > -1; --
i) {
1997 index += (from < to) ? -1 : 1;
2011 || !
d->validIndex(from)
2012 || !
d->validIndex(to))
2015 auto &fromTab = *
d->tabList.at(from);
2016 auto &toTab = *
d->tabList.at(to);
2019 int oldPressedPosition = 0;
2020 if (
d->pressedIndex != -1) {
2022 oldPressedPosition = vertical ?
d->tabList.at(
d->pressedIndex)->rect.y()
2023 :
d->tabList.at(
d->pressedIndex)->rect.x();
2029 int width = vertical ? fromTab.rect.height() : fromTab.rect.width();
2036 auto &tab = *
d->tabList.at(
i);
2038 tab.rect.moveTop(tab.rect.y() +
width);
2040 tab.rect.moveLeft(tab.rect.x() +
width);
2042 if (rtl && !vertical)
2044 if (tab.dragOffset != 0)
2050 fromTab.rect.moveTop(toTab.rect.bottom() + 1);
2052 fromTab.rect.moveTop(toTab.rect.top() -
width);
2055 fromTab.rect.moveLeft(toTab.rect.right() + 1);
2057 fromTab.rect.moveLeft(toTab.rect.left() -
width);
2061 d->tabList.move(from, to);
2064 for (
const auto tab : std::as_const(
d->tabList))
2065 tab->lastTab =
d->calculateNewPosition(from, to, tab->lastTab);
2068 int previousIndex =
d->currentIndex;
2069 d->currentIndex =
d->calculateNewPosition(from, to,
d->currentIndex);
2072 if (
d->pressedIndex != -1) {
2073 d->pressedIndex =
d->calculateNewPosition(from, to,
d->pressedIndex);
2074 const auto pressedTab =
d->tabList.at(
d->pressedIndex);
2075 int newPressedPosition = vertical ? pressedTab->rect.top() : pressedTab->rect.left();
2076 int diff = oldPressedPosition - newPressedPosition;
2080 d->dragStartPosition.setY(
d->dragStartPosition.y() - diff);
2082 d->dragStartPosition.setX(
d->dragStartPosition.x() - diff);
2088 if (previousIndex !=
d->currentIndex)
2101 int preLocation = vertical ?
q->tabRect(from).y() :
q->tabRect(from).x();
2102 q->setUpdatesEnabled(
false);
2103 q->moveTab(from, to);
2104 q->setUpdatesEnabled(
true);
2105 int postLocation = vertical ?
q->tabRect(to).y() :
q->tabRect(to).x();
2106 int length = postLocation - preLocation;
2126 const QPoint pos =
event->position().toPoint();
2127 const bool isEventInCornerButtons = (!
d->leftB->isHidden() &&
d->leftB->geometry().contains(
pos))
2128 || (!
d->rightB->isHidden() &&
d->rightB->geometry().contains(
pos));
2129 if (!isEventInCornerButtons) {
2139 if (
d->pressedIndex != -1 &&
d->movable)
2140 d->moveTabFinished(
d->pressedIndex);
2142 d->pressedIndex =
d->indexAtPos(
event->position().toPoint());
2144 if (
d->validIndex(
d->pressedIndex)) {
2145 QStyleOptionTabBarBase optTabBase;
2146 optTabBase.initFrom(
this);
2147 optTabBase.documentMode =
d->documentMode;
2153 d->dragStartPosition =
event->position().toPoint();
2165 if (
d->pressedIndex != -1
2167 d->moveTabFinished(
d->pressedIndex);
2170 if (!
d->dragInProgress &&
d->pressedIndex != -1) {
2172 d->dragInProgress =
true;
2173 d->setupMovableTab();
2178 &&
d->dragInProgress
2179 &&
d->validIndex(
d->pressedIndex)) {
2183 dragDistance = (
event->position().toPoint().y() -
d->dragStartPosition.y());
2185 dragDistance = (
event->position().toPoint().x() -
d->dragStartPosition.x());
2187 d->tabList.at(
d->pressedIndex)->dragOffset = dragDistance;
2191 startingRect.moveTop(startingRect.y() + dragDistance);
2193 startingRect.moveLeft(startingRect.x() + dragDistance);
2196 if (dragDistance < 0)
2197 overIndex =
tabAt(startingRect.topLeft());
2199 overIndex =
tabAt(startingRect.topRight());
2201 if (overIndex !=
d->pressedIndex && overIndex != -1) {
2205 if (dragDistance < 0) {
2209 for (
int i =
d->pressedIndex;
2210 offset > 0 ? i < overIndex : i > overIndex;
2213 int needsToBeOver = (vertical ? overIndexRect.height() : overIndexRect.width()) / 2;
2214 if (dragDistance > needsToBeOver)
2219 if (
d->pressedIndex != -1)
2220 d->layoutTab(
d->pressedIndex);
2241 grabRect.
adjust(0, -taboverlap, 0, taboverlap);
2243 grabRect.adjust(-taboverlap, 0, taboverlap, 0);
2245 QPixmap grabImage(grabRect.size() *
q->devicePixelRatio());
2250 QStyleOptionTab tab;
2252 tab.position = QStyleOptionTab::Moving;
2254 tab.rect.moveTopLeft(
QPoint(0, taboverlap));
2256 tab.rect.moveTopLeft(
QPoint(taboverlap, 0));
2266 if (pressedTab.leftWidget)
2267 pressedTab.leftWidget->raise();
2268 if (pressedTab.rightWidget)
2269 pressedTab.rightWidget->raise();
2281 bool allAnimationsFinished =
true;
2282#if QT_CONFIG(animation)
2283 for (
const auto tab : std::as_const(
tabList)) {
2285 allAnimationsFinished =
false;
2290 if (allAnimationsFinished && cleanup) {
2293 for (
auto tab : std::as_const(
tabList)) {
2294 tab->dragOffset = 0;
2320 if (
d->movable &&
d->dragInProgress &&
d->validIndex(
d->pressedIndex)) {
2321 int length =
d->tabList.at(
d->pressedIndex)->dragOffset;
2327 d->tabList.at(
d->pressedIndex)->startAnimation(
d, duration);
2328 d->dragInProgress =
false;
2329 d->movingTab->setVisible(
false);
2330 d->dragStartPosition =
QPoint();
2334 int oldPressedIndex =
d->pressedIndex;
2335 int i =
d->indexAtPos(
event->position().toPoint()) ==
d->pressedIndex ?
d->pressedIndex : -1;
2336 d->pressedIndex = -1;
2337 QStyleOptionTabBarBase optTabBase;
2338 optTabBase.initFrom(
this);
2339 optTabBase.documentMode =
d->documentMode;
2340 const bool selectOnRelease =
2342 if (selectOnRelease)
2344 if (
d->validIndex(oldPressedIndex))
2353 const QPoint pos =
event->position().toPoint();
2354 const bool isEventInCornerButtons = (!
d->leftB->isHidden() &&
d->leftB->geometry().contains(
pos))
2355 || (!
d->rightB->isHidden() &&
d->rightB->geometry().contains(
pos));
2356 if (!isEventInCornerButtons)
2372 d->setCurrentNextEnabledIndex(
offset);
2377#if QT_CONFIG(wheelevent)
2378void QTabBar::wheelEvent(QWheelEvent *
event)
2382 const bool wheelVertical =
qAbs(
event->angleDelta().y()) >
qAbs(
event->angleDelta().x());
2388 if (tabsVertical == wheelVertical)
2389 delta = wheelVertical ?
event->pixelDelta().y() :
event->pixelDelta().x();
2392 if (delta &&
d->validIndex(
d->lastVisible)) {
2393 const int oldScrollOffset =
d->scrollOffset;
2394 const QRect lastTabRect =
d->tabList.at(
d->lastVisible)->rect;
2395 const QRect scrollRect =
d->normalizedScrollRect(
d->lastVisible);
2396 int scrollRectExtent = scrollRect.
right();
2397 if (!
d->leftB->isVisible())
2398 scrollRectExtent += tabsVertical ?
d->leftB->height() :
d->leftB->width();
2399 if (!
d->rightB->isVisible())
2400 scrollRectExtent += tabsVertical ?
d->rightB->height() :
d->rightB->width();
2402 const int maxScrollOffset =
qMax((tabsVertical ?
2403 lastTabRect.bottom() :
2404 lastTabRect.
right()) - scrollRectExtent, 0);
2405 d->scrollOffset =
qBound(0,
d->scrollOffset - delta, maxScrollOffset);
2406 d->leftB->setEnabled(
d->scrollOffset > -scrollRect.
left());
2407 d->rightB->setEnabled(maxScrollOffset >
d->scrollOffset);
2408 if (oldScrollOffset !=
d->scrollOffset) {
2415 d->accumulatedAngleDelta +=
event->angleDelta();
2416 const int xSteps =
d->accumulatedAngleDelta.x() / QWheelEvent::DefaultDeltasPerStep;
2417 const int ySteps =
d->accumulatedAngleDelta.y() / QWheelEvent::DefaultDeltasPerStep;
2419 if (xSteps > 0 || ySteps > 0) {
2421 d->accumulatedAngleDelta =
QPoint();
2422 }
else if (xSteps < 0 || ySteps < 0) {
2424 d->accumulatedAngleDelta =
QPoint();
2426 const int oldCurrentIndex =
d->currentIndex;
2427 d->setCurrentNextEnabledIndex(
offset);
2428 if (oldCurrentIndex !=
d->currentIndex) {
2433 QWidget::wheelEvent(
event);
2443 q->setCurrentIndex(
index);
2454 switch (
event->type()) {
2456 if (!
d->elideModeSetByUser)
2458 if (!
d->useScrollButtonsSetByUser)
2462 d->textSizes.clear();
2478 if (
event->timerId() ==
d->switchTabTimerId) {
2480 d->switchTabTimerId = 0;
2482 d->switchTabCurrentIndex = -1;
2503 return d->elideMode;
2509 d->elideMode =
mode;
2510 d->elideModeSetByUser =
true;
2511 d->textSizes.clear();
2530 return d_func()->useScrollButtons;
2536 d->useScrollButtonsSetByUser =
true;
2537 if (
d->useScrollButtons == useButtons)
2539 d->useScrollButtons = useButtons;
2560 return d->closeButtonOnTabs;
2566 if (
d->closeButtonOnTabs == closable)
2568 d->closeButtonOnTabs = closable;
2571 for (
auto tab : std::as_const(
d->tabList)) {
2572 if (closeSide ==
LeftSide && tab->leftWidget) {
2573 tab->leftWidget->deleteLater();
2574 tab->leftWidget =
nullptr;
2576 if (closeSide ==
RightSide && tab->rightWidget) {
2577 tab->rightWidget->deleteLater();
2578 tab->rightWidget =
nullptr;
2582 bool newButtons =
false;
2583 for (
int i = 0;
i <
d->tabList.size(); ++
i) {
2640 return d->selectionBehaviorOnRemove;
2646 d->selectionBehaviorOnRemove = behavior;
2662 return d->expanding;
2710 return d_func()->documentMode;
2718 d->updateMacBorderMetrics();
2741 if (
d->autoHide ==
hide)
2766 return d->changeCurrentOnDrag;
2772 d->changeCurrentOnDrag = change;
2774 d->killSwitchTabTimer();
2794 if (index < 0 || index >=
d->tabList.size())
2802 auto &tab = *
d->tabList.at(
index);
2805 tab.leftWidget->hide();
2808 if (tab.rightWidget)
2809 tab.rightWidget->
hide();
2810 tab.rightWidget =
widget;
2824 if (
const auto tab =
d->at(
index)) {
2831#if QT_CONFIG(accessibility)
2839 tab->accessibleName =
name;
2840 QAccessibleEvent
event(
this, QAccessible::NameChanged);
2841 event.setChild(
index);
2842 QAccessible::updateAccessibility(&
event);
2854 return tab->accessibleName;
2859CloseButton::CloseButton(
QWidget *parent)
2866#if QT_CONFIG(tooltip)
2872QSize CloseButton::sizeHint()
const
2900 if (
isEnabled() && underMouse() && !isChecked() && !isDown())
2907 if (
const QTabBar *tb = qobject_cast<const QTabBar *>(parent())) {
2908 int index = tb->currentIndex();
2917#if QT_CONFIG(animation)
2918void QTabBarPrivate::Tab::TabBarAnimation::updateCurrentValue(
const QVariant ¤t)
2925 if (
newState == Stopped)
priv->moveTabFinished(
priv->tabList.indexOf(tab));
2931#include "moc_qtabbar.cpp"
2932#include "qtabbar.moc"
State
This enum describes the state of the animation.
int startDragDistance
the minimum distance required for a drag and drop operation to start.
The QColor class provides colors based on RGB, HSV or CMYK values.
bool isValid() const noexcept
Returns true if the color is valid; otherwise returns false.
\reentrant \inmodule QtGui
QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags=0) const
static QPlatformNativeInterface * platformNativeInterface()
The QHelpEvent class provides an event that is used to request helpful information about a particular...
const QPoint & pos() const
Returns the mouse cursor position when the event was generated, relative to the widget to which the e...
The QHideEvent class provides an event which is sent after a widget is hidden.
The QIcon class provides scalable icons in different modes and states.
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
The QKeyEvent class describes a key event.
static QKeySequence mnemonic(const QString &text)
Returns the shortcut key sequence for the mnemonic in text, or an empty key sequence if no mnemonics ...
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
This is an overloaded function that will start a timer of type timerType and a timeout of interval mi...
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
virtual void timerEvent(QTimerEvent *event)
This event handler can be reimplemented in a subclass to receive timer events for the object.
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
void killTimer(int id)
Kills the timer with timer identifier, id.
The QPaintEvent class contains event parameters for paint events.
The QPainter class performs low-level painting on widgets and other paint devices.
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
void setDevicePixelRatio(qreal scaleFactor)
Sets the device pixel ratio for the pixmap.
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
\inmodule QtCore\reentrant
constexpr void setY(int y) noexcept
Sets the y coordinate of this point to the given y coordinate.
constexpr int y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr QSize size() const noexcept
Returns the size of the rectangle.
constexpr void translate(int dx, int dy) noexcept
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position.
constexpr int width() const noexcept
Returns the width of the rectangle.
constexpr QRect translated(int dx, int dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
QRect united(const QRect &other) const noexcept
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr void setHeight(int h) noexcept
Sets the height of the rectangle to the given height.
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
The QRegion class specifies a clip region for a painter.
The QResizeEvent class contains event parameters for resize events.
iterator find(const T &value)
iterator insert(const T &value)
The QShortcutEvent class provides an event which is generated when the user presses a key combination...
The QShowEvent class provides an event that is sent when a widget is shown.
QPointF position() const
Returns the position of the point in this event, relative to the widget or item that received the eve...
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString left(qsizetype n) const &
qsizetype size() const noexcept
Returns the number of characters in this string.
QString right(qsizetype n) const &
The QStyleOption class stores the parameters used by QStyle functions.
void initFrom(const QWidget *w)
The QStylePainter class is a convenience class for drawing QStyle elements inside a widget.
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w=nullptr) const =0
Returns the size of the element described by the specified option and type, based on the provided con...
@ SH_TabBar_CloseButtonPosition
@ SH_TabBar_AllowWheelScrolling
@ SH_TabBar_ChangeCurrentDelay
@ SH_TabBar_PreferNoArrows
@ SH_TabBar_SelectMouseType
virtual int styleHint(StyleHint stylehint, const QStyleOption *opt=nullptr, const QWidget *widget=nullptr, QStyleHintReturn *returnData=nullptr) const =0
Returns an integer representing the specified style hint for the given widget described by the provid...
virtual QRect subElementRect(SubElement subElement, const QStyleOption *option, const QWidget *widget=nullptr) const =0
Returns the sub-area for the given element as described in the provided style option.
static QRect visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect)
Returns the given logicalRectangle converted to screen coordinates based on the specified direction.
@ PM_TabCloseIndicatorWidth
@ PM_TabBarScrollButtonWidth
@ PM_TabCloseIndicatorHeight
@ PE_IndicatorTabTearRight
@ PE_IndicatorTabTearLeft
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
Returns the value of the given pixel metric.
@ SE_TabBarTearIndicatorLeft
@ SE_TabBarTabRightButton
@ SE_TabBarTearIndicatorRight
@ SE_TabBarScrollRightButton
@ SE_TabBarScrollLeftButton
void initBasicStyleOption(QStyleOptionTab *option, int tabIndex) const
int calculateNewPosition(int from, int to, int index) const
bool validIndex(int index) const
int hoveredTabIndex() const
void killSwitchTabTimer()
int selectNewCurrentIndexFrom(int currentIndex)
void moveTab(int index, int offset)
QRect normalizedScrollRect(int index=-1)
void updateMacBorderMetrics()
Qt::TextElideMode elideMode
int switchTabCurrentIndex
Qt::MouseButtons mouseButtons
void layoutWidgets(int start=0)
void layoutTab(int index)
void setCurrentNextEnabledIndex(int offset)
\reimp
void makeVisible(int index)
void calculateFirstLastVisible(int index, bool visible, bool remove)
void moveTabFinished(int index)
QMovableTabWidget * movingTab
static void initStyleBaseOption(QStyleOptionTabBarBase *optTabBase, QTabBar *tabbar, QSize size)
void slide(int from, int to)
int indexAtPos(const QPoint &p) const
The QTabBar class provides a tab bar, e.g.
Qt::TextElideMode elideMode
how to elide text in the tab bar
void setUsesScrollButtons(bool useButtons)
void setTabsClosable(bool closable)
virtual QSize minimumTabSizeHint(int index) const
Returns the minimum tab size hint for the tab at position index.
void setTabButton(int index, ButtonPosition position, QWidget *widget)
Sets widget on the tab index.
bool movable
This property holds whether the user can move the tabs within the tabbar area.
void paintEvent(QPaintEvent *) override
\reimp
void setSelectionBehaviorOnRemove(SelectionBehavior behavior)
int count
the number of tabs in the tab bar
int currentIndex
the index of the tab bar's visible tab
bool event(QEvent *) override
\reimp
void setShape(Shape shape)
QSize sizeHint() const override
\reimp
QString tabText(int index) const
Returns the text of the tab at position index, or an empty string if index is out of range.
void setTabData(int index, const QVariant &data)
Sets the data of the tab at position index to data.
void mousePressEvent(QMouseEvent *) override
\reimp
bool drawBase
defines whether or not tab bar should draw its base.
virtual void tabRemoved(int index)
This virtual handler is called after a tab was removed from position index.
void setCurrentIndex(int index)
void setTabText(int index, const QString &text)
Sets the text of the tab at position index to text.
void currentChanged(int index)
This signal is emitted when the tab bar's current tab changes.
virtual void initStyleOption(QStyleOptionTab *option, int tabIndex) const
Initialize option with the values from the tab at tabIndex.
bool expanding
When expanding is true QTabBar will expand the tabs to use the empty space.
void removeTab(int index)
Removes the tab at position index.
void tabBarDoubleClicked(int index)
This signal is emitted when the user double clicks on a tab at index.
void setDocumentMode(bool set)
bool usesScrollButtons
Whether or not a tab bar should use buttons to scroll tabs when it has many tabs.
QIcon tabIcon(int index) const
Returns the icon of the tab at position index, or a null icon if index is out of range.
void setIconSize(const QSize &size)
QVariant tabData(int index) const
Returns the data of the tab at position index, or a null variant if index is out of range.
void setAutoHide(bool hide)
void showEvent(QShowEvent *) override
\reimp
void mouseReleaseEvent(QMouseEvent *) override
\reimp
void mouseDoubleClickEvent(QMouseEvent *) override
\reimp
void hideEvent(QHideEvent *) override
\reimp
void resizeEvent(QResizeEvent *) override
\reimp
void setTabVisible(int index, bool visible)
If visible is true, make the tab at position index visible, otherwise make it hidden.
bool isTabEnabled(int index) const
Returns true if the tab at position index is enabled; otherwise returns false.
~QTabBar()
Destroys the tab bar.
void timerEvent(QTimerEvent *event) override
\reimp
QColor tabTextColor(int index) const
Returns the text color of the tab with the given index, or a invalid color if index is out of range.
void mouseMoveEvent(QMouseEvent *) override
\reimp
void setTabIcon(int index, const QIcon &icon)
Sets the icon of the tab at position index to icon.
virtual void tabInserted(int index)
This virtual handler is called after a new tab was added or inserted at position index.
void setTabEnabled(int index, bool enabled)
If enabled is true then the tab at position index is enabled; otherwise the item at position index is...
void tabMoved(int from, int to)
void keyPressEvent(QKeyEvent *) override
\reimp
void setDrawBase(bool drawTheBase)
QSize iconSize
The size for icons in the tab bar.
QRect tabRect(int index) const
Returns the visual rectangle of the tab at position index, or a null rectangle if index is hidden,...
Shape shape
the shape of the tabs in the tab bar
void moveTab(int from, int to)
Moves the item at index position from to index position to.
SelectionBehavior selectionBehaviorOnRemove
What tab should be set as current when removeTab is called if the removed tab is also the current tab...
bool autoHide
If true, the tab bar is automatically hidden when it contains less than 2 tabs.
void setMovable(bool movable)
int insertTab(int index, const QString &text)
Inserts a new tab with text text at position index.
void setTabTextColor(int index, const QColor &color)
Sets the color of the text in the tab with the given index to the specified color.
int tabAt(const QPoint &pos) const
bool changeCurrentOnDrag
If true, then the current tab is automatically changed when dragging over the tabbar.
int addTab(const QString &text)
Adds a new tab with text text.
QTabBar(QWidget *parent=nullptr)
Creates a new tab bar with the given parent.
void setElideMode(Qt::TextElideMode mode)
QWidget * tabButton(int index, ButtonPosition position) const
Returns the widget set a tab index and position or \nullptr if one is not set.
void tabBarClicked(int index)
This signal is emitted when user clicks on a tab at an index.
bool documentMode
Whether or not the tab bar is rendered in a mode suitable for the main window.
void changeEvent(QEvent *) override
\reimp
Shape
This enum type lists the built-in shapes supported by QTabBar.
bool isTabVisible(int index) const
Returns true if the tab at position index is visible; otherwise returns false.
void setExpanding(bool enabled)
virtual void tabLayoutChange()
This virtual handler is called whenever the tab layout changes.
QSize minimumSizeHint() const override
\reimp
virtual QSize tabSizeHint(int index) const
Returns the size hint for the tab at position index.
void setChangeCurrentOnDrag(bool change)
bool tabsClosable
Whether or not a tab bar should place close buttons on each tab.
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
static void showText(const QPoint &pos, const QString &text, QWidget *w=nullptr)
Shows text as a "What's This?" window, at global position pos.
QSet< QString >::iterator it
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
void qGeomCalc(QList< QLayoutStruct > &chain, int start, int count, int pos, int space, int spacer)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qBound(const T &min, const T &val, const T &max)
constexpr const T & qMax(const T &a, const T &b)
constexpr T qAbs(const T &t)
static bool contains(const QJsonArray &haystack, unsigned needle)
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLuint GLintptr offset
GLdouble GLdouble GLdouble GLdouble q
decorationRoleName setToolTip
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static QString computeElidedText(Qt::TextElideMode mode, const QString &text)
#define ANIMATION_DURATION
constexpr bool verticalTabs(QTabBar::Shape shape) noexcept
settings remove("monkey")