┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelix Ernst <[email protected]>2026-06-16 22:08:24 +0200
committerFelix Ernst <[email protected]>2026-06-16 22:08:24 +0200
commit12b4a8a91e0b9b8dd00816b5fb84e8e09000afcd (patch)
treece2d2a94849f33dacbbb0fe484387b107aab59b0 /src
parent64d3f0756f096bb3632248b1535cb58767b2d1b0 (diff)
Add "Focus Other View" action
Replace the setting "Switch between views with Tab key" with a dedicated "Focus Other View" action (which can be bound to the Tab key if the user wants to). The "Focus Other View" action moves the keyboard focus to the inactive split view. When there is no other view, split view is triggered instead. The action is located in `Menubar>View`. ### Motivation The Tab key is essential for keyboard navigation within an application. The old "Switch between views with Tab key" setting forces users to give up on the intended purpose of the Tab key, which means many keyboard-bound users currently do not have a way to switch between views when using the "Split" feature. The dedicated "Focus Other View" action gives users more control, and they can change the keyboard shortcut as they are used to.
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/dolphinmainwindow.cpp7
-rw-r--r--src/dolphintabwidget.cpp10
-rw-r--r--src/dolphintabwidget.h3
-rw-r--r--src/dolphinui.rc1
-rw-r--r--src/dolphinuiforphones.rc1
-rw-r--r--src/settings/dolphin_generalsettings.kcfg4
-rw-r--r--src/settings/dolphin_tab_key_shortcut_for_focus_other_view.py27
-rw-r--r--src/settings/dolphin_tab_key_shortcut_for_focus_other_view.upd8
-rw-r--r--src/settings/interface/folderstabssettingspage.cpp11
-rw-r--r--src/settings/interface/folderstabssettingspage.h1
-rw-r--r--src/tests/dolphinmainwindowtest.cpp39
-rw-r--r--src/views/dolphinview.cpp7
13 files changed, 98 insertions, 23 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1a195747a..319c5512b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -642,6 +642,8 @@ install( FILES settings/dolphin_detailsmodesettings.upd
settings/dolphin_statusandlocationbarssettings.upd
settings/dolphin_replace_view_mode_with_view_settings_in_toolbar.upd
settings/dolphin_replace_view_mode_with_view_settings_in_toolbar.py
+ settings/dolphin_tab_key_shortcut_for_focus_other_view.upd
+ settings/dolphin_tab_key_shortcut_for_focus_other_view.py
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR} )
# install KF6 kconfig updater C++ scripts to kconf_update_bin
diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp
index ed7215b5a..51fec8247 100644
--- a/src/dolphinmainwindow.cpp
+++ b/src/dolphinmainwindow.cpp
@@ -1897,6 +1897,13 @@ void DolphinMainWindow::setupActions()
actionCollection()->setDefaultShortcut(moveToOtherViewAction, Qt::SHIFT | Qt::Key_F6);
connect(moveToOtherViewAction, &QAction::triggered, this, &DolphinMainWindow::moveToInactiveSplitView);
+ QAction *focusOtherViewAction = actionCollection()->addAction(QStringLiteral("focus_inactive_split_view"));
+ focusOtherViewAction->setText(i18nc("@action:inmenu", "Focus Other View"));
+ focusOtherViewAction->setToolTip(i18nc("@info:tooltip", "Move keyboard focus to the inactive view."));
+ focusOtherViewAction->setIcon(QIcon::fromTheme(QStringLiteral("swap-panels")));
+ actionCollection()->setDefaultShortcut(focusOtherViewAction, Qt::CTRL | Qt::Key_F3);
+ connect(focusOtherViewAction, &QAction::triggered, m_tabWidget, &DolphinTabWidget::focusInactiveSplitView);
+
QAction *showFilterBar = actionCollection()->addAction(QStringLiteral("show_filter_bar"));
showFilterBar->setText(i18nc("@action:inmenu Tools", "Filter…"));
showFilterBar->setToolTip(i18nc("@info:tooltip", "Show Filter Bar"));
diff --git a/src/dolphintabwidget.cpp b/src/dolphintabwidget.cpp
index bbf80e4bf..7fbf10b19 100644
--- a/src/dolphintabwidget.cpp
+++ b/src/dolphintabwidget.cpp
@@ -383,6 +383,16 @@ void DolphinTabWidget::moveToInactiveSplitView()
inactiveView->moveSelectedItems(selectedItems, inactiveView->url());
}
+void DolphinTabWidget::focusInactiveSplitView()
+{
+ DolphinTabPage *const tabPage = currentTabPage();
+ if (!tabPage->splitViewEnabled()) {
+ tabPage->setSplitViewEnabled(true, WithAnimation, tabPage->activeViewContainer()->url());
+ } else {
+ activateViewContainerAt(ViewIndex{currentIndex(), !tabPage->primaryViewActive()});
+ }
+}
+
void DolphinTabWidget::detachTab(int index)
{
Q_ASSERT(index >= 0);
diff --git a/src/dolphintabwidget.h b/src/dolphintabwidget.h
index ca101e2db..5d3e84c0a 100644
--- a/src/dolphintabwidget.h
+++ b/src/dolphintabwidget.h
@@ -196,6 +196,9 @@ public Q_SLOTS:
/** Moves all selected items to the inactive view. */
void moveToInactiveSplitView();
+ /** Moves keyboard focus to the inactive view, making it the active view. */
+ void focusInactiveSplitView();
+
private Q_SLOTS:
/**
* Opens the tab with the index \a index in a new Dolphin instance and closes
diff --git a/src/dolphinui.rc b/src/dolphinui.rc
index c82e104f3..395436d74 100644
--- a/src/dolphinui.rc
+++ b/src/dolphinui.rc
@@ -53,6 +53,7 @@
<Separator/>
<Action name="split_view_menu" />
<Action name="popout_split_view" />
+ <Action name="focus_inactive_split_view" />
<Action name="split_stash" />
<Action name="redisplay" />
<Action name="stop" />
diff --git a/src/dolphinuiforphones.rc b/src/dolphinuiforphones.rc
index eba2b970a..3a9e89c29 100644
--- a/src/dolphinuiforphones.rc
+++ b/src/dolphinuiforphones.rc
@@ -53,6 +53,7 @@
<Separator/>
<Action name="split_view_menu" />
<Action name="popout_split_view" />
+ <Action name="focus_inactive_split_view" />
<Action name="split_stash" />
<Action name="redisplay" />
<Action name="stop" />
diff --git a/src/settings/dolphin_generalsettings.kcfg b/src/settings/dolphin_generalsettings.kcfg
index 48fecb2d0..b29526d64 100644
--- a/src/settings/dolphin_generalsettings.kcfg
+++ b/src/settings/dolphin_generalsettings.kcfg
@@ -115,10 +115,6 @@
<label>Show a bar for easy pasting after a cut or copy was done using the selection mode bottom bar.</label>
<default>true</default>
</entry>
- <entry name="UseTabForSwitchingSplitView" type="Bool">
- <label>Use tab for switching between right and left view</label>
- <default>false</default>
- </entry>
<entry name="CloseSplitViewChoice" type="Enum">
<choices>
<choice name="ActiveView" />
diff --git a/src/settings/dolphin_tab_key_shortcut_for_focus_other_view.py b/src/settings/dolphin_tab_key_shortcut_for_focus_other_view.py
new file mode 100644
index 000000000..4a18ad094
--- /dev/null
+++ b/src/settings/dolphin_tab_key_shortcut_for_focus_other_view.py
@@ -0,0 +1,27 @@
+#SPDX-FileCopyrightText: 2026 Felix Ernst <[email protected]>
+#SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+
+import os
+import sys
+from pathlib import Path
+import xml.etree.ElementTree as ET
+
+use_tab_setting_detected = False
+
+XDG_CONFIG_HOME = Path(os.getenv("XDG_CONFIG_HOME") or (Path.home() / ".config"))
+custom_settings_file = XDG_CONFIG_HOME / "dolphinrc"
+print(custom_settings_file)
+if custom_settings_file.exists():
+ with open(custom_settings_file, "r+") as f:
+ lines = [line for line in f if line.find("UseTabForSwitchingSplitView=true") >= 0]
+ if len(lines) > 0:
+ use_tab_setting_detected = True
+
+XDG_DATA_HOME = Path(os.getenv("XDG_DATA_HOME") or (Path.home() / ".local/share"))
+custom_ui_file = XDG_DATA_HOME / "kxmlgui5/dolphin/dolphinui.rc"
+if use_tab_setting_detected and custom_ui_file.exists():
+ tree = ET.parse(custom_ui_file)
+ root = tree.getroot()
+ for actionProperties in root.iter("ActionProperties"):
+ ET.SubElement(actionProperties, "Action", {"name":"focus_inactive_split_view", "shortcut":"Ctrl+F3; Tab"})
+ tree.write(custom_ui_file, encoding="utf-8")
diff --git a/src/settings/dolphin_tab_key_shortcut_for_focus_other_view.upd b/src/settings/dolphin_tab_key_shortcut_for_focus_other_view.upd
new file mode 100644
index 000000000..579eb233a
--- /dev/null
+++ b/src/settings/dolphin_tab_key_shortcut_for_focus_other_view.upd
@@ -0,0 +1,8 @@
+#SPDX-FileCopyrightText: 2026 Felix Ernst <[email protected]>
+#SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+
+#Configuration update for Dolphin
+Version=6
+
+Id=tab_key_shortcut_for_focus_other_view
+Script=dolphin_tab_key_shortcut_for_focus_other_view.py,python3
diff --git a/src/settings/interface/folderstabssettingspage.cpp b/src/settings/interface/folderstabssettingspage.cpp
index 10303258c..fa1b1b80f 100644
--- a/src/settings/interface/folderstabssettingspage.cpp
+++ b/src/settings/interface/folderstabssettingspage.cpp
@@ -44,7 +44,6 @@ FoldersTabsSettingsPage::FoldersTabsSettingsPage(QWidget *parent)
, m_filterBar(nullptr)
, m_showFullPathInTitlebar(nullptr)
, m_openExternallyCalledFolderInNewTab(nullptr)
- , m_useTabForSplitViewSwitch(nullptr)
, m_closeSplitComboBox(nullptr)
{
QFormLayout *topLayout = new QFormLayout(this);
@@ -160,10 +159,6 @@ FoldersTabsSettingsPage::FoldersTabsSettingsPage(QWidget *parent)
closeSplitViewHLayout->addWidget(m_closeSplitComboBox);
topLayout->addRow(i18nc("@title:group", "Split view: "), closeSplitViewWidget);
- // 'Switch between panes of split views with tab key'
- m_useTabForSplitViewSwitch = new QCheckBox(i18nc("option:check split view panes", "Switch between views with Tab key"));
- topLayout->addRow(QString(), m_useTabForSplitViewSwitch);
-
// 'Begin in split view mode'
m_splitView = new QCheckBox(i18nc("@option:check Startup Settings", "Open new windows in split view mode"));
topLayout->addRow(QString(), m_splitView);
@@ -182,8 +177,6 @@ FoldersTabsSettingsPage::FoldersTabsSettingsPage(QWidget *parent)
connect(m_openExternallyCalledFolderInNewTab, &QCheckBox::toggled, this, &FoldersTabsSettingsPage::slotSettingsChanged);
connect(m_showFullPathInTitlebar, &QCheckBox::toggled, this, &FoldersTabsSettingsPage::slotSettingsChanged);
- connect(m_useTabForSplitViewSwitch, &QCheckBox::toggled, this, &FoldersTabsSettingsPage::changed);
-
connect(m_closeSplitComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &FoldersTabsSettingsPage::changed);
connect(m_alwaysShowTabBar, &QCheckBox::toggled, this, &FoldersTabsSettingsPage::changed);
@@ -203,8 +196,6 @@ void FoldersTabsSettingsPage::applySettings()
{
GeneralSettings *settings = GeneralSettings::self();
- settings->setUseTabForSwitchingSplitView(m_useTabForSplitViewSwitch->isChecked());
-
settings->setCloseSplitViewChoice(m_closeSplitComboBox->currentIndex());
const QUrl url(QUrl::fromUserInput(m_homeUrl->text(), QString(), QUrl::AssumeLocalFile));
@@ -322,8 +313,6 @@ void FoldersTabsSettingsPage::loadSettings()
m_showFullPathInTitlebar->setChecked(GeneralSettings::showFullPathInTitlebar());
m_openExternallyCalledFolderInNewTab->setChecked(GeneralSettings::openExternallyCalledFolderInNewTab());
- m_useTabForSplitViewSwitch->setChecked(GeneralSettings::useTabForSwitchingSplitView());
-
m_closeSplitComboBox->setCurrentIndex(GeneralSettings::closeSplitViewChoice());
m_alwaysShowTabBar->setChecked(GeneralSettings::alwaysShowTabBar());
diff --git a/src/settings/interface/folderstabssettingspage.h b/src/settings/interface/folderstabssettingspage.h
index 690407b39..cf926e557 100644
--- a/src/settings/interface/folderstabssettingspage.h
+++ b/src/settings/interface/folderstabssettingspage.h
@@ -70,7 +70,6 @@ private:
QCheckBox *m_filterBar;
QCheckBox *m_showFullPathInTitlebar;
QCheckBox *m_openExternallyCalledFolderInNewTab;
- QCheckBox *m_useTabForSplitViewSwitch;
QComboBox *m_closeSplitComboBox;
};
diff --git a/src/tests/dolphinmainwindowtest.cpp b/src/tests/dolphinmainwindowtest.cpp
index 534ac4654..a629268c1 100644
--- a/src/tests/dolphinmainwindowtest.cpp
+++ b/src/tests/dolphinmainwindowtest.cpp
@@ -65,6 +65,7 @@ private Q_SLOTS:
void testWindowTitle();
void testFocusLocationBar();
void testFocusPlacesPanel();
+ void testFocusOtherView();
void testPlacesPanelWidthResistance();
void testGoActions();
void testOpenFiles();
@@ -576,6 +577,44 @@ void DolphinMainWindowTest::testFocusPlacesPanel()
"Activating a place should move focus to the view even if the view already has that place loaded.");
}
+void DolphinMainWindowTest::testFocusOtherView()
+{
+ m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false);
+ m_mainWindow->show();
+ QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data()));
+ QVERIFY(m_mainWindow->isVisible());
+ QTRY_VERIFY_WITH_TIMEOUT(QApplication::activeWindow() != nullptr, 100);
+
+ QAction *const focusOtherViewAction = m_mainWindow->actionCollection()->action(QStringLiteral("focus_inactive_split_view"));
+
+ /** Triggering the "Focus Other View" action when there is no other view should create such a view and focus it. */
+ QVERIFY(!m_mainWindow->m_tabWidget->currentTabPage()->splitViewEnabled());
+ const DolphinViewContainer *const previouslyActiveView = m_mainWindow->activeViewContainer();
+ QVERIFY(previouslyActiveView->isAncestorOf(QApplication::focusWidget()));
+ focusOtherViewAction->trigger();
+ QVERIFY(m_mainWindow->m_tabWidget->currentTabPage()->splitViewEnabled());
+ QVERIFY(!previouslyActiveView->isAncestorOf(QApplication::focusWidget()));
+
+ const DolphinViewContainer *const otherView = m_mainWindow->activeViewContainer();
+ QVERIFY(previouslyActiveView != otherView);
+ QVERIFY(otherView->isAncestorOf(QApplication::focusWidget()));
+
+ /** "Focus Other View" and "Split" have the same behaviour when there is only one view. Make sure their default keyboard shortcuts stay similar. */
+ QVERIFY(focusOtherViewAction->shortcut().toString().contains(m_mainWindow->actionCollection()->action(QStringLiteral("split_view"))->shortcut().toString())
+ || focusOtherViewAction->shortcut().toString().contains(
+ m_mainWindow->actionCollection()->action(QStringLiteral("split_view_menu"))->shortcut().toString()));
+
+ /** Test the typical usage of "Focus Other View" */
+ QVERIFY(previouslyActiveView != otherView);
+ QVERIFY(otherView->isAncestorOf(QApplication::focusWidget()));
+ focusOtherViewAction->trigger();
+ QVERIFY(previouslyActiveView->isAncestorOf(QApplication::focusWidget()));
+ focusOtherViewAction->trigger();
+ QVERIFY(otherView->isAncestorOf(QApplication::focusWidget()));
+ focusOtherViewAction->trigger();
+ QVERIFY(previouslyActiveView->isAncestorOf(QApplication::focusWidget()));
+}
+
/**
* The places panel will resize itself if any of the other widgets requires too much horizontal space
* but a user never wants the size of the places panel to change unless they resized it themselves explicitly.
diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp
index 50c14ff77..78b8b9949 100644
--- a/src/views/dolphinview.cpp
+++ b/src/views/dolphinview.cpp
@@ -1093,13 +1093,6 @@ bool DolphinView::eventFilter(QObject *watched, QEvent *event)
case QEvent::KeyPress:
hideToolTip(ToolTipManager::HideBehavior::Instantly);
- if (GeneralSettings::useTabForSwitchingSplitView()) {
- QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
- if (keyEvent->key() == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier) {
- Q_EMIT toggleActiveViewRequested();
- return true;
- }
- }
break;
case QEvent::KeyRelease:
if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Control) {