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// Qt-Security score:significant reason:default
4
5#ifndef QTABBAR_P_H
6#define QTABBAR_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtWidgets/private/qtwidgetsglobal_p.h>
20#include "qtabbar.h"
21#include "private/qwidget_p.h"
22
23#include <qicon.h>
24#include <qtoolbutton.h>
25#include <qbasictimer.h>
26#if QT_CONFIG(animation)
27#include <qvariantanimation.h>
28#endif
29
30#define ANIMATION_DURATION 250
31
32#include <qstyleoption.h>
33#include <utility>
34
36
37QT_BEGIN_NAMESPACE
38
39class QMovableTabWidget : public QWidget
40{
41public:
42 explicit QMovableTabWidget(QWidget *parent = nullptr);
43 void setPixmap(const QPixmap &pixmap);
44
45protected:
46 void paintEvent(QPaintEvent *e) override;
47
48private:
49 QPixmap m_pixmap;
50};
51
52class Q_WIDGETS_EXPORT QTabBarPrivate : public QWidgetPrivate
53{
54 Q_DECLARE_PUBLIC(QTabBar)
55public:
56 QTabBarPrivate()
57 : layoutDirty(false), drawBase(true), elideModeSetByUser(false), useScrollButtons(false),
58 useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
59 movable(false), dragInProgress(false), documentMode(false),
60 autoHide(false), changeCurrentOnDrag(false)
61 {}
62 ~QTabBarPrivate()
63 {
64 qDeleteAll(tabList);
65 }
66
67 QRect hoverRect;
68 QPoint dragStartPosition;
69 QPoint mousePosition = {-1, -1};
70#if QT_CONFIG(wheelevent)
71 QPoint accumulatedAngleDelta;
72#endif
73 QSize iconSize;
74 QToolButton* rightB = nullptr; // right or bottom
75 QToolButton* leftB = nullptr; // left or top
76 QMovableTabWidget *movingTab = nullptr;
77 int hoverIndex = -1;
78 int switchTabCurrentIndex = -1;
79 QBasicTimer switchTabTimer;
80 Qt::TextElideMode elideMode = Qt::ElideNone;
81 QTabBar::SelectionBehavior selectionBehaviorOnRemove = QTabBar::SelectRightTab;
82 QTabBar::Shape shape = QTabBar::RoundedNorth;
83 Qt::MouseButtons mouseButtons = Qt::NoButton;
84
85 int currentIndex = -1;
86 int pressedIndex = -1;
87 int firstVisible = 0;
88 int lastVisible = -1;
89 int scrollOffset = 0;
90
91 bool layoutDirty : 1;
92 bool drawBase : 1;
93 bool elideModeSetByUser : 1;
94 bool useScrollButtons : 1;
95 bool useScrollButtonsSetByUser : 1;
96 bool expanding : 1;
97 bool closeButtonOnTabs : 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 const Tab *lastVisibleTab() const
211 {
212 auto it = std::find_if(tabList.rbegin(), tabList.rend(),
213 [](const Tab *tab) { return tab->visible; });
214 return it == tabList.rend() ? nullptr : *it;
215 }
216
217 // shared by tabwidget and qtabbar
218 static void initStyleBaseOption(QStyleOptionTabBarBase *optTabBase, QTabBar *tabbar, QSize size)
219 {
220 QStyleOptionTab tabOverlap;
221 tabOverlap.shape = tabbar->shape();
222 int overlap = tabbar->style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, &tabOverlap, tabbar);
223 QWidget *theParent = tabbar->parentWidget();
224 optTabBase->initFrom(tabbar);
225 optTabBase->shape = tabbar->shape();
226 optTabBase->documentMode = tabbar->documentMode();
227 if (theParent && overlap > 0) {
228 QRect rect;
229 switch (tabOverlap.shape) {
230 case QTabBar::RoundedNorth:
231 case QTabBar::TriangularNorth:
232 rect.setRect(0, size.height()-overlap, size.width(), overlap);
233 break;
234 case QTabBar::RoundedSouth:
235 case QTabBar::TriangularSouth:
236 rect.setRect(0, 0, size.width(), overlap);
237 break;
238 case QTabBar::RoundedEast:
239 case QTabBar::TriangularEast:
240 rect.setRect(0, 0, overlap, size.height());
241 break;
242 case QTabBar::RoundedWest:
243 case QTabBar::TriangularWest:
244 rect.setRect(size.width() - overlap, 0, overlap, size.height());
245 break;
246 }
247 optTabBase->rect = rect;
248 }
249 }
250
251 void killSwitchTabTimer();
252
253};
254
255constexpr inline bool verticalTabs(QTabBar::Shape shape) noexcept
256{
257 return shape == QTabBar::RoundedWest
258 || shape == QTabBar::RoundedEast
259 || shape == QTabBar::TriangularWest
260 || shape == QTabBar::TriangularEast;
261}
262
263QT_END_NAMESPACE
264
265#endif
QT_REQUIRE_CONFIG(tabbar)
constexpr bool verticalTabs(QTabBar::Shape shape) noexcept
Definition qtabbar_p.h:255