Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtabbar.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "private/qlayoutengine_p.h"
5#if QT_CONFIG(itemviews)
7#endif
8#include "qapplication.h"
9#include "qevent.h"
10#include "qpainter.h"
11#include "qstyle.h"
12#include "qstyleoption.h"
13#include "qstylepainter.h"
14#if QT_CONFIG(tabwidget)
15#include "qtabwidget.h"
16#endif
17#if QT_CONFIG(tooltip)
18#include "qtooltip.h"
19#endif
20#if QT_CONFIG(whatsthis)
21#include "qwhatsthis.h"
22#endif
23#include "private/qtextengine_p.h"
24#if QT_CONFIG(accessibility)
25#include "qaccessible.h"
26#endif
27#ifdef Q_OS_MACOS
28#include <qpa/qplatformnativeinterface.h>
29#endif
30
31#include "qdebug.h"
32#include "private/qapplication_p.h"
33#include "private/qtabbar_p.h"
34
36
37using namespace Qt::StringLiterals;
38
39namespace {
40class CloseButton : public QAbstractButton
41{
43
44public:
45 explicit CloseButton(QWidget *parent = nullptr);
46
47 QSize sizeHint() const override;
48 QSize minimumSizeHint() const override
49 { return sizeHint(); }
50 void enterEvent(QEnterEvent *event) override;
51 void leaveEvent(QEvent *event) override;
52 void paintEvent(QPaintEvent *event) override;
53};
54}
55
60
62{
63 m_pixmap = pixmap;
64 update();
65}
66
68{
69 Q_UNUSED(e);
70 QPainter p(this);
71 p.drawPixmap(0, 0, m_pixmap);
72}
73
75{
76#if defined(Q_OS_MACOS)
77 Q_Q(QTabBar);
78 // Extend the unified title and toolbar area to cover the tab bar iff
79 // 1) the tab bar is in document mode
80 // 2) the tab bar is directly below an "unified" area.
81 // The extending itself is done in the Cocoa platform plugin and Mac style,
82 // this function registers geometry and visibility state for the tab bar.
83
84 // Calculate geometry
85 int upper, lower;
86 if (documentMode) {
87 QPoint windowPos = q->mapTo(q->window(), QPoint(0,0));
88 upper = windowPos.y();
89 int tabStripHeight = q->tabSizeHint(0).height();
90 int pixelTweak = -3;
91 lower = upper + tabStripHeight + pixelTweak;
92 } else {
93 upper = 0;
94 lower = 0;
95 }
96
98 if (!nativeInterface)
99 return;
100 quintptr identifier = reinterpret_cast<quintptr>(q);
101
102 // Set geometry
104 nativeInterface->nativeResourceFunctionForIntegration("registerContentBorderArea");
105 if (!function)
106 return; // Not Cocoa platform plugin.
107 typedef void (*RegisterContentBorderAreaFunction)(QWindow *window, quintptr identifier, int upper, int lower);
108 (reinterpret_cast<RegisterContentBorderAreaFunction>(function))(q->window()->windowHandle(), identifier, upper, lower);
109
110 // Set visibility state
111 function = nativeInterface->nativeResourceFunctionForIntegration("setContentBorderAreaEnabled");
112 if (!function)
113 return;
114 typedef void (*SetContentBorderAreaEnabledFunction)(QWindow *window, quintptr identifier, bool enable);
115 (reinterpret_cast<SetContentBorderAreaEnabledFunction>(function))(q->window()->windowHandle(), identifier, q->isVisible());
116#endif
117}
118
125void QTabBarPrivate::initBasicStyleOption(QStyleOptionTab *option, int tabIndex) const
126{
127 Q_Q(const QTabBar);
128 const int totalTabs = tabList.size();
129
130 if (!option || (tabIndex < 0 || tabIndex >= totalTabs))
131 return;
132
133 const QTabBarPrivate::Tab &tab = *tabList.at(tabIndex);
134 option->initFrom(q);
136 option->rect = q->tabRect(tabIndex);
137 const bool isCurrent = tabIndex == currentIndex;
138 option->row = 0;
139 if (tabIndex == pressedIndex)
141 if (isCurrent)
143 if (isCurrent && q->hasFocus())
145 if (!tab.enabled)
146 option->state &= ~QStyle::State_Enabled;
147 if (q->isActiveWindow())
149 if (!dragInProgress && option->rect == hoverRect)
151 option->shape = shape;
152 option->text = tab.text;
153
154 if (tab.textColor.isValid())
155 option->palette.setColor(q->foregroundRole(), tab.textColor);
156 option->icon = tab.icon;
157 option->iconSize = q->iconSize(); // Will get the default value then.
158
159 option->leftButtonSize = tab.leftWidget ? tab.leftWidget->size() : QSize();
160 option->rightButtonSize = tab.rightWidget ? tab.rightWidget->size() : QSize();
161 option->documentMode = documentMode;
162
163 if (tabIndex > 0 && tabIndex - 1 == currentIndex)
164 option->selectedPosition = QStyleOptionTab::PreviousIsSelected;
165 else if (tabIndex + 1 < totalTabs && tabIndex + 1 == currentIndex)
166 option->selectedPosition = QStyleOptionTab::NextIsSelected;
167 else
168 option->selectedPosition = QStyleOptionTab::NotAdjacent;
169
170 const bool paintBeginning = (tabIndex == firstVisible) || (dragInProgress && tabIndex == pressedIndex + 1);
171 const bool paintEnd = (tabIndex == lastVisible) || (dragInProgress && tabIndex == pressedIndex - 1);
172 if (paintBeginning) {
173 if (paintEnd)
174 option->position = QStyleOptionTab::OnlyOneTab;
175 else
176 option->position = QStyleOptionTab::Beginning;
177 } else if (paintEnd) {
178 option->position = QStyleOptionTab::End;
179 } else {
180 option->position = QStyleOptionTab::Middle;
181 }
182
183#if QT_CONFIG(tabwidget)
184 if (const QTabWidget *tw = qobject_cast<const QTabWidget *>(q->parentWidget())) {
185 option->features |= QStyleOptionTab::HasFrame;
186 if (tw->cornerWidget(Qt::TopLeftCorner) || tw->cornerWidget(Qt::BottomLeftCorner))
187 option->cornerWidgets |= QStyleOptionTab::LeftCornerWidget;
188 if (tw->cornerWidget(Qt::TopRightCorner) || tw->cornerWidget(Qt::BottomRightCorner))
189 option->cornerWidgets |= QStyleOptionTab::RightCornerWidget;
190 }
191#endif
192 option->tabIndex = tabIndex;
193}
194
202void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const
203{
204 Q_D(const QTabBar);
205 d->initBasicStyleOption(option, tabIndex);
206
208 option->text = fontMetrics().elidedText(option->text, d->elideMode, textRect.width(),
210}
211
364{
365 Q_Q(QTabBar);
366 leftB = new QToolButton(q);
367 leftB->setObjectName(u"ScrollLeftButton"_s);
368 leftB->setAutoRepeat(true);
371 leftB->hide();
372 rightB = new QToolButton(q);
373 rightB->setObjectName(u"ScrollRightButton"_s);
374 rightB->setAutoRepeat(true);
377 rightB->hide();
378#ifdef QT_KEYPAD_NAVIGATION
379 if (QApplicationPrivate::keypadNavigationEnabled()) {
382 q->setFocusPolicy(Qt::NoFocus);
383 } else
384#endif
385 q->setFocusPolicy(Qt::TabFocus);
386
387#if QT_CONFIG(accessibility)
388 leftB->setAccessibleName(QTabBar::tr("Scroll Left"));
389 rightB->setAccessibleName(QTabBar::tr("Scroll Right"));
390#endif
392 elideMode = Qt::TextElideMode(q->style()->styleHint(QStyle::SH_TabBar_ElideMode, nullptr, q));
393 useScrollButtons = !q->style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, nullptr, q);
394}
395
397{
398 Q_Q(const QTabBar);
399 if (q->tabRect(currentIndex).contains(p))
400 return currentIndex;
401 for (int i = 0; i < tabList.size(); ++i)
402 if (tabList.at(i)->enabled && q->tabRect(i).contains(p))
403 return i;
404 return -1;
405}
406
408{
409 Q_Q(QTabBar);
410 layoutDirty = false;
411 QSize size = q->size();
412 int last, available;
413 int maxExtent;
414 bool vertTabs = verticalTabs(shape);
415 int tabChainIndex = 0;
416 int hiddenTabs = 0;
417
418 Qt::Alignment tabAlignment = Qt::Alignment(q->style()->styleHint(QStyle::SH_TabBar_Alignment, nullptr, q));
419 QList<QLayoutStruct> tabChain(tabList.size() + 2);
420
421 // We put an empty item at the front and back and set its expansive attribute
422 // depending on tabAlignment and expanding.
423 tabChain[tabChainIndex].init();
424 tabChain[tabChainIndex].expansive = (!expanding)
425 && (tabAlignment != Qt::AlignLeft)
426 && (tabAlignment != Qt::AlignJustify);
427 tabChain[tabChainIndex].empty = true;
428 ++tabChainIndex;
429
430 // We now go through our list of tabs and set the minimum size and the size hint
431 // This will allow us to elide text if necessary. Since we don't set
432 // a maximum size, tabs will EXPAND to fill up the empty space.
433 // Since tab widget is rather *ahem* strict about keeping the geometry of the
434 // tab bar to its absolute minimum, this won't bleed through, but will show up
435 // if you use tab bar on its own (a.k.a. not a bug, but a feature).
436 // Update: if expanding is false, we DO set a maximum size to prevent the tabs
437 // being wider than necessary.
438 if (!vertTabs) {
439 int minx = 0;
440 int x = 0;
441 int maxHeight = 0;
442 for (int i = 0; i < tabList.size(); ++i) {
443 const auto tab = tabList.at(i);
444 if (!tab->visible) {
445 ++hiddenTabs;
446 continue;
447 }
448 QSize sz = q->tabSizeHint(i);
449 tab->maxRect = QRect(x, 0, sz.width(), sz.height());
450 x += sz.width();
451 maxHeight = qMax(maxHeight, sz.height());
452 sz = q->minimumTabSizeHint(i);
453 tab->minRect = QRect(minx, 0, sz.width(), sz.height());
454 minx += sz.width();
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;
460
461 if (!expanding)
462 tabChain[tabChainIndex].maximumSize = tabChain[tabChainIndex].sizeHint;
463 ++tabChainIndex;
464 }
465
466 last = minx;
467 available = size.width();
468 maxExtent = maxHeight;
469 } else {
470 int miny = 0;
471 int y = 0;
472 int maxWidth = 0;
473 for (int i = 0; i < tabList.size(); ++i) {
474 auto tab = tabList.at(i);
475 if (!tab->visible) {
476 ++hiddenTabs;
477 continue;
478 }
479 QSize sz = q->tabSizeHint(i);
480 tab->maxRect = QRect(0, y, sz.width(), sz.height());
481 y += sz.height();
482 maxWidth = qMax(maxWidth, sz.width());
483 sz = q->minimumTabSizeHint(i);
484 tab->minRect = QRect(0, miny, sz.width(), sz.height());
485 miny += sz.height();
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;
491
492 if (!expanding)
493 tabChain[tabChainIndex].maximumSize = tabChain[tabChainIndex].sizeHint;
494 ++tabChainIndex;
495 }
496
497 last = miny;
498 available = size.height();
499 maxExtent = maxWidth;
500 }
501
502 // Mirror our front item.
503 tabChain[tabChainIndex].init();
504 tabChain[tabChainIndex].expansive = (!expanding)
505 && (tabAlignment != Qt::AlignRight)
506 && (tabAlignment != Qt::AlignJustify);
507 tabChain[tabChainIndex].empty = true;
508 Q_ASSERT(tabChainIndex == tabChain.size() - 1 - hiddenTabs); // add an assert just to make sure.
509
510 // Do the calculation
511 qGeomCalc(tabChain, 0, tabChain.size(), 0, qMax(available, last), 0);
512
513 // Use the results
514 hiddenTabs = 0;
515 for (int i = 0; i < tabList.size(); ++i) {
516 auto tab = tabList.at(i);
517 if (!tab->visible) {
518 tab->rect = QRect();
519 ++hiddenTabs;
520 continue;
521 }
522 const QLayoutStruct &lstruct = tabChain.at(i + 1 - hiddenTabs);
523 if (!vertTabs)
524 tab->rect.setRect(lstruct.pos, 0, lstruct.size, maxExtent);
525 else
526 tab->rect.setRect(0, lstruct.pos, maxExtent, lstruct.size);
527 }
528
529 if (useScrollButtons && tabList.size() && last > available) {
531
532 Q_Q(QTabBar);
534 opt.initFrom(q);
535 QRect scrollButtonLeftRect = q->style()->subElementRect(QStyle::SE_TabBarScrollLeftButton, &opt, q);
536 QRect scrollButtonRightRect = q->style()->subElementRect(QStyle::SE_TabBarScrollRightButton, &opt, q);
537 int scrollButtonWidth = q->style()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, &opt, q);
538
539 // Normally SE_TabBarScrollLeftButton should have the same width as PM_TabBarScrollButtonWidth.
540 // But if that is not the case, we set the actual button width to PM_TabBarScrollButtonWidth, and
541 // use the extra space from SE_TabBarScrollLeftButton as margins towards the tabs.
542 if (vertTabs) {
543 scrollButtonLeftRect.setHeight(scrollButtonWidth);
544 scrollButtonRightRect.setY(scrollButtonRightRect.bottom() + 1 - scrollButtonWidth);
545 scrollButtonRightRect.setHeight(scrollButtonWidth);
548 } else if (q->layoutDirection() == Qt::RightToLeft) {
549 scrollButtonRightRect.setWidth(scrollButtonWidth);
550 scrollButtonLeftRect.setX(scrollButtonLeftRect.right() + 1 - scrollButtonWidth);
551 scrollButtonLeftRect.setWidth(scrollButtonWidth);
554 } else {
555 scrollButtonLeftRect.setWidth(scrollButtonWidth);
556 scrollButtonRightRect.setX(scrollButtonRightRect.right() + 1 - scrollButtonWidth);
557 scrollButtonRightRect.setWidth(scrollButtonWidth);
560 }
561
562 leftB->setGeometry(scrollButtonLeftRect);
563 leftB->setEnabled(false);
564 leftB->show();
565
566 rightB->setGeometry(scrollButtonRightRect);
567 rightB->setEnabled(last + scrollRect.left() > scrollRect.x() + scrollRect.width());
568 rightB->show();
569 } else {
570 rightB->hide();
571 leftB->hide();
572 }
573
575 q->tabLayoutChange();
576}
577
579{
580 // "Normalized scroll rect" means return the free space on the tab bar
581 // that doesn't overlap with scroll buttons or tear indicators, and
582 // always return the rect as horizontal Qt::LeftToRight, even if the
583 // tab bar itself is in a different orientation.
584
585 Q_Q(QTabBar);
586 // If scrollbuttons are not visible, then there's no tear either, and
587 // the entire widget is the scroll rect.
588 if (leftB->isHidden())
589 return verticalTabs(shape) ? q->rect().transposed() : q->rect();
590
591 QStyleOptionTab opt;
592 q->initStyleOption(&opt, currentIndex);
593 opt.rect = q->rect();
594
595 QRect scrollButtonLeftRect = q->style()->subElementRect(QStyle::SE_TabBarScrollLeftButton, &opt, q);
596 QRect scrollButtonRightRect = q->style()->subElementRect(QStyle::SE_TabBarScrollRightButton, &opt, q);
597 QRect tearLeftRect = q->style()->subElementRect(QStyle::SE_TabBarTearIndicatorLeft, &opt, q);
598 QRect tearRightRect = q->style()->subElementRect(QStyle::SE_TabBarTearIndicatorRight, &opt, q);
599
600 if (verticalTabs(shape)) {
601 int topEdge, bottomEdge;
602 bool leftButtonIsOnTop = scrollButtonLeftRect.y() < q->height() / 2;
603 bool rightButtonIsOnTop = scrollButtonRightRect.y() < q->height() / 2;
604
605 if (leftButtonIsOnTop && rightButtonIsOnTop) {
606 topEdge = scrollButtonRightRect.bottom() + 1;
607 bottomEdge = q->height();
608 } else if (!leftButtonIsOnTop && !rightButtonIsOnTop) {
609 topEdge = 0;
610 bottomEdge = scrollButtonLeftRect.top();
611 } else {
612 topEdge = scrollButtonLeftRect.bottom() + 1;
613 bottomEdge = scrollButtonRightRect.top();
614 }
615
616 bool tearTopVisible = index != 0 && topEdge != -scrollOffset;
617 bool tearBottomVisible = index != tabList.size() - 1 && bottomEdge != tabList.constLast()->rect.bottom() + 1 - scrollOffset;
618 if (tearTopVisible && !tearLeftRect.isNull())
619 topEdge = tearLeftRect.bottom() + 1;
620 if (tearBottomVisible && !tearRightRect.isNull())
621 bottomEdge = tearRightRect.top();
622
623 return QRect(topEdge, 0, bottomEdge - topEdge, q->height());
624 } else {
625 if (q->layoutDirection() == Qt::RightToLeft) {
626 scrollButtonLeftRect = QStyle::visualRect(Qt::RightToLeft, q->rect(), scrollButtonLeftRect);
627 scrollButtonRightRect = QStyle::visualRect(Qt::RightToLeft, q->rect(), scrollButtonRightRect);
628 tearLeftRect = QStyle::visualRect(Qt::RightToLeft, q->rect(), tearLeftRect);
629 tearRightRect = QStyle::visualRect(Qt::RightToLeft, q->rect(), tearRightRect);
630 }
631
632 int leftEdge, rightEdge;
633 bool leftButtonIsOnLeftSide = scrollButtonLeftRect.x() < q->width() / 2;
634 bool rightButtonIsOnLeftSide = scrollButtonRightRect.x() < q->width() / 2;
635
636 if (leftButtonIsOnLeftSide && rightButtonIsOnLeftSide) {
637 leftEdge = scrollButtonRightRect.right() + 1;
638 rightEdge = q->width();
639 } else if (!leftButtonIsOnLeftSide && !rightButtonIsOnLeftSide) {
640 leftEdge = 0;
641 rightEdge = scrollButtonLeftRect.left();
642 } else {
643 leftEdge = scrollButtonLeftRect.right() + 1;
644 rightEdge = scrollButtonRightRect.left();
645 }
646
647 bool tearLeftVisible = index != 0 && leftEdge != -scrollOffset;
648 bool tearRightVisible = index != tabList.size() - 1 && rightEdge != tabList.constLast()->rect.right() + 1 - scrollOffset;
649 if (tearLeftVisible && !tearLeftRect.isNull())
650 leftEdge = tearLeftRect.right() + 1;
651 if (tearRightVisible && !tearRightRect.isNull())
652 rightEdge = tearRightRect.left();
653
654 return QRect(leftEdge, 0, rightEdge - leftEdge, q->height());
655 }
656}
657
659{
660 if (dragInProgress)
661 return currentIndex;
662 if (hoverIndex >= 0)
663 return hoverIndex;
664 return -1;
665}
666
668{
669 Q_Q(QTabBar);
670 if (!validIndex(index))
671 return;
672
673 const QRect tabRect = tabList.at(index)->rect;
674 const int oldScrollOffset = scrollOffset;
675 const bool horiz = !verticalTabs(shape);
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();
681 const QRect entireScrollRect = normalizedScrollRect(0); // ignore tears
682 const int scrolledTabBarStart = qMax(1, scrollRect.left() + scrollOffset);
683 const int scrolledTabBarEnd = qMin(lastTabEnd - 1, scrollRect.right() + scrollOffset);
684
685 if (available >= lastTabEnd) {
686 // the entire tabbar fits, reset scroll
687 scrollOffset = 0;
688 } else if (tabStart < scrolledTabBarStart) {
689 // Tab is outside on the left, so scroll left.
690 scrollOffset = tabStart - scrollRect.left();
691 } else if (tabEnd > scrolledTabBarEnd) {
692 // Tab is outside on the right, so scroll right.
693 scrollOffset = qMax(0, tabEnd - scrollRect.right());
694 } else if (scrollOffset + entireScrollRect.width() > lastTabEnd + 1) {
695 // fill any free space on the right without overshooting
696 scrollOffset = qMax(0, lastTabEnd - entireScrollRect.width() + 1);
697 }
698
700 rightB->setEnabled(scrollOffset < lastTabEnd - scrollRect.right());
701
702 if (oldScrollOffset != scrollOffset) {
703 q->update();
705 }
706}
707
709{
710 Q_Q(QTabBar);
711 if (switchTabTimerId) {
712 q->killTimer(switchTabTimerId);
714 }
716}
717
719{
720 Q_Q(QTabBar);
721 Q_ASSERT(index >= 0);
722
723 const Tab *tab = tabList.at(index);
724 bool vertical = verticalTabs(shape);
725 if (!(tab->leftWidget || tab->rightWidget))
726 return;
727
728 QStyleOptionTab opt;
729 q->initStyleOption(&opt, index);
730 if (tab->leftWidget) {
731 QRect rect = q->style()->subElementRect(QStyle::SE_TabBarTabLeftButton, &opt, q);
732 QPoint p = rect.topLeft();
733 if ((index == pressedIndex) || paintWithOffsets) {
734 if (vertical)
735 p.setY(p.y() + tab->dragOffset);
736 else
737 p.setX(p.x() + tab->dragOffset);
738 }
739 tab->leftWidget->move(p);
740 }
741 if (tab->rightWidget) {
742 QRect rect = q->style()->subElementRect(QStyle::SE_TabBarTabRightButton, &opt, q);
743 QPoint p = rect.topLeft();
744 if ((index == pressedIndex) || paintWithOffsets) {
745 if (vertical)
746 p.setY(p.y() + tab->dragOffset);
747 else
748 p.setX(p.x() + tab->dragOffset);
749 }
750 tab->rightWidget->move(p);
751 }
752}
753
755{
756 Q_Q(QTabBar);
757 for (int i = start; i < q->count(); ++i) {
758 layoutTab(i);
759 }
760}
761
763{
764 Q_Q(QTabBar);
765
766 if (autoHide)
767 q->setVisible(q->count() > 1);
768}
769
771{
772 Q_Q(QTabBar);
773 QObject *object = q->sender();
774 int tabToClose = -1;
776 for (int i = 0; i < tabList.size(); ++i) {
777 if (closeSide == QTabBar::LeftSide) {
778 if (tabList.at(i)->leftWidget == object) {
779 tabToClose = i;
780 break;
781 }
782 } else {
783 if (tabList.at(i)->rightWidget == object) {
784 tabToClose = i;
785 break;
786 }
787 }
788 }
789 if (tabToClose != -1)
790 emit q->tabCloseRequested(tabToClose);
791}
792
794{
795 Q_Q(QTabBar);
796 const QObject *sender = q->sender();
797 const bool horizontal = !verticalTabs(shape);
799
800 int i = -1;
801
802 if (sender == leftB) {
803 for (i = tabList.size() - 1; i >= 0; --i) {
804 int start = horizontal ? tabList.at(i)->rect.left() : tabList.at(i)->rect.top();
805 if (start < scrollRect.left()) {
806 makeVisible(i);
807 return;
808 }
809 }
810 } else if (sender == rightB) {
811 for (i = 0; i < tabList.size(); ++i) {
812 const auto tabRect = tabList.at(i)->rect;
813 int start = horizontal ? tabRect.left() : tabRect.top();
814 int end = horizontal ? tabRect.right() : tabRect.bottom();
815 if (end > scrollRect.right() && start > scrollOffset) {
816 makeVisible(i);
817 return;
818 }
819 }
820 }
821}
822
824{
825 Q_Q(QTabBar);
826
827 // be safe in case a subclass is also handling move with the tabs
828 if (pressedIndex != -1
829 && movable
833 pressedIndex = -1;
834 }
835
836 if (!q->isVisible()) {
837 layoutDirty = true;
838 } else {
839 layoutTabs();
841 q->update();
842 q->updateGeometry();
843 }
844}
845
850 :QWidget(*new QTabBarPrivate, parent, { })
851{
852 Q_D(QTabBar);
853 d->init();
854}
855
856
863
873{
874 Q_D(const QTabBar);
875 return d->shape;
876}
877
879{
880 Q_D(QTabBar);
881 if (d->shape == shape)
882 return;
883 d->shape = shape;
884 d->refresh();
885}
886
897void QTabBar::setDrawBase(bool drawBase)
898{
899 Q_D(QTabBar);
900 if (d->drawBase == drawBase)
901 return;
902 d->drawBase = drawBase;
903 update();
904}
905
907{
908 Q_D(const QTabBar);
909 return d->drawBase;
910}
911
917{
918 return insertTab(-1, text);
919}
920
928{
929 return insertTab(-1, icon, text);
930}
931
938{
939 return insertTab(index, QIcon(), text);
940}
941
955{
956 Q_D(QTabBar);
957 if (!d->validIndex(index)) {
958 index = d->tabList.size();
959 d->tabList.append(new QTabBarPrivate::Tab(icon, text));
960 } else {
961 d->tabList.insert(index, new QTabBarPrivate::Tab(icon, text));
962 }
963#ifndef QT_NO_SHORTCUT
964 d->tabList.at(index)->shortcutId = grabShortcut(QKeySequence::mnemonic(text));
965#endif
966 d->firstVisible = qMax(qMin(index, d->firstVisible), 0);
967 d->refresh();
968 if (d->tabList.size() == 1)
970 else if (index <= d->currentIndex)
971 ++d->currentIndex;
972
973 if (index <= d->lastVisible)
974 ++d->lastVisible;
975 else
976 d->lastVisible = index;
977
978 if (d->closeButtonOnTabs) {
979 QStyleOptionTab opt;
982 QAbstractButton *closeButton = new CloseButton(this);
983 QObjectPrivate::connect(closeButton, &CloseButton::clicked,
985 setTabButton(index, closeSide, closeButton);
986 }
987
988 for (const auto tab : std::as_const(d->tabList)) {
989 if (tab->lastTab >= index)
990 ++tab->lastTab;
991 }
992
993 if (tabAt(d->mousePosition) == index) {
994 d->hoverIndex = index;
995 d->hoverRect = tabRect(index);
996 }
997
999 d->autoHideTabs();
1000 return index;
1001}
1002
1003
1010{
1011 Q_D(QTabBar);
1012 if (d->validIndex(index)) {
1013 auto removedTab = d->tabList.at(index);
1014 if (d->dragInProgress)
1015 d->moveTabFinished(d->pressedIndex);
1016
1017#ifndef QT_NO_SHORTCUT
1018 releaseShortcut(d->tabList.at(index)->shortcutId);
1019#endif
1020 if (removedTab->leftWidget) {
1021 removedTab->leftWidget->hide();
1022 removedTab->leftWidget->deleteLater();
1023 removedTab->leftWidget = nullptr;
1024 }
1025 if (removedTab->rightWidget) {
1026 removedTab->rightWidget->hide();
1027 removedTab->rightWidget->deleteLater();
1028 removedTab->rightWidget = nullptr;
1029 }
1030
1031 int newIndex = removedTab->lastTab;
1032 d->tabList.removeAt(index);
1033 delete removedTab;
1034 for (auto tab : std::as_const(d->tabList)) {
1035 if (tab->lastTab == index)
1036 tab->lastTab = -1;
1037 if (tab->lastTab > index)
1038 --tab->lastTab;
1039 }
1040
1041 d->calculateFirstLastVisible(index, false, true);
1042
1043 if (index == d->currentIndex) {
1044 // The current tab is going away, in order to make sure
1045 // we emit that "current has changed", we need to reset this
1046 // around.
1047 d->currentIndex = -1;
1048 if (d->tabList.size() > 0) {
1049 switch(d->selectionBehaviorOnRemove) {
1050 case SelectPreviousTab:
1051 if (newIndex > index)
1052 newIndex--;
1053 if (d->validIndex(newIndex) && d->tabList.at(newIndex)->visible)
1054 break;
1055 Q_FALLTHROUGH();
1056 case SelectRightTab:
1057 newIndex = qBound(d->firstVisible, index, d->lastVisible);
1058 break;
1059 case SelectLeftTab:
1060 newIndex = qBound(d->firstVisible, index-1, d->lastVisible);
1061 break;
1062 default:
1063 break;
1064 }
1065
1066 if (d->validIndex(newIndex)) {
1067 // don't loose newIndex's old through setCurrentIndex
1068 int bump = d->tabList.at(newIndex)->lastTab;
1069 setCurrentIndex(newIndex);
1070 d->tabList.at(newIndex)->lastTab = bump;
1071 } else {
1072 // we had a valid current index, but there are no visible tabs left
1073 emit currentChanged(-1);
1074 }
1075 } else {
1076 emit currentChanged(-1);
1077 }
1078 } else if (index < d->currentIndex) {
1079 setCurrentIndex(d->currentIndex - 1);
1080 }
1081 d->refresh();
1082 d->autoHideTabs();
1083 if (d->hoverRect.isValid()) {
1084 update(d->hoverRect);
1085 d->hoverIndex = tabAt(d->mousePosition);
1086 if (d->validIndex(d->hoverIndex)) {
1087 d->hoverRect = tabRect(d->hoverIndex);
1088 update(d->hoverRect);
1089 } else {
1090 d->hoverRect = QRect();
1091 }
1092 }
1094 }
1095}
1096
1097
1103{
1104 Q_D(const QTabBar);
1105 if (const QTabBarPrivate::Tab *tab = d->at(index))
1106 return tab->enabled;
1107 return false;
1108}
1109
1115{
1116 Q_D(QTabBar);
1117 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1118 tab->enabled = enabled;
1119#ifndef QT_NO_SHORTCUT
1120 setShortcutEnabled(tab->shortcutId, enabled);
1121#endif
1122 update();
1123 if (!enabled && index == d->currentIndex)
1124 setCurrentIndex(d->selectNewCurrentIndexFrom(index+1));
1125 else if (enabled && !isTabVisible(d->currentIndex))
1126 setCurrentIndex(d->selectNewCurrentIndexFrom(index));
1127 }
1128}
1129
1130
1137{
1138 Q_D(const QTabBar);
1139 if (d->validIndex(index))
1140 return d->tabList.at(index)->visible;
1141 return false;
1142}
1143
1149void QTabBar::setTabVisible(int index, bool visible)
1150{
1151 Q_D(QTabBar);
1152 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1153 d->layoutDirty = (visible != tab->visible);
1154 if (!d->layoutDirty)
1155 return;
1156 tab->visible = visible;
1157 if (tab->leftWidget)
1158 tab->leftWidget->setVisible(visible);
1159 if (tab->rightWidget)
1160 tab->rightWidget->setVisible(visible);
1161#ifndef QT_NO_SHORTCUT
1162 setShortcutEnabled(tab->shortcutId, visible);
1163#endif
1164 d->calculateFirstLastVisible(index, visible, false);
1165 if (!visible && index == d->currentIndex) {
1166 const int newindex = d->selectNewCurrentIndexFrom(index+1);
1167 setCurrentIndex(newindex);
1168 }
1169 update();
1170 }
1171}
1172
1173
1179{
1180 Q_D(const QTabBar);
1181 if (const QTabBarPrivate::Tab *tab = d->at(index))
1182 return tab->text;
1183 return QString();
1184}
1185
1190{
1191 Q_D(QTabBar);
1192 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1193 d->textSizes.remove(tab->text);
1194 tab->text = text;
1195#ifndef QT_NO_SHORTCUT
1196 releaseShortcut(tab->shortcutId);
1197 tab->shortcutId = grabShortcut(QKeySequence::mnemonic(text));
1198 setShortcutEnabled(tab->shortcutId, tab->enabled);
1199#endif
1200 d->refresh();
1201 }
1202}
1203
1211{
1212 Q_D(const QTabBar);
1213 if (const QTabBarPrivate::Tab *tab = d->at(index))
1214 return tab->textColor;
1215 return QColor();
1216}
1217
1226{
1227 Q_D(QTabBar);
1228 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1229 tab->textColor = color;
1231 }
1232}
1233
1239{
1240 Q_D(const QTabBar);
1241 if (const QTabBarPrivate::Tab *tab = d->at(index))
1242 return tab->icon;
1243 return QIcon();
1244}
1245
1250{
1251 Q_D(QTabBar);
1252 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1253 bool simpleIconChange = (!icon.isNull() && !tab->icon.isNull());
1254 tab->icon = icon;
1255 if (simpleIconChange)
1257 else
1258 d->refresh();
1259 }
1260}
1261
1262#if QT_CONFIG(tooltip)
1266void QTabBar::setTabToolTip(int index, const QString & tip)
1267{
1268 Q_D(QTabBar);
1269 if (QTabBarPrivate::Tab *tab = d->at(index))
1270 tab->toolTip = tip;
1271}
1272
1277QString QTabBar::tabToolTip(int index) const
1278{
1279 Q_D(const QTabBar);
1280 if (const QTabBarPrivate::Tab *tab = d->at(index))
1281 return tab->toolTip;
1282 return QString();
1283}
1284#endif // QT_CONFIG(tooltip)
1285
1286#if QT_CONFIG(whatsthis)
1293void QTabBar::setTabWhatsThis(int index, const QString &text)
1294{
1295 Q_D(QTabBar);
1296 if (QTabBarPrivate::Tab *tab = d->at(index))
1297 tab->whatsThis = text;
1298}
1299
1306QString QTabBar::tabWhatsThis(int index) const
1307{
1308 Q_D(const QTabBar);
1309 if (const QTabBarPrivate::Tab *tab = d->at(index))
1310 return tab->whatsThis;
1311 return QString();
1312}
1313
1314#endif // QT_CONFIG(whatsthis)
1315
1320{
1321 Q_D(QTabBar);
1322 if (QTabBarPrivate::Tab *tab = d->at(index))
1323 tab->data = data;
1324}
1325
1331{
1332 Q_D(const QTabBar);
1333 if (const QTabBarPrivate::Tab *tab = d->at(index))
1334 return tab->data;
1335 return QVariant();
1336}
1337
1343{
1344 Q_D(const QTabBar);
1345 if (const QTabBarPrivate::Tab *tab = d->at(index)) {
1346 if (d->layoutDirty)
1347 const_cast<QTabBarPrivate*>(d)->layoutTabs();
1348 if (!tab->visible)
1349 return QRect();
1350 QRect r = tab->rect;
1351 if (verticalTabs(d->shape))
1352 r.translate(0, -d->scrollOffset);
1353 else
1354 r.translate(-d->scrollOffset, 0);
1355 if (!verticalTabs(d->shape))
1357 return r;
1358 }
1359 return QRect();
1360}
1361
1369{
1370 Q_D(const QTabBar);
1371 if (d->validIndex(d->currentIndex)
1372 && tabRect(d->currentIndex).contains(position)) {
1373 return d->currentIndex;
1374 }
1375 const int max = d->tabList.size();
1376 for (int i = 0; i < max; ++i) {
1377 if (tabRect(i).contains(position)) {
1378 return i;
1379 }
1380 }
1381 return -1;
1382}
1383
1392{
1393 Q_D(const QTabBar);
1394 if (d->validIndex(d->currentIndex))
1395 return d->currentIndex;
1396 return -1;
1397}
1398
1399
1401{
1402 Q_D(QTabBar);
1403 if (d->dragInProgress && d->pressedIndex != -1)
1404 return;
1405 if (d->currentIndex == index)
1406 return;
1407
1408 int oldIndex = d->currentIndex;
1409 if (auto tab = d->at(index)) {
1410 d->currentIndex = index;
1411 // If the size hint depends on whether the tab is selected (for instance a style
1412 // sheet rule that sets a bold font on the 'selected' tab) then we need to
1413 // re-layout the entire tab bar. To minimize the cost, do that only if the
1414 // size hint changes for the tab that becomes the current tab (the old current tab
1415 // will most certainly do the same). QTBUG-6905
1416 if (tabRect(index).size() != tabSizeHint(index))
1417 d->layoutTabs();
1418 update();
1419 if (!isVisible())
1420 d->layoutDirty = true;
1421 else
1422 d->makeVisible(index);
1423 if (d->validIndex(oldIndex)) {
1424 tab->lastTab = oldIndex;
1425 d->layoutTab(oldIndex);
1426 }
1427 d->layoutTab(index);
1428#if QT_CONFIG(accessibility)
1429 if (QAccessible::isActive()) {
1430 if (hasFocus()) {
1431 QAccessibleEvent focusEvent(this, QAccessible::Focus);
1432 focusEvent.setChild(index);
1433 QAccessible::updateAccessibility(&focusEvent);
1434 }
1435 QAccessibleEvent selectionEvent(this, QAccessible::Selection);
1436 selectionEvent.setChild(index);
1437 QAccessible::updateAccessibility(&selectionEvent);
1438 }
1439#endif
1441 }
1442}
1443
1455{
1456 Q_D(const QTabBar);
1457 if (d->iconSize.isValid())
1458 return d->iconSize;
1459 int iconExtent = style()->pixelMetric(QStyle::PM_TabBarIconSize, nullptr, this);
1460 return QSize(iconExtent, iconExtent);
1461
1462}
1463
1465{
1466 Q_D(QTabBar);
1467 d->iconSize = size;
1468 d->layoutDirty = true;
1469 update();
1471}
1472
1479{
1480 Q_D(const QTabBar);
1481 return d->tabList.size();
1482}
1483
1484
1488{
1489 Q_D(const QTabBar);
1490 if (d->layoutDirty)
1491 const_cast<QTabBarPrivate*>(d)->layoutTabs();
1492 QRect r;
1493 for (const auto tab : d->tabList) {
1494 if (tab->visible)
1495 r = r.united(tab->maxRect);
1496 }
1497 return r.size();
1498}
1499
1503{
1504 Q_D(const QTabBar);
1505 if (d->layoutDirty)
1506 const_cast<QTabBarPrivate*>(d)->layoutTabs();
1507 if (!d->useScrollButtons) {
1508 QRect r;
1509 for (const auto tab : d->tabList) {
1510 if (tab->visible)
1511 r = r.united(tab->minRect);
1512 }
1513 return r.size();
1514 }
1515 if (verticalTabs(d->shape))
1516 return QSize(sizeHint().width(), d->rightB->sizeHint().height() * 2 + 75);
1517 else
1518 return QSize(d->rightB->sizeHint().width() * 2 + 75, sizeHint().height());
1519}
1520
1521// Compute the most-elided possible text, for minimumSizeHint
1523{
1524 if (text.size() <= 3)
1525 return text;
1526
1527 static const auto Ellipses = "..."_L1;
1528 QString ret;
1529 switch (mode) {
1530 case Qt::ElideRight:
1531 ret = QStringView{text}.left(2) + Ellipses;
1532 break;
1533 case Qt::ElideMiddle:
1534 ret = QStringView{text}.left(1) + Ellipses + QStringView{text}.right(1);
1535 break;
1536 case Qt::ElideLeft:
1537 ret = Ellipses + QStringView{text}.right(2);
1538 break;
1539 case Qt::ElideNone:
1540 ret = text;
1541 break;
1542 }
1543 return ret;
1544}
1545
1552{
1553 Q_D(const QTabBar);
1554 QTabBarPrivate::Tab *tab = d->tabList.at(index);
1555 QString oldText = tab->text;
1556 tab->text = computeElidedText(d->elideMode, oldText);
1558 tab->text = oldText;
1559 return size;
1560}
1561
1566{
1567 //Note: this must match with the computations in QCommonStylePrivate::tabLayout
1568 Q_D(const QTabBar);
1569 if (const QTabBarPrivate::Tab *tab = d->at(index)) {
1570 QStyleOptionTab opt;
1571 d->initBasicStyleOption(&opt, index);
1572 opt.text = tab->text;
1573 QSize iconSize = tab->icon.isNull() ? QSize(0, 0) : opt.iconSize;
1574 int hframe = style()->pixelMetric(QStyle::PM_TabBarTabHSpace, &opt, this);
1575 int vframe = style()->pixelMetric(QStyle::PM_TabBarTabVSpace, &opt, this);
1576 const QFontMetrics fm = fontMetrics();
1577
1578 int maxWidgetHeight = qMax(opt.leftButtonSize.height(), opt.rightButtonSize.height());
1579 int maxWidgetWidth = qMax(opt.leftButtonSize.width(), opt.rightButtonSize.width());
1580
1581 int widgetWidth = 0;
1582 int widgetHeight = 0;
1583 int padding = 0;
1584 if (!opt.leftButtonSize.isEmpty()) {
1585 padding += 4;
1586 widgetWidth += opt.leftButtonSize.width();
1587 widgetHeight += opt.leftButtonSize.height();
1588 }
1589 if (!opt.rightButtonSize.isEmpty()) {
1590 padding += 4;
1591 widgetWidth += opt.rightButtonSize.width();
1592 widgetHeight += opt.rightButtonSize.height();
1593 }
1594 if (!opt.icon.isNull())
1595 padding += 4;
1596
1597 QHash<QString, QSize>::iterator it = d->textSizes.find(tab->text);
1598 if (it == d->textSizes.end())
1599 it = d->textSizes.insert(tab->text, fm.size(Qt::TextShowMnemonic, tab->text));
1600 const int textWidth = it.value().width();
1601 QSize csz;
1602 if (verticalTabs(d->shape)) {
1603 csz = QSize( qMax(maxWidgetWidth, qMax(fm.height(), iconSize.height())) + vframe,
1604 textWidth + iconSize.width() + hframe + widgetHeight + padding);
1605 } else {
1606 csz = QSize(textWidth + iconSize.width() + hframe + widgetWidth + padding,
1607 qMax(maxWidgetHeight, qMax(fm.height(), iconSize.height())) + vframe);
1608 }
1609
1610 QSize retSize = style()->sizeFromContents(QStyle::CT_TabBarTab, &opt, csz, this);
1611 return retSize;
1612 }
1613 return QSize();
1614}
1615
1623{
1624 Q_UNUSED(index);
1625}
1626
1634{
1635 Q_UNUSED(index);
1636}
1637
1644{
1645}
1646
1647
1651{
1652 Q_D(QTabBar);
1653 if (d->layoutDirty)
1654 d->refresh();
1655 if (!d->validIndex(d->currentIndex))
1656 setCurrentIndex(0);
1657 else
1658 d->makeVisible(d->currentIndex);
1659 d->updateMacBorderMetrics();
1660}
1661
1665{
1666 Q_D(QTabBar);
1667 d->updateMacBorderMetrics();
1668}
1669
1673{
1674 Q_D(QTabBar);
1675 switch (event->type()) {
1676 case QEvent::HoverMove:
1677 case QEvent::HoverEnter: {
1678 QHoverEvent *he = static_cast<QHoverEvent *>(event);
1679 d->mousePosition = he->position().toPoint();
1680 if (!d->hoverRect.contains(d->mousePosition)) {
1681 if (d->hoverRect.isValid())
1682 update(d->hoverRect);
1683 d->hoverIndex = tabAt(d->mousePosition);
1684 if (d->validIndex(d->hoverIndex)) {
1685 d->hoverRect = tabRect(d->hoverIndex);
1686 update(d->hoverRect);
1687 } else {
1688 d->hoverRect = QRect();
1689 }
1690 }
1691 return true;
1692 }
1693 case QEvent::HoverLeave: {
1694 d->mousePosition = {-1, -1};
1695 if (d->hoverRect.isValid())
1696 update(d->hoverRect);
1697 d->hoverIndex = -1;
1698 d->hoverRect = QRect();
1699#if QT_CONFIG(wheelevent)
1700 d->accumulatedAngleDelta = QPoint();
1701#endif
1702 return true;
1703 }
1704#if QT_CONFIG(tooltip)
1705 case QEvent::ToolTip:
1706 if (const QTabBarPrivate::Tab *tab = d->at(tabAt(static_cast<QHelpEvent*>(event)->pos()))) {
1707 if (!tab->toolTip.isEmpty()) {
1708 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), tab->toolTip, this);
1709 return true;
1710 }
1711 }
1712 break;
1713#endif // QT_CONFIG(tooltip)
1714#if QT_CONFIG(whatsthis)
1715 case QEvent::QEvent::QueryWhatsThis: {
1716 const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()));
1717 if (!tab || tab->whatsThis.isEmpty())
1718 event->ignore();
1719 return true;
1720 }
1721 case QEvent::WhatsThis:
1722 if (const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()))) {
1723 if (!tab->whatsThis.isEmpty()) {
1724 QWhatsThis::showText(static_cast<QHelpEvent*>(event)->globalPos(),
1725 tab->whatsThis, this);
1726 return true;
1727 }
1728 }
1729 break;
1730#endif // QT_CONFIG(whatsthis)
1731#ifndef QT_NO_SHORTCUT
1732
1733 case QEvent::Shortcut: {
1734 QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
1735 for (int i = 0; i < d->tabList.size(); ++i) {
1736 const QTabBarPrivate::Tab *tab = d->tabList.at(i);
1737 if (tab->shortcutId == se->shortcutId()) {
1739 return true;
1740 }
1741 }
1742 }
1743 break;
1744#endif
1745 case QEvent::Move:
1746 d->updateMacBorderMetrics();
1747 break;
1748#if QT_CONFIG(draganddrop)
1749
1750 case QEvent::DragEnter:
1751 if (d->changeCurrentOnDrag)
1752 event->accept();
1753 break;
1754 case QEvent::DragMove:
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)
1760 killTimer(d->switchTabTimerId);
1761 d->switchTabTimerId = startTimer(style()->styleHint(QStyle::SH_TabBar_ChangeCurrentDelay));
1762 }
1763 event->ignore();
1764 }
1765 break;
1766 case QEvent::DragLeave:
1767 case QEvent::Drop:
1768 d->killSwitchTabTimer();
1769 event->ignore();
1770 break;
1771#endif
1774 case QEvent::MouseMove:
1775 d->mousePosition = static_cast<QMouseEvent *>(event)->position().toPoint();
1776 d->mouseButtons = static_cast<QMouseEvent *>(event)->buttons();
1777 break;
1778 default:
1779 break;
1780 }
1781
1782 return QWidget::event(event);
1783}
1784
1788{
1789 Q_D(QTabBar);
1790 if (d->layoutDirty)
1792
1793 // when resizing, we want to keep the scroll offset as much as possible
1794 d->layoutTabs();
1795
1796 d->makeVisible(d->currentIndex);
1797}
1798
1802{
1803 Q_D(QTabBar);
1804
1805 QStyleOptionTabBarBase optTabBase;
1806 QTabBarPrivate::initStyleBaseOption(&optTabBase, this, size());
1807
1808 QStylePainter p(this);
1809 int selected = -1;
1810 int cutLeft = -1;
1811 int cutRight = -1;
1812 bool vertical = verticalTabs(d->shape);
1813 QStyleOptionTab cutTabLeft;
1814 QStyleOptionTab cutTabRight;
1815 selected = d->currentIndex;
1816 if (d->dragInProgress)
1817 selected = d->pressedIndex;
1818 const QRect scrollRect = d->normalizedScrollRect();
1819
1820 for (int i = 0; i < d->tabList.size(); ++i)
1821 optTabBase.tabBarRect |= tabRect(i);
1822
1823 optTabBase.selectedTabRect = tabRect(selected);
1824
1825 if (d->drawBase)
1826 p.drawPrimitive(QStyle::PE_FrameTabBarBase, optTabBase);
1827
1828 // the buttons might be semi-transparent or not fill their rect, but we don't
1829 // want the tab underneath to shine through, so clip the button area; QTBUG-50866
1830 if (d->leftB->isVisible() || d->rightB->isVisible()) {
1832 opt.initFrom(this);
1833 QRegion buttonRegion;
1834 if (d->leftB->isVisible())
1835 buttonRegion |= style()->subElementRect(QStyle::SE_TabBarScrollLeftButton, &opt, this);
1836 if (d->rightB->isVisible())
1837 buttonRegion |= style()->subElementRect(QStyle::SE_TabBarScrollRightButton, &opt, this);
1838 if (!buttonRegion.isEmpty())
1839 p.setClipRegion(QRegion(rect()) - buttonRegion);
1840 }
1841
1842 for (int i = 0; i < d->tabList.size(); ++i) {
1843 const auto tab = d->tabList.at(i);
1844 if (!tab->visible)
1845 continue;
1846 QStyleOptionTab tabOption;
1847 initStyleOption(&tabOption, i);
1848 if (d->paintWithOffsets && tab->dragOffset != 0) {
1849 if (vertical) {
1850 tabOption.rect.moveTop(tabOption.rect.y() + tab->dragOffset);
1851 } else {
1852 tabOption.rect.moveLeft(tabOption.rect.x() + tab->dragOffset);
1853 }
1854 }
1855 if (!(tabOption.state & QStyle::State_Enabled)) {
1856 tabOption.palette.setCurrentColorGroup(QPalette::Disabled);
1857 }
1858
1859 // If this tab is partially obscured, make a note of it so that we can pass the information
1860 // along when we draw the tear.
1861 QRect tabRect = tab->rect;
1862 int tabStart = vertical ? tabRect.top() : tabRect.left();
1863 int tabEnd = vertical ? tabRect.bottom() : tabRect.right();
1864 if (tabStart < scrollRect.left() + d->scrollOffset) {
1865 cutLeft = i;
1866 cutTabLeft = tabOption;
1867 } else if (tabEnd > scrollRect.right() + d->scrollOffset) {
1868 cutRight = i;
1869 cutTabRight = tabOption;
1870 }
1871
1872 // Don't bother drawing a tab if the entire tab is outside of the visible tab bar.
1873 if ((!vertical && (tabOption.rect.right() < 0 || tabOption.rect.left() > width()))
1874 || (vertical && (tabOption.rect.bottom() < 0 || tabOption.rect.top() > height())))
1875 continue;
1876
1877 optTabBase.tabBarRect |= tabOption.rect;
1878 if (i == selected)
1879 continue;
1880
1881 p.drawControl(QStyle::CE_TabBarTab, tabOption);
1882 }
1883
1884 // Draw the selected tab last to get it "on top"
1885 if (selected >= 0) {
1886 QStyleOptionTab tabOption;
1887 const auto tab = d->tabList.at(selected);
1888 initStyleOption(&tabOption, selected);
1889
1890 if (d->paintWithOffsets && tab->dragOffset != 0) {
1891 // if the drag offset is != 0, a move is in progress (drag or animation)
1892 // => set the tab position to Moving to preserve the rect
1893 tabOption.position = QStyleOptionTab::TabPosition::Moving;
1894
1895 if (vertical)
1896 tabOption.rect.moveTop(tabOption.rect.y() + tab->dragOffset);
1897 else
1898 tabOption.rect.moveLeft(tabOption.rect.x() + tab->dragOffset);
1899 }
1900
1901 // Calculate the rect of a moving tab
1902 const int taboverlap = style()->pixelMetric(QStyle::PM_TabBarTabOverlap, nullptr, this);
1903 const QRect &movingRect = verticalTabs(d->shape)
1904 ? tabOption.rect.adjusted(0, -taboverlap, 0, taboverlap)
1905 : tabOption.rect.adjusted(-taboverlap, 0, taboverlap, 0);
1906
1907 // If a drag is in process, set the moving tab's geometry here
1908 // (in an animation, it is already set)
1909 if (d->dragInProgress)
1910 d->movingTab->setGeometry(movingRect);
1911
1912 p.drawControl(QStyle::CE_TabBarTab, tabOption);
1913 }
1914
1915 // Only draw the tear indicator if necessary. Most of the time we don't need too.
1916 if (d->leftB->isVisible() && cutLeft >= 0) {
1917 cutTabLeft.rect = rect();
1918 cutTabLeft.rect = style()->subElementRect(QStyle::SE_TabBarTearIndicatorLeft, &cutTabLeft, this);
1919 p.drawPrimitive(QStyle::PE_IndicatorTabTearLeft, cutTabLeft);
1920 }
1921
1922 if (d->rightB->isVisible() && cutRight >= 0) {
1923 cutTabRight.rect = rect();
1924 cutTabRight.rect = style()->subElementRect(QStyle::SE_TabBarTearIndicatorRight, &cutTabRight, this);
1925 p.drawPrimitive(QStyle::PE_IndicatorTabTearRight, cutTabRight);
1926 }
1927}
1928
1929/*
1930 When index changes visibility, we have to find first & last visible indexes.
1931 If remove is set, we force both
1932 */
1934{
1935 if (visible) {
1938 } else {
1939 if (remove || (index == firstVisible)) {
1940 firstVisible = -1;
1941 for (int i = 0; i < tabList.size(); ++i) {
1942 if (tabList.at(i)->visible) {
1943 firstVisible = i;
1944 break;
1945 }
1946 }
1947 }
1948 if (remove || (index == lastVisible)) {
1949 lastVisible = -1;
1950 for (int i = tabList.size() - 1; i >= 0; --i) {
1951 if (tabList.at(i)->visible) {
1952 lastVisible = i;
1953 break;
1954 }
1955 }
1956 }
1957 }
1958}
1959
1960/*
1961 Selects the new current index starting at "fromIndex". If "fromIndex" is visible we're done.
1962 Else it tries any index AFTER fromIndex, then any BEFORE fromIndex and, if everything fails,
1963 it returns -1 indicating that no index is available
1964 */
1966{
1967 int newindex = -1;
1968 for (int i = fromIndex; i < tabList.size(); ++i) {
1969 if (at(i)->visible && at(i)->enabled) {
1970 newindex = i;
1971 break;
1972 }
1973 }
1974 if (newindex < 0) {
1975 for (int i = fromIndex-1; i > -1; --i) {
1976 if (at(i)->visible && at(i)->enabled) {
1977 newindex = i;
1978 break;
1979 }
1980 }
1981 }
1982
1983 return newindex;
1984}
1985
1986/*
1987 Given that index at position from moved to position to where return where index goes.
1988 */
1989int QTabBarPrivate::calculateNewPosition(int from, int to, int index) const
1990{
1991 if (index == from)
1992 return to;
1993
1994 int start = qMin(from, to);
1995 int end = qMax(from, to);
1996 if (index >= start && index <= end)
1997 index += (from < to) ? -1 : 1;
1998 return index;
1999}
2000
2007void QTabBar::moveTab(int from, int to)
2008{
2009 Q_D(QTabBar);
2010 if (from == to
2011 || !d->validIndex(from)
2012 || !d->validIndex(to))
2013 return;
2014
2015 auto &fromTab = *d->tabList.at(from);
2016 auto &toTab = *d->tabList.at(to);
2017
2018 bool vertical = verticalTabs(d->shape);
2019 int oldPressedPosition = 0;
2020 if (d->pressedIndex != -1) {
2021 // Record the position of the pressed tab before reordering the tabs.
2022 oldPressedPosition = vertical ? d->tabList.at(d->pressedIndex)->rect.y()
2023 : d->tabList.at(d->pressedIndex)->rect.x();
2024 }
2025
2026 // Update the locations of the tabs first
2027 int start = qMin(from, to);
2028 int end = qMax(from, to);
2029 int width = vertical ? fromTab.rect.height() : fromTab.rect.width();
2030 if (from < to)
2031 width *= -1;
2032 bool rtl = isRightToLeft();
2033 for (int i = start; i <= end; ++i) {
2034 if (i == from)
2035 continue;
2036 auto &tab = *d->tabList.at(i);
2037 if (vertical)
2038 tab.rect.moveTop(tab.rect.y() + width);
2039 else
2040 tab.rect.moveLeft(tab.rect.x() + width);
2041 int direction = -1;
2042 if (rtl && !vertical)
2043 direction *= -1;
2044 if (tab.dragOffset != 0)
2045 tab.dragOffset += (direction * width);
2046 }
2047
2048 if (vertical) {
2049 if (from < to)
2050 fromTab.rect.moveTop(toTab.rect.bottom() + 1);
2051 else
2052 fromTab.rect.moveTop(toTab.rect.top() - width);
2053 } else {
2054 if (from < to)
2055 fromTab.rect.moveLeft(toTab.rect.right() + 1);
2056 else
2057 fromTab.rect.moveLeft(toTab.rect.left() - width);
2058 }
2059
2060 // Move the actual data structures
2061 d->tabList.move(from, to);
2062
2063 // update lastTab locations
2064 for (const auto tab : std::as_const(d->tabList))
2065 tab->lastTab = d->calculateNewPosition(from, to, tab->lastTab);
2066
2067 // update external variables
2068 int previousIndex = d->currentIndex;
2069 d->currentIndex = d->calculateNewPosition(from, to, d->currentIndex);
2070
2071 // If we are in the middle of a drag update the dragStartPosition
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;
2077 if (isRightToLeft() && !vertical)
2078 diff *= -1;
2079 if (vertical)
2080 d->dragStartPosition.setY(d->dragStartPosition.y() - diff);
2081 else
2082 d->dragStartPosition.setX(d->dragStartPosition.x() - diff);
2083 }
2084
2085 d->layoutWidgets(start);
2086 update();
2087 emit tabMoved(from, to);
2088 if (previousIndex != d->currentIndex)
2089 emit currentChanged(d->currentIndex);
2091}
2092
2093void QTabBarPrivate::slide(int from, int to)
2094{
2095 Q_Q(QTabBar);
2096 if (from == to
2097 || !validIndex(from)
2098 || !validIndex(to))
2099 return;
2100 bool vertical = verticalTabs(shape);
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;
2107 tabList.at(to)->dragOffset -= length;
2108 tabList.at(to)->startAnimation(this, ANIMATION_DURATION);
2109}
2110
2112{
2113 if (!validIndex(index))
2114 return;
2115 tabList.at(index)->dragOffset = offset;
2116 layoutTab(index); // Make buttons follow tab
2117 q_func()->update();
2118}
2119
2123{
2124 Q_D(QTabBar);
2125
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) {
2130 const int index = d->indexAtPos(pos);
2132 }
2133
2134 if (event->button() != Qt::LeftButton) {
2135 event->ignore();
2136 return;
2137 }
2138 // Be safe!
2139 if (d->pressedIndex != -1 && d->movable)
2140 d->moveTabFinished(d->pressedIndex);
2141
2142 d->pressedIndex = d->indexAtPos(event->position().toPoint());
2143
2144 if (d->validIndex(d->pressedIndex)) {
2145 QStyleOptionTabBarBase optTabBase;
2146 optTabBase.initFrom(this);
2147 optTabBase.documentMode = d->documentMode;
2148 if (event->type() == style()->styleHint(QStyle::SH_TabBar_SelectMouseType, &optTabBase, this))
2149 setCurrentIndex(d->pressedIndex);
2150 else
2151 repaint(tabRect(d->pressedIndex));
2152 if (d->movable) {
2153 d->dragStartPosition = event->position().toPoint();
2154 }
2155 }
2156}
2157
2161{
2162 Q_D(QTabBar);
2163 if (d->movable) {
2164 // Be safe!
2165 if (d->pressedIndex != -1
2166 && event->buttons() == Qt::NoButton)
2167 d->moveTabFinished(d->pressedIndex);
2168
2169 // Start drag
2170 if (!d->dragInProgress && d->pressedIndex != -1) {
2171 if ((event->position().toPoint() - d->dragStartPosition).manhattanLength() > QApplication::startDragDistance()) {
2172 d->dragInProgress = true;
2173 d->setupMovableTab();
2174 }
2175 }
2176
2177 if (event->buttons() == Qt::LeftButton
2178 && d->dragInProgress
2179 && d->validIndex(d->pressedIndex)) {
2180 bool vertical = verticalTabs(d->shape);
2181 int dragDistance;
2182 if (vertical) {
2183 dragDistance = (event->position().toPoint().y() - d->dragStartPosition.y());
2184 } else {
2185 dragDistance = (event->position().toPoint().x() - d->dragStartPosition.x());
2186 }
2187 d->tabList.at(d->pressedIndex)->dragOffset = dragDistance;
2188
2189 QRect startingRect = tabRect(d->pressedIndex);
2190 if (vertical)
2191 startingRect.moveTop(startingRect.y() + dragDistance);
2192 else
2193 startingRect.moveLeft(startingRect.x() + dragDistance);
2194
2195 int overIndex;
2196 if (dragDistance < 0)
2197 overIndex = tabAt(startingRect.topLeft());
2198 else
2199 overIndex = tabAt(startingRect.topRight());
2200
2201 if (overIndex != d->pressedIndex && overIndex != -1) {
2202 int offset = 1;
2203 if (isRightToLeft() && !vertical)
2204 offset *= -1;
2205 if (dragDistance < 0) {
2206 dragDistance *= -1;
2207 offset *= -1;
2208 }
2209 for (int i = d->pressedIndex;
2210 offset > 0 ? i < overIndex : i > overIndex;
2211 i += offset) {
2212 QRect overIndexRect = tabRect(overIndex);
2213 int needsToBeOver = (vertical ? overIndexRect.height() : overIndexRect.width()) / 2;
2214 if (dragDistance > needsToBeOver)
2215 d->slide(i + offset, d->pressedIndex);
2216 }
2217 }
2218 // Buttons needs to follow the dragged tab
2219 if (d->pressedIndex != -1)
2220 d->layoutTab(d->pressedIndex);
2221
2222 update();
2223 }
2224 }
2225
2226 if (event->buttons() != Qt::LeftButton) {
2227 event->ignore();
2228 return;
2229 }
2230}
2231
2233{
2234 Q_Q(QTabBar);
2235 if (!movingTab)
2237
2238 int taboverlap = q->style()->pixelMetric(QStyle::PM_TabBarTabOverlap, nullptr ,q);
2239 QRect grabRect = q->tabRect(pressedIndex);
2240 if (verticalTabs(shape))
2241 grabRect.adjust(0, -taboverlap, 0, taboverlap);
2242 else
2243 grabRect.adjust(-taboverlap, 0, taboverlap, 0);
2244
2245 QPixmap grabImage(grabRect.size() * q->devicePixelRatio());
2246 grabImage.setDevicePixelRatio(q->devicePixelRatio());
2247 grabImage.fill(Qt::transparent);
2248 QStylePainter p(&grabImage, q);
2249
2250 QStyleOptionTab tab;
2251 q->initStyleOption(&tab, pressedIndex);
2252 tab.position = QStyleOptionTab::Moving;
2253 if (verticalTabs(shape))
2254 tab.rect.moveTopLeft(QPoint(0, taboverlap));
2255 else
2256 tab.rect.moveTopLeft(QPoint(taboverlap, 0));
2257 p.drawControl(QStyle::CE_TabBarTab, tab);
2258 p.end();
2259
2260 movingTab->setPixmap(grabImage);
2261 movingTab->setGeometry(grabRect);
2262 movingTab->raise();
2263
2264 // Re-arrange widget order to avoid overlaps
2265 const auto &pressedTab = *tabList.at(pressedIndex);
2266 if (pressedTab.leftWidget)
2267 pressedTab.leftWidget->raise();
2268 if (pressedTab.rightWidget)
2269 pressedTab.rightWidget->raise();
2270 if (leftB)
2271 leftB->raise();
2272 if (rightB)
2273 rightB->raise();
2274 movingTab->setVisible(true);
2275}
2276
2278{
2279 Q_Q(QTabBar);
2280 bool cleanup = (pressedIndex == index) || (pressedIndex == -1) || !validIndex(index);
2281 bool allAnimationsFinished = true;
2282#if QT_CONFIG(animation)
2283 for (const auto tab : std::as_const(tabList)) {
2284 if (tab->animation && tab->animation->state() == QAbstractAnimation::Running) {
2285 allAnimationsFinished = false;
2286 break;
2287 }
2288 }
2289#endif // animation
2290 if (allAnimationsFinished && cleanup) {
2291 if (movingTab)
2292 movingTab->setVisible(false); // We might not get a mouse release
2293 for (auto tab : std::as_const(tabList)) {
2294 tab->dragOffset = 0;
2295 }
2296 if (pressedIndex != -1 && movable) {
2297 pressedIndex = -1;
2298 dragInProgress = false;
2300 }
2301 layoutWidgets();
2302 } else {
2303 if (!validIndex(index))
2304 return;
2305 tabList.at(index)->dragOffset = 0;
2306 }
2307 q->update();
2308}
2309
2313{
2314 Q_D(QTabBar);
2315 if (event->button() != Qt::LeftButton) {
2316 event->ignore();
2317 return;
2318 }
2319
2320 if (d->movable && d->dragInProgress && d->validIndex(d->pressedIndex)) {
2321 int length = d->tabList.at(d->pressedIndex)->dragOffset;
2322 int width = verticalTabs(d->shape)
2323 ? tabRect(d->pressedIndex).height()
2324 : tabRect(d->pressedIndex).width();
2325 int duration = qMin(ANIMATION_DURATION,
2327 d->tabList.at(d->pressedIndex)->startAnimation(d, duration);
2328 d->dragInProgress = false;
2329 d->movingTab->setVisible(false);
2330 d->dragStartPosition = QPoint();
2331 }
2332
2333 // mouse release event might happen outside the tab, so keep the pressed index
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))
2345 update(tabRect(oldPressedIndex));
2346}
2347
2351{
2352 Q_D(QTabBar);
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)
2358
2360}
2361
2365{
2366 Q_D(QTabBar);
2367 if (event->key() != Qt::Key_Left && event->key() != Qt::Key_Right) {
2368 event->ignore();
2369 return;
2370 }
2371 int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1;
2372 d->setCurrentNextEnabledIndex(offset);
2373}
2374
2377#if QT_CONFIG(wheelevent)
2378void QTabBar::wheelEvent(QWheelEvent *event)
2379{
2380 Q_D(QTabBar);
2381 if (style()->styleHint(QStyle::SH_TabBar_AllowWheelScrolling)) {
2382 const bool wheelVertical = qAbs(event->angleDelta().y()) > qAbs(event->angleDelta().x());
2383 const bool tabsVertical = verticalTabs(d->shape);
2384 if (event->device()->capabilities().testFlag(QInputDevice::Capability::PixelScroll)) {
2385 // For wheels/touch pads with pixel precision, scroll the tab bar if
2386 // it has the right orientation.
2387 int delta = 0;
2388 if (tabsVertical == wheelVertical)
2389 delta = wheelVertical ? event->pixelDelta().y() : event->pixelDelta().x();
2391 delta = -delta;
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();
2401
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) {
2409 event->accept();
2410 update();
2411 return;
2412 }
2413 }
2414 } else {
2415 d->accumulatedAngleDelta += event->angleDelta();
2416 const int xSteps = d->accumulatedAngleDelta.x() / QWheelEvent::DefaultDeltasPerStep;
2417 const int ySteps = d->accumulatedAngleDelta.y() / QWheelEvent::DefaultDeltasPerStep;
2418 int offset = 0;
2419 if (xSteps > 0 || ySteps > 0) {
2420 offset = -1;
2421 d->accumulatedAngleDelta = QPoint();
2422 } else if (xSteps < 0 || ySteps < 0) {
2423 offset = 1;
2424 d->accumulatedAngleDelta = QPoint();
2425 }
2426 const int oldCurrentIndex = d->currentIndex;
2427 d->setCurrentNextEnabledIndex(offset);
2428 if (oldCurrentIndex != d->currentIndex) {
2429 event->accept();
2430 return;
2431 }
2432 }
2433 QWidget::wheelEvent(event);
2434 }
2435}
2436#endif // QT_CONFIG(wheelevent)
2437
2439{
2440 Q_Q(QTabBar);
2441 for (int index = currentIndex + offset; validIndex(index); index += offset) {
2442 if (tabList.at(index)->enabled && tabList.at(index)->visible) {
2443 q->setCurrentIndex(index);
2444 break;
2445 }
2446 }
2447}
2448
2452{
2453 Q_D(QTabBar);
2454 switch (event->type()) {
2456 if (!d->elideModeSetByUser)
2457 d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, nullptr, this));
2458 if (!d->useScrollButtonsSetByUser)
2459 d->useScrollButtons = !style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, nullptr, this);
2460 Q_FALLTHROUGH();
2461 case QEvent::FontChange:
2462 d->textSizes.clear();
2463 d->refresh();
2464 break;
2465 default:
2466 break;
2467 }
2468
2470}
2471
2476{
2477 Q_D(QTabBar);
2478 if (event->timerId() == d->switchTabTimerId) {
2479 killTimer(d->switchTabTimerId);
2480 d->switchTabTimerId = 0;
2481 setCurrentIndex(d->switchTabCurrentIndex);
2482 d->switchTabCurrentIndex = -1;
2483 }
2485}
2486
2501{
2502 Q_D(const QTabBar);
2503 return d->elideMode;
2504}
2505
2507{
2508 Q_D(QTabBar);
2509 d->elideMode = mode;
2510 d->elideModeSetByUser = true;
2511 d->textSizes.clear();
2512 d->refresh();
2513}
2514
2529{
2530 return d_func()->useScrollButtons;
2531}
2532
2534{
2535 Q_D(QTabBar);
2536 d->useScrollButtonsSetByUser = true;
2537 if (d->useScrollButtons == useButtons)
2538 return;
2539 d->useScrollButtons = useButtons;
2540 d->refresh();
2541}
2542
2558{
2559 Q_D(const QTabBar);
2560 return d->closeButtonOnTabs;
2561}
2562
2563void QTabBar::setTabsClosable(bool closable)
2564{
2565 Q_D(QTabBar);
2566 if (d->closeButtonOnTabs == closable)
2567 return;
2568 d->closeButtonOnTabs = closable;
2570 if (!closable) {
2571 for (auto tab : std::as_const(d->tabList)) {
2572 if (closeSide == LeftSide && tab->leftWidget) {
2573 tab->leftWidget->deleteLater();
2574 tab->leftWidget = nullptr;
2575 }
2576 if (closeSide == RightSide && tab->rightWidget) {
2577 tab->rightWidget->deleteLater();
2578 tab->rightWidget = nullptr;
2579 }
2580 }
2581 } else {
2582 bool newButtons = false;
2583 for (int i = 0; i < d->tabList.size(); ++i) {
2584 if (tabButton(i, closeSide))
2585 continue;
2586 newButtons = true;
2587 QAbstractButton *closeButton = new CloseButton(this);
2588 QObjectPrivate::connect(closeButton, &CloseButton::clicked,
2590 setTabButton(i, closeSide, closeButton);
2591 }
2592 if (newButtons)
2593 d->layoutTabs();
2594 }
2595 update();
2596}
2597
2638{
2639 Q_D(const QTabBar);
2640 return d->selectionBehaviorOnRemove;
2641}
2642
2644{
2645 Q_D(QTabBar);
2646 d->selectionBehaviorOnRemove = behavior;
2647}
2648
2660{
2661 Q_D(const QTabBar);
2662 return d->expanding;
2663}
2664
2666{
2667 Q_D(QTabBar);
2668 if (d->expanding == enabled)
2669 return;
2670 d->expanding = enabled;
2671 d->layoutTabs();
2672}
2673
2685{
2686 Q_D(const QTabBar);
2687 return d->movable;
2688}
2689
2690void QTabBar::setMovable(bool movable)
2691{
2692 Q_D(QTabBar);
2693 d->movable = movable;
2694}
2695
2696
2709{
2710 return d_func()->documentMode;
2711}
2712
2714{
2715 Q_D(QTabBar);
2716
2717 d->documentMode = enabled;
2718 d->updateMacBorderMetrics();
2719}
2720
2733{
2734 Q_D(const QTabBar);
2735 return d->autoHide;
2736}
2737
2739{
2740 Q_D(QTabBar);
2741 if (d->autoHide == hide)
2742 return;
2743
2744 d->autoHide = hide;
2745 if (hide)
2746 d->autoHideTabs();
2747 else
2748 setVisible(true);
2749}
2750
2764{
2765 Q_D(const QTabBar);
2766 return d->changeCurrentOnDrag;
2767}
2768
2770{
2771 Q_D(QTabBar);
2772 d->changeCurrentOnDrag = change;
2773 if (!change)
2774 d->killSwitchTabTimer();
2775}
2776
2792{
2793 Q_D(QTabBar);
2794 if (index < 0 || index >= d->tabList.size())
2795 return;
2796 if (widget) {
2797 widget->setParent(this);
2798 // make sure our left and right widgets stay on top
2799 widget->lower();
2800 widget->show();
2801 }
2802 auto &tab = *d->tabList.at(index);
2803 if (position == LeftSide) {
2804 if (tab.leftWidget)
2805 tab.leftWidget->hide();
2806 tab.leftWidget = widget;
2807 } else {
2808 if (tab.rightWidget)
2809 tab.rightWidget->hide();
2810 tab.rightWidget = widget;
2811 }
2812 d->layoutTabs();
2813 d->refresh();
2814 update();
2815}
2816
2822{
2823 Q_D(const QTabBar);
2824 if (const auto tab = d->at(index)) {
2825 return position == LeftSide ? tab->leftWidget
2826 : tab->rightWidget;
2827 }
2828 return nullptr;
2829}
2830
2831#if QT_CONFIG(accessibility)
2835void QTabBar::setAccessibleTabName(int index, const QString &name)
2836{
2837 Q_D(QTabBar);
2838 if (QTabBarPrivate::Tab *tab = d->at(index)) {
2839 tab->accessibleName = name;
2840 QAccessibleEvent event(this, QAccessible::NameChanged);
2841 event.setChild(index);
2842 QAccessible::updateAccessibility(&event);
2843 }
2844}
2845
2850QString QTabBar::accessibleTabName(int index) const
2851{
2852 Q_D(const QTabBar);
2853 if (const QTabBarPrivate::Tab *tab = d->at(index))
2854 return tab->accessibleName;
2855 return QString();
2856}
2857#endif // QT_CONFIG(accessibility)
2858
2859CloseButton::CloseButton(QWidget *parent)
2860 : QAbstractButton(parent)
2861{
2863#ifndef QT_NO_CURSOR
2865#endif
2866#if QT_CONFIG(tooltip)
2867 setToolTip(tr("Close Tab"));
2868#endif
2869 resize(sizeHint());
2870}
2871
2872QSize CloseButton::sizeHint() const
2873{
2874 ensurePolished();
2875 int width = style()->pixelMetric(QStyle::PM_TabCloseIndicatorWidth, nullptr, this);
2876 int height = style()->pixelMetric(QStyle::PM_TabCloseIndicatorHeight, nullptr, this);
2877 return QSize(width, height);
2878}
2879
2880void CloseButton::enterEvent(QEnterEvent *event)
2881{
2882 if (isEnabled())
2883 update();
2885}
2886
2887void CloseButton::leaveEvent(QEvent *event)
2888{
2889 if (isEnabled())
2890 update();
2892}
2893
2894void CloseButton::paintEvent(QPaintEvent *)
2895{
2896 QPainter p(this);
2898 opt.initFrom(this);
2900 if (isEnabled() && underMouse() && !isChecked() && !isDown())
2902 if (isChecked())
2904 if (isDown())
2906
2907 if (const QTabBar *tb = qobject_cast<const QTabBar *>(parent())) {
2908 int index = tb->currentIndex();
2910 if (tb->tabButton(index, position) == this)
2912 }
2913
2914 style()->drawPrimitive(QStyle::PE_IndicatorTabClose, &opt, &p, this);
2915}
2916
2917#if QT_CONFIG(animation)
2918void QTabBarPrivate::Tab::TabBarAnimation::updateCurrentValue(const QVariant &current)
2919{
2920 priv->moveTab(priv->tabList.indexOf(tab), current.toInt());
2921}
2922
2923void QTabBarPrivate::Tab::TabBarAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State)
2924{
2925 if (newState == Stopped) priv->moveTabFinished(priv->tabList.indexOf(tab));
2926}
2927#endif
2928
2930
2931#include "moc_qtabbar.cpp"
2932#include "qtabbar.moc"
State
This enum describes the state of the animation.
The QAbstractButton class is the abstract base class of button widgets, providing functionality commo...
void clicked(bool checked=false)
This signal is emitted when the button is activated (i.e., pressed down then released while the mouse...
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.
Definition qcolor.h:31
bool isValid() const noexcept
Returns true if the color is valid; otherwise returns false.
Definition qcolor.h:285
\inmodule QtGui
Definition qevent.h:165
\inmodule QtCore
Definition qcoreevent.h:45
@ StyleChange
Definition qcoreevent.h:136
@ DragEnter
Definition qcoreevent.h:101
@ FontChange
Definition qcoreevent.h:133
@ MouseMove
Definition qcoreevent.h:63
@ MouseButtonPress
Definition qcoreevent.h:60
@ HoverLeave
Definition qcoreevent.h:176
@ HoverEnter
Definition qcoreevent.h:175
@ DragLeave
Definition qcoreevent.h:103
@ HoverMove
Definition qcoreevent.h:177
@ WhatsThis
Definition qcoreevent.h:148
@ MouseButtonRelease
Definition qcoreevent.h:61
\reentrant \inmodule QtGui
QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags=0) const
static QPlatformNativeInterface * platformNativeInterface()
\inmodule QtCore
Definition qhash.h:1103
The QHelpEvent class provides an event that is used to request helpful information about a particular...
Definition qevent.h:788
const QPoint & pos() const
Returns the mouse cursor position when the event was generated, relative to the widget to which the e...
Definition qevent.h:798
The QHideEvent class provides an event which is sent after a widget is hidden.
Definition qevent.h:586
\inmodule QtGui
Definition qevent.h:246
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:1019
The QKeyEvent class describes a key event.
Definition qevent.h:424
static QKeySequence mnemonic(const QString &text)
Returns the shortcut key sequence for the mnemonic in text, or an empty key sequence if no mnemonics ...
\inmodule QtGui
Definition qevent.h:196
void paintEvent(QPaintEvent *e) override
This event handler can be reimplemented in a subclass to receive paint events passed in event.
Definition qtabbar.cpp:67
void setPixmap(const QPixmap &pixmap)
Definition qtabbar.cpp:61
QMovableTabWidget(QWidget *parent=nullptr)
Definition qtabbar.cpp:56
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)
Definition qobject_p.h:299
\inmodule QtCore
Definition qobject.h:103
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...
Definition qobject.cpp:1817
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2658
virtual void timerEvent(QTimerEvent *event)
This event handler can be reimplemented in a subclass to receive timer events for the object.
Definition qobject.cpp:1470
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:127
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1912
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:486
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
@ Disabled
Definition qpalette.h:49
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
void setDevicePixelRatio(qreal scaleFactor)
Sets the device pixel ratio for the pixmap.
Definition qpixmap.cpp:604
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition qpixmap.cpp:850
The QPlatformNativeInterface class provides an abstraction for retrieving native resource handles.
virtual NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource)
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr void setY(int y) noexcept
Sets the y coordinate of this point to the given y coordinate.
Definition qpoint.h:145
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
\inmodule QtCore\reentrant
Definition qrect.h:30
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.
Definition qrect.h:373
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:182
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:176
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...
Definition qrect.cpp:855
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:173
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:242
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.
Definition qrect.h:245
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
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,...
Definition qrect.h:261
QRect united(const QRect &other) const noexcept
Definition qrect.h:420
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
constexpr void setHeight(int h) noexcept
Sets the height of the rectangle to the given height.
Definition qrect.h:384
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:179
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:548
iterator end()
Definition qset.h:140
iterator find(const T &value)
Definition qset.h:159
iterator insert(const T &value)
Definition qset.h:155
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.
Definition qevent.h:578
QPointF position() const
Returns the position of the point in this event, relative to the widget or item that received the eve...
Definition qevent.h:119
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
Definition qsize.h:121
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString left(qsizetype n) const &
Definition qstring.h:363
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
QString right(qsizetype n) const &
Definition qstring.h:375
The QStyleOption class stores the parameters used by QStyle functions.
QStyle::State state
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.
Definition qstyle.h:29
@ State_MouseOver
Definition qstyle.h:80
@ State_Sunken
Definition qstyle.h:69
@ State_HasFocus
Definition qstyle.h:75
@ State_Active
Definition qstyle.h:83
@ State_AutoRaise
Definition qstyle.h:79
@ State_Enabled
Definition qstyle.h:67
@ State_On
Definition qstyle.h:72
@ State_Raised
Definition qstyle.h:68
@ State_Selected
Definition qstyle.h:82
@ CT_TabBarTab
Definition qstyle.h:558
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_ElideMode
Definition qstyle.h:652
@ SH_TabBar_CloseButtonPosition
Definition qstyle.h:677
@ SH_TabBar_Alignment
Definition qstyle.h:590
@ SH_TabBar_AllowWheelScrolling
Definition qstyle.h:704
@ SH_TabBar_ChangeCurrentDelay
Definition qstyle.h:691
@ SH_TabBar_PreferNoArrows
Definition qstyle.h:623
@ SH_TabBar_SelectMouseType
Definition qstyle.h:589
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...
@ CE_TabBarTab
Definition qstyle.h:181
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.
Definition qstyle.cpp:2143
@ PM_TabBarTabHSpace
Definition qstyle.h:440
@ PM_TabCloseIndicatorWidth
Definition qstyle.h:522
@ PM_TabBarIconSize
Definition qstyle.h:503
@ PM_TabBarTabVSpace
Definition qstyle.h:441
@ PM_TabBarScrollButtonWidth
Definition qstyle.h:481
@ PM_TabCloseIndicatorHeight
Definition qstyle.h:523
@ PM_TabBarTabOverlap
Definition qstyle.h:439
@ PE_FrameTabBarBase
Definition qstyle.h:115
@ PE_IndicatorTabTearRight
Definition qstyle.h:161
@ PE_IndicatorTabTearLeft
Definition qstyle.h:145
@ PE_IndicatorTabClose
Definition qstyle.h:158
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
Definition qstyle.h:277
@ SE_TabBarTabRightButton
Definition qstyle.h:309
@ SE_TabBarTearIndicatorRight
Definition qstyle.h:318
@ SE_TabBarTabText
Definition qstyle.h:310
@ SE_TabBarScrollRightButton
Definition qstyle.h:317
@ SE_TabBarScrollLeftButton
Definition qstyle.h:316
@ SE_TabBarTabLeftButton
Definition qstyle.h:308
void initBasicStyleOption(QStyleOptionTab *option, int tabIndex) const
Definition qtabbar.cpp:125
int calculateNewPosition(int from, int to, int index) const
Definition qtabbar.cpp:1989
QRect hoverRect
Definition qtabbar_p.h:66
bool validIndex(int index) const
Definition qtabbar_p.h:187
int hoveredTabIndex() const
Definition qtabbar.cpp:658
void killSwitchTabTimer()
Definition qtabbar.cpp:708
int selectNewCurrentIndexFrom(int currentIndex)
Definition qtabbar.cpp:1965
void autoHideTabs()
Definition qtabbar.cpp:762
void moveTab(int index, int offset)
Definition qtabbar.cpp:2111
QToolButton * rightB
Definition qtabbar_p.h:73
QPoint dragStartPosition
Definition qtabbar_p.h:67
void closeTab()
Definition qtabbar.cpp:770
int switchTabTimerId
Definition qtabbar_p.h:78
QRect normalizedScrollRect(int index=-1)
Definition qtabbar.cpp:578
void updateMacBorderMetrics()
Definition qtabbar.cpp:74
Qt::TextElideMode elideMode
Definition qtabbar_p.h:79
bool useScrollButtons
Definition qtabbar_p.h:93
int switchTabCurrentIndex
Definition qtabbar_p.h:77
Qt::MouseButtons mouseButtons
Definition qtabbar_p.h:82
void scrollTabs()
Definition qtabbar.cpp:793
void layoutWidgets(int start=0)
Definition qtabbar.cpp:754
bool paintWithOffsets
Definition qtabbar_p.h:97
void layoutTab(int index)
Definition qtabbar.cpp:718
void setCurrentNextEnabledIndex(int offset)
\reimp
Definition qtabbar.cpp:2438
void makeVisible(int index)
Definition qtabbar.cpp:667
QTabBar::Shape shape
Definition qtabbar_p.h:81
void layoutTabs()
Definition qtabbar.cpp:407
void setupMovableTab()
Definition qtabbar.cpp:2232
void calculateFirstLastVisible(int index, bool visible, bool remove)
Definition qtabbar.cpp:1933
void moveTabFinished(int index)
Definition qtabbar.cpp:2277
QMovableTabWidget * movingTab
Definition qtabbar_p.h:75
QToolButton * leftB
Definition qtabbar_p.h:74
static void initStyleBaseOption(QStyleOptionTabBarBase *optTabBase, QTabBar *tabbar, QSize size)
Definition qtabbar_p.h:211
bool dragInProgress
Definition qtabbar_p.h:99
void slide(int from, int to)
Definition qtabbar.cpp:2093
QList< Tab * > tabList
Definition qtabbar_p.h:172
int indexAtPos(const QPoint &p) const
Definition qtabbar.cpp:396
The QTabBar class provides a tab bar, e.g.
Definition qtabbar.h:19
Qt::TextElideMode elideMode
how to elide text in the tab bar
Definition qtabbar.h:27
void setUsesScrollButtons(bool useButtons)
Definition qtabbar.cpp:2533
void setTabsClosable(bool closable)
Definition qtabbar.cpp:2563
ButtonPosition
Definition qtabbar.h:47
@ LeftSide
Definition qtabbar.h:48
@ RightSide
Definition qtabbar.h:49
virtual QSize minimumTabSizeHint(int index) const
Returns the minimum tab size hint for the tab at position index.
Definition qtabbar.cpp:1551
void setTabButton(int index, ButtonPosition position, QWidget *widget)
Sets widget on the tab index.
Definition qtabbar.cpp:2791
bool movable
This property holds whether the user can move the tabs within the tabbar area.
Definition qtabbar.h:33
void paintEvent(QPaintEvent *) override
\reimp
Definition qtabbar.cpp:1801
void setSelectionBehaviorOnRemove(SelectionBehavior behavior)
Definition qtabbar.cpp:2643
int count
the number of tabs in the tab bar
Definition qtabbar.h:24
int currentIndex
the index of the tab bar's visible tab
Definition qtabbar.h:23
bool event(QEvent *) override
\reimp
Definition qtabbar.cpp:1672
void setShape(Shape shape)
Definition qtabbar.cpp:878
QSize sizeHint() const override
\reimp
Definition qtabbar.cpp:1487
QString tabText(int index) const
Returns the text of the tab at position index, or an empty string if index is out of range.
Definition qtabbar.cpp:1178
void setTabData(int index, const QVariant &data)
Sets the data of the tab at position index to data.
Definition qtabbar.cpp:1319
void mousePressEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2122
bool drawBase
defines whether or not tab bar should draw its base.
Definition qtabbar.h:25
virtual void tabRemoved(int index)
This virtual handler is called after a tab was removed from position index.
Definition qtabbar.cpp:1633
void setCurrentIndex(int index)
Definition qtabbar.cpp:1400
void setTabText(int index, const QString &text)
Sets the text of the tab at position index to text.
Definition qtabbar.cpp:1189
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.
Definition qtabbar.cpp:202
bool expanding
When expanding is true QTabBar will expand the tabs to use the empty space.
Definition qtabbar.h:32
void removeTab(int index)
Removes the tab at position index.
Definition qtabbar.cpp:1009
bool isMovable() const
Definition qtabbar.cpp:2684
void tabBarDoubleClicked(int index)
This signal is emitted when the user double clicks on a tab at index.
void setDocumentMode(bool set)
Definition qtabbar.cpp:2713
bool usesScrollButtons
Whether or not a tab bar should use buttons to scroll tabs when it has many tabs.
Definition qtabbar.h:28
QIcon tabIcon(int index) const
Returns the icon of the tab at position index, or a null icon if index is out of range.
Definition qtabbar.cpp:1238
void setIconSize(const QSize &size)
Definition qtabbar.cpp:1464
QVariant tabData(int index) const
Returns the data of the tab at position index, or a null variant if index is out of range.
Definition qtabbar.cpp:1330
void setAutoHide(bool hide)
Definition qtabbar.cpp:2738
void showEvent(QShowEvent *) override
\reimp
Definition qtabbar.cpp:1650
void mouseReleaseEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2312
void mouseDoubleClickEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2350
void hideEvent(QHideEvent *) override
\reimp
Definition qtabbar.cpp:1664
void resizeEvent(QResizeEvent *) override
\reimp
Definition qtabbar.cpp:1787
void setTabVisible(int index, bool visible)
If visible is true, make the tab at position index visible, otherwise make it hidden.
Definition qtabbar.cpp:1149
bool isTabEnabled(int index) const
Returns true if the tab at position index is enabled; otherwise returns false.
Definition qtabbar.cpp:1102
~QTabBar()
Destroys the tab bar.
Definition qtabbar.cpp:860
void timerEvent(QTimerEvent *event) override
\reimp
Definition qtabbar.cpp:2475
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.
Definition qtabbar.cpp:1210
void mouseMoveEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2160
void setTabIcon(int index, const QIcon &icon)
Sets the icon of the tab at position index to icon.
Definition qtabbar.cpp:1249
virtual void tabInserted(int index)
This virtual handler is called after a new tab was added or inserted at position index.
Definition qtabbar.cpp:1622
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...
Definition qtabbar.cpp:1114
void tabMoved(int from, int to)
void keyPressEvent(QKeyEvent *) override
\reimp
Definition qtabbar.cpp:2364
void setDrawBase(bool drawTheBase)
Definition qtabbar.cpp:897
QSize iconSize
The size for icons in the tab bar.
Definition qtabbar.h:26
QRect tabRect(int index) const
Returns the visual rectangle of the tab at position index, or a null rectangle if index is hidden,...
Definition qtabbar.cpp:1342
Shape shape
the shape of the tabs in the tab bar
Definition qtabbar.h:22
void moveTab(int from, int to)
Moves the item at index position from to index position to.
Definition qtabbar.cpp:2007
SelectionBehavior selectionBehaviorOnRemove
What tab should be set as current when removeTab is called if the removed tab is also the current tab...
Definition qtabbar.h:31
bool autoHide
If true, the tab bar is automatically hidden when it contains less than 2 tabs.
Definition qtabbar.h:35
void setMovable(bool movable)
Definition qtabbar.cpp:2690
int insertTab(int index, const QString &text)
Inserts a new tab with text text at position index.
Definition qtabbar.cpp:937
void setTabTextColor(int index, const QColor &color)
Sets the color of the text in the tab with the given index to the specified color.
Definition qtabbar.cpp:1225
int tabAt(const QPoint &pos) const
Definition qtabbar.cpp:1368
SelectionBehavior
Definition qtabbar.h:52
@ SelectLeftTab
Definition qtabbar.h:53
@ SelectPreviousTab
Definition qtabbar.h:55
@ SelectRightTab
Definition qtabbar.h:54
bool changeCurrentOnDrag
If true, then the current tab is automatically changed when dragging over the tabbar.
Definition qtabbar.h:36
int addTab(const QString &text)
Adds a new tab with text text.
Definition qtabbar.cpp:916
QTabBar(QWidget *parent=nullptr)
Creates a new tab bar with the given parent.
Definition qtabbar.cpp:849
void setElideMode(Qt::TextElideMode mode)
Definition qtabbar.cpp:2506
QWidget * tabButton(int index, ButtonPosition position) const
Returns the widget set a tab index and position or \nullptr if one is not set.
Definition qtabbar.cpp:2821
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.
Definition qtabbar.h:34
void changeEvent(QEvent *) override
\reimp
Definition qtabbar.cpp:2451
Shape
This enum type lists the built-in shapes supported by QTabBar.
Definition qtabbar.h:42
bool isTabVisible(int index) const
Returns true if the tab at position index is visible; otherwise returns false.
Definition qtabbar.cpp:1136
void setExpanding(bool enabled)
Definition qtabbar.cpp:2665
virtual void tabLayoutChange()
This virtual handler is called whenever the tab layout changes.
Definition qtabbar.cpp:1643
QSize minimumSizeHint() const override
\reimp
Definition qtabbar.cpp:1502
virtual QSize tabSizeHint(int index) const
Returns the size hint for the tab at position index.
Definition qtabbar.cpp:1565
void setChangeCurrentOnDrag(bool change)
Definition qtabbar.cpp:2769
bool tabsClosable
Whether or not a tab bar should place close buttons on each tab.
Definition qtabbar.h:29
The QTabWidget class provides a stack of tabbed widgets.
Definition qtabwidget.h:20
\inmodule QtCore
Definition qcoreevent.h:366
The QToolButton class provides a quick-access button to commands or options, usually used inside a QT...
Definition qtoolbutton.h:20
void setArrowType(Qt::ArrowType type)
static void showText(const QPoint &pos, const QString &text, QWidget *w=nullptr, const QRect &rect={}, int msecShowTime=-1)
Shows text as a tool tip, with the global position pos as the point of interest.
Definition qtooltip.cpp:439
\inmodule QtCore
Definition qvariant.h:65
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.
void scrollRect(const QRect &, int dx, int dy)
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void repaint()
Repaints the widget directly by calling paintEvent() immediately, unless updates are disabled or the ...
void releaseShortcut(int id)
Removes the shortcut with the given id from Qt's shortcut system.
void setGeometry(int x, int y, int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:886
void raise()
Raises this widget to the top of the parent widget's stack.
Qt::LayoutDirection layoutDirection
the layout direction for this widget.
Definition qwidget.h:170
virtual void leaveEvent(QEvent *event)
This event handler can be reimplemented in a subclass to receive widget leave events which are passed...
Definition qwidget.cpp:9731
void setParent(QWidget *parent)
Sets the parent of the widget to parent, and resets the window flags.
void updateGeometry()
Notifies the layout system that this widget has changed and may need to change geometry.
void setSizePolicy(QSizePolicy)
bool isHidden() const
Returns true if the widget is hidden, otherwise returns false.
Definition qwidget.h:877
QSize size
the size of the widget excluding any window frame
Definition qwidget.h:113
void setEnabled(bool)
Definition qwidget.cpp:3358
int width
the width of the widget excluding any window frame
Definition qwidget.h:114
QPoint pos
the position of the widget within its parent widget
Definition qwidget.h:111
void move(int x, int y)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:880
QFontMetrics fontMetrics() const
Returns the font metrics for the widget's current font.
Definition qwidget.h:847
void setFocusPolicy(Qt::FocusPolicy policy)
Definition qwidget.cpp:7822
void hide()
Hides the widget.
Definition qwidget.cpp:8135
int height
the height of the widget excluding any window frame
Definition qwidget.h:115
QRect rect
the internal geometry of the widget excluding any window frame
Definition qwidget.h:116
void show()
Shows the widget and its child widgets.
Definition qwidget.cpp:7875
virtual void setVisible(bool visible)
Definition qwidget.cpp:8255
virtual void enterEvent(QEnterEvent *event)
This event handler can be reimplemented in a subclass to receive widget enter events which are passed...
Definition qwidget.cpp:9715
void lower()
Lowers the widget to the bottom of the parent widget's stack.
void update()
Updates the widget unless updates are disabled or the widget is hidden.
virtual void changeEvent(QEvent *)
This event handler can be reimplemented to handle state changes.
Definition qwidget.cpp:9382
void setShortcutEnabled(int id, bool enable=true)
If enable is true, the shortcut with the given id is enabled; otherwise the shortcut is disabled.
bool isRightToLeft() const
Definition qwidget.h:419
bool enabled
whether the widget is enabled
Definition qwidget.h:105
bool event(QEvent *event) override
This is the main event handler; it handles event event.
Definition qwidget.cpp:8866
int grabShortcut(const QKeySequence &key, Qt::ShortcutContext context=Qt::WindowShortcut)
Adds a shortcut to Qt's shortcut system that watches for the given key sequence in the given context.
QStyle * style() const
Definition qwidget.cpp:2600
void resize(int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:883
bool hasFocus() const
Definition qwidget.cpp:6446
bool isVisible() const
Definition qwidget.h:874
void setCursor(const QCursor &)
Definition qwidget.cpp:4960
bool visible
whether the widget is visible
Definition qwidget.h:144
\inmodule QtGui
Definition qwindow.h:63
QOpenGLWidget * widget
[1]
QString text
QSet< QString >::iterator it
rect
[4]
direction
QStyleOptionButton opt
QRect textRect
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
bool isEnabled()
@ BottomLeftCorner
@ TopRightCorner
@ TopLeftCorner
@ BottomRightCorner
@ AlignRight
Definition qnamespace.h:146
@ AlignJustify
Definition qnamespace.h:149
@ AlignLeft
Definition qnamespace.h:144
@ LeftButton
Definition qnamespace.h:58
@ NoButton
Definition qnamespace.h:57
@ RightToLeft
@ NoFocus
Definition qnamespace.h:107
@ TabFocus
Definition qnamespace.h:108
@ UpArrow
@ RightArrow
@ LeftArrow
@ DownArrow
@ TextShowMnemonic
Definition qnamespace.h:173
@ ArrowCursor
@ transparent
Definition qnamespace.h:47
@ Key_Right
Definition qnamespace.h:679
@ Key_Left
Definition qnamespace.h:677
TextElideMode
Definition qnamespace.h:188
@ ElideMiddle
Definition qnamespace.h:191
@ ElideRight
Definition qnamespace.h:190
@ ElideNone
Definition qnamespace.h:192
@ ElideLeft
Definition qnamespace.h:189
#define Q_FALLTHROUGH()
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)
return ret
static const QMetaObjectPrivate * priv(const uint *data)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLenum GLuint GLenum GLsizei length
GLuint object
[3]
GLdouble GLdouble right
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei width
GLuint color
[2]
GLboolean enable
GLuint start
GLenum GLuint GLintptr offset
GLuint name
GLint y
struct _cl_event * event
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
GLuint GLenum option
decorationRoleName setToolTip
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QString computeElidedText(Qt::TextElideMode mode, const QString &text)
Definition qtabbar.cpp:1522
#define ANIMATION_DURATION
Definition qtabbar_p.h:29
constexpr bool verticalTabs(QTabBar::Shape shape) noexcept
Definition qtabbar_p.h:248
#define tr(X)
#define Q_OBJECT
#define emit
#define Q_UNUSED(x)
size_t quintptr
Definition qtypes.h:167
settings remove("monkey")
edit hide()
widget render & pixmap
aWidget window() -> setWindowTitle("New Window Title")
[2]
QAction * at
QWidget * leftWidget
Definition qtabbar_p.h:132
QWidget * rightWidget
Definition qtabbar_p.h:133