KDDockWidgets API Documentation  1.5
TabBarWidget.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KDDockWidgets.
3 
4  SPDX-FileCopyrightText: 2019-2022 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 
29 namespace KDDockWidgets {
30 namespace { // anonymous namespace to silence -Wweak-vtables
31 class MyProxy : public QProxyStyle
32 {
33 public:
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 
56 using namespace KDDockWidgets;
57 
58 static MyProxy *proxyStyle()
59 {
60  static auto *proxy = new MyProxy;
61  return proxy;
62 }
63 
64 TabBarWidget::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 
73 int TabBarWidget::tabAt(QPoint localPos) const
74 {
75  return QTabBar::tabAt(localPos);
76 }
77 
78 DockWidgetBase *TabBarWidget::currentDockWidget() const
79 {
80  const int index = currentIndex();
81  return index == -1 ? nullptr
82  : dockWidgetAt(index);
83 }
84 
85 void TabBarWidget::mousePressEvent(QMouseEvent *e)
86 {
87  onMousePress(e->pos());
89 }
90 
91 void 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 
99 void TabBarWidget::mouseDoubleClickEvent(QMouseEvent *e)
100 {
101  TabBar::onMouseDoubleClick(e->pos());
102 }
103 
104 bool 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 
137 bool 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 
158 QString TabBarWidget::text(int index) const
159 {
160  return tabText(index);
161 }
162 
163 QRect TabBarWidget::rectForTab(int index) const
164 {
165  return QTabBar::tabRect(index);
166 }
167 
168 void TabBarWidget::moveTabTo(int from, int to)
169 {
170  moveTab(from, to);
171 }
QTabBar::event
virtual bool event(QEvent *event) override
QMouseEvent::pos
QPoint pos() const const
QEvent::Show
Show
proxyStyle
static MyProxy * proxyStyle()
Definition: TabBarWidget.cpp:58
QRect
QTabBar
QWidget
QPoint::x
int x() const const
QPoint::y
int y() const const
QTabBar::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *event) override
QTabBar::tabAt
int tabAt(const QPoint &position) const const
QTabBar::mousePressEvent
virtual void mousePressEvent(QMouseEvent *event) override
QStyleHintReturn
QMouseEvent
QTabBar::tabRect
QRect tabRect(int index) const const
QString
QStyleOption
QProxyStyle
Config.h
Application-wide config to tune certain behaviours of the framework.
QStyle::StyleHint
StyleHint
QApplication::startDragDistance
startDragDistance
QEvent::type
QEvent::Type type() const const
QEvent
KDDockWidgets::DockWidgetBase
The DockWidget base-class. DockWidget and DockWidgetBase are only split in two so we can share some c...
Definition: DockWidgetBase.h:61
KDDockWidgets
Definition: Config.cpp:36
QPoint

© 2019-2022 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 Mon Mar 7 2022 02:01:21 for KDDockWidgets API Documentation by doxygen 1.8.20