diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 518c8b7d2f..7b0210aef9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -171,6 +171,7 @@ set(dolphin_SRCS dolphinmainwindow.cpp dolphinviewcontainer.cpp dolphincontextmenu.cpp + dolphintabbar.cpp dolphinrecenttabsmenu.cpp dolphintabpage.cpp filterbar/filterbar.cpp diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 0c48928bf4..41bd626ee8 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -26,6 +26,7 @@ #include "dolphincontextmenu.h" #include "dolphinnewfilemenu.h" #include "dolphinrecenttabsmenu.h" +#include "dolphintabbar.h" #include "dolphinviewcontainer.h" #include "dolphintabpage.h" #include "panels/folders/folderspanel.h" @@ -75,7 +76,6 @@ #include #include #include -#include #include #include #include @@ -144,25 +144,19 @@ DolphinMainWindow::DolphinMainWindow() : connect(this, SIGNAL(urlChanged(KUrl)), m_remoteEncoding, SLOT(slotAboutToOpenUrl())); - m_tabBar = new KTabBar(this); - m_tabBar->setMovable(true); - m_tabBar->setTabsClosable(true); + m_tabBar = new DolphinTabBar(this); connect(m_tabBar, SIGNAL(currentChanged(int)), this, SLOT(setActiveTab(int))); connect(m_tabBar, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int))); - connect(m_tabBar, SIGNAL(contextMenu(int,QPoint)), - this, SLOT(openTabContextMenu(int,QPoint))); - connect(m_tabBar, SIGNAL(newTabRequest()), - this, SLOT(openNewTab())); - connect(m_tabBar, SIGNAL(testCanDecode(const QDragMoveEvent*,bool&)), - this, SLOT(slotTestCanDecode(const QDragMoveEvent*,bool&))); - connect(m_tabBar, SIGNAL(mouseMiddleClick(int)), - this, SLOT(closeTab(int))); + connect(m_tabBar, SIGNAL(openNewActivatedTab(int)), + this, SLOT(openNewActivatedTab(int))); connect(m_tabBar, SIGNAL(tabMoved(int,int)), this, SLOT(slotTabMoved(int,int))); - connect(m_tabBar, SIGNAL(receivedDropEvent(int,QDropEvent*)), + connect(m_tabBar, SIGNAL(tabDropEvent(int,QDropEvent*)), this, SLOT(tabDropEvent(int,QDropEvent*))); + connect(m_tabBar, SIGNAL(tabDetachRequested(int)), + this, SLOT(detachTab(int))); m_tabBar->blockSignals(true); // signals get unblocked after at least 2 tabs are open m_tabBar->hide(); @@ -443,6 +437,13 @@ void DolphinMainWindow::openNewActivatedTab(const KUrl& primaryUrl, const KUrl& setActiveTab(m_viewTab.count() - 1); } +void DolphinMainWindow::openNewActivatedTab(int index) +{ + Q_ASSERT(index >= 0); + const DolphinTabPage* tabPage = m_viewTab.at(index); + openNewActivatedTab(tabPage->activeViewContainer()->url()); +} + void DolphinMainWindow::activateNextTab() { if (m_viewTab.count() >= 2) { @@ -981,50 +982,23 @@ void DolphinMainWindow::closeTab(int index) } } -void DolphinMainWindow::openTabContextMenu(int index, const QPoint& pos) +void DolphinMainWindow::detachTab(int index) { - KMenu menu(this); + Q_ASSERT(index >= 0); - QAction* newTabAction = menu.addAction(KIcon("tab-new"), i18nc("@action:inmenu", "New Tab")); - newTabAction->setShortcut(actionCollection()->action("new_tab")->shortcut()); + const QString separator(QLatin1Char(' ')); + QString command = QLatin1String("dolphin"); - QAction* detachTabAction = menu.addAction(KIcon("tab-detach"), i18nc("@action:inmenu", "Detach Tab")); - - QAction* closeOtherTabsAction = menu.addAction(KIcon("tab-close-other"), i18nc("@action:inmenu", "Close Other Tabs")); - - QAction* closeTabAction = menu.addAction(KIcon("tab-close"), i18nc("@action:inmenu", "Close Tab")); - closeTabAction->setShortcut(actionCollection()->action("close_tab")->shortcut()); - QAction* selectedAction = menu.exec(pos); - if (selectedAction == newTabAction) { - const KUrl url = m_viewTab.at(index)->activeViewContainer()->url(); - openNewTab(url); - m_tabBar->setCurrentIndex(m_viewTab.count() - 1); - } else if (selectedAction == detachTabAction) { - const QString separator(QLatin1Char(' ')); - QString command = QLatin1String("dolphin"); - - const DolphinTabPage* tabPage = m_viewTab.at(index); - - command += separator + tabPage->primaryViewContainer()->url().url(); - if (tabPage->splitViewEnabled()) { - command += separator + tabPage->secondaryViewContainer()->url().url(); - command += separator + QLatin1String("-split"); - } - - KRun::runCommand(command, this); - - closeTab(index); - } else if (selectedAction == closeOtherTabsAction) { - const int count = m_tabBar->count(); - for (int i = 0; i < index; ++i) { - closeTab(0); - } - for (int i = index + 1; i < count; ++i) { - closeTab(1); - } - } else if (selectedAction == closeTabAction) { - closeTab(index); + const DolphinTabPage* tabPage = m_viewTab.at(index); + command += separator + tabPage->primaryViewContainer()->url().url(); + if (tabPage->splitViewEnabled()) { + command += separator + tabPage->secondaryViewContainer()->url().url(); + command += separator + QLatin1String("-split"); } + + KRun::runCommand(command, this); + + closeTab(index); } void DolphinMainWindow::slotTabMoved(int from, int to) @@ -1033,11 +1007,6 @@ void DolphinMainWindow::slotTabMoved(int from, int to) m_tabIndex = m_tabBar->currentIndex(); } -void DolphinMainWindow::slotTestCanDecode(const QDragMoveEvent* event, bool& canDecode) -{ - canDecode = KUrl::List::canDecode(event->mimeData()); -} - void DolphinMainWindow::handleUrl(const KUrl& url) { delete m_lastHandleUrlStatJob; diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h index 7c3bff47fd..9c7f185bce 100644 --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -38,6 +38,7 @@ typedef KIO::FileUndoManager::CommandType CommandType; class DolphinViewActionHandler; class DolphinApplication; class DolphinSettingsDialog; +class DolphinTabBar; class DolphinViewContainer; class DolphinRemoteEncoding; class DolphinTabPage; @@ -46,7 +47,6 @@ class KFileItem; class KFileItemList; class KJob; class KNewFileMenu; -class KTabBar; class KUrl; class QSplitter; class QToolButton; @@ -358,6 +358,12 @@ private slots: */ void openNewActivatedTab(const KUrl& primaryUrl, const KUrl& secondaryUrl = KUrl()); + /** + * Opens a new tab showing the url from tab at the given \a index and + * activates the tab. + */ + void openNewActivatedTab(int index); + void activateNextTab(); void activatePrevTab(); @@ -393,10 +399,10 @@ private slots: void closeTab(int index); /** - * Opens a context menu for the tab with the index \a index - * on the position \a pos. + * Opens the tab with the index \a index in a new Dolphin instance and closes + * this tab. */ - void openTabContextMenu(int index, const QPoint& pos); + void detachTab(int index); /** * Is connected to the QTabBar signal tabMoved(int from, int to). @@ -405,12 +411,6 @@ private slots: */ void slotTabMoved(int from, int to); - /** - * Is connected to the KTabBar signal testCanDecode() and adjusts - * the output parameter \a accept. - */ - void slotTestCanDecode(const QDragMoveEvent* event, bool& accept); - /** * If the URL can be listed, open it in the current view, otherwise * run it through KRun. @@ -549,7 +549,7 @@ private: }; KNewFileMenu* m_newFileMenu; - KTabBar* m_tabBar; + DolphinTabBar* m_tabBar; DolphinViewContainer* m_activeViewContainer; QVBoxLayout* m_centralWidgetLayout; int m_id; diff --git a/src/dolphintabbar.cpp b/src/dolphintabbar.cpp new file mode 100644 index 0000000000..78bd5edcb9 --- /dev/null +++ b/src/dolphintabbar.cpp @@ -0,0 +1,174 @@ +/*************************************************************************** + * Copyright (C) 2014 by Emmanuel Pescosta * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "dolphintabbar.h" + +#include +#include +#include +#include +#include +#include + +DolphinTabBar::DolphinTabBar(QWidget* parent) : + QTabBar(parent), + m_autoActivationIndex(-1) +{ + setAcceptDrops(true); + setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); + setMovable(true); + setTabsClosable(true); + + m_autoActivationTimer = new QTimer(this); + m_autoActivationTimer->setSingleShot(true); + m_autoActivationTimer->setInterval(800); + connect(m_autoActivationTimer, SIGNAL(timeout()), + this, SLOT(slotAutoActivationTimeout())); +} + +void DolphinTabBar::dragEnterEvent(QDragEnterEvent* event) +{ + const QMimeData* mimeData = event->mimeData(); + const int index = tabAt(event->pos()); + + if (KUrl::List::canDecode(mimeData)) { + event->acceptProposedAction(); + updateAutoActivationTimer(index); + } + + QTabBar::dragEnterEvent(event); +} + +void DolphinTabBar::dragLeaveEvent(QDragLeaveEvent* event) +{ + updateAutoActivationTimer(-1); + + QTabBar::dragLeaveEvent(event); +} + +void DolphinTabBar::dragMoveEvent(QDragMoveEvent* event) +{ + const QMimeData* mimeData = event->mimeData(); + const int index = tabAt(event->pos()); + + if (KUrl::List::canDecode(mimeData)) { + updateAutoActivationTimer(index); + } + + QTabBar::dragMoveEvent(event); +} + +void DolphinTabBar::dropEvent(QDropEvent* event) +{ + // Disable the auto activation timer + updateAutoActivationTimer(-1); + + const QMimeData* mimeData = event->mimeData(); + const int index = tabAt(event->pos()); + + if (index >= 0 && KUrl::List::canDecode(mimeData)) { + emit tabDropEvent(index, event); + } + + QTabBar::dropEvent(event); +} + +void DolphinTabBar::mousePressEvent(QMouseEvent* event) +{ + const int index = tabAt(event->pos()); + + if (index >= 0 && event->button() == Qt::MiddleButton) { + // Mouse middle click on a tab closes this tab. + emit tabCloseRequested(index); + return; + } + + QTabBar::mousePressEvent(event); +} + +void DolphinTabBar::mouseDoubleClickEvent(QMouseEvent* event) +{ + const int index = tabAt(event->pos()); + + if (index < 0) { + // Double click on the empty tabbar area opens a new activated tab + // with the url from the current tab. + emit openNewActivatedTab(currentIndex()); + return; + } + + QTabBar::mouseDoubleClickEvent(event); +} + +void DolphinTabBar::contextMenuEvent(QContextMenuEvent* event) +{ + const int index = tabAt(event->pos()); + + if (index >= 0) { + // Tab context menu + KMenu menu(this); + + QAction* newTabAction = menu.addAction(KIcon("tab-new"), i18nc("@action:inmenu", "New Tab")); + QAction* detachTabAction = menu.addAction(KIcon("tab-detach"), i18nc("@action:inmenu", "Detach Tab")); + QAction* closeOtherTabsAction = menu.addAction(KIcon("tab-close-other"), i18nc("@action:inmenu", "Close Other Tabs")); + QAction* closeTabAction = menu.addAction(KIcon("tab-close"), i18nc("@action:inmenu", "Close Tab")); + + QAction* selectedAction = menu.exec(event->globalPos()); + if (selectedAction == newTabAction) { + emit openNewActivatedTab(index); + } else if (selectedAction == detachTabAction) { + emit tabDetachRequested(index); + } else if (selectedAction == closeOtherTabsAction) { + const int tabCount = count(); + for (int i = 0; i < index; i++) { + emit tabCloseRequested(0); + } + for (int i = index + 1; i < tabCount; i++) { + emit tabCloseRequested(1); + } + } else if (selectedAction == closeTabAction) { + emit tabCloseRequested(index); + } + + return; + } + + QTabBar::contextMenuEvent(event); +} + +void DolphinTabBar::slotAutoActivationTimeout() +{ + if (m_autoActivationIndex >= 0) { + setCurrentIndex(m_autoActivationIndex); + updateAutoActivationTimer(-1); + } +} + +void DolphinTabBar::updateAutoActivationTimer(const int index) +{ + if (m_autoActivationIndex != index) { + m_autoActivationIndex = index; + + if (m_autoActivationIndex < 0) { + m_autoActivationTimer->stop(); + } else { + m_autoActivationTimer->start(); + } + } +} diff --git a/src/dolphintabbar.h b/src/dolphintabbar.h new file mode 100644 index 0000000000..d2b2e9e575 --- /dev/null +++ b/src/dolphintabbar.h @@ -0,0 +1,65 @@ +/*************************************************************************** + * Copyright (C) 2014 by Emmanuel Pescosta * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DOLPHIN_TAB_BAR_H +#define DOLPHIN_TAB_BAR_H + +#include + +class DolphinTabBar : public QTabBar +{ + Q_OBJECT + +public: + explicit DolphinTabBar(QWidget* parent); + +signals: + void openNewActivatedTab(int index); + void tabDropEvent(int index, QDropEvent* event); + void tabDetachRequested(int index); + +protected: + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dragLeaveEvent(QDragLeaveEvent* event); + virtual void dragMoveEvent(QDragMoveEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual void mousePressEvent(QMouseEvent* event); + virtual void mouseDoubleClickEvent(QMouseEvent* event); + + /** + * Opens a context menu for the tab on the \a event position. + */ + virtual void contextMenuEvent(QContextMenuEvent* event); + +private slots: + void slotAutoActivationTimeout(); + +private: + /** + * If \a index is a valid index (>= 0), store the index and start the timer + * (if the interval >= 0 ms). If the index is not valid (< 0), stop the timer. + */ + void updateAutoActivationTimer(const int index); + +private: + QTimer* m_autoActivationTimer; + int m_autoActivationIndex; +}; + +#endif // DOLPHIN_TAB_BAR_H