1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QTABBAR_P_H
41#define QTABBAR_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtWidgets/private/qtwidgetsglobal_p.h>
55#include "qtabbar.h"
56#include "private/qwidget_p.h"
57
58#include <qicon.h>
59#include <qtoolbutton.h>
60#include <qdebug.h>
61#if QT_CONFIG(animation)
62#include <qvariantanimation.h>
63#endif
64
65#define ANIMATION_DURATION 250
66
67#include <qstyleoption.h>
68
69QT_REQUIRE_CONFIG(tabbar);
70
71QT_BEGIN_NAMESPACE
72
73class QMovableTabWidget : public QWidget
74{
75public:
76 explicit QMovableTabWidget(QWidget *parent = nullptr);
77 void setPixmap(const QPixmap &pixmap);
78
79protected:
80 void paintEvent(QPaintEvent *e) override;
81
82private:
83 QPixmap m_pixmap;
84};
85
86class Q_WIDGETS_EXPORT QTabBarPrivate : public QWidgetPrivate
87{
88 Q_DECLARE_PUBLIC(QTabBar)
89public:
90 QTabBarPrivate()
91 :currentIndex(-1), pressedIndex(-1), firstVisible(0), lastVisible(-1), shape(QTabBar::RoundedNorth), layoutDirty(false),
92 drawBase(true), scrollOffset(0), hoverIndex(-1), elideModeSetByUser(false), useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
93 selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false),
94 dragInProgress(false), documentMode(false), autoHide(false), changeCurrentOnDrag(false),
95 switchTabCurrentIndex(-1), switchTabTimerId(0), movingTab(nullptr)
96 {}
97
98 int currentIndex;
99 int pressedIndex;
100 int firstVisible;
101 int lastVisible;
102 QTabBar::Shape shape;
103 bool layoutDirty;
104 bool drawBase;
105 int scrollOffset;
106
107 struct Tab {
108 inline Tab(const QIcon &ico, const QString &txt)
109 : enabled(true) , visible(true), shortcutId(0), text(txt), icon(ico),
110 leftWidget(nullptr), rightWidget(nullptr), lastTab(-1), dragOffset(0)
111#if QT_CONFIG(animation)
112 , animation(nullptr)
113#endif // animation
114 {}
115 bool operator==(const Tab &other) const { return &other == this; }
116 bool enabled;
117 bool visible;
118 int shortcutId;
119 QString text;
120#ifndef QT_NO_TOOLTIP
121 QString toolTip;
122#endif
123#if QT_CONFIG(whatsthis)
124 QString whatsThis;
125#endif
126 QIcon icon;
127 QRect rect;
128 QRect minRect;
129 QRect maxRect;
130
131 QColor textColor;
132 QVariant data;
133 QWidget *leftWidget;
134 QWidget *rightWidget;
135 int lastTab;
136 int dragOffset;
137#ifndef QT_NO_ACCESSIBILITY
138 QString accessibleName;
139#endif
140
141#if QT_CONFIG(animation)
142 ~Tab() { delete 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 } *animation;
155
156 void startAnimation(QTabBarPrivate *priv, int duration) {
157 if (!priv->isAnimated()) {
158 priv->moveTabFinished(index: priv->tabList.indexOf(t: *this));
159 return;
160 }
161 if (!animation)
162 animation = new 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 Tab *at(int index);
183 const Tab *at(int index) const;
184
185 int indexAtPos(const QPoint &p) const;
186
187 inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(stylehint: QStyle::SH_Widget_Animation_Duration, opt: nullptr, widget: q) > 0; }
188 inline bool validIndex(int index) const { return index >= 0 && index < tabList.count(); }
189 void setCurrentNextEnabledIndex(int offset);
190
191 QToolButton* rightB; // right or bottom
192 QToolButton* leftB; // left or top
193
194 void _q_scrollTabs();
195 void _q_closeTab();
196 void moveTab(int index, int offset);
197 void moveTabFinished(int index);
198 QRect hoverRect;
199 int hoverIndex;
200
201 void refresh();
202 void layoutTabs();
203 void layoutWidgets(int start = 0);
204 void layoutTab(int index);
205 void updateMacBorderMetrics();
206 bool isTabInMacUnifiedToolbarArea() const;
207 void setupMovableTab();
208 void autoHideTabs();
209 QRect normalizedScrollRect(int index = -1);
210 int hoveredTabIndex() const;
211
212 void initBasicStyleOption(QStyleOptionTab *option, int tabIndex) const;
213
214 void makeVisible(int index);
215 QSize iconSize;
216 Qt::TextElideMode elideMode;
217 bool elideModeSetByUser;
218 bool useScrollButtons;
219 bool useScrollButtonsSetByUser;
220
221 bool expanding;
222 bool closeButtonOnTabs;
223 QTabBar::SelectionBehavior selectionBehaviorOnRemove;
224
225 QPoint dragStartPosition;
226 bool paintWithOffsets;
227 bool movable;
228 bool dragInProgress;
229 bool documentMode;
230 bool autoHide;
231 bool changeCurrentOnDrag;
232
233 int switchTabCurrentIndex;
234 int switchTabTimerId;
235
236 QMovableTabWidget *movingTab;
237 // shared by tabwidget and qtabbar
238 static void initStyleBaseOption(QStyleOptionTabBarBase *optTabBase, QTabBar *tabbar, QSize size)
239 {
240 QStyleOptionTab tabOverlap;
241 tabOverlap.shape = tabbar->shape();
242 int overlap = tabbar->style()->pixelMetric(metric: QStyle::PM_TabBarBaseOverlap, option: &tabOverlap, widget: tabbar);
243 QWidget *theParent = tabbar->parentWidget();
244 optTabBase->init(w: tabbar);
245 optTabBase->shape = tabbar->shape();
246 optTabBase->documentMode = tabbar->documentMode();
247 if (theParent && overlap > 0) {
248 QRect rect;
249 switch (tabOverlap.shape) {
250 case QTabBar::RoundedNorth:
251 case QTabBar::TriangularNorth:
252 rect.setRect(ax: 0, ay: size.height()-overlap, aw: size.width(), ah: overlap);
253 break;
254 case QTabBar::RoundedSouth:
255 case QTabBar::TriangularSouth:
256 rect.setRect(ax: 0, ay: 0, aw: size.width(), ah: overlap);
257 break;
258 case QTabBar::RoundedEast:
259 case QTabBar::TriangularEast:
260 rect.setRect(ax: 0, ay: 0, aw: overlap, ah: size.height());
261 break;
262 case QTabBar::RoundedWest:
263 case QTabBar::TriangularWest:
264 rect.setRect(ax: size.width() - overlap, ay: 0, aw: overlap, ah: size.height());
265 break;
266 }
267 optTabBase->rect = rect;
268 }
269 }
270
271 void killSwitchTabTimer();
272
273};
274
275QT_END_NAMESPACE
276
277#endif
278

source code of qtbase/src/widgets/widgets/qtabbar_p.h