Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtabbar_p.h
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#ifndef QTABBAR_P_H
5#define QTABBAR_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtWidgets/private/qtwidgetsglobal_p.h>
19#include "qtabbar.h"
20#include "private/qwidget_p.h"
21
22#include <qicon.h>
23#include <qtoolbutton.h>
24#include <qbasictimer.h>
25#if QT_CONFIG(animation)
26#include <qvariantanimation.h>
27#endif
28
29#define ANIMATION_DURATION 250
30
31#include <qstyleoption.h>
32#include <utility>
33
35
36QT_BEGIN_NAMESPACE
37
38class QMovableTabWidget : public QWidget
39{
40public:
41 explicit QMovableTabWidget(QWidget *parent = nullptr);
42 void setPixmap(const QPixmap &pixmap);
43
44protected:
45 void paintEvent(QPaintEvent *e) override;
46
47private:
48 QPixmap m_pixmap;
49};
50
51class Q_WIDGETS_EXPORT QTabBarPrivate : public QWidgetPrivate
52{
53 Q_DECLARE_PUBLIC(QTabBar)
54public:
55 QTabBarPrivate()
56 : layoutDirty(false), drawBase(true), elideModeSetByUser(false), useScrollButtons(false),
57 useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
58 paintWithOffsets(true), movable(false), dragInProgress(false), documentMode(false),
59 autoHide(false), changeCurrentOnDrag(false)
60 {}
61 ~QTabBarPrivate()
62 {
63 qDeleteAll(tabList);
64 }
65
66 QRect hoverRect;
67 QPoint dragStartPosition;
68 QPoint mousePosition = {-1, -1};
69#if QT_CONFIG(wheelevent)
70 QPoint accumulatedAngleDelta;
71#endif
72 QSize iconSize;
73 QToolButton* rightB = nullptr; // right or bottom
74 QToolButton* leftB = nullptr; // left or top
75 QMovableTabWidget *movingTab = nullptr;
76 int hoverIndex = -1;
77 int switchTabCurrentIndex = -1;
78 QBasicTimer switchTabTimer;
79 Qt::TextElideMode elideMode = Qt::ElideNone;
80 QTabBar::SelectionBehavior selectionBehaviorOnRemove = QTabBar::SelectRightTab;
81 QTabBar::Shape shape = QTabBar::RoundedNorth;
82 Qt::MouseButtons mouseButtons = Qt::NoButton;
83
84 int currentIndex = -1;
85 int pressedIndex = -1;
86 int firstVisible = 0;
87 int lastVisible = -1;
88 int scrollOffset = 0;
89
90 bool layoutDirty : 1;
91 bool drawBase : 1;
92 bool elideModeSetByUser : 1;
93 bool useScrollButtons : 1;
94 bool useScrollButtonsSetByUser : 1;
95 bool expanding : 1;
96 bool closeButtonOnTabs : 1;
97 bool paintWithOffsets : 1;
98 bool movable : 1;
99 bool dragInProgress : 1;
100 bool documentMode : 1;
101 bool autoHide : 1;
102 bool changeCurrentOnDrag : 1;
103
104 struct Tab {
105 inline Tab(const QIcon &ico, const QString &txt)
106 : text(txt), icon(ico), enabled(true), visible(true), measuringMinimum(false)
107 {
108 }
109 /*
110 Tabs are managed by instance; they are not the same even
111 if all properties are the same.
112 */
113 Q_DISABLE_COPY_MOVE(Tab);
114
115 QString text;
116#if QT_CONFIG(tooltip)
117 QString toolTip;
118#endif
119#if QT_CONFIG(whatsthis)
120 QString whatsThis;
121#endif
122#if QT_CONFIG(accessibility)
123 QString accessibleName;
124#endif
125 QIcon icon;
126 QRect rect;
127 QRect minRect;
128 QRect maxRect;
129
130 QColor textColor;
131 QVariant data;
132 QWidget *leftWidget = nullptr;
133 QWidget *rightWidget = nullptr;
134 int shortcutId = 0;
135 int lastTab = -1;
136 int dragOffset = 0;
137 uint enabled : 1;
138 uint visible : 1;
139 uint measuringMinimum : 1;
140
141#if QT_CONFIG(animation)
142 struct TabBarAnimation : public QVariantAnimation {
143 TabBarAnimation(Tab *t, QTabBarPrivate *_priv) : tab(t), priv(_priv)
144 { setEasingCurve(QEasingCurve::InOutQuad); }
145
146 void updateCurrentValue(const QVariant &current) override;
147
148 void updateState(State newState, State) override;
149 private:
150 //these are needed for the callbacks
151 Tab *tab;
152 QTabBarPrivate *priv;
153 };
154 std::unique_ptr<TabBarAnimation> animation;
155
156 void startAnimation(QTabBarPrivate *priv, int duration) {
157 if (!priv->isAnimated()) {
158 priv->moveTabFinished(priv->tabList.indexOf(this));
159 return;
160 }
161 if (!animation)
162 animation = std::make_unique<TabBarAnimation>(this, priv);
163 animation->setStartValue(dragOffset);
164 animation->setEndValue(0);
165 animation->setDuration(duration);
166 animation->start();
167 }
168#else
169 void startAnimation(QTabBarPrivate *priv, int duration)
170 { Q_UNUSED(duration); priv->moveTabFinished(priv->tabList.indexOf(this)); }
171#endif // animation
172 };
173 QList<Tab*> tabList;
174 mutable QHash<QString, QSize> textSizes;
175
176 void calculateFirstLastVisible(int index, bool visible, bool remove);
177 int selectNewCurrentIndexFrom(int currentIndex);
178 int calculateNewPosition(int from, int to, int index) const;
179 void slide(int from, int to);
180 void init();
181
182 inline Tab *at(int index) { return tabList.value(index, nullptr); }
183 inline const Tab *at(int index) const { return tabList.value(index, nullptr); }
184
185 int indexAtPos(const QPoint &p) const;
186
187 inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, q) > 0; }
188 inline bool validIndex(int index) const { return index >= 0 && index < tabList.size(); }
189 void setCurrentNextEnabledIndex(int offset);
190
191 void scrollTabs();
192 void closeTab();
193 void moveTab(int index, int offset);
194 void moveTabFinished(int index);
195
196 void refresh();
197 void layoutTabs();
198 void layoutWidgets(int start = 0);
199 void layoutTab(int index);
200 void updateMacBorderMetrics();
201 bool isTabInMacUnifiedToolbarArea() const;
202 void setupMovableTab();
203 void autoHideTabs();
204 QRect normalizedScrollRect(int index = -1);
205 int hoveredTabIndex() const;
206
207 void initBasicStyleOption(QStyleOptionTab *option, int tabIndex) const;
208
209 void makeVisible(int index);
210
211 // shared by tabwidget and qtabbar
212 static void initStyleBaseOption(QStyleOptionTabBarBase *optTabBase, QTabBar *tabbar, QSize size)
213 {
214 QStyleOptionTab tabOverlap;
215 tabOverlap.shape = tabbar->shape();
216 int overlap = tabbar->style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, &tabOverlap, tabbar);
217 QWidget *theParent = tabbar->parentWidget();
218 optTabBase->initFrom(tabbar);
219 optTabBase->shape = tabbar->shape();
220 optTabBase->documentMode = tabbar->documentMode();
221 if (theParent && overlap > 0) {
222 QRect rect;
223 switch (tabOverlap.shape) {
224 case QTabBar::RoundedNorth:
225 case QTabBar::TriangularNorth:
226 rect.setRect(0, size.height()-overlap, size.width(), overlap);
227 break;
228 case QTabBar::RoundedSouth:
229 case QTabBar::TriangularSouth:
230 rect.setRect(0, 0, size.width(), overlap);
231 break;
232 case QTabBar::RoundedEast:
233 case QTabBar::TriangularEast:
234 rect.setRect(0, 0, overlap, size.height());
235 break;
236 case QTabBar::RoundedWest:
237 case QTabBar::TriangularWest:
238 rect.setRect(size.width() - overlap, 0, overlap, size.height());
239 break;
240 }
241 optTabBase->rect = rect;
242 }
243 }
244
245 void killSwitchTabTimer();
246
247};
248
249constexpr inline bool verticalTabs(QTabBar::Shape shape) noexcept
250{
251 return shape == QTabBar::RoundedWest
252 || shape == QTabBar::RoundedEast
253 || shape == QTabBar::TriangularWest
254 || shape == QTabBar::TriangularEast;
255}
256
257QT_END_NAMESPACE
258
259#endif
QT_REQUIRE_CONFIG(tabbar)
constexpr bool verticalTabs(QTabBar::Shape shape) noexcept
Definition qtabbar_p.h:249