]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphintabbar.cpp
Improve DnD handling in read-only dirs
[dolphin.git] / src / dolphintabbar.cpp
1 /*
2 * SPDX-FileCopyrightText: 2014 Emmanuel Pescosta <emmanuelpescosta099@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "dolphintabbar.h"
8
9 #include <KLocalizedString>
10
11 #include <QDragEnterEvent>
12 #include <QMenu>
13 #include <QMimeData>
14 #include <QTimer>
15
16 class PreventFocusWhileHidden : public QObject
17 {
18 public:
19 PreventFocusWhileHidden(QObject *parent)
20 : QObject(parent){};
21
22 protected:
23 bool eventFilter(QObject *obj, QEvent *ev) override
24 {
25 switch (ev->type()) {
26 case QEvent::Hide:
27 static_cast<QWidget *>(obj)->setFocusPolicy(Qt::NoFocus);
28 return false;
29 case QEvent::Show:
30 static_cast<QWidget *>(obj)->setFocusPolicy(Qt::TabFocus);
31 return false;
32 default:
33 return false;
34 }
35 };
36 };
37
38 DolphinTabBar::DolphinTabBar(QWidget *parent)
39 : QTabBar(parent)
40 , m_autoActivationIndex(-1)
41 , m_tabToBeClosedOnMiddleMouseButtonRelease(-1)
42 {
43 setAcceptDrops(true);
44 setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab);
45 setMovable(true);
46 setTabsClosable(true);
47
48 setFocusPolicy(Qt::NoFocus);
49 installEventFilter(new PreventFocusWhileHidden(this));
50
51 m_autoActivationTimer = new QTimer(this);
52 m_autoActivationTimer->setSingleShot(true);
53 m_autoActivationTimer->setInterval(800);
54 connect(m_autoActivationTimer, &QTimer::timeout, this, &DolphinTabBar::slotAutoActivationTimeout);
55 }
56
57 void DolphinTabBar::dragEnterEvent(QDragEnterEvent *event)
58 {
59 const QMimeData *mimeData = event->mimeData();
60 const int index = tabAt(event->position().toPoint());
61
62 if (mimeData->hasUrls()) {
63 event->acceptProposedAction();
64 updateAutoActivationTimer(index);
65 }
66
67 QTabBar::dragEnterEvent(event);
68 }
69
70 void DolphinTabBar::dragLeaveEvent(QDragLeaveEvent *event)
71 {
72 updateAutoActivationTimer(-1);
73
74 QTabBar::dragLeaveEvent(event);
75 }
76
77 void DolphinTabBar::dragMoveEvent(QDragMoveEvent *event)
78 {
79 const QMimeData *mimeData = event->mimeData();
80 const int index = tabAt(event->position().toPoint());
81
82 if (mimeData->hasUrls()) {
83 Q_EMIT tabDragMoveEvent(index, event);
84 updateAutoActivationTimer(index);
85 }
86
87 QTabBar::dragMoveEvent(event);
88 }
89
90 void DolphinTabBar::dropEvent(QDropEvent *event)
91 {
92 // Disable the auto activation timer
93 updateAutoActivationTimer(-1);
94
95 const QMimeData *mimeData = event->mimeData();
96 const int index = tabAt(event->position().toPoint());
97
98 if (mimeData->hasUrls()) {
99 Q_EMIT tabDropEvent(index, event);
100 }
101
102 QTabBar::dropEvent(event);
103 }
104
105 void DolphinTabBar::mousePressEvent(QMouseEvent *event)
106 {
107 const int index = tabAt(event->pos());
108
109 if (index >= 0 && event->button() == Qt::MiddleButton) {
110 m_tabToBeClosedOnMiddleMouseButtonRelease = index;
111 return;
112 }
113
114 QTabBar::mousePressEvent(event);
115 }
116
117 void DolphinTabBar::mouseReleaseEvent(QMouseEvent *event)
118 {
119 const int index = tabAt(event->pos());
120
121 if (index >= 0 && index == m_tabToBeClosedOnMiddleMouseButtonRelease && event->button() == Qt::MiddleButton) {
122 // Mouse middle click on a tab closes this tab.
123 Q_EMIT tabCloseRequested(index);
124 return;
125 }
126
127 QTabBar::mouseReleaseEvent(event);
128 }
129
130 void DolphinTabBar::mouseDoubleClickEvent(QMouseEvent *event)
131 {
132 if (event->buttons() & Qt::LeftButton) {
133 int index = tabAt(event->pos());
134
135 if (index < 0) {
136 // empty tabbar area case
137 index = currentIndex();
138 }
139 // Double left click on the tabbar opens a new activated tab
140 // with the url from the doubleclicked tab or currentTab otherwise.
141 Q_EMIT openNewActivatedTab(index);
142 }
143
144 QTabBar::mouseDoubleClickEvent(event);
145 }
146
147 void DolphinTabBar::contextMenuEvent(QContextMenuEvent *event)
148 {
149 const int index = tabAt(event->pos());
150
151 if (index >= 0) {
152 // Tab context menu
153 QMenu menu(this);
154
155 QAction *newTabAction = menu.addAction(QIcon::fromTheme(QStringLiteral("tab-new")), i18nc("@action:inmenu", "New Tab"));
156 QAction *detachTabAction = menu.addAction(QIcon::fromTheme(QStringLiteral("tab-detach")), i18nc("@action:inmenu", "Detach Tab"));
157 QAction *closeOtherTabsAction = menu.addAction(QIcon::fromTheme(QStringLiteral("tab-close-other")), i18nc("@action:inmenu", "Close Other Tabs"));
158 QAction *closeTabAction = menu.addAction(QIcon::fromTheme(QStringLiteral("tab-close")), i18nc("@action:inmenu", "Close Tab"));
159
160 QAction *selectedAction = menu.exec(event->globalPos());
161 if (selectedAction == newTabAction) {
162 Q_EMIT openNewActivatedTab(index);
163 } else if (selectedAction == detachTabAction) {
164 Q_EMIT tabDetachRequested(index);
165 } else if (selectedAction == closeOtherTabsAction) {
166 const int tabCount = count();
167 for (int i = 0; i < index; i++) {
168 Q_EMIT tabCloseRequested(0);
169 }
170 for (int i = index + 1; i < tabCount; i++) {
171 Q_EMIT tabCloseRequested(1);
172 }
173 } else if (selectedAction == closeTabAction) {
174 Q_EMIT tabCloseRequested(index);
175 }
176
177 return;
178 }
179
180 QTabBar::contextMenuEvent(event);
181 }
182
183 void DolphinTabBar::slotAutoActivationTimeout()
184 {
185 if (m_autoActivationIndex >= 0) {
186 setCurrentIndex(m_autoActivationIndex);
187 updateAutoActivationTimer(-1);
188 }
189 }
190
191 void DolphinTabBar::updateAutoActivationTimer(const int index)
192 {
193 if (m_autoActivationIndex != index) {
194 m_autoActivationIndex = index;
195
196 if (m_autoActivationIndex < 0) {
197 m_autoActivationTimer->stop();
198 } else {
199 m_autoActivationTimer->start();
200 }
201 }
202 }
203
204 #include "moc_dolphintabbar.cpp"