Qt 6.x
The Qt SDK
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
58{
59}
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);
370 leftB->hide();
371 rightB = new QToolButton(q);
372 rightB->setObjectName(u"ScrollRightButton"_s);
373 rightB->setAutoRepeat(true);
375 rightB->hide();
376#ifdef QT_KEYPAD_NAVIGATION
377 if (QApplicationPrivate::keypadNavigationEnabled()) {
380 q->setFocusPolicy(Qt::NoFocus);
381 } else
382#endif
383 q->setFocusPolicy(Qt::TabFocus);
384
385#if QT_CONFIG(accessibility)
386 leftB->setAccessibleName(QTabBar::tr("Scroll Left"));
387 rightB->setAccessibleName(QTabBar::tr("Scroll Right"));
388#endif
390 elideMode = Qt::TextElideMode(q->style()->styleHint(QStyle::SH_TabBar_ElideMode, nullptr, q));
391 useScrollButtons = !q->style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, nullptr, q);
392}
393
395{
396 Q_Q(const QTabBar);
397 if (q->tabRect(currentIndex).contains(p))
398 return currentIndex;
399 for (int i = 0; i < tabList.size(); ++i)
400 if (tabList.at(i)->enabled && q->tabRect(i).contains(p))
401 return i;
402 return -1;
403}
404
406{
407 Q_Q(QTabBar);
408 layoutDirty = false;
409 QSize size = q->size();
410 int last, available;
411 int maxExtent;
412 bool vertTabs = verticalTabs(shape);
413 int tabChainIndex = 0;
414 int hiddenTabs = 0;
415
416 Qt::Alignment tabAlignment = Qt::Alignment(q->style()->styleHint(QStyle::SH_TabBar_Alignment, nullptr, q));
417 QList<QLayoutStruct> tabChain(tabList.size() + 2);
418
419 // We put an empty item at the front and back and set its expansive attribute
420 // depending on tabAlignment and expanding.
421 tabChain[tabChainIndex].init();
422 tabChain[tabChainIndex].expansive = (!expanding)
423 && (tabAlignment != Qt::AlignLeft)
424 && (tabAlignment != Qt::AlignJustify);
425 tabChain[tabChainIndex].empty = true;
426 ++tabChainIndex;
427
428 // We now go through our list of tabs and set the minimum size and the size hint
429 // This will allow us to elide text if necessary. Since we don't set
430 // a maximum size, tabs will EXPAND to fill up the empty space.
431 // Since tab widget is rather *ahem* strict about keeping the geometry of the
432 // tab bar to its absolute minimum, this won't bleed through, but will show up
433 // if you use tab bar on its own (a.k.a. not a bug, but a feature).
434 // Update: if expanding is false, we DO set a maximum size to prevent the tabs
435 // being wider than necessary.
436 if (!vertTabs) {
437 int minx = 0;
438 int x = 0;
439 int maxHeight = 0;
440 for (int i = 0; i < tabList.size(); ++i) {
441 const auto tab = tabList.at(i);
442 if (!tab->visible) {
443 ++hiddenTabs;
444 continue;
445 }
446 QSize sz = q->tabSizeHint(i);
447 tab->maxRect = QRect(x, 0, sz.width(), sz.height());
448 x += sz.width();
449 maxHeight = qMax(maxHeight, sz.height());
450 sz = q->minimumTabSizeHint(i);
451 tab->minRect = QRect(minx, 0, sz.width(), sz.height());
452 minx += sz.width();
453 tabChain[tabChainIndex].init();
454 tabChain[tabChainIndex].sizeHint = tab->maxRect.width();
455 tabChain[tabChainIndex].minimumSize = sz.width();
456 tabChain[tabChainIndex].empty = false;
457 tabChain[tabChainIndex].expansive = true;
458
459 if (!expanding)
460 tabChain[tabChainIndex].maximumSize = tabChain[tabChainIndex].sizeHint;
461 ++tabChainIndex;
462 }
463
464 last = minx;
465 available = size.width();
466 maxExtent = maxHeight;
467 } else {
468 int miny = 0;
469 int y = 0;
470 int maxWidth = 0;
471 for (int i = 0; i < tabList.size(); ++i) {
472 auto tab = tabList.at(i);
473 if (!tab->visible) {
474 ++hiddenTabs;
475 continue;
476 }
477 QSize sz = q->tabSizeHint(i);
478 tab->maxRect = QRect(0, y, sz.width(), sz.height());
479 y += sz.height();
480 maxWidth = qMax(maxWidth, sz.width());
481 sz = q->minimumTabSizeHint(i);
482 tab->minRect = QRect(0, miny, sz.width(), sz.height());
483 miny += sz.height();
484 tabChain[tabChainIndex].init();
485 tabChain[tabChainIndex].sizeHint = tab->maxRect.height();
486 tabChain[tabChainIndex].minimumSize = sz.height();
487 tabChain[tabChainIndex].empty = false;
488 tabChain[tabChainIndex].expansive = true;
489
490 if (!expanding)
491 tabChain[tabChainIndex].maximumSize = tabChain[tabChainIndex].sizeHint;
492 ++tabChainIndex;
493 }
494
495 last = miny;
496 available = size.height();
497 maxExtent = maxWidth;
498 }
499
500 // Mirror our front item.
501 tabChain[tabChainIndex].init();
502 tabChain[tabChainIndex].expansive = (!expanding)
503 && (tabAlignment != Qt::AlignRight)
504 && (tabAlignment != Qt::AlignJustify);
505 tabChain[tabChainIndex].empty = true;
506 Q_ASSERT(tabChainIndex == tabChain.size() - 1 - hiddenTabs); // add an assert just to make sure.
507
508 // Do the calculation
509 qGeomCalc(tabChain, 0, tabChain.size(), 0, qMax(available, last), 0);
510
511 // Use the results
512 hiddenTabs = 0;
513 for (int i = 0; i < tabList.size(); ++i) {
514 auto tab = tabList.at(i);
515 if (!tab->visible) {
516 tab->rect = QRect();
517 ++hiddenTabs;
518 continue;
519 }
520 const QLayoutStruct &lstruct = tabChain.at(i + 1 - hiddenTabs);
521 if (!vertTabs)
522 tab->rect.setRect(lstruct.pos, 0, lstruct.size, maxExtent);
523 else
524 tab->rect.setRect(0, lstruct.pos, maxExtent, lstruct.size);
525 }
526
527 if (useScrollButtons && tabList.size() && last > available) {
529
530 Q_Q(QTabBar);
532 opt.initFrom(q);
533 QRect scrollButtonLeftRect = q->style()->subElementRect(QStyle::SE_TabBarScrollLeftButton, &opt, q);
534 QRect scrollButtonRightRect = q->style()->subElementRect(QStyle::SE_TabBarScrollRightButton, &opt, q);
535 int scrollButtonWidth = q->style()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, &opt, q);
536
537 // Normally SE_TabBarScrollLeftButton should have the same width as PM_TabBarScrollButtonWidth.
538 // But if that is not the case, we set the actual button width to PM_TabBarScrollButtonWidth, and
539 // use the extra space from SE_TabBarScrollLeftButton as margins towards the tabs.
540 if (vertTabs) {
541 scrollButtonLeftRect.setHeight(scrollButtonWidth);
542 scrollButtonRightRect.setY(scrollButtonRightRect.bottom() + 1 - scrollButtonWidth);
543 scrollButtonRightRect.setHeight(scrollButtonWidth);
546 } else if (q->layoutDirection() == Qt::RightToLeft) {
547 scrollButtonRightRect.setWidth(scrollButtonWidth);
548 scrollButtonLeftRect.setX(scrollButtonLeftRect.right() + 1 - scrollButtonWidth);
549 scrollButtonLeftRect.setWidth(scrollButtonWidth);
552 } else {
553 scrollButtonLeftRect.setWidth(scrollButtonWidth);
554 scrollButtonRightRect.setX(scrollButtonRightRect.right() + 1 - scrollButtonWidth);
555 scrollButtonRightRect.setWidth(scrollButtonWidth);
558 }
559
560 leftB->setGeometry(scrollButtonLeftRect);
561 leftB->setEnabled(false);
562 leftB->show();
563
564 rightB->setGeometry(scrollButtonRightRect);
565 rightB->setEnabled(last + scrollRect.left() > scrollRect.x() + scrollRect.width());
566 rightB->show();
567 } else {
568 rightB->hide();
569 leftB->hide();
570 }
571
573 q->tabLayoutChange();
574}
575
577{
578 // "Normalized scroll rect" means return the free space on the tab bar
579 // that doesn't overlap with scroll buttons or tear indicators, and
580 // always return the rect as horizontal Qt::LeftToRight, even if the
581 // tab bar itself is in a different orientation.
582
583 Q_Q(QTabBar);
584 // If scrollbuttons are not visible, then there's no tear either, and
585 // the entire widget is the scroll rect.
586 if (leftB->isHidden())
587 return verticalTabs(shape) ? q->rect().transposed() : q->rect();
588
589 QStyleOptionTab opt;
590 q->initStyleOption(&opt, currentIndex);
591 opt.rect = q->rect();
592
593 QRect scrollButtonLeftRect = q->style()->subElementRect(QStyle::SE_TabBarScrollLeftButton, &opt, q);
594 QRect scrollButtonRightRect = q->style()->subElementRect(QStyle::SE_TabBarScrollRightButton, &opt, q);
595 QRect tearLeftRect = q->style()->subElementRect(QStyle::SE_TabBarTearIndicatorLeft, &opt, q);
596 QRect tearRightRect = q->style()->subElementRect(QStyle::SE_TabBarTearIndicatorRight, &opt, q);
597
598 if (verticalTabs(shape)) {
599 int topEdge, bottomEdge;
600 bool leftButtonIsOnTop = scrollButtonLeftRect.y() < q->height() / 2;
601 bool rightButtonIsOnTop = scrollButtonRightRect.y() < q->height() / 2;
602
603 if (leftButtonIsOnTop && rightButtonIsOnTop) {
604 topEdge = scrollButtonRightRect.bottom() + 1;
605 bottomEdge = q->height();
606 } else if (!leftButtonIsOnTop && !rightButtonIsOnTop) {
607 topEdge = 0;
608 bottomEdge = scrollButtonLeftRect.top();
609 } else {
610 topEdge = scrollButtonLeftRect.bottom() + 1;
611 bottomEdge = scrollButtonRightRect.top();
612 }
613
614 bool tearTopVisible = index != 0 && topEdge != -scrollOffset;
615 bool tearBottomVisible = index != tabList.size() - 1 && bottomEdge != tabList.constLast()->rect.bottom() + 1 - scrollOffset;
616 if (tearTopVisible && !tearLeftRect.isNull())
617 topEdge = tearLeftRect.bottom() + 1;
618 if (tearBottomVisible && !tearRightRect.isNull())
619 bottomEdge = tearRightRect.top();
620
621 return QRect(topEdge, 0, bottomEdge - topEdge, q->height());
622 } else {
623 if (q->layoutDirection() == Qt::RightToLeft) {
624 scrollButtonLeftRect = QStyle::visualRect(Qt::RightToLeft, q->rect(), scrollButtonLeftRect);
625 scrollButtonRightRect = QStyle::visualRect(Qt::RightToLeft, q->rect(), scrollButtonRightRect);
626 tearLeftRect = QStyle::visualRect(Qt::RightToLeft, q->rect(), tearLeftRect);
627 tearRightRect = QStyle::visualRect(Qt::RightToLeft, q->rect(), tearRightRect);
628 }
629
630 int leftEdge, rightEdge;
631 bool leftButtonIsOnLeftSide = scrollButtonLeftRect.x() < q->width() / 2;
632 bool rightButtonIsOnLeftSide = scrollButtonRightRect.x() < q->width() / 2;
633
634 if (leftButtonIsOnLeftSide && rightButtonIsOnLeftSide) {
635 leftEdge = scrollButtonRightRect.right() + 1;
636 rightEdge = q->width();
637 } else if (!leftButtonIsOnLeftSide && !rightButtonIsOnLeftSide) {
638 leftEdge = 0;
639 rightEdge = scrollButtonLeftRect.left();
640 } else {
641 leftEdge = scrollButtonLeftRect.right() + 1;
642 rightEdge = scrollButtonRightRect.left();
643 }
644
645 bool tearLeftVisible = index != 0 && leftEdge != -scrollOffset;
646 bool tearRightVisible = index != tabList.size() - 1 && rightEdge != tabList.constLast()->rect.right() + 1 - scrollOffset;
647 if (tearLeftVisible && !tearLeftRect.isNull())
648 leftEdge = tearLeftRect.right() + 1;
649 if (tearRightVisible && !tearRightRect.isNull())
650 rightEdge = tearRightRect.left();
651
652 return QRect(leftEdge, 0, rightEdge - leftEdge, q->height());
653 }
654}
655
657{
658 if (dragInProgress)
659 return currentIndex;
660 if (hoverIndex >= 0)
661 return hoverIndex;
662 return -1;
663}
664
666{
667 Q_Q(QTabBar);
668 if (!validIndex(index))
669 return;
670
671 const QRect tabRect = tabList.at(index)->rect;
672 const int oldScrollOffset = scrollOffset;
673 const bool horiz = !verticalTabs(shape);
674 const int available = horiz ? q->width() : q->height();
675 const int tabStart = horiz ? tabRect.left() : tabRect.top();
676 const int tabEnd = horiz ? tabRect.right() : tabRect.bottom();
677 const int lastTabEnd = horiz ? tabList.constLast()->rect.right() : tabList.constLast()->rect.bottom();
679 const QRect entireScrollRect = normalizedScrollRect(0); // ignore tears
680 const int scrolledTabBarStart = qMax(1, scrollRect.left() + scrollOffset);
681 const int scrolledTabBarEnd = qMin(lastTabEnd - 1, scrollRect.right() + scrollOffset);
682
683 if (tabStart < scrolledTabBarStart) {
684 // Tab is outside on the left, so scroll left.
685 scrollOffset = tabStart - scrollRect.left();
686 } else if (tabEnd > scrolledTabBarEnd) {
687 // Tab is outside on the right, so scroll right.
688 scrollOffset = qMax(0, tabEnd - scrollRect.right());
689 } else if (scrollOffset + entireScrollRect.width() > lastTabEnd + 1) {
690 // fill any free space on the right without overshooting
691 scrollOffset = qMax(0, lastTabEnd - entireScrollRect.width() + 1);
692 } else if (available >= lastTabEnd) {
693 // the entire tabbar fits, reset scroll
694 scrollOffset = 0;
695 }
696
698 rightB->setEnabled(scrollOffset < lastTabEnd - scrollRect.right());
699
700 if (oldScrollOffset != scrollOffset) {
701 q->update();
703 }
704}
705
707{
708 Q_Q(QTabBar);
709 if (switchTabTimerId) {
710 q->killTimer(switchTabTimerId);
712 }
714}
715
717{
718 Q_Q(QTabBar);
719 Q_ASSERT(index >= 0);
720
721 const Tab *tab = tabList.at(index);
722 bool vertical = verticalTabs(shape);
723 if (!(tab->leftWidget || tab->rightWidget))
724 return;
725
726 QStyleOptionTab opt;
727 q->initStyleOption(&opt, index);
728 if (tab->leftWidget) {
729 QRect rect = q->style()->subElementRect(QStyle::SE_TabBarTabLeftButton, &opt, q);
730 QPoint p = rect.topLeft();
731 if ((index == pressedIndex) || paintWithOffsets) {
732 if (vertical)
733 p.setY(p.y() + tab->dragOffset);
734 else
735 p.setX(p.x() + tab->dragOffset);
736 }
737 tab->leftWidget->move(p);
738 }
739 if (tab->rightWidget) {
740 QRect rect = q->style()->subElementRect(QStyle::SE_TabBarTabRightButton, &opt, q);
741 QPoint p = rect.topLeft();
742 if ((index == pressedIndex) || paintWithOffsets) {
743 if (vertical)
744 p.setY(p.y() + tab->dragOffset);
745 else
746 p.setX(p.x() + tab->dragOffset);
747 }
748 tab->rightWidget->move(p);
749 }
750}
751
753{
754 Q_Q(QTabBar);
755 for (int i = start; i < q->count(); ++i) {
756 layoutTab(i);
757 }
758}
759
761{
762 Q_Q(QTabBar);
763
764 if (autoHide)
765 q->setVisible(q->count() > 1);
766}
767
769{
770 Q_Q(QTabBar);
771 QObject *object = q->sender();
772 int tabToClose = -1;
774 for (int i = 0; i < tabList.size(); ++i) {
775 if (closeSide == QTabBar::LeftSide) {
776 if (tabList.at(i)->leftWidget == object) {
777 tabToClose = i;
778 break;
779 }
780 } else {
781 if (tabList.at(i)->rightWidget == object) {
782 tabToClose = i;
783 break;
784 }
785 }
786 }
787 if (tabToClose != -1)
788 emit q->tabCloseRequested(tabToClose);
789}
790
792{
793 Q_Q(QTabBar);
794 const QObject *sender = q->sender();
795 const bool horizontal = !verticalTabs(shape);
797
798 int i = -1;
799
800 if (sender == leftB) {
801 for (i = tabList.size() - 1; i >= 0; --i) {
802 int start = horizontal ? tabList.at(i)->rect.left() : tabList.at(i)->rect.top();
803 if (start < scrollRect.left()) {
804 makeVisible(i);
805 return;
806 }
807 }
808 } else if (sender == rightB) {
809 for (i = 0; i < tabList.size(); ++i) {
810 const auto tabRect = tabList.at(i)->rect;
811 int start = horizontal ? tabRect.left() : tabRect.top();
812 int end = horizontal ? tabRect.right() : tabRect.bottom();
813 if (end > scrollRect.right() && start > scrollOffset) {
814 makeVisible(i);
815 return;
816 }
817 }
818 }
819}
820
822{
823 Q_Q(QTabBar);
824
825 // be safe in case a subclass is also handling move with the tabs
826 if (pressedIndex != -1
827 && movable
831 pressedIndex = -1;
832 }
833
834 if (!q->isVisible()) {
835 layoutDirty = true;
836 } else {
837 layoutTabs();
839 q->update();
840 q->updateGeometry();
841 }
842}
843
848 :QWidget(*new QTabBarPrivate, parent, { })
849{
850 Q_D(QTabBar);
851 d->init();
852}
853
854
859{
860}
861
871{
872 Q_D(const QTabBar);
873 return d->shape;
874}
875
877{
878 Q_D(QTabBar);
879 if (d->shape == shape)
880 return;
881 d->shape = shape;
882 d->refresh();
883}
884
895void QTabBar::setDrawBase(bool drawBase)
896{
897 Q_D(QTabBar);
898 if (d->drawBase == drawBase)
899 return;
900 d->drawBase = drawBase;
901 update();
902}
903
905{
906 Q_D(const QTabBar);
907 return d->drawBase;
908}
909
915{
916 return insertTab(-1, text);
917}
918
926{
927 return insertTab(-1, icon, text);
928}
929
936{
937 return insertTab(index, QIcon(), text);
938}
939
953{
954 Q_D(QTabBar);
955 if (!d->validIndex(index)) {
956 index = d->tabList.size();
957 d->tabList.append(new QTabBarPrivate::Tab(icon, text));
958 } else {
959 d->tabList.insert(index, new QTabBarPrivate::Tab(icon, text));
960 }
961#ifndef QT_NO_SHORTCUT
962 d->tabList.at(index)->shortcutId = grabShortcut(QKeySequence::mnemonic(text));
963#endif
964 d->firstVisible = qMax(qMin(index, d->firstVisible), 0);
965 d->refresh();
966 if (d->tabList.size() == 1)
968 else if (index <= d->currentIndex)
969 ++d->currentIndex;
970
971 if (index <= d->lastVisible)
972 ++d->lastVisible;
973 else
974 d->lastVisible = index;
975
976 if (d->closeButtonOnTabs) {
977 QStyleOptionTab opt;
980 QAbstractButton *closeButton = new CloseButton(this);
981 connect(closeButton, SIGNAL(clicked()), this, SLOT(_q_closeTab()));
982 setTabButton(index, closeSide, closeButton);
983 }
984
985 for (const auto tab : std::as_const(d->tabList)) {
986 if (tab->lastTab >= index)
987 ++tab->lastTab;
988 }
989
990 if (tabAt(d->mousePosition) == index) {
991 d->hoverIndex = index;
992 d->hoverRect = tabRect(index);
993 }
994
996 d->autoHideTabs();
997 return index;
998}
999
1000
1007{
1008 Q_D(QTabBar);
1009 if (d->validIndex(index)) {
1010 auto removedTab = d->tabList.at(index);
1011 if (d->dragInProgress)
1012 d->moveTabFinished(d->pressedIndex);
1013
1014#ifndef QT_NO_SHORTCUT
1015 releaseShortcut(d->tabList.at(index)->shortcutId);
1016#endif
1017 if (removedTab->leftWidget) {
1018 removedTab->leftWidget->hide();
1019 removedTab->leftWidget->deleteLater();
1020 removedTab->leftWidget = nullptr;
1021 }
1022 if (removedTab->rightWidget) {
1023 removedTab->rightWidget->hide();
1024 removedTab->rightWidget->deleteLater();
1025 removedTab->rightWidget = nullptr;
1026 }
1027
1028 int newIndex = removedTab->lastTab;
1029 d->tabList.removeAt(index);
1030 delete removedTab;
1031 for (auto tab : std::as_const(d->tabList)) {
1032 if (tab->lastTab == index)
1033 tab->lastTab = -1;
1034 if (tab->lastTab > index)
1035 --tab->lastTab;
1036 }
1037
1038 d->calculateFirstLastVisible(index, false, true);
1039
1040 if (index == d->currentIndex) {
1041 // The current tab is going away, in order to make sure
1042 // we emit that "current has changed", we need to reset this
1043 // around.
1044 d->currentIndex = -1;
1045 if (d->tabList.size() > 0) {
1046 switch(d->selectionBehaviorOnRemove) {
1047 case SelectPreviousTab:
1048 if (newIndex > index)
1049 newIndex--;
1050 if (d->validIndex(newIndex) && d->tabList.at(newIndex)->visible)
1051 break;
1052 Q_FALLTHROUGH();
1053 case SelectRightTab:
1054 newIndex = qBound(d->firstVisible, index, d->lastVisible);
1055 break;
1056 case SelectLeftTab:
1057 newIndex = qBound(d->firstVisible, index-1, d->lastVisible);
1058 break;
1059 default:
1060 break;
1061 }
1062
1063 if (d->validIndex(newIndex)) {
1064 // don't loose newIndex's old through setCurrentIndex
1065 int bump = d->tabList.at(newIndex)->lastTab;
1066 setCurrentIndex(newIndex);
1067 d->tabList.at(newIndex)->lastTab = bump;
1068 } else {
1069 // we had a valid current index, but there are no visible tabs left
1070 emit currentChanged(-1);
1071 }
1072 } else {
1073 emit currentChanged(-1);
1074 }
1075 } else if (index < d->currentIndex) {
1076 setCurrentIndex(d->currentIndex - 1);
1077 }
1078 d->refresh();
1079 d->autoHideTabs();
1080 if (d->hoverRect.isValid()) {
1081 update(d->hoverRect);
1082 d->hoverIndex = tabAt(d->mousePosition);
1083 if (d->validIndex(d->hoverIndex)) {
1084 d->hoverRect = tabRect(d->hoverIndex);
1085 update(d->hoverRect);
1086 } else {
1087 d->hoverRect = QRect();
1088 }
1089 }
1091 }
1092}
1093
1094
1100{
1101 Q_D(const QTabBar);
1102 if (const QTabBarPrivate::Tab *tab = d->at(index))
1103 return tab->enabled;
1104 return false;
1105}
1106
1112{
1113 Q_D(QTabBar);
1114 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1115 tab->enabled = enabled;
1116#ifndef QT_NO_SHORTCUT
1117 setShortcutEnabled(tab->shortcutId, enabled);
1118#endif
1119 update();
1120 if (!enabled && index == d->currentIndex)
1121 setCurrentIndex(d->selectNewCurrentIndexFrom(index+1));
1122 else if (enabled && !isTabVisible(d->currentIndex))
1123 setCurrentIndex(d->selectNewCurrentIndexFrom(index));
1124 }
1125}
1126
1127
1134{
1135 Q_D(const QTabBar);
1136 if (d->validIndex(index))
1137 return d->tabList.at(index)->visible;
1138 return false;
1139}
1140
1146void QTabBar::setTabVisible(int index, bool visible)
1147{
1148 Q_D(QTabBar);
1149 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1150 d->layoutDirty = (visible != tab->visible);
1151 if (!d->layoutDirty)
1152 return;
1153 tab->visible = visible;
1154 if (tab->leftWidget)
1155 tab->leftWidget->setVisible(visible);
1156 if (tab->rightWidget)
1157 tab->rightWidget->setVisible(visible);
1158#ifndef QT_NO_SHORTCUT
1159 setShortcutEnabled(tab->shortcutId, visible);
1160#endif
1161 d->calculateFirstLastVisible(index, visible, false);
1162 if (!visible && index == d->currentIndex) {
1163 const int newindex = d->selectNewCurrentIndexFrom(index+1);
1164 setCurrentIndex(newindex);
1165 }
1166 update();
1167 }
1168}
1169
1170
1176{
1177 Q_D(const QTabBar);
1178 if (const QTabBarPrivate::Tab *tab = d->at(index))
1179 return tab->text;
1180 return QString();
1181}
1182
1187{
1188 Q_D(QTabBar);
1189 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1190 d->textSizes.remove(tab->text);
1191 tab->text = text;
1192#ifndef QT_NO_SHORTCUT
1193 releaseShortcut(tab->shortcutId);
1194 tab->shortcutId = grabShortcut(QKeySequence::mnemonic(text));
1195 setShortcutEnabled(tab->shortcutId, tab->enabled);
1196#endif
1197 d->refresh();
1198 }
1199}
1200
1208{
1209 Q_D(const QTabBar);
1210 if (const QTabBarPrivate::Tab *tab = d->at(index))
1211 return tab->textColor;
1212 return QColor();
1213}
1214
1223{
1224 Q_D(QTabBar);
1225 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1226 tab->textColor = color;
1228 }
1229}
1230
1236{
1237 Q_D(const QTabBar);
1238 if (const QTabBarPrivate::Tab *tab = d->at(index))
1239 return tab->icon;
1240 return QIcon();
1241}
1242
1247{
1248 Q_D(QTabBar);
1249 if (QTabBarPrivate::Tab *tab = d->at(index)) {
1250 bool simpleIconChange = (!icon.isNull() && !tab->icon.isNull());
1251 tab->icon = icon;
1252 if (simpleIconChange)
1254 else
1255 d->refresh();
1256 }
1257}
1258
1259#if QT_CONFIG(tooltip)
1263void QTabBar::setTabToolTip(int index, const QString & tip)
1264{
1265 Q_D(QTabBar);
1266 if (QTabBarPrivate::Tab *tab = d->at(index))
1267 tab->toolTip = tip;
1268}
1269
1274QString QTabBar::tabToolTip(int index) const
1275{
1276 Q_D(const QTabBar);
1277 if (const QTabBarPrivate::Tab *tab = d->at(index))
1278 return tab->toolTip;
1279 return QString();
1280}
1281#endif // QT_CONFIG(tooltip)
1282
1283#if QT_CONFIG(whatsthis)
1290void QTabBar::setTabWhatsThis(int index, const QString &text)
1291{
1292 Q_D(QTabBar);
1293 if (QTabBarPrivate::Tab *tab = d->at(index))
1294 tab->whatsThis = text;
1295}
1296
1303QString QTabBar::tabWhatsThis(int index) const
1304{
1305 Q_D(const QTabBar);
1306 if (const QTabBarPrivate::Tab *tab = d->at(index))
1307 return tab->whatsThis;
1308 return QString();
1309}
1310
1311#endif // QT_CONFIG(whatsthis)
1312
1317{
1318 Q_D(QTabBar);
1319 if (QTabBarPrivate::Tab *tab = d->at(index))
1320 tab->data = data;
1321}
1322
1328{
1329 Q_D(const QTabBar);
1330 if (const QTabBarPrivate::Tab *tab = d->at(index))
1331 return tab->data;
1332 return QVariant();
1333}
1334
1340{
1341 Q_D(const QTabBar);
1342 if (const QTabBarPrivate::Tab *tab = d->at(index)) {
1343 if (d->layoutDirty)
1344 const_cast<QTabBarPrivate*>(d)->layoutTabs();
1345 if (!tab->visible)
1346 return QRect();
1347 QRect r = tab->rect;
1348 if (verticalTabs(d->shape))
1349 r.translate(0, -d->scrollOffset);
1350 else
1351 r.translate(-d->scrollOffset, 0);
1352 if (!verticalTabs(d->shape))
1354 return r;
1355 }
1356 return QRect();
1357}
1358
1366{
1367 Q_D(const QTabBar);
1368 if (d->validIndex(d->currentIndex)
1369 && tabRect(d->currentIndex).contains(position)) {
1370 return d->currentIndex;
1371 }
1372 const int max = d->tabList.size();
1373 for (int i = 0; i < max; ++i) {
1374 if (tabRect(i).contains(position)) {
1375 return i;
1376 }
1377 }
1378 return -1;
1379}
1380
1389{
1390 Q_D(const QTabBar);
1391 if (d->validIndex(d->currentIndex))
1392 return d->currentIndex;
1393 return -1;
1394}
1395
1396
1398{
1399 Q_D(QTabBar);
1400 if (d->dragInProgress && d->pressedIndex != -1)
1401 return;
1402 if (d->currentIndex == index)
1403 return;
1404
1405 int oldIndex = d->currentIndex;
1406 if (auto tab = d->at(index)) {
1407 d->currentIndex = index;
1408 // If the size hint depends on whether the tab is selected (for instance a style
1409 // sheet rule that sets a bold font on the 'selected' tab) then we need to
1410 // re-layout the entire tab bar. To minimize the cost, do that only if the
1411 // size hint changes for the tab that becomes the current tab (the old current tab
1412 // will most certainly do the same). QTBUG-6905
1413 if (tabRect(index).size() != tabSizeHint(index))
1414 d->layoutTabs();
1415 update();
1416 d->makeVisible(index);
1417 if (d->validIndex(oldIndex)) {
1418 tab->lastTab = oldIndex;
1419 d->layoutTab(oldIndex);
1420 }
1421 d->layoutTab(index);
1422#if QT_CONFIG(accessibility)
1423 if (QAccessible::isActive()) {
1424 if (hasFocus()) {
1425 QAccessibleEvent focusEvent(this, QAccessible::Focus);
1426 focusEvent.setChild(index);
1427 QAccessible::updateAccessibility(&focusEvent);
1428 }
1429 QAccessibleEvent selectionEvent(this, QAccessible::Selection);
1430 selectionEvent.setChild(index);
1431 QAccessible::updateAccessibility(&selectionEvent);
1432 }
1433#endif
1435 }
1436}
1437
1449{
1450 Q_D(const QTabBar);
1451 if (d->iconSize.isValid())
1452 return d->iconSize;
1453 int iconExtent = style()->pixelMetric(QStyle::PM_TabBarIconSize, nullptr, this);
1454 return QSize(iconExtent, iconExtent);
1455
1456}
1457
1459{
1460 Q_D(QTabBar);
1461 d->iconSize = size;
1462 d->layoutDirty = true;
1463 update();
1465}
1466
1473{
1474 Q_D(const QTabBar);
1475 return d->tabList.size();
1476}
1477
1478
1482{
1483 Q_D(const QTabBar);
1484 if (d->layoutDirty)
1485 const_cast<QTabBarPrivate*>(d)->layoutTabs();
1486 QRect r;
1487 for (const auto tab : d->tabList) {
1488 if (tab->visible)
1489 r = r.united(tab->maxRect);
1490 }
1491 return r.size();
1492}
1493
1497{
1498 Q_D(const QTabBar);
1499 if (d->layoutDirty)
1500 const_cast<QTabBarPrivate*>(d)->layoutTabs();
1501 if (!d->useScrollButtons) {
1502 QRect r;
1503 for (const auto tab : d->tabList) {
1504 if (tab->visible)
1505 r = r.united(tab->minRect);
1506 }
1507 return r.size();
1508 }
1509 if (verticalTabs(d->shape))
1510 return QSize(sizeHint().width(), d->rightB->sizeHint().height() * 2 + 75);
1511 else
1512 return QSize(d->rightB->sizeHint().width() * 2 + 75, sizeHint().height());
1513}
1514
1515// Compute the most-elided possible text, for minimumSizeHint
1517{
1518 if (text.size() <= 3)
1519 return text;
1520
1521 static const auto Ellipses = "..."_L1;
1522 QString ret;
1523 switch (mode) {
1524 case Qt::ElideRight:
1525 ret = QStringView{text}.left(2) + Ellipses;
1526 break;
1527 case Qt::ElideMiddle:
1528 ret = QStringView{text}.left(1) + Ellipses + QStringView{text}.right(1);
1529 break;
1530 case Qt::ElideLeft:
1531 ret = Ellipses + QStringView{text}.right(2);
1532 break;
1533 case Qt::ElideNone:
1534 ret = text;
1535 break;
1536 }
1537 return ret;
1538}
1539
1546{
1547 Q_D(const QTabBar);
1548 QTabBarPrivate::Tab *tab = d->tabList.at(index);
1549 QString oldText = tab->text;
1550 tab->text = computeElidedText(d->elideMode, oldText);
1552 tab->text = oldText;
1553 return size;
1554}
1555
1560{
1561 //Note: this must match with the computations in QCommonStylePrivate::tabLayout
1562 Q_D(const QTabBar);
1563 if (const QTabBarPrivate::Tab *tab = d->at(index)) {
1564 QStyleOptionTab opt;
1565 d->initBasicStyleOption(&opt, index);
1566 opt.text = tab->text;
1567 QSize iconSize = tab->icon.isNull() ? QSize(0, 0) : opt.iconSize;
1568 int hframe = style()->pixelMetric(QStyle::PM_TabBarTabHSpace, &opt, this);
1569 int vframe = style()->pixelMetric(QStyle::PM_TabBarTabVSpace, &opt, this);
1570 const QFontMetrics fm = fontMetrics();
1571
1572 int maxWidgetHeight = qMax(opt.leftButtonSize.height(), opt.rightButtonSize.height());
1573 int maxWidgetWidth = qMax(opt.leftButtonSize.width(), opt.rightButtonSize.width());
1574
1575 int widgetWidth = 0;
1576 int widgetHeight = 0;
1577 int padding = 0;
1578 if (!opt.leftButtonSize.isEmpty()) {
1579 padding += 4;
1580 widgetWidth += opt.leftButtonSize.width();
1581 widgetHeight += opt.leftButtonSize.height();
1582 }
1583 if (!opt.rightButtonSize.isEmpty()) {
1584 padding += 4;
1585 widgetWidth += opt.rightButtonSize.width();
1586 widgetHeight += opt.rightButtonSize.height();
1587 }
1588 if (!opt.icon.isNull())
1589 padding += 4;
1590
1591 QHash<QString, QSize>::iterator it = d->textSizes.find(tab->text);
1592 if (it == d->textSizes.end())
1593 it = d->textSizes.insert(tab->text, fm.size(Qt::TextShowMnemonic, tab->text));
1594 const int textWidth = it.value().width();
1595 QSize csz;
1596 if (verticalTabs(d->shape)) {
1597 csz = QSize( qMax(maxWidgetWidth, qMax(fm.height(), iconSize.height())) + vframe,
1598 textWidth + iconSize.width() + hframe + widgetHeight + padding);
1599 } else {
1600 csz = QSize(textWidth + iconSize.width() + hframe + widgetWidth + padding,
1601 qMax(maxWidgetHeight, qMax(fm.height(), iconSize.height())) + vframe);
1602 }
1603
1604 QSize retSize = style()->sizeFromContents(QStyle::CT_TabBarTab, &opt, csz, this);
1605 return retSize;
1606 }
1607 return QSize();
1608}
1609
1617{
1618 Q_UNUSED(index);
1619}
1620
1628{
1629 Q_UNUSED(index);
1630}
1631
1638{
1639}
1640
1641
1645{
1646 Q_D(QTabBar);
1647 if (d->layoutDirty)
1648 d->refresh();
1649 if (!d->validIndex(d->currentIndex))
1650 setCurrentIndex(0);
1651 else
1652 d->makeVisible(d->currentIndex);
1653 d->updateMacBorderMetrics();
1654}
1655
1659{
1660 Q_D(QTabBar);
1661 d->updateMacBorderMetrics();
1662}
1663
1667{
1668 Q_D(QTabBar);
1669 switch (event->type()) {
1670 case QEvent::HoverMove:
1671 case QEvent::HoverEnter: {
1672 QHoverEvent *he = static_cast<QHoverEvent *>(event);
1673 d->mousePosition = he->position().toPoint();
1674 if (!d->hoverRect.contains(d->mousePosition)) {
1675 if (d->hoverRect.isValid())
1676 update(d->hoverRect);
1677 d->hoverIndex = tabAt(d->mousePosition);
1678 if (d->validIndex(d->hoverIndex)) {
1679 d->hoverRect = tabRect(d->hoverIndex);
1680 update(d->hoverRect);
1681 } else {
1682 d->hoverRect = QRect();
1683 }
1684 }
1685 return true;
1686 }
1687 case QEvent::HoverLeave: {
1688 d->mousePosition = {-1, -1};
1689 if (d->hoverRect.isValid())
1690 update(d->hoverRect);
1691 d->hoverIndex = -1;
1692 d->hoverRect = QRect();
1693#if QT_CONFIG(wheelevent)
1694 d->accumulatedAngleDelta = QPoint();
1695#endif
1696 return true;
1697 }
1698#if QT_CONFIG(tooltip)
1699 case QEvent::ToolTip:
1700 if (const QTabBarPrivate::Tab *tab = d->at(tabAt(static_cast<QHelpEvent*>(event)->pos()))) {
1701 if (!tab->toolTip.isEmpty()) {
1702 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), tab->toolTip, this);
1703 return true;
1704 }
1705 }
1706 break;
1707#endif // QT_CONFIG(tooltip)
1708#if QT_CONFIG(whatsthis)
1709 case QEvent::QEvent::QueryWhatsThis: {
1710 const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()));
1711 if (!tab || tab->whatsThis.isEmpty())
1712 event->ignore();
1713 return true;
1714 }
1715 case QEvent::WhatsThis:
1716 if (const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()))) {
1717 if (!tab->whatsThis.isEmpty()) {
1718 QWhatsThis::showText(static_cast<QHelpEvent*>(event)->globalPos(),
1719 tab->whatsThis, this);
1720 return true;
1721 }
1722 }
1723 break;
1724#endif // QT_CONFIG(whatsthis)
1725#ifndef QT_NO_SHORTCUT
1726
1727 case QEvent::Shortcut: {
1728 QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
1729 for (int i = 0; i < d->tabList.size(); ++i) {
1730 const QTabBarPrivate::Tab *tab = d->tabList.at(i);
1731 if (tab->shortcutId == se->shortcutId()) {
1733 return true;
1734 }
1735 }
1736 }
1737 break;
1738#endif
1739 case QEvent::Move:
1740 d->updateMacBorderMetrics();
1741 break;
1742#if QT_CONFIG(draganddrop)
1743
1744 case QEvent::DragEnter:
1745 if (d->changeCurrentOnDrag)
1746 event->accept();
1747 break;
1748 case QEvent::DragMove:
1749 if (d->changeCurrentOnDrag) {
1750 const int tabIndex = tabAt(static_cast<QDragMoveEvent *>(event)->position().toPoint());
1751 if (isTabEnabled(tabIndex) && d->switchTabCurrentIndex != tabIndex) {
1752 d->switchTabCurrentIndex = tabIndex;
1753 if (d->switchTabTimerId)
1754 killTimer(d->switchTabTimerId);
1755 d->switchTabTimerId = startTimer(style()->styleHint(QStyle::SH_TabBar_ChangeCurrentDelay));
1756 }
1757 event->ignore();
1758 }
1759 break;
1760 case QEvent::DragLeave:
1761 case QEvent::Drop:
1762 d->killSwitchTabTimer();
1763 event->ignore();
1764 break;
1765#endif
1768 case QEvent::MouseMove:
1769 d->mousePosition = static_cast<QMouseEvent *>(event)->position().toPoint();
1770 d->mouseButtons = static_cast<QMouseEvent *>(event)->buttons();
1771 break;
1772 default:
1773 break;
1774 }
1775
1776 return QWidget::event(event);
1777}
1778
1782{
1783 Q_D(QTabBar);
1784 if (d->layoutDirty)
1786
1787 // when resizing, we want to keep the scroll offset as much as possible
1788 d->layoutTabs();
1789
1790 d->makeVisible(d->currentIndex);
1791}
1792
1796{
1797 Q_D(QTabBar);
1798
1799 QStyleOptionTabBarBase optTabBase;
1800 QTabBarPrivate::initStyleBaseOption(&optTabBase, this, size());
1801
1802 QStylePainter p(this);
1803 int selected = -1;
1804 int cutLeft = -1;
1805 int cutRight = -1;
1806 bool vertical = verticalTabs(d->shape);
1807 QStyleOptionTab cutTabLeft;
1808 QStyleOptionTab cutTabRight;
1809 selected = d->currentIndex;
1810 if (d->dragInProgress)
1811 selected = d->pressedIndex;
1812 const QRect scrollRect = d->normalizedScrollRect();
1813
1814 for (int i = 0; i < d->tabList.size(); ++i)
1815 optTabBase.tabBarRect |= tabRect(i);
1816
1817 optTabBase.selectedTabRect = tabRect(selected);
1818
1819 if (d->drawBase)
1820 p.drawPrimitive(QStyle::PE_FrameTabBarBase, optTabBase);
1821
1822 // the buttons might be semi-transparent or not fill their rect, but we don't
1823 // want the tab underneath to shine through, so clip the button area; QTBUG-50866
1824 if (d->leftB->isVisible() || d->rightB->isVisible()) {
1826 opt.initFrom(this);
1827 QRegion buttonRegion;
1828 if (d->leftB->isVisible())
1829 buttonRegion |= style()->subElementRect(QStyle::SE_TabBarScrollLeftButton, &opt, this);
1830 if (d->rightB->isVisible())
1831 buttonRegion |= style()->subElementRect(QStyle::SE_TabBarScrollRightButton, &opt, this);
1832 if (!buttonRegion.isEmpty())
1833 p.setClipRegion(QRegion(rect()) - buttonRegion);
1834 }
1835
1836 for (int i = 0; i < d->tabList.size(); ++i) {
1837 const auto tab = d->tabList.at(i);
1838 if (!tab->visible)
1839 continue;
1840 QStyleOptionTab tabOption;
1841 initStyleOption(&tabOption, i);
1842 if (d->paintWithOffsets && tab->dragOffset != 0) {
1843 if (vertical) {
1844 tabOption.rect.moveTop(tabOption.rect.y() + tab->dragOffset);
1845 } else {
1846 tabOption.rect.moveLeft(tabOption.rect.x() + tab->dragOffset);
1847 }
1848 }
1849 if (!(tabOption.state & QStyle::State_Enabled)) {
1850 tabOption.palette.setCurrentColorGroup(QPalette::Disabled);
1851 }
1852
1853 // If this tab is partially obscured, make a note of it so that we can pass the information
1854 // along when we draw the tear.
1855 QRect tabRect = tab->rect;
1856 int tabStart = vertical ? tabRect.top() : tabRect.left();
1857 int tabEnd = vertical ? tabRect.bottom() : tabRect.right();
1858 if (tabStart < scrollRect.left() + d->scrollOffset) {
1859 cutLeft = i;
1860 cutTabLeft = tabOption;
1861 } else if (tabEnd > scrollRect.right() + d->scrollOffset) {
1862 cutRight = i;
1863 cutTabRight = tabOption;
1864 }
1865
1866 // Don't bother drawing a tab if the entire tab is outside of the visible tab bar.
1867 if ((!vertical && (tabOption.rect.right() < 0 || tabOption.rect.left() > width()))
1868 || (vertical && (tabOption.rect.bottom() < 0 || tabOption.rect.top() > height())))
1869 continue;
1870
1871 optTabBase.tabBarRect |= tabOption.rect;
1872 if (i == selected)
1873 continue;
1874
1875 p.drawControl(QStyle::CE_TabBarTab, tabOption);
1876 }
1877
1878 // Draw the selected tab last to get it "on top"
1879 if (selected >= 0) {
1880 QStyleOptionTab tabOption;
1881 const auto tab = d->tabList.at(selected);
1882 initStyleOption(&tabOption, selected);
1883
1884 if (d->paintWithOffsets && tab->dragOffset != 0) {
1885 // if the drag offset is != 0, a move is in progress (drag or animation)
1886 // => set the tab position to Moving to preserve the rect
1887 tabOption.position = QStyleOptionTab::TabPosition::Moving;
1888
1889 if (vertical)
1890 tabOption.rect.moveTop(tabOption.rect.y() + tab->dragOffset);
1891 else
1892 tabOption.rect.moveLeft(tabOption.rect.x() + tab->dragOffset);
1893 }
1894
1895 // Calculate the rect of a moving tab
1896 const int taboverlap = style()->pixelMetric(QStyle::PM_TabBarTabOverlap, nullptr, this);
1897 const QRect &movingRect = verticalTabs(d->shape)
1898 ? tabOption.rect.adjusted(0, -taboverlap, 0, taboverlap)
1899 : tabOption.rect.adjusted(-taboverlap, 0, taboverlap, 0);
1900
1901 // If a drag is in process, set the moving tab's geometry here
1902 // (in an animation, it is already set)
1903 if (d->dragInProgress)
1904 d->movingTab->setGeometry(movingRect);
1905
1906 p.drawControl(QStyle::CE_TabBarTab, tabOption);
1907 }
1908
1909 // Only draw the tear indicator if necessary. Most of the time we don't need too.
1910 if (d->leftB->isVisible() && cutLeft >= 0) {
1911 cutTabLeft.rect = rect();
1912 cutTabLeft.rect = style()->subElementRect(QStyle::SE_TabBarTearIndicatorLeft, &cutTabLeft, this);
1913 p.drawPrimitive(QStyle::PE_IndicatorTabTearLeft, cutTabLeft);
1914 }
1915
1916 if (d->rightB->isVisible() && cutRight >= 0) {
1917 cutTabRight.rect = rect();
1918 cutTabRight.rect = style()->subElementRect(QStyle::SE_TabBarTearIndicatorRight, &cutTabRight, this);
1919 p.drawPrimitive(QStyle::PE_IndicatorTabTearRight, cutTabRight);
1920 }
1921}
1922
1923/*
1924 When index changes visibility, we have to find first & last visible indexes.
1925 If remove is set, we force both
1926 */
1928{
1929 if (visible) {
1932 } else {
1933 if (remove || (index == firstVisible)) {
1934 firstVisible = -1;
1935 for (int i = 0; i < tabList.size(); ++i) {
1936 if (tabList.at(i)->visible) {
1937 firstVisible = i;
1938 break;
1939 }
1940 }
1941 }
1942 if (remove || (index == lastVisible)) {
1943 lastVisible = -1;
1944 for (int i = tabList.size() - 1; i >= 0; --i) {
1945 if (tabList.at(i)->visible) {
1946 lastVisible = i;
1947 break;
1948 }
1949 }
1950 }
1951 }
1952}
1953
1954/*
1955 Selects the new current index starting at "fromIndex". If "fromIndex" is visible we're done.
1956 Else it tries any index AFTER fromIndex, then any BEFORE fromIndex and, if everything fails,
1957 it returns -1 indicating that no index is available
1958 */
1960{
1961 int newindex = -1;
1962 for (int i = fromIndex; i < tabList.size(); ++i) {
1963 if (at(i)->visible && at(i)->enabled) {
1964 newindex = i;
1965 break;
1966 }
1967 }
1968 if (newindex < 0) {
1969 for (int i = fromIndex-1; i > -1; --i) {
1970 if (at(i)->visible && at(i)->enabled) {
1971 newindex = i;
1972 break;
1973 }
1974 }
1975 }
1976
1977 return newindex;
1978}
1979
1980/*
1981 Given that index at position from moved to position to where return where index goes.
1982 */
1983int QTabBarPrivate::calculateNewPosition(int from, int to, int index) const
1984{
1985 if (index == from)
1986 return to;
1987
1988 int start = qMin(from, to);
1989 int end = qMax(from, to);
1990 if (index >= start && index <= end)
1991 index += (from < to) ? -1 : 1;
1992 return index;
1993}
1994
2001void QTabBar::moveTab(int from, int to)
2002{
2003 Q_D(QTabBar);
2004 if (from == to
2005 || !d->validIndex(from)
2006 || !d->validIndex(to))
2007 return;
2008
2009 auto &fromTab = *d->tabList.at(from);
2010 auto &toTab = *d->tabList.at(to);
2011
2012 bool vertical = verticalTabs(d->shape);
2013 int oldPressedPosition = 0;
2014 if (d->pressedIndex != -1) {
2015 // Record the position of the pressed tab before reordering the tabs.
2016 oldPressedPosition = vertical ? d->tabList.at(d->pressedIndex)->rect.y()
2017 : d->tabList.at(d->pressedIndex)->rect.x();
2018 }
2019
2020 // Update the locations of the tabs first
2021 int start = qMin(from, to);
2022 int end = qMax(from, to);
2023 int width = vertical ? fromTab.rect.height() : fromTab.rect.width();
2024 if (from < to)
2025 width *= -1;
2026 bool rtl = isRightToLeft();
2027 for (int i = start; i <= end; ++i) {
2028 if (i == from)
2029 continue;
2030 auto &tab = *d->tabList.at(i);
2031 if (vertical)
2032 tab.rect.moveTop(tab.rect.y() + width);
2033 else
2034 tab.rect.moveLeft(tab.rect.x() + width);
2035 int direction = -1;
2036 if (rtl && !vertical)
2037 direction *= -1;
2038 if (tab.dragOffset != 0)
2039 tab.dragOffset += (direction * width);
2040 }
2041
2042 if (vertical) {
2043 if (from < to)
2044 fromTab.rect.moveTop(toTab.rect.bottom() + 1);
2045 else
2046 fromTab.rect.moveTop(toTab.rect.top() - width);
2047 } else {
2048 if (from < to)
2049 fromTab.rect.moveLeft(toTab.rect.right() + 1);
2050 else
2051 fromTab.rect.moveLeft(toTab.rect.left() - width);
2052 }
2053
2054 // Move the actual data structures
2055 d->tabList.move(from, to);
2056
2057 // update lastTab locations
2058 for (const auto tab : std::as_const(d->tabList))
2059 tab->lastTab = d->calculateNewPosition(from, to, tab->lastTab);
2060
2061 // update external variables
2062 int previousIndex = d->currentIndex;
2063 d->currentIndex = d->calculateNewPosition(from, to, d->currentIndex);
2064
2065 // If we are in the middle of a drag update the dragStartPosition
2066 if (d->pressedIndex != -1) {
2067 d->pressedIndex = d->calculateNewPosition(from, to, d->pressedIndex);
2068 const auto pressedTab = d->tabList.at(d->pressedIndex);
2069 int newPressedPosition = vertical ? pressedTab->rect.top() : pressedTab->rect.left();
2070 int diff = oldPressedPosition - newPressedPosition;
2071 if (isRightToLeft() && !vertical)
2072 diff *= -1;
2073 if (vertical)
2074 d->dragStartPosition.setY(d->dragStartPosition.y() - diff);
2075 else
2076 d->dragStartPosition.setX(d->dragStartPosition.x() - diff);
2077 }
2078
2079 d->layoutWidgets(start);
2080 update();
2081 emit tabMoved(from, to);
2082 if (previousIndex != d->currentIndex)
2083 emit currentChanged(d->currentIndex);
2085}
2086
2087void QTabBarPrivate::slide(int from, int to)
2088{
2089 Q_Q(QTabBar);
2090 if (from == to
2091 || !validIndex(from)
2092 || !validIndex(to))
2093 return;
2094 bool vertical = verticalTabs(shape);
2095 int preLocation = vertical ? q->tabRect(from).y() : q->tabRect(from).x();
2096 q->setUpdatesEnabled(false);
2097 q->moveTab(from, to);
2098 q->setUpdatesEnabled(true);
2099 int postLocation = vertical ? q->tabRect(to).y() : q->tabRect(to).x();
2100 int length = postLocation - preLocation;
2101 tabList.at(to)->dragOffset -= length;
2102 tabList.at(to)->startAnimation(this, ANIMATION_DURATION);
2103}
2104
2106{
2107 if (!validIndex(index))
2108 return;
2109 tabList.at(index)->dragOffset = offset;
2110 layoutTab(index); // Make buttons follow tab
2111 q_func()->update();
2112}
2113
2117{
2118 Q_D(QTabBar);
2119
2120 const QPoint pos = event->position().toPoint();
2121 const bool isEventInCornerButtons = (!d->leftB->isHidden() && d->leftB->geometry().contains(pos))
2122 || (!d->rightB->isHidden() && d->rightB->geometry().contains(pos));
2123 if (!isEventInCornerButtons) {
2124 const int index = d->indexAtPos(pos);
2126 }
2127
2128 if (event->button() != Qt::LeftButton) {
2129 event->ignore();
2130 return;
2131 }
2132 // Be safe!
2133 if (d->pressedIndex != -1 && d->movable)
2134 d->moveTabFinished(d->pressedIndex);
2135
2136 d->pressedIndex = d->indexAtPos(event->position().toPoint());
2137
2138 if (d->validIndex(d->pressedIndex)) {
2139 QStyleOptionTabBarBase optTabBase;
2140 optTabBase.initFrom(this);
2141 optTabBase.documentMode = d->documentMode;
2142 if (event->type() == style()->styleHint(QStyle::SH_TabBar_SelectMouseType, &optTabBase, this))
2143 setCurrentIndex(d->pressedIndex);
2144 else
2145 repaint(tabRect(d->pressedIndex));
2146 if (d->movable) {
2147 d->dragStartPosition = event->position().toPoint();
2148 }
2149 }
2150}
2151
2155{
2156 Q_D(QTabBar);
2157 if (d->movable) {
2158 // Be safe!
2159 if (d->pressedIndex != -1
2160 && event->buttons() == Qt::NoButton)
2161 d->moveTabFinished(d->pressedIndex);
2162
2163 // Start drag
2164 if (!d->dragInProgress && d->pressedIndex != -1) {
2165 if ((event->position().toPoint() - d->dragStartPosition).manhattanLength() > QApplication::startDragDistance()) {
2166 d->dragInProgress = true;
2167 d->setupMovableTab();
2168 }
2169 }
2170
2171 if (event->buttons() == Qt::LeftButton
2172 && d->dragInProgress
2173 && d->validIndex(d->pressedIndex)) {
2174 bool vertical = verticalTabs(d->shape);
2175 int dragDistance;
2176 if (vertical) {
2177 dragDistance = (event->position().toPoint().y() - d->dragStartPosition.y());
2178 } else {
2179 dragDistance = (event->position().toPoint().x() - d->dragStartPosition.x());
2180 }
2181 d->tabList.at(d->pressedIndex)->dragOffset = dragDistance;
2182
2183 QRect startingRect = tabRect(d->pressedIndex);
2184 if (vertical)
2185 startingRect.moveTop(startingRect.y() + dragDistance);
2186 else
2187 startingRect.moveLeft(startingRect.x() + dragDistance);
2188
2189 int overIndex;
2190 if (dragDistance < 0)
2191 overIndex = tabAt(startingRect.topLeft());
2192 else
2193 overIndex = tabAt(startingRect.topRight());
2194
2195 if (overIndex != d->pressedIndex && overIndex != -1) {
2196 int offset = 1;
2197 if (isRightToLeft() && !vertical)
2198 offset *= -1;
2199 if (dragDistance < 0) {
2200 dragDistance *= -1;
2201 offset *= -1;
2202 }
2203 for (int i = d->pressedIndex;
2204 offset > 0 ? i < overIndex : i > overIndex;
2205 i += offset) {
2206 QRect overIndexRect = tabRect(overIndex);
2207 int needsToBeOver = (vertical ? overIndexRect.height() : overIndexRect.width()) / 2;
2208 if (dragDistance > needsToBeOver)
2209 d->slide(i + offset, d->pressedIndex);
2210 }
2211 }
2212 // Buttons needs to follow the dragged tab
2213 if (d->pressedIndex != -1)
2214 d->layoutTab(d->pressedIndex);
2215
2216 update();
2217 }
2218 }
2219
2220 if (event->buttons() != Qt::LeftButton) {
2221 event->ignore();
2222 return;
2223 }
2224}
2225
2227{
2228 Q_Q(QTabBar);
2229 if (!movingTab)
2231
2232 int taboverlap = q->style()->pixelMetric(QStyle::PM_TabBarTabOverlap, nullptr ,q);
2233 QRect grabRect = q->tabRect(pressedIndex);
2234 if (verticalTabs(shape))
2235 grabRect.adjust(0, -taboverlap, 0, taboverlap);
2236 else
2237 grabRect.adjust(-taboverlap, 0, taboverlap, 0);
2238
2239 QPixmap grabImage(grabRect.size() * q->devicePixelRatio());
2240 grabImage.setDevicePixelRatio(q->devicePixelRatio());
2241 grabImage.fill(Qt::transparent);
2242 QStylePainter p(&grabImage, q);
2243
2244 QStyleOptionTab tab;
2245 q->initStyleOption(&tab, pressedIndex);
2246 tab.position = QStyleOptionTab::OnlyOneTab;
2247 if (verticalTabs(shape))
2248 tab.rect.moveTopLeft(QPoint(0, taboverlap));
2249 else
2250 tab.rect.moveTopLeft(QPoint(taboverlap, 0));
2251 p.drawControl(QStyle::CE_TabBarTab, tab);
2252 p.end();
2253
2254 movingTab->setPixmap(grabImage);
2255 movingTab->setGeometry(grabRect);
2256 movingTab->raise();
2257
2258 // Re-arrange widget order to avoid overlaps
2259 const auto &pressedTab = *tabList.at(pressedIndex);
2260 if (pressedTab.leftWidget)
2261 pressedTab.leftWidget->raise();
2262 if (pressedTab.rightWidget)
2263 pressedTab.rightWidget->raise();
2264 if (leftB)
2265 leftB->raise();
2266 if (rightB)
2267 rightB->raise();
2268 movingTab->setVisible(true);
2269}
2270
2272{
2273 Q_Q(QTabBar);
2274 bool cleanup = (pressedIndex == index) || (pressedIndex == -1) || !validIndex(index);
2275 bool allAnimationsFinished = true;
2276#if QT_CONFIG(animation)
2277 for (const auto tab : std::as_const(tabList)) {
2278 if (tab->animation && tab->animation->state() == QAbstractAnimation::Running) {
2279 allAnimationsFinished = false;
2280 break;
2281 }
2282 }
2283#endif // animation
2284 if (allAnimationsFinished && cleanup) {
2285 if (movingTab)
2286 movingTab->setVisible(false); // We might not get a mouse release
2287 for (auto tab : std::as_const(tabList)) {
2288 tab->dragOffset = 0;
2289 }
2290 if (pressedIndex != -1 && movable) {
2291 pressedIndex = -1;
2292 dragInProgress = false;
2294 }
2295 layoutWidgets();
2296 } else {
2297 if (!validIndex(index))
2298 return;
2299 tabList.at(index)->dragOffset = 0;
2300 }
2301 q->update();
2302}
2303
2307{
2308 Q_D(QTabBar);
2309 if (event->button() != Qt::LeftButton) {
2310 event->ignore();
2311 return;
2312 }
2313
2314 if (d->movable && d->dragInProgress && d->validIndex(d->pressedIndex)) {
2315 int length = d->tabList.at(d->pressedIndex)->dragOffset;
2316 int width = verticalTabs(d->shape)
2317 ? tabRect(d->pressedIndex).height()
2318 : tabRect(d->pressedIndex).width();
2319 int duration = qMin(ANIMATION_DURATION,
2321 d->tabList.at(d->pressedIndex)->startAnimation(d, duration);
2322 d->dragInProgress = false;
2323 d->movingTab->setVisible(false);
2324 d->dragStartPosition = QPoint();
2325 }
2326
2327 // mouse release event might happen outside the tab, so keep the pressed index
2328 int oldPressedIndex = d->pressedIndex;
2329 int i = d->indexAtPos(event->position().toPoint()) == d->pressedIndex ? d->pressedIndex : -1;
2330 d->pressedIndex = -1;
2331 QStyleOptionTabBarBase optTabBase;
2332 optTabBase.initFrom(this);
2333 optTabBase.documentMode = d->documentMode;
2334 const bool selectOnRelease =
2336 if (selectOnRelease)
2338 if (d->validIndex(oldPressedIndex))
2339 update(tabRect(oldPressedIndex));
2340}
2341
2345{
2346 Q_D(QTabBar);
2347 const QPoint pos = event->position().toPoint();
2348 const bool isEventInCornerButtons = (!d->leftB->isHidden() && d->leftB->geometry().contains(pos))
2349 || (!d->rightB->isHidden() && d->rightB->geometry().contains(pos));
2350 if (!isEventInCornerButtons)
2352
2354}
2355
2359{
2360 Q_D(QTabBar);
2361 if (event->key() != Qt::Key_Left && event->key() != Qt::Key_Right) {
2362 event->ignore();
2363 return;
2364 }
2365 int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1;
2366 d->setCurrentNextEnabledIndex(offset);
2367}
2368
2371#if QT_CONFIG(wheelevent)
2372void QTabBar::wheelEvent(QWheelEvent *event)
2373{
2374 Q_D(QTabBar);
2375 if (style()->styleHint(QStyle::SH_TabBar_AllowWheelScrolling)) {
2376 const bool wheelVertical = qAbs(event->angleDelta().y()) > qAbs(event->angleDelta().x());
2377 const bool tabsVertical = verticalTabs(d->shape);
2378 if (event->device()->capabilities().testFlag(QInputDevice::Capability::PixelScroll)) {
2379 // For wheels/touch pads with pixel precision, scroll the tab bar if
2380 // it has the right orientation.
2381 int delta = 0;
2382 if (tabsVertical == wheelVertical)
2383 delta = wheelVertical ? event->pixelDelta().y() : event->pixelDelta().x();
2385 delta = -delta;
2386 if (delta && d->validIndex(d->lastVisible)) {
2387 const int oldScrollOffset = d->scrollOffset;
2388 const QRect lastTabRect = d->tabList.at(d->lastVisible)->rect;
2389 const QRect scrollRect = d->normalizedScrollRect(d->lastVisible);
2390 int scrollRectExtent = scrollRect.right();
2391 if (!d->leftB->isVisible())
2392 scrollRectExtent += tabsVertical ? d->leftB->height() : d->leftB->width();
2393 if (!d->rightB->isVisible())
2394 scrollRectExtent += tabsVertical ? d->rightB->height() : d->rightB->width();
2395
2396 const int maxScrollOffset = qMax((tabsVertical ?
2397 lastTabRect.bottom() :
2398 lastTabRect.right()) - scrollRectExtent, 0);
2399 d->scrollOffset = qBound(0, d->scrollOffset - delta, maxScrollOffset);
2400 d->leftB->setEnabled(d->scrollOffset > -scrollRect.left());
2401 d->rightB->setEnabled(maxScrollOffset > d->scrollOffset);
2402 if (oldScrollOffset != d->scrollOffset) {
2403 event->accept();
2404 update();
2405 return;
2406 }
2407 }
2408 } else {
2409 d->accumulatedAngleDelta += event->angleDelta();
2410 const int xSteps = d->accumulatedAngleDelta.x() / QWheelEvent::DefaultDeltasPerStep;
2411 const int ySteps = d->accumulatedAngleDelta.y() / QWheelEvent::DefaultDeltasPerStep;
2412 int offset = 0;
2413 if (xSteps > 0 || ySteps > 0) {
2414 offset = -1;
2415 d->accumulatedAngleDelta = QPoint();
2416 } else if (xSteps < 0 || ySteps < 0) {
2417 offset = 1;
2418 d->accumulatedAngleDelta = QPoint();
2419 }
2420 const int oldCurrentIndex = d->currentIndex;
2421 d->setCurrentNextEnabledIndex(offset);
2422 if (oldCurrentIndex != d->currentIndex) {
2423 event->accept();
2424 return;
2425 }
2426 }
2427 QWidget::wheelEvent(event);
2428 }
2429}
2430#endif // QT_CONFIG(wheelevent)
2431
2433{
2434 Q_Q(QTabBar);
2435 for (int index = currentIndex + offset; validIndex(index); index += offset) {
2436 if (tabList.at(index)->enabled) {
2437 q->setCurrentIndex(index);
2438 break;
2439 }
2440 }
2441}
2442
2446{
2447 Q_D(QTabBar);
2448 switch (event->type()) {
2450 if (!d->elideModeSetByUser)
2451 d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, nullptr, this));
2452 if (!d->useScrollButtonsSetByUser)
2453 d->useScrollButtons = !style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, nullptr, this);
2454 Q_FALLTHROUGH();
2455 case QEvent::FontChange:
2456 d->textSizes.clear();
2457 d->refresh();
2458 break;
2459 default:
2460 break;
2461 }
2462
2464}
2465
2470{
2471 Q_D(QTabBar);
2472 if (event->timerId() == d->switchTabTimerId) {
2473 killTimer(d->switchTabTimerId);
2474 d->switchTabTimerId = 0;
2475 setCurrentIndex(d->switchTabCurrentIndex);
2476 d->switchTabCurrentIndex = -1;
2477 }
2479}
2480
2495{
2496 Q_D(const QTabBar);
2497 return d->elideMode;
2498}
2499
2501{
2502 Q_D(QTabBar);
2503 d->elideMode = mode;
2504 d->elideModeSetByUser = true;
2505 d->textSizes.clear();
2506 d->refresh();
2507}
2508
2523{
2524 return d_func()->useScrollButtons;
2525}
2526
2528{
2529 Q_D(QTabBar);
2530 d->useScrollButtonsSetByUser = true;
2531 if (d->useScrollButtons == useButtons)
2532 return;
2533 d->useScrollButtons = useButtons;
2534 d->refresh();
2535}
2536
2552{
2553 Q_D(const QTabBar);
2554 return d->closeButtonOnTabs;
2555}
2556
2557void QTabBar::setTabsClosable(bool closable)
2558{
2559 Q_D(QTabBar);
2560 if (d->closeButtonOnTabs == closable)
2561 return;
2562 d->closeButtonOnTabs = closable;
2564 if (!closable) {
2565 for (auto tab : std::as_const(d->tabList)) {
2566 if (closeSide == LeftSide && tab->leftWidget) {
2567 tab->leftWidget->deleteLater();
2568 tab->leftWidget = nullptr;
2569 }
2570 if (closeSide == RightSide && tab->rightWidget) {
2571 tab->rightWidget->deleteLater();
2572 tab->rightWidget = nullptr;
2573 }
2574 }
2575 } else {
2576 bool newButtons = false;
2577 for (int i = 0; i < d->tabList.size(); ++i) {
2578 if (tabButton(i, closeSide))
2579 continue;
2580 newButtons = true;
2581 QAbstractButton *closeButton = new CloseButton(this);
2582 connect(closeButton, SIGNAL(clicked()), this, SLOT(_q_closeTab()));
2583 setTabButton(i, closeSide, closeButton);
2584 }
2585 if (newButtons)
2586 d->layoutTabs();
2587 }
2588 update();
2589}
2590
2631{
2632 Q_D(const QTabBar);
2633 return d->selectionBehaviorOnRemove;
2634}
2635
2637{
2638 Q_D(QTabBar);
2639 d->selectionBehaviorOnRemove = behavior;
2640}
2641
2653{
2654 Q_D(const QTabBar);
2655 return d->expanding;
2656}
2657
2659{
2660 Q_D(QTabBar);
2661 if (d->expanding == enabled)
2662 return;
2663 d->expanding = enabled;
2664 d->layoutTabs();
2665}
2666
2678{
2679 Q_D(const QTabBar);
2680 return d->movable;
2681}
2682
2683void QTabBar::setMovable(bool movable)
2684{
2685 Q_D(QTabBar);
2686 d->movable = movable;
2687}
2688
2689
2702{
2703 return d_func()->documentMode;
2704}
2705
2707{
2708 Q_D(QTabBar);
2709
2710 d->documentMode = enabled;
2711 d->updateMacBorderMetrics();
2712}
2713
2726{
2727 Q_D(const QTabBar);
2728 return d->autoHide;
2729}
2730
2732{
2733 Q_D(QTabBar);
2734 if (d->autoHide == hide)
2735 return;
2736
2737 d->autoHide = hide;
2738 if (hide)
2739 d->autoHideTabs();
2740 else
2741 setVisible(true);
2742}
2743
2757{
2758 Q_D(const QTabBar);
2759 return d->changeCurrentOnDrag;
2760}
2761
2763{
2764 Q_D(QTabBar);
2765 d->changeCurrentOnDrag = change;
2766 if (!change)
2767 d->killSwitchTabTimer();
2768}
2769
2785{
2786 Q_D(QTabBar);
2787 if (index < 0 || index >= d->tabList.size())
2788 return;
2789 if (widget) {
2790 widget->setParent(this);
2791 // make sure our left and right widgets stay on top
2792 widget->lower();
2793 widget->show();
2794 }
2795 auto &tab = *d->tabList.at(index);
2796 if (position == LeftSide) {
2797 if (tab.leftWidget)
2798 tab.leftWidget->hide();
2799 tab.leftWidget = widget;
2800 } else {
2801 if (tab.rightWidget)
2802 tab.rightWidget->hide();
2803 tab.rightWidget = widget;
2804 }
2805 d->layoutTabs();
2806 d->refresh();
2807 update();
2808}
2809
2815{
2816 Q_D(const QTabBar);
2817 if (const auto tab = d->at(index)) {
2818 return position == LeftSide ? tab->leftWidget
2819 : tab->rightWidget;
2820 }
2821 return nullptr;
2822}
2823
2824#if QT_CONFIG(accessibility)
2828void QTabBar::setAccessibleTabName(int index, const QString &name)
2829{
2830 Q_D(QTabBar);
2831 if (QTabBarPrivate::Tab *tab = d->at(index)) {
2832 tab->accessibleName = name;
2833 QAccessibleEvent event(this, QAccessible::NameChanged);
2834 event.setChild(index);
2835 QAccessible::updateAccessibility(&event);
2836 }
2837}
2838
2843QString QTabBar::accessibleTabName(int index) const
2844{
2845 Q_D(const QTabBar);
2846 if (const QTabBarPrivate::Tab *tab = d->at(index))
2847 return tab->accessibleName;
2848 return QString();
2849}
2850#endif // QT_CONFIG(accessibility)
2851
2852CloseButton::CloseButton(QWidget *parent)
2854{
2856#ifndef QT_NO_CURSOR
2858#endif
2859#if QT_CONFIG(tooltip)
2860 setToolTip(tr("Close Tab"));
2861#endif
2862 resize(sizeHint());
2863}
2864
2865QSize CloseButton::sizeHint() const
2866{
2867 ensurePolished();
2868 int width = style()->pixelMetric(QStyle::PM_TabCloseIndicatorWidth, nullptr, this);
2869 int height = style()->pixelMetric(QStyle::PM_TabCloseIndicatorHeight, nullptr, this);
2870 return QSize(width, height);
2871}
2872
2873void CloseButton::enterEvent(QEnterEvent *event)
2874{
2875 if (isEnabled())
2876 update();
2878}
2879
2880void CloseButton::leaveEvent(QEvent *event)
2881{
2882 if (isEnabled())
2883 update();
2885}
2886
2887void CloseButton::paintEvent(QPaintEvent *)
2888{
2889 QPainter p(this);
2891 opt.initFrom(this);
2893 if (isEnabled() && underMouse() && !isChecked() && !isDown())
2895 if (isChecked())
2897 if (isDown())
2899
2900 if (const QTabBar *tb = qobject_cast<const QTabBar *>(parent())) {
2901 int index = tb->currentIndex();
2903 if (tb->tabButton(index, position) == this)
2905 }
2906
2907 style()->drawPrimitive(QStyle::PE_IndicatorTabClose, &opt, &p, this);
2908}
2909
2910#if QT_CONFIG(animation)
2911void QTabBarPrivate::Tab::TabBarAnimation::updateCurrentValue(const QVariant &current)
2912{
2913 priv->moveTab(priv->tabList.indexOf(tab), current.toInt());
2914}
2915
2916void QTabBarPrivate::Tab::TabBarAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State)
2917{
2918 if (newState == Stopped) priv->moveTabFinished(priv->tabList.indexOf(tab));
2919}
2920#endif
2921
2923
2924#include "moc_qtabbar.cpp"
2925#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 paintEvent(QPaintEvent *e) override=0
\reimp
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:164
\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
int height() const
Returns the height of the font.
QSize size(int flags, const QString &str, int tabstops=0, int *tabarray=nullptr) const
Returns the size in pixels of text.
QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags=0) const
static QPlatformNativeInterface * platformNativeInterface()
\inmodule QtCore
Definition qhash.h:1093
The QHelpEvent class provides an event that is used to request helpful information about a particular...
Definition qevent.h:787
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:797
The QHideEvent class provides an event which is sent after a widget is hidden.
Definition qevent.h:585
\inmodule QtGui
Definition qevent.h:245
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:973
The QKeyEvent class describes a key event.
Definition qevent.h:423
static QKeySequence mnemonic(const QString &text)
Returns the shortcut key sequence for the mnemonic in text, or an empty key sequence if no mnemonics ...
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool empty() const noexcept
Definition qlist.h:682
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
\inmodule QtGui
Definition qevent.h:195
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
\inmodule QtCore
Definition qobject.h:90
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:1792
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
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:2521
virtual void timerEvent(QTimerEvent *event)
This event handler can be reimplemented in a subclass to receive timer events for the object.
Definition qobject.cpp:1433
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:114
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1872
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:485
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
@ Disabled
Definition qpalette.h:48
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:608
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition qpixmap.cpp:854
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:394
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
\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:372
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:163
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:181
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:220
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
constexpr QPoint topRight() const noexcept
Returns the position of the rectangle's top-right corner.
Definition qrect.h:226
constexpr void moveLeft(int pos) noexcept
Moves the rectangle horizontally, leaving the rectangle's left edge at the given x coordinate.
Definition qrect.h:285
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:851
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:184
constexpr void setWidth(int w) noexcept
Sets the width of the rectangle to the given width.
Definition qrect.h:380
constexpr void setX(int x) noexcept
Sets the left edge of the rectangle to the given x coordinate.
Definition qrect.h:214
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:241
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:244
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
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:260
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:187
constexpr void setHeight(int h) noexcept
Sets the height of the rectangle to the given height.
Definition qrect.h:383
constexpr void moveTop(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top edge at the given y coordinate.
Definition qrect.h:288
constexpr void setY(int y) noexcept
Sets the top edge of the rectangle to the given y coordinate.
Definition qrect.h:217
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:178
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:547
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:577
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:118
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
Definition qsize.h:120
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QString right(qsizetype n) const
Returns a substring that contains the n rightmost characters of the string.
Definition qstring.cpp:5180
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
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:556
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:650
@ SH_TabBar_CloseButtonPosition
Definition qstyle.h:675
@ SH_TabBar_Alignment
Definition qstyle.h:588
@ SH_TabBar_AllowWheelScrolling
Definition qstyle.h:702
@ SH_TabBar_ChangeCurrentDelay
Definition qstyle.h:689
@ SH_TabBar_PreferNoArrows
Definition qstyle.h:621
@ SH_TabBar_SelectMouseType
Definition qstyle.h:587
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:2144
@ PM_TabBarTabHSpace
Definition qstyle.h:440
@ PM_TabCloseIndicatorWidth
Definition qstyle.h:520
@ PM_TabBarIconSize
Definition qstyle.h:501
@ PM_TabBarTabVSpace
Definition qstyle.h:441
@ PM_TabBarScrollButtonWidth
Definition qstyle.h:479
@ PM_TabCloseIndicatorHeight
Definition qstyle.h:521
@ 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:1983
QRect hoverRect
Definition qtabbar_p.h:66
bool validIndex(int index) const
Definition qtabbar_p.h:187
int hoveredTabIndex() const
Definition qtabbar.cpp:656
void killSwitchTabTimer()
Definition qtabbar.cpp:706
void _q_closeTab()
Definition qtabbar.cpp:768
int selectNewCurrentIndexFrom(int currentIndex)
Definition qtabbar.cpp:1959
void autoHideTabs()
Definition qtabbar.cpp:760
void moveTab(int index, int offset)
Definition qtabbar.cpp:2105
QToolButton * rightB
Definition qtabbar_p.h:73
QPoint dragStartPosition
Definition qtabbar_p.h:67
void _q_scrollTabs()
Definition qtabbar.cpp:791
int switchTabTimerId
Definition qtabbar_p.h:78
QRect normalizedScrollRect(int index=-1)
Definition qtabbar.cpp:576
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 layoutWidgets(int start=0)
Definition qtabbar.cpp:752
bool paintWithOffsets
Definition qtabbar_p.h:97
void layoutTab(int index)
Definition qtabbar.cpp:716
void setCurrentNextEnabledIndex(int offset)
\reimp
Definition qtabbar.cpp:2432
void makeVisible(int index)
Definition qtabbar.cpp:665
QTabBar::Shape shape
Definition qtabbar_p.h:81
void layoutTabs()
Definition qtabbar.cpp:405
void setupMovableTab()
Definition qtabbar.cpp:2226
void calculateFirstLastVisible(int index, bool visible, bool remove)
Definition qtabbar.cpp:1927
void moveTabFinished(int index)
Definition qtabbar.cpp:2271
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:2087
QList< Tab * > tabList
Definition qtabbar_p.h:172
int indexAtPos(const QPoint &p) const
Definition qtabbar.cpp:394
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:2527
void setTabsClosable(bool closable)
Definition qtabbar.cpp:2557
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:1545
void setTabButton(int index, ButtonPosition position, QWidget *widget)
Sets widget on the tab index.
Definition qtabbar.cpp:2784
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:1795
void setSelectionBehaviorOnRemove(SelectionBehavior behavior)
Definition qtabbar.cpp:2636
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:1666
void setShape(Shape shape)
Definition qtabbar.cpp:876
QSize sizeHint() const override
\reimp
Definition qtabbar.cpp:1481
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:1175
void setTabData(int index, const QVariant &data)
Sets the data of the tab at position index to data.
Definition qtabbar.cpp:1316
void mousePressEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2116
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:1627
void setCurrentIndex(int index)
Definition qtabbar.cpp:1397
void setTabText(int index, const QString &text)
Sets the text of the tab at position index to text.
Definition qtabbar.cpp:1186
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:1006
bool isMovable() const
Definition qtabbar.cpp:2677
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:2706
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:1235
void setIconSize(const QSize &size)
Definition qtabbar.cpp:1458
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:1327
void setAutoHide(bool hide)
Definition qtabbar.cpp:2731
void showEvent(QShowEvent *) override
\reimp
Definition qtabbar.cpp:1644
void mouseReleaseEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2306
void mouseDoubleClickEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2344
void hideEvent(QHideEvent *) override
\reimp
Definition qtabbar.cpp:1658
void resizeEvent(QResizeEvent *) override
\reimp
Definition qtabbar.cpp:1781
void setTabVisible(int index, bool visible)
If visible is true, make the tab at position index visible, otherwise make it hidden.
Definition qtabbar.cpp:1146
bool isTabEnabled(int index) const
Returns true if the tab at position index is enabled; otherwise returns false.
Definition qtabbar.cpp:1099
~QTabBar()
Destroys the tab bar.
Definition qtabbar.cpp:858
void timerEvent(QTimerEvent *event) override
\reimp
Definition qtabbar.cpp:2469
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:1207
void mouseMoveEvent(QMouseEvent *) override
\reimp
Definition qtabbar.cpp:2154
void setTabIcon(int index, const QIcon &icon)
Sets the icon of the tab at position index to icon.
Definition qtabbar.cpp:1246
virtual void tabInserted(int index)
This virtual handler is called after a new tab was added or inserted at position index.
Definition qtabbar.cpp:1616
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:1111
void tabMoved(int from, int to)
void keyPressEvent(QKeyEvent *) override
\reimp
Definition qtabbar.cpp:2358
void setDrawBase(bool drawTheBase)
Definition qtabbar.cpp:895
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:1339
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:2001
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:2683
int insertTab(int index, const QString &text)
Inserts a new tab with text text at position index.
Definition qtabbar.cpp:935
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:1222
int tabAt(const QPoint &pos) const
Definition qtabbar.cpp:1365
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:914
QTabBar(QWidget *parent=nullptr)
Creates a new tab bar with the given parent.
Definition qtabbar.cpp:847
void setElideMode(Qt::TextElideMode mode)
Definition qtabbar.cpp:2500
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:2814
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:2445
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:1133
void setExpanding(bool enabled)
Definition qtabbar.cpp:2658
virtual void tabLayoutChange()
This virtual handler is called whenever the tab layout changes.
Definition qtabbar.cpp:1637
QSize minimumSizeHint() const override
\reimp
Definition qtabbar.cpp:1496
virtual QSize tabSizeHint(int index) const
Returns the size hint for the tab at position index.
Definition qtabbar.cpp:1559
void setChangeCurrentOnDrag(bool change)
Definition qtabbar.cpp:2762
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:359
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:427
\inmodule QtCore
Definition qvariant.h:64
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:9777
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:3365
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:7904
QSize minimumSizeHint
the recommended minimum size for the widget
Definition qwidget.h:149
void hide()
Hides the widget.
Definition qwidget.cpp:8209
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:7956
virtual void setVisible(bool visible)
Definition qwidget.cpp:8329
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:9761
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:9428
QSize sizeHint
the recommended size for the widget
Definition qwidget.h:148
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:8912
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:2607
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:6471
void setCursor(const QCursor &)
Definition qwidget.cpp:4967
bool visible
whether the widget is visible
Definition qwidget.h:144
\inmodule QtGui
Definition qwindow.h:63
QOpenGLWidget * widget
[1]
QString text
double e
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:145
@ AlignJustify
Definition qnamespace.h:148
@ AlignLeft
Definition qnamespace.h:143
@ LeftButton
Definition qnamespace.h:57
@ NoButton
Definition qnamespace.h:56
@ RightToLeft
@ NoFocus
Definition qnamespace.h:106
@ TabFocus
Definition qnamespace.h:107
@ UpArrow
@ RightArrow
@ LeftArrow
@ DownArrow
@ TextShowMnemonic
Definition qnamespace.h:172
@ ArrowCursor
@ transparent
Definition qnamespace.h:46
@ Key_Right
Definition qnamespace.h:674
@ Key_Left
Definition qnamespace.h:672
TextElideMode
Definition qnamespace.h:187
@ ElideMiddle
Definition qnamespace.h:190
@ ElideRight
Definition qnamespace.h:189
@ ElideNone
Definition qnamespace.h:191
@ ElideLeft
Definition qnamespace.h:188
#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
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
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
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei width
GLboolean enable
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
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:1516
#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:72
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
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent