KDDockWidgets API Documentation 1.7
Loading...
Searching...
No Matches
TabBarWidget.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2019-2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: Sérgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
20#include "TabBarWidget_p.h"
21#include "Config.h"
22
23#include <QMouseEvent>
24#include <QApplication>
25#include <QProxyStyle>
26
27// clazy:excludeall=ctor-missing-parent-argument,missing-qobject-macro
28
29namespace KDDockWidgets {
30namespace { // anonymous namespace to silence -Wweak-vtables
31class MyProxy : public QProxyStyle
32{
33public:
34 MyProxy()
35 : QProxyStyle(qApp->style())
36 {
37 setParent(qApp);
38 }
39
40 int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
41 const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
42 {
44 // QTabBar has a bug which causes the paint event to dereference a tab which was already removed.
45 // Because, after the tab being removed, the d->pressedIndex is only reset after the animation ends.
46 // So disable the animation. Crash can be repro by enabling movable tabs, and detaching a tab quickly from
47 // a floating window containing two dock widgets. Reproduced on Windows
48 return 0;
49 }
50 return baseStyle()->styleHint(hint, option, widget, returnData);
51 }
52};
53}
54}
55
56using namespace KDDockWidgets;
57
58static MyProxy *proxyStyle()
59{
60 static auto *proxy = new MyProxy;
61 return proxy;
62}
63
64TabBarWidget::TabBarWidget(TabWidget *parent)
65 : QTabBar(parent->asWidget())
66 , TabBar(this, parent)
67 , m_tabWidget(parent)
68{
69 setMovable(Config::self().flags() & Config::Flag_AllowReorderTabs);
70 setStyle(proxyStyle());
71}
72
73int TabBarWidget::tabAt(QPoint localPos) const
74{
75 return QTabBar::tabAt(localPos);
76}
77
78DockWidgetBase *TabBarWidget::currentDockWidget() const
79{
80 const int index = currentIndex();
81 return index == -1 ? nullptr
82 : dockWidgetAt(index);
83}
84
85void TabBarWidget::mousePressEvent(QMouseEvent *e)
86{
87 onMousePress(e->pos());
89}
90
91void TabBarWidget::mouseMoveEvent(QMouseEvent *e)
92{
93 if (count() > 1) {
94 // Only allow to re-order tabs if we have more than 1 tab, otherwise it's just weird.
96 }
97}
98
99void TabBarWidget::mouseDoubleClickEvent(QMouseEvent *e)
100{
101 TabBar::onMouseDoubleClick(e->pos());
102}
103
104bool TabBarWidget::dragCanStart(QPoint pressPos, QPoint pos) const
105{
106 // Here we allow the user to re-order tabs instead of dragging them off.
107 // To do that we just return false here, and QTabBar will handle the mouse event, assuming QTabBar::isMovable.
108
109 const bool defaultResult = Draggable::dragCanStart(pressPos, pos);
110
111 if (!defaultResult || !isMovable()) {
112 // Nothing more to do. If the drag wouldn't start anyway, return false.
113 // And if the tabs aren't movable, just return the default result, which just considers
114 // QApplication::startDragDistances
115 return defaultResult;
116 }
117
118 const int index = tabAt(mapFromGlobal(pos));
119 if (index == -1)
120 return defaultResult;
121
122 const int deltaX = qAbs(pos.x() - pressPos.x());
123 const int deltaY = qAbs(pos.y() - pressPos.y());
124
125 if (deltaY > 5 * QApplication::startDragDistance()) {
126 // Moving up or down too much results in a detach. No tab re-ordering allowed.
127 return true;
128 } else if (deltaY > QApplication::startDragDistance() && deltaX < QApplication::startDragDistance()) {
129 // Moved a bit up or down, but not left/right, then detach too.
130 // Only if it's going considerably left/right we allow to re-order tabs.
131 return true;
132 }
133
134 return false;
135}
136
137bool TabBarWidget::event(QEvent *ev)
138{
139 // Qt has a bug in QWidgetPrivate::deepestFocusProxy(), it doesn't honour visibility
140 // of the focus scope. Once an hidden widget is focused the chain is broken and tab
141 // stops working (#180)
142
143 auto parent = parentWidget();
144 if (!parent)
145 return QTabBar::event(ev);
146
147 const bool result = QTabBar::event(ev);
148
149 if (ev->type() == QEvent::Show) {
150 parent->setFocusProxy(this);
151 } else if (ev->type() == QEvent::Hide) {
152 parent->setFocusProxy(nullptr);
153 }
154
155 return result;
156}
157
158QString TabBarWidget::text(int index) const
159{
160 return tabText(index);
161}
162
163QRect TabBarWidget::rectForTab(int index) const
164{
165 return QTabBar::tabRect(index);
166}
167
168void TabBarWidget::moveTabTo(int from, int to)
169{
170 moveTab(from, to);
171}
172
173void TabBarWidget::tabInserted(int index)
174{
176 Q_EMIT dockWidgetInserted(index);
177}
178
179void TabBarWidget::tabRemoved(int index)
180{
181 QTabBar::tabRemoved(index);
182 Q_EMIT dockWidgetRemoved(index);
183}
Application-wide config to tune certain behaviours of the framework.
static MyProxy * proxyStyle()
static Config & self()
returns the singleton Config instance
Definition Config.cpp:84
@ Flag_AllowReorderTabs
Allows user to re-order tabs by dragging them.
Definition Config.h:94
The DockWidget base-class. DockWidget and DockWidgetBase are only split in two so we can share some c...
QEvent::Type type() const const
QPoint pos() const const
int x() const const
int y() const const
virtual bool event(QEvent *event) override
virtual void mouseMoveEvent(QMouseEvent *event) override
virtual void mousePressEvent(QMouseEvent *event) override
int tabAt(const QPoint &position) const const
virtual void tabInserted(int index)
QRect tabRect(int index) const const
virtual void tabRemoved(int index)

© 2019-2023 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated on Wed Nov 1 2023 00:02:31 for KDDockWidgets API Documentation by doxygen 1.9.8