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 paintWithOffsets(true), 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 paintWithOffsets : 1;
99 bool movable : 1;
100 bool dragInProgress : 1;
101 bool documentMode : 1;
102 bool autoHide : 1;
103 bool changeCurrentOnDrag : 1;
104
105 struct Tab {
106 inline Tab(const QIcon &ico, const QString &txt)
107 : text(txt), icon(ico), enabled(true), visible(true), measuringMinimum(false)
108 {
109 }
110 /*
111 Tabs are managed by instance; they are not the same even
112 if all properties are the same.
113 */
114 Q_DISABLE_COPY_MOVE(Tab);
115
116 QString text;
117#if QT_CONFIG(tooltip)
118 QString toolTip;
119#endif
120#if QT_CONFIG(whatsthis)
121 QString whatsThis;
122#endif
123#if QT_CONFIG(accessibility)
124 QString accessibleName;
125#endif
126 QIcon icon;
127 QRect rect;
128 QRect minRect;
129 QRect maxRect;
130
131 QColor textColor;
132 QVariant data;
133 QWidget *leftWidget = nullptr;
134 QWidget *rightWidget = nullptr;
135 int shortcutId = 0;
136 int lastTab = -1;
137 int dragOffset = 0;
138 uint enabled : 1;
139 uint visible : 1;
140 uint measuringMinimum : 1;
141
142#if QT_CONFIG(animation)
143 struct TabBarAnimation : public QVariantAnimation {
144 TabBarAnimation(Tab *t, QTabBarPrivate *_priv) : tab(t), priv(_priv)
145 { setEasingCurve(QEasingCurve::InOutQuad); }
146
147 void updateCurrentValue(const QVariant &current) override;
148
149 void updateState(State newState, State) override;
150 private:
151 //these are needed for the callbacks
152 Tab *tab;
153 QTabBarPrivate *priv;
154 };
155 std::unique_ptr<TabBarAnimation> animation;
156
157 void startAnimation(QTabBarPrivate *priv, int duration) {
158 if (!priv->isAnimated()) {
159 priv->moveTabFinished(priv->tabList.indexOf(this));
160 return;
161 }
162 if (!animation)
163 animation = std::make_unique<TabBarAnimation>(this, priv);
164 animation->setStartValue(dragOffset);
165 animation->setEndValue(0);
166 animation->setDuration(duration);
167 animation->start();
168 }
169#else
170 void startAnimation(QTabBarPrivate *priv, int duration)
171 { Q_UNUSED(duration); priv->moveTabFinished(priv->tabList.indexOf(this)); }
172#endif // animation
173 };
174 QList<Tab*> tabList;
175 mutable QHash<QString, QSize> textSizes;
176
177 void calculateFirstLastVisible(int index, bool visible, bool remove);
178 int selectNewCurrentIndexFrom(int currentIndex);
179 int calculateNewPosition(int from, int to, int index) const;
180 void slide(int from, int to);
181 void init();
182
183 inline Tab *at(int index) { return tabList.value(index, nullptr); }
184 inline const Tab *at(int index) const { return tabList.value(index, nullptr); }
185
186 int indexAtPos(const QPoint &p) const;
187
188 inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, q) > 0; }
189 inline bool validIndex(int index) const { return index >= 0 && index < tabList.size(); }
190 void setCurrentNextEnabledIndex(int offset);
191
192 void scrollTabs();
193 void closeTab();
194 void moveTab(int index, int offset);
195 void moveTabFinished(int index);
196
197 void refresh();
198 void layoutTabs();
199 void layoutWidgets(int start = 0);
200 void layoutTab(int index);
201 void updateMacBorderMetrics();
202 bool isTabInMacUnifiedToolbarArea() const;
203 void setupMovableTab();
204 void autoHideTabs();
205 QRect normalizedScrollRect(int index = -1);
206 int hoveredTabIndex() const;
207
208 void initBasicStyleOption(QStyleOptionTab *option, int tabIndex) const;
209
210 void makeVisible(int index);
211 const Tab *lastVisibleTab() const
212 {
213 auto it = std::find_if(tabList.rbegin(), tabList.rend(),
214 [](const Tab *tab) { return tab->visible; });
215 return it == tabList.rend() ? nullptr : *it;
216 }
217
218 // shared by tabwidget and qtabbar
219 static void initStyleBaseOption(QStyleOptionTabBarBase *optTabBase, QTabBar *tabbar, QSize size)
220 {
221 QStyleOptionTab tabOverlap;
222 tabOverlap.shape = tabbar->shape();
223 int overlap = tabbar->style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, &tabOverlap, tabbar);
224 QWidget *theParent = tabbar->parentWidget();
225 optTabBase->initFrom(tabbar);
226 optTabBase->shape = tabbar->shape();
227 optTabBase->documentMode = tabbar->documentMode();
228 if (theParent && overlap > 0) {
229 QRect rect;
230 switch (tabOverlap.shape) {
231 case QTabBar::RoundedNorth:
232 case QTabBar::TriangularNorth:
233 rect.setRect(0, size.height()-overlap, size.width(), overlap);
234 break;
235 case QTabBar::RoundedSouth:
236 case QTabBar::TriangularSouth:
237 rect.setRect(0, 0, size.width(), overlap);
238 break;
239 case QTabBar::RoundedEast:
240 case QTabBar::TriangularEast:
241 rect.setRect(0, 0, overlap, size.height());
242 break;
243 case QTabBar::RoundedWest:
244 case QTabBar::TriangularWest:
245 rect.setRect(size.width() - overlap, 0, overlap, size.height());
246 break;
247 }
248 optTabBase->rect = rect;
249 }
250 }
251
252 void killSwitchTabTimer();
253
254};
255
256constexpr inline bool verticalTabs(QTabBar::Shape shape) noexcept
257{
258 return shape == QTabBar::RoundedWest
259 || shape == QTabBar::RoundedEast
260 || shape == QTabBar::TriangularWest
261 || shape == QTabBar::TriangularEast;
262}
263
264QT_END_NAMESPACE
265
266#endif
QT_REQUIRE_CONFIG(tabbar)
constexpr bool verticalTabs(QTabBar::Shape shape) noexcept
Definition qtabbar_p.h:256