]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Enable Ctrl/Shift-Click to open folder in a new tab/window
authorAlessio Bonfiglio <alessio.bonfiglio@mail.polimi.it>
Fri, 17 Dec 2021 14:11:46 +0000 (14:11 +0000)
committerMéven Car <meven29@gmail.com>
Fri, 17 Dec 2021 14:11:46 +0000 (14:11 +0000)
and more

12 files changed:
src/dolphinmainwindow.cpp
src/dolphinmainwindow.h
src/dolphinviewcontainer.cpp
src/dolphinviewcontainer.h
src/kitemviews/kitemlistcontroller.cpp
src/kitemviews/kitemlistcontroller.h
src/panels/folders/folderspanel.cpp
src/panels/folders/folderspanel.h
src/panels/places/placespanel.cpp
src/panels/places/placespanel.h
src/views/dolphinview.cpp
src/views/dolphinview.h

index e034e58f8c7b558f4a2ce4e4d6e2b8c31bff948a..11338ec1f7fe719f72611ad683898838347fdb8d 100644 (file)
@@ -445,6 +445,16 @@ void DolphinMainWindow::openNewTab(const QUrl& url)
     m_tabWidget->openNewTab(url, QUrl());
 }
 
+void DolphinMainWindow::openNewTabAndActivate(const QUrl &url)
+{
+    m_tabWidget->openNewActivatedTab(url, QUrl());
+}
+
+void DolphinMainWindow::openNewWindow(const QUrl &url)
+{
+    Dolphin::openNewWindow({url}, this);
+}
+
 void DolphinMainWindow::slotSplitViewChanged()
 {
     m_tabWidget->currentTabPage()->setSplitViewEnabled(GeneralSettings::splitView(), WithAnimation);
@@ -1859,8 +1869,10 @@ void DolphinMainWindow::setupDockWidgets()
             foldersPanel, &FoldersPanel::setUrl);
     connect(foldersPanel, &FoldersPanel::folderActivated,
             this, &DolphinMainWindow::changeUrl);
-    connect(foldersPanel, &FoldersPanel::folderMiddleClicked,
+    connect(foldersPanel, &FoldersPanel::folderInNewTab,
             this, &DolphinMainWindow::openNewTab);
+    connect(foldersPanel, &FoldersPanel::folderInNewActiveTab,
+            this, &DolphinMainWindow::openNewTabAndActivate);
     connect(foldersPanel, &FoldersPanel::errorMessage,
             this, &DolphinMainWindow::showErrorMessage);
 
@@ -1942,8 +1954,10 @@ void DolphinMainWindow::setupDockWidgets()
     addDockWidget(Qt::LeftDockWidgetArea, placesDock);
     connect(m_placesPanel, &PlacesPanel::placeActivated,
             this, &DolphinMainWindow::slotPlaceActivated);
-    connect(m_placesPanel, &PlacesPanel::placeMiddleClicked,
+    connect(m_placesPanel, &PlacesPanel::placeActivatedInNewTab,
             this, &DolphinMainWindow::openNewTab);
+    connect(m_placesPanel, &PlacesPanel::placeActivatedInNewActiveTab,
+            this, &DolphinMainWindow::openNewTabAndActivate);
     connect(m_placesPanel, &PlacesPanel::errorMessage,
             this, &DolphinMainWindow::showErrorMessage);
     connect(this, &DolphinMainWindow::urlChanged,
@@ -2134,6 +2148,10 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
             this, &DolphinMainWindow::updateSearchAction);
     connect(container, &DolphinViewContainer::captionChanged,
             this, &DolphinMainWindow::updateWindowTitle);
+    connect(container, &DolphinViewContainer::tabRequested,
+            this, &DolphinMainWindow::openNewTab);
+    connect(container, &DolphinViewContainer::activeTabRequested,
+            this, &DolphinMainWindow::openNewTabAndActivate);
 
     const QAction* toggleSearchAction = actionCollection()->action(QStringLiteral("toggle_search"));
     connect(toggleSearchAction, &QAction::triggered, container, &DolphinViewContainer::setSearchModeEnabled);
@@ -2147,6 +2165,10 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
             this, &DolphinMainWindow::fileItemsChanged);
     connect(view, &DolphinView::tabRequested,
             this, &DolphinMainWindow::openNewTab);
+    connect(view, &DolphinView::activeTabRequested,
+            this, &DolphinMainWindow::openNewTabAndActivate);
+    connect(view, &DolphinView::windowRequested,
+            this, &DolphinMainWindow::openNewWindow);
     connect(view, &DolphinView::requestContextMenu,
             this, &DolphinMainWindow::openContextMenu);
     connect(view, &DolphinView::directoryLoadingStarted,
@@ -2181,6 +2203,10 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
             this, &DolphinMainWindow::slotEditableStateChanged);
     connect(navigator, &KUrlNavigator::tabRequested,
             this, &DolphinMainWindow::openNewTab);
+    connect(navigator, &KUrlNavigator::activeTabRequested,
+            this, &DolphinMainWindow::openNewTabAndActivate);
+    connect(navigator, &KUrlNavigator::newWindowRequested,
+            this, &DolphinMainWindow::openNewWindow);
 
 }
 
index 46515cc8bee4000411f58e7b9fb70fbf5b286eb8..761766df8562080400d5a185fb7f18ddae6044a5 100644 (file)
@@ -171,6 +171,16 @@ public Q_SLOTS:
      */
     void openNewTab(const QUrl& url);
 
+    /**
+     * Opens a new tab  showing the URL \a url and activate it.
+     */
+    void openNewTabAndActivate(const QUrl &url);
+
+    /**
+     * Opens a new window showing the URL \a url.
+     */
+    void openNewWindow(const QUrl &url);
+
     /** @see GeneralSettings::splitViewChanged() */
     void slotSplitViewChanged();
 
index a647b6f43f9d1286fc319d94c05cd55b4c8c3c4e..48e73ca898a49a8ed20bfde778c3c96ae2ec78d3 100644 (file)
@@ -32,6 +32,7 @@
 #include <KUrlComboBox>
 
 #include <QDropEvent>
+#include <QGuiApplication>
 #include <QLoggingCategory>
 #include <QMimeData>
 #include <QTimer>
@@ -642,7 +643,7 @@ void DolphinViewContainer::slotUrlIsFileError(const QUrl& url)
     }
 }
 
-void DolphinViewContainer::slotItemActivated(const KFileItemitem)
+void DolphinViewContainer::slotItemActivated(const KFileItem &item)
 {
     // It is possible to activate items on inactive views by
     // drag & drop operations. Assure that activating an item always
@@ -651,7 +652,17 @@ void DolphinViewContainer::slotItemActivated(const KFileItem& item)
 
     const QUrl& url = DolphinView::openItemAsFolderUrl(item, GeneralSettings::browseThroughArchives());
     if (!url.isEmpty()) {
-        setUrl(url);
+        const auto modifiers = QGuiApplication::keyboardModifiers();
+        // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+        if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) {
+            Q_EMIT activeTabRequested(url);
+        } else if (modifiers & Qt::ControlModifier) {
+            Q_EMIT tabRequested(url);
+        } else if (modifiers & Qt::ShiftModifier) {
+            Dolphin::openNewWindow({KFilePlacesModel::convertedUrl(url)}, this);
+        } else {
+            setUrl(url);
+        }
         return;
     }
 
index 5d23219529017f585a7afc85f3123784d1c1ba1b..f78f85e55c5c75746a39565d42f2d6468f7a98a0 100644 (file)
@@ -229,6 +229,16 @@ Q_SIGNALS:
      */
     void captionChanged();
 
+    /**
+     * Is emitted if a new tab should be opened in the background for the URL \a url.
+     */
+    void tabRequested(const QUrl &url);
+
+    /**
+     * Is emitted if a new tab should be opened for the URL \a url and set as active.
+     */
+    void activeTabRequested(const QUrl &url);
+
 private Q_SLOTS:
     /**
      * Updates the number of items (= number of files + number of
@@ -281,7 +291,7 @@ private Q_SLOTS:
      * directory is opened in the view. If the item is a file, the file
      * gets started by the corresponding application.
      */
-    void slotItemActivated(const KFileItemitem);
+    void slotItemActivated(const KFileItem &item);
 
     /**
      * Handles activation of multiple files. The files get started by
index 8687872ee81b6f75d22fd6577e8bfc8f8c7f3587..d0bcd6cebc9b82a733db1d2474cd09cbd5a2e6db 100644 (file)
@@ -1583,14 +1583,10 @@ bool KItemListController::onRelease(const QPointF& pos, const Qt::KeyboardModifi
 
                 Q_EMIT itemExpansionToggleClicked(index);
                 emitItemActivated = false;
-            } else if (shiftOrControlPressed) {
-                // The mouse click should only update the selection, not trigger the item
+            } else if (shiftOrControlPressed && m_selectionBehavior != SingleSelection) {
+                // The mouse click should only update the selection, not trigger the item, except when
+                // we are in single selection mode
                 emitItemActivated = false;
-                // When Ctrl-clicking an item when in single selection mode
-                // i.e. where Ctrl won't change the selection, pretend it was middle clicked
-                if (controlPressed && m_selectionBehavior == SingleSelection) {
-                    Q_EMIT itemMiddleClicked(index);
-                }
             } else if (!(m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) || m_singleClickActivationEnforced)) {
                 if (touch) {
                 emitItemActivated = true;
index 24339134e717ebf696ca6d4ffd23639b0a6015fc..f4092576adf56f54aad08f62ee13d9a652da7207 100644 (file)
@@ -137,7 +137,7 @@ Q_SIGNALS:
      * Is emitted if more than one item has been activated by pressing Return/Enter
      * when having a selection.
      */
-    void itemsActivated(const KItemSetindexes);
+    void itemsActivated(const KItemSet &indexes);
 
     void itemMiddleClicked(int index);
 
index 19a05d2b69542fa58f49f1424f128a883f10cd05..d3d8b81f14d6ed34c8cb1e0fcd457b5cc0bbc10d 100644 (file)
@@ -189,7 +189,19 @@ void FoldersPanel::slotItemActivated(int index)
 {
     const KFileItem item = m_model->fileItem(index);
     if (!item.isNull()) {
-        Q_EMIT folderActivated(item.url());
+        const auto modifiers = QGuiApplication::keyboardModifiers();
+        // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+        if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) {
+            Q_EMIT folderInNewActiveTab(item.url());
+        } else if (modifiers & Qt::ControlModifier) {
+            Q_EMIT folderInNewTab(item.url());
+        } else if (modifiers & Qt::ShiftModifier) {
+            // The shift modifier is not considered because it is used to expand the tree view without actually
+            // opening the folder
+            return;
+        } else {
+            Q_EMIT folderActivated(item.url());
+        }
     }
 }
 
@@ -197,7 +209,13 @@ void FoldersPanel::slotItemMiddleClicked(int index)
 {
     const KFileItem item = m_model->fileItem(index);
     if (!item.isNull()) {
-        Q_EMIT folderMiddleClicked(item.url());
+        const auto modifiers = QGuiApplication::keyboardModifiers();
+        // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+        if (modifiers & Qt::ShiftModifier) {
+            Q_EMIT folderInNewActiveTab(item.url());
+        } else {
+            Q_EMIT folderInNewTab(item.url());
+        }
     }
 }
 
index 26c8e4cb9590d5bd60d42f9772bde0705ebb5646..3ce7870ffe1562aa8a1cee03b85c3266b066e1fa 100644 (file)
@@ -42,7 +42,8 @@ public:
 
 Q_SIGNALS:
     void folderActivated(const QUrl& url);
-    void folderMiddleClicked(const QUrl& url);
+    void folderInNewTab(const QUrl &url);
+    void folderInNewActiveTab(const QUrl &url);
     void errorMessage(const QString& error);
 
 protected:
index 83e014a82e87846eb65262214e5a3022caf1d825..b9fc4a897ab647899fc9070cef8efe03e1a36060 100644 (file)
@@ -36,6 +36,7 @@
 #include <KPropertiesDialog>
 
 #include <QActionGroup>
+#include <QApplication>
 #include <QGraphicsSceneDragDropEvent>
 #include <QIcon>
 #include <QMenu>
 #include <QToolTip>
 
 PlacesPanel::PlacesPanel(QWidget* parent) :
-    Panel(parent),
-    m_controller(nullptr),
-    m_model(nullptr),
-    m_view(nullptr),
-    m_storageSetupFailedUrl(),
-    m_triggerStorageSetupButton(),
-    m_itemDropEventIndex(-1),
-    m_itemDropEventMimeData(nullptr),
-    m_itemDropEvent(nullptr),
-    m_tooltipTimer()
+        Panel(parent),
+        m_controller(nullptr),
+        m_model(nullptr),
+        m_view(nullptr),
+        m_storageSetupFailedUrl(),
+        m_triggerStorageSetupModifier(),
+        m_itemDropEventIndex(-1),
+        m_itemDropEventMimeData(nullptr),
+        m_itemDropEvent(nullptr),
+        m_tooltipTimer()
 {
     m_tooltipTimer.setInterval(500);
     m_tooltipTimer.setSingleShot(true);
@@ -163,12 +164,28 @@ bool PlacesPanel::eventFilter(QObject * /* obj */, QEvent *event)
 
 void PlacesPanel::slotItemActivated(int index)
 {
-    triggerItem(index, Qt::LeftButton);
+    const auto modifiers = QGuiApplication::keyboardModifiers();
+    // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+    if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) {
+        triggerItem(index, TriggerItemModifier::ToNewActiveTab);
+    } else if (modifiers & Qt::ControlModifier) {
+        triggerItem(index, TriggerItemModifier::ToNewTab);
+    } else if (modifiers & Qt::ShiftModifier) {
+        triggerItem(index, TriggerItemModifier::ToNewWindow);
+    } else {
+        triggerItem(index, TriggerItemModifier::None);
+    }
 }
 
 void PlacesPanel::slotItemMiddleClicked(int index)
 {
-    triggerItem(index, Qt::MiddleButton);
+    const auto modifiers = QGuiApplication::keyboardModifiers();
+    // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+    if (modifiers & Qt::ShiftModifier) {
+        triggerItem(index, TriggerItemModifier::ToNewActiveTab);
+    } else {
+        triggerItem(index, TriggerItemModifier::ToNewTab);
+    }
 }
 
 void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos)
@@ -287,9 +304,7 @@ void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos)
             } else if (action == openInNewWindowAction) {
                 Dolphin::openNewWindow({KFilePlacesModel::convertedUrl(m_model->data(index).value("url").toUrl())}, this);
             } else if (action == openInNewTabAction) {
-                // TriggerItem does set up the storage first and then it will
-                // emit the slotItemMiddleClicked signal, because of Qt::MiddleButton.
-                triggerItem(index, Qt::MiddleButton);
+                triggerItem(index, TriggerItemModifier::ToNewTab);
             } else if (action == mountAction) {
                 m_model->requestStorageSetup(index);
             } else if (action == teardownAction) {
@@ -480,14 +495,14 @@ void PlacesPanel::slotStorageSetupDone(int index, bool success)
     disconnect(m_model, &PlacesItemModel::storageSetupDone,
                this, &PlacesPanel::slotStorageSetupDone);
 
-    if (m_triggerStorageSetupButton == Qt::NoButton) {
+    if (m_triggerStorageSetupModifier == TriggerItemModifier::None) {
         return;
     }
 
     if (success) {
         Q_ASSERT(!m_model->storageSetupNeeded(index));
-        triggerItem(index, m_triggerStorageSetupButton);
-        m_triggerStorageSetupButton = Qt::NoButton;
+        triggerItem(index, m_triggerStorageSetupModifier);
+        m_triggerStorageSetupModifier = TriggerItemModifier::None;
     } else {
         setUrl(m_storageSetupFailedUrl);
         m_storageSetupFailedUrl = QUrl();
@@ -553,7 +568,7 @@ void PlacesPanel::selectItem()
     }
 }
 
-void PlacesPanel::triggerItem(int index, Qt::MouseButton button)
+void PlacesPanel::triggerItem(int index, TriggerItemModifier modifier)
 {
     const PlacesItem* item = m_model->placesItem(index);
     if (!item) {
@@ -561,7 +576,7 @@ void PlacesPanel::triggerItem(int index, Qt::MouseButton button)
     }
 
     if (m_model->storageSetupNeeded(index)) {
-        m_triggerStorageSetupButton = button;
+        m_triggerStorageSetupModifier = modifier;
         m_storageSetupFailedUrl = url();
 
         connect(m_model, &PlacesItemModel::storageSetupDone,
@@ -569,14 +584,23 @@ void PlacesPanel::triggerItem(int index, Qt::MouseButton button)
 
         m_model->requestStorageSetup(index);
     } else {
-        m_triggerStorageSetupButton = Qt::NoButton;
+        m_triggerStorageSetupModifier = TriggerItemModifier::None;
 
         const QUrl url = m_model->data(index).value("url").toUrl();
         if (!url.isEmpty()) {
-            if (button == Qt::MiddleButton) {
-                Q_EMIT placeMiddleClicked(KFilePlacesModel::convertedUrl(url));
-            } else {
-                Q_EMIT placeActivated(KFilePlacesModel::convertedUrl(url));
+            switch (modifier) {
+                case TriggerItemModifier::ToNewTab:
+                    Q_EMIT placeActivatedInNewTab(KFilePlacesModel::convertedUrl(url));
+                    break;
+                case TriggerItemModifier::ToNewActiveTab:
+                    Q_EMIT placeActivatedInNewActiveTab(KFilePlacesModel::convertedUrl(url));
+                    break;
+                case TriggerItemModifier::ToNewWindow:
+                    Dolphin::openNewWindow({KFilePlacesModel::convertedUrl(url)}, this);
+                    break;
+                case TriggerItemModifier::None:
+                    Q_EMIT placeActivated(KFilePlacesModel::convertedUrl(url));
+                    break;
             }
         }
     }
index 39f8da36562c7732d5d9c104bbc8f143e16e7db3..ce28c8c0807cc808cc06943f9e8581ff37cbd03e 100644 (file)
@@ -35,7 +35,8 @@ public:
 
 Q_SIGNALS:
     void placeActivated(const QUrl& url);
-    void placeMiddleClicked(const QUrl& url);
+    void placeActivatedInNewTab(const QUrl &url);
+    void placeActivatedInNewActiveTab(const QUrl &url);
     void errorMessage(const QString& error);
     void storageTearDownRequested(const QString& mountPath);
     void storageTearDownExternallyRequested(const QString& mountPath);
@@ -63,6 +64,9 @@ private Q_SLOTS:
     void slotStorageSetupDone(int index, bool success);
     void slotShowTooltip();
 
+private:
+    enum class TriggerItemModifier { None, ToNewTab, ToNewActiveTab, ToNewWindow };
+
 private:
     void addEntry();
     void editEntry(int index);
@@ -73,7 +77,7 @@ private:
      */
     void selectItem();
 
-    void triggerItem(int index, Qt::MouseButton button);
+    void triggerItem(int index, TriggerItemModifier modifier);
 
     QAction* buildGroupContextMenu(QMenu* menu, int index);
 
@@ -83,7 +87,7 @@ private:
     PlacesView* m_view;
 
     QUrl m_storageSetupFailedUrl;
-    Qt::MouseButton m_triggerStorageSetupButton;
+    TriggerItemModifier m_triggerStorageSetupModifier;
 
     int m_itemDropEventIndex;
     QMimeData* m_itemDropEventMimeData;
index 9a063d857f79dc07261af1d5012fb15c1db6dda4..bb537b982af6b3a35d575a2c9f2d64e2b5285600 100644 (file)
@@ -974,12 +974,14 @@ void DolphinView::slotItemActivated(int index)
     }
 }
 
-void DolphinView::slotItemsActivated(const KItemSetindexes)
+void DolphinView::slotItemsActivated(const KItemSet &indexes)
 {
     Q_ASSERT(indexes.count() >= 2);
 
     abortTwoClicksRenaming();
 
+    const auto modifiers = QGuiApplication::keyboardModifiers();
+
     if (indexes.count() > 5) {
         QString question = i18np("Are you sure you want to open 1 item?", "Are you sure you want to open %1 items?", indexes.count());
         const int answer = KMessageBox::warningYesNo(this, question);
@@ -995,8 +997,15 @@ void DolphinView::slotItemsActivated(const KItemSet& indexes)
         KFileItem item = m_model->fileItem(index);
         const QUrl& url = openItemAsFolderUrl(item);
 
-        if (!url.isEmpty()) { // Open folders in new tabs
-            Q_EMIT tabRequested(url);
+        if (!url.isEmpty()) {
+            // Open folders in new tabs or in new windows depending on the modifier
+            // The ctrl+shift behavior is ignored because we are handling multiple items
+            // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+            if (modifiers & Qt::ShiftModifier && !(modifiers & Qt::ControlModifier)) {
+                Q_EMIT windowRequested(url);
+            } else {
+                Q_EMIT tabRequested(url);
+            }
         } else {
             items.append(item);
         }
@@ -1013,10 +1022,21 @@ void DolphinView::slotItemMiddleClicked(int index)
 {
     const KFileItem& item = m_model->fileItem(index);
     const QUrl& url = openItemAsFolderUrl(item);
+    const auto modifiers = QGuiApplication::keyboardModifiers();
     if (!url.isEmpty()) {
-        Q_EMIT tabRequested(url);
+        // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+        if (modifiers & Qt::ShiftModifier) {
+            Q_EMIT activeTabRequested(url);
+        } else {
+            Q_EMIT tabRequested(url);
+        }
     } else if (isTabsForFilesEnabled()) {
-        Q_EMIT tabRequested(item.url());
+        // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+        if (modifiers & Qt::ShiftModifier) {
+            Q_EMIT activeTabRequested(item.url());
+        } else {
+            Q_EMIT tabRequested(item.url());
+        }
     }
 }
 
index 11926d5582d7f1384d875723e3417065ce6d1b9d..0f288f94218b323156edfda03ad84b4b5737910e 100644 (file)
@@ -425,13 +425,13 @@ Q_SIGNALS:
     /**
      * Is emitted when clicking on an item with the left mouse button.
      */
-    void itemActivated(const KFileItemitem);
+    void itemActivated(const KFileItem &item);
 
     /**
      * Is emitted when multiple items have been activated by e. g.
      * context menu open with.
      */
-    void itemsActivated(const KFileItemListitems);
+    void itemsActivated(const KFileItemList &items);
 
     /**
      * Is emitted if items have been added or deleted.
@@ -443,6 +443,16 @@ Q_SIGNALS:
      */
     void tabRequested(const QUrl& url);
 
+    /**
+     * Is emitted if a new tab should be opened for the URL \a url and set as active.
+     */
+    void activeTabRequested(const QUrl &url);
+
+    /**
+     * Is emitted if a new window should be opened for the URL \a url.
+     */
+    void windowRequested(const QUrl &url);
+
     /**
      * Is emitted if the view mode (IconsView, DetailsView,
      * PreviewsView) has been changed.
@@ -619,7 +629,7 @@ private Q_SLOTS:
     void activate();
 
     void slotItemActivated(int index);
-    void slotItemsActivated(const KItemSetindexes);
+    void slotItemsActivated(const KItemSet &indexes);
     void slotItemMiddleClicked(int index);
     void slotItemContextMenuRequested(int index, const QPointF& pos);
     void slotViewContextMenuRequested(const QPointF& pos);