]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/dolphinmainwindow.cpp
Share actions with main window to avoid duplicating icon name and text
[dolphin.git] / src / dolphinmainwindow.cpp
index 92d673a956b067c7aa881d468bfb0279d9a2c7e4..734a6ac84779300a0a0bb3a3482f75e55af2ab80 100644 (file)
 #include "dolphinbookmarkhandler.h"
 #include "dolphindockwidget.h"
 #include "dolphincontextmenu.h"
+#include "dolphinnavigatorswidgetaction.h"
 #include "dolphinnewfilemenu.h"
 #include "dolphinrecenttabsmenu.h"
+#include "dolphinurlnavigatorscontroller.h"
 #include "dolphinviewcontainer.h"
 #include "dolphintabpage.h"
 #include "middleclickactioneventfilter.h"
@@ -70,7 +72,6 @@
 #include <QDialog>
 #include <QFileInfo>
 #include <QLineEdit>
-#include <QMenu>
 #include <QMenuBar>
 #include <QPushButton>
 #include <QShowEvent>
@@ -133,15 +134,16 @@ DolphinMainWindow::DolphinMainWindow() :
     connect(undoManager, &KIO::FileUndoManager::jobRecordingFinished,
             this, &DolphinMainWindow::showCommand);
 
-    GeneralSettings* generalSettings = GeneralSettings::self();
-    const bool firstRun = (generalSettings->version() < 200);
+    const bool firstRun = (GeneralSettings::version() < 200);
     if (firstRun) {
-        generalSettings->setViewPropsTimestamp(QDateTime::currentDateTime());
+        GeneralSettings::setViewPropsTimestamp(QDateTime::currentDateTime());
     }
 
     setAcceptDrops(true);
 
-    m_tabWidget = new DolphinTabWidget(this);
+    auto *navigatorsWidgetAction = new DolphinNavigatorsWidgetAction(this);
+    actionCollection()->addAction(QStringLiteral("url_navigators"), navigatorsWidgetAction);
+    m_tabWidget = new DolphinTabWidget(navigatorsWidgetAction, this);
     m_tabWidget->setObjectName("tabWidget");
     connect(m_tabWidget, &DolphinTabWidget::activeViewChanged,
             this, &DolphinMainWindow::activeViewChanged);
@@ -170,8 +172,8 @@ DolphinMainWindow::DolphinMainWindow() :
     connect(clipboard, &QClipboard::dataChanged,
             this, &DolphinMainWindow::updatePasteAction);
 
-    QAction* showFilterBarAction = actionCollection()->action(QStringLiteral("show_filter_bar"));
-    showFilterBarAction->setChecked(generalSettings->filterBar());
+    QAction* toggleFilterBarAction = actionCollection()->action(QStringLiteral("toggle_filter"));
+    toggleFilterBarAction->setChecked(GeneralSettings::filterBar());
 
     if (firstRun) {
         menuBar()->setVisible(false);
@@ -186,6 +188,8 @@ DolphinMainWindow::DolphinMainWindow() :
         createControlButton();
     }
 
+    updateAllowedToolbarAreas();
+
     // enable middle-click on back/forward/up to open in a new tab
     auto *middleClickEventFilter = new MiddleClickActionEventFilter(this);
     connect(middleClickEventFilter, &MiddleClickActionEventFilter::actionMiddleClicked, this, &DolphinMainWindow::slotToolBarActionMiddleClicked);
@@ -205,13 +209,32 @@ DolphinMainWindow::~DolphinMainWindow()
 QVector<DolphinViewContainer*> DolphinMainWindow::viewContainers() const
 {
     QVector<DolphinViewContainer*> viewContainers;
-    viewContainers.reserve(m_tabWidget->count());
+
     for (int i = 0; i < m_tabWidget->count(); ++i) {
-        viewContainers << m_tabWidget->tabPageAt(i)->activeViewContainer();
+        DolphinTabPage *tabPage = m_tabWidget->tabPageAt(i);
+
+        viewContainers << tabPage->primaryViewContainer();
+        if (tabPage->splitViewEnabled()) {
+            viewContainers << tabPage->secondaryViewContainer();
+        }
     }
     return viewContainers;
 }
 
+void DolphinMainWindow::setViewsWithInvalidPathsToHome()
+{
+    const QVector<DolphinViewContainer*> theViewContainers = viewContainers();
+    for (DolphinViewContainer *viewContainer : theViewContainers) {
+
+        // Only consider local dirs, not remote locations and abstract protocols
+        if (viewContainer->url().isLocalFile()) {
+            if (!QFileInfo::exists(viewContainer->url().toLocalFile())) {
+                viewContainer->setUrl(QUrl::fromLocalFile(QDir::homePath()));
+            }
+        }
+    }
+}
+
 void DolphinMainWindow::openDirectories(const QList<QUrl>& dirs, bool splitView)
 {
     m_tabWidget->openDirectories(dirs, splitView);
@@ -227,6 +250,16 @@ void DolphinMainWindow::openFiles(const QList<QUrl>& files, bool splitView)
     m_tabWidget->openFiles(files, splitView);
 }
 
+bool DolphinMainWindow::isFoldersPanelEnabled() const
+{
+    return actionCollection()->action(QStringLiteral("show_folders_panel"))->isChecked();
+}
+
+bool DolphinMainWindow::isInformationPanelEnabled() const
+{
+    return actionCollection()->action(QStringLiteral("show_information_panel"))->isChecked();
+}
+
 void DolphinMainWindow::openFiles(const QStringList& files, bool splitView)
 {
     openFiles(QUrl::fromStringList(files), splitView);
@@ -288,7 +321,7 @@ void DolphinMainWindow::changeUrl(const QUrl &url)
     updateViewActions();
     updateGoActions();
 
-    emit urlChanged(url);
+    Q_EMIT urlChanged(url);
 }
 
 void DolphinMainWindow::slotTerminalDirectoryChanged(const QUrl& url)
@@ -323,12 +356,12 @@ void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection)
         compareFilesAction->setEnabled(false);
     }
 
-    emit selectionChanged(selection);
+    Q_EMIT selectionChanged(selection);
 }
 
 void DolphinMainWindow::updateHistory()
 {
-    const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    const KUrlNavigator *urlNavigator = m_activeViewContainer->urlNavigatorInternalWithHistory();
     const int index = urlNavigator->historyIndex();
 
     QAction* backAction = actionCollection()->action(KStandardAction::name(KStandardAction::Back));
@@ -349,8 +382,8 @@ void DolphinMainWindow::updateHistory()
 
 void DolphinMainWindow::updateFilterBarAction(bool show)
 {
-    QAction* showFilterBarAction = actionCollection()->action(QStringLiteral("show_filter_bar"));
-    showFilterBarAction->setChecked(show);
+    QAction* toggleFilterBarAction = actionCollection()->action(QStringLiteral("toggle_filter"));
+    toggleFilterBarAction->setChecked(show);
 }
 
 void DolphinMainWindow::openNewMainWindow()
@@ -409,7 +442,7 @@ void DolphinMainWindow::openInNewTab()
     const KFileItemList& list = m_activeViewContainer->view()->selectedItems();
     bool tabCreated = false;
 
-    foreach (const KFileItem& item, list) {
+    for (const KFileItem& item : list) {
         const QUrl& url = DolphinView::openItemAsFolderUrl(item);
         if (!url.isEmpty()) {
             openNewTabAfterCurrentTab(url);
@@ -475,7 +508,10 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event)
         closedByUser = false;
     }
 
-    if (m_tabWidget->count() > 1 && GeneralSettings::confirmClosingMultipleTabs() && closedByUser) {
+    if (m_tabWidget->count() > 1
+        && GeneralSettings::confirmClosingMultipleTabs()
+        && !GeneralSettings::rememberOpenedTabs()
+        && closedByUser) {
         // Ask the user if he really wants to quit and close all tabs.
         // Open a confirmation dialog with 3 buttons:
         // QDialogButtonBox::Yes    -> Quit
@@ -696,7 +732,7 @@ void DolphinMainWindow::slotToolBarActionMiddleClicked(QAction *action)
 
 void DolphinMainWindow::slotAboutToShowBackPopupMenu()
 {
-    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    const KUrlNavigator *urlNavigator = m_activeViewContainer->urlNavigatorInternalWithHistory();
     int entries = 0;
     m_backAction->menu()->clear();
     for (int i = urlNavigator->historyIndex() + 1; i < urlNavigator->historySize() && entries < MaxNumberOfNavigationentries; ++i, ++entries) {
@@ -709,7 +745,7 @@ void DolphinMainWindow::slotAboutToShowBackPopupMenu()
 void DolphinMainWindow::slotGoBack(QAction* action)
 {
     int gotoIndex = action->data().value<int>();
-    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    const KUrlNavigator *urlNavigator = m_activeViewContainer->urlNavigatorInternalWithHistory();
     for (int i = gotoIndex - urlNavigator->historyIndex(); i > 0; --i) {
         goBack();
     }
@@ -718,14 +754,14 @@ void DolphinMainWindow::slotGoBack(QAction* action)
 void DolphinMainWindow::slotBackForwardActionMiddleClicked(QAction* action)
 {
     if (action) {
-        KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
+        const KUrlNavigator *urlNavigator = activeViewContainer()->urlNavigatorInternalWithHistory();
         openNewTabAfterCurrentTab(urlNavigator->locationUrl(action->data().value<int>()));
     }
 }
 
 void DolphinMainWindow::slotAboutToShowForwardPopupMenu()
 {
-    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    const KUrlNavigator *urlNavigator = m_activeViewContainer->urlNavigatorInternalWithHistory();
     int entries = 0;
     m_forwardAction->menu()->clear();
     for (int i = urlNavigator->historyIndex() - 1; i >= 0 && entries < MaxNumberOfNavigationentries; --i, ++entries) {
@@ -738,7 +774,7 @@ void DolphinMainWindow::slotAboutToShowForwardPopupMenu()
 void DolphinMainWindow::slotGoForward(QAction* action)
 {
     int gotoIndex = action->data().value<int>();
-    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    const KUrlNavigator *urlNavigator = m_activeViewContainer->urlNavigatorInternalWithHistory();
     for (int i = urlNavigator->historyIndex() - gotoIndex; i > 0; --i) {
         goForward();
     }
@@ -810,6 +846,15 @@ void DolphinMainWindow::showFilterBar()
     m_activeViewContainer->setFilterBarVisible(true);
 }
 
+void DolphinMainWindow::toggleFilterBar()
+{
+    const bool checked = !m_activeViewContainer->isFilterBarVisible();
+    m_activeViewContainer->setFilterBarVisible(checked);
+
+    QAction* toggleFilterBarAction = actionCollection()->action(QStringLiteral("toggle_filter"));
+    toggleFilterBarAction->setChecked(checked);
+}
+
 void DolphinMainWindow::toggleEditLocation()
 {
     clearStatusBar();
@@ -840,7 +885,8 @@ void DolphinMainWindow::replaceLocation()
 void DolphinMainWindow::togglePanelLockState()
 {
     const bool newLockState = !GeneralSettings::lockPanels();
-    foreach (QObject* child, children()) {
+    const auto childrenObjects = children();
+    for (QObject* child : childrenObjects) {
         DolphinDockWidget* dock = qobject_cast<DolphinDockWidget*>(child);
         if (dock) {
             dock->setLocked(newLockState);
@@ -859,7 +905,7 @@ void DolphinMainWindow::slotTerminalPanelVisibilityChanged()
 
 void DolphinMainWindow::goBack()
 {
-    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    DolphinUrlNavigator *urlNavigator = m_activeViewContainer->urlNavigatorInternalWithHistory();
     urlNavigator->goBack();
 
     if (urlNavigator->locationState().isEmpty()) {
@@ -871,29 +917,29 @@ void DolphinMainWindow::goBack()
 
 void DolphinMainWindow::goForward()
 {
-    m_activeViewContainer->urlNavigator()->goForward();
+    m_activeViewContainer->urlNavigatorInternalWithHistory()->goForward();
 }
 
 void DolphinMainWindow::goUp()
 {
-    m_activeViewContainer->urlNavigator()->goUp();
+    m_activeViewContainer->urlNavigatorInternalWithHistory()->goUp();
 }
 
 void DolphinMainWindow::goHome()
 {
-    m_activeViewContainer->urlNavigator()->goHome();
+    m_activeViewContainer->urlNavigatorInternalWithHistory()->goHome();
 }
 
 void DolphinMainWindow::goBackInNewTab()
 {
-    KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
+    const KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigatorInternalWithHistory();
     const int index = urlNavigator->historyIndex() + 1;
     openNewTabAfterCurrentTab(urlNavigator->locationUrl(index));
 }
 
 void DolphinMainWindow::goForwardInNewTab()
 {
-    KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
+    const KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigatorInternalWithHistory();
     const int index = urlNavigator->historyIndex() - 1;
     openNewTabAfterCurrentTab(urlNavigator->locationUrl(index));
 }
@@ -1023,8 +1069,10 @@ void DolphinMainWindow::editSettings()
         container->view()->writeSettings();
 
         const QUrl url = container->url();
-        DolphinSettingsDialog* settingsDialog = new DolphinSettingsDialog(url, this);
+        DolphinSettingsDialog* settingsDialog = new DolphinSettingsDialog(url, this, actionCollection());
         connect(settingsDialog, &DolphinSettingsDialog::settingsChanged, this, &DolphinMainWindow::refreshViews);
+        connect(settingsDialog, &DolphinSettingsDialog::settingsChanged,
+                &DolphinUrlNavigatorsController::slotReadSettings);
         settingsDialog->setAttribute(Qt::WA_DeleteOnClose);
         settingsDialog->show();
         m_settingsDialog = settingsDialog;
@@ -1043,7 +1091,7 @@ void DolphinMainWindow::handleUrl(const QUrl& url)
     } else {
         m_lastHandleUrlOpenJob = new KIO::OpenUrlJob(url);
         m_lastHandleUrlOpenJob->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this));
-        m_lastHandleUrlOpenJob->setRunExecutables(true);
+        m_lastHandleUrlOpenJob->setShowOpenOrExecuteDialog(true);
 
         connect(m_lastHandleUrlOpenJob, &KIO::OpenUrlJob::mimeTypeFound, this,
                 [this, url](const QString &mimetype) {
@@ -1221,7 +1269,12 @@ void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer)
         // view and url navigator) and main window.
         oldViewContainer->disconnect(this);
         oldViewContainer->view()->disconnect(this);
-        oldViewContainer->urlNavigator()->disconnect(this);
+        auto navigators = static_cast<DolphinNavigatorsWidgetAction *>
+                          (actionCollection()->action(QStringLiteral("url_navigators")));
+        navigators->primaryUrlNavigator()->disconnect(this);
+        if (auto secondaryUrlNavigator = navigators->secondaryUrlNavigator()) {
+            secondaryUrlNavigator->disconnect(this);
+        }
 
         // except the requestItemInfo so that on hover the information panel can still be updated
         connect(oldViewContainer->view(), &DolphinView::requestItemInfo,
@@ -1240,7 +1293,7 @@ void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer)
     updateSearchAction();
 
     const QUrl url = viewContainer->url();
-    emit urlChanged(url);
+    Q_EMIT urlChanged(url);
 }
 
 void DolphinMainWindow::tabCountChanged(int count)
@@ -1264,6 +1317,10 @@ void DolphinMainWindow::updateWindowTitle()
 
 void DolphinMainWindow::slotStorageTearDownFromPlacesRequested(const QString& mountPath)
 {
+    connect(m_placesPanel, &PlacesPanel::storageTearDownSuccessful, this, [this, mountPath]() {
+        setViewsToHomeIfMountPathOpen(mountPath);
+    });
+
     if (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) {
         m_tearDownFromPlacesRequested = true;
         m_terminalPanel->goHome();
@@ -1275,12 +1332,27 @@ void DolphinMainWindow::slotStorageTearDownFromPlacesRequested(const QString& mo
 
 void DolphinMainWindow::slotStorageTearDownExternallyRequested(const QString& mountPath)
 {
+    connect(m_placesPanel, &PlacesPanel::storageTearDownSuccessful, this, [this, mountPath]() {
+        setViewsToHomeIfMountPathOpen(mountPath);
+    });
+
     if (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) {
         m_tearDownFromPlacesRequested = false;
         m_terminalPanel->goHome();
     }
 }
 
+void DolphinMainWindow::setViewsToHomeIfMountPathOpen(const QString& mountPath)
+{
+    const QVector<DolphinViewContainer*> theViewContainers = viewContainers();
+    for (DolphinViewContainer *viewContainer : theViewContainers) {
+        if (viewContainer && viewContainer->url().toLocalFile().startsWith(mountPath)) {
+            viewContainer->setUrl(QUrl::fromLocalFile(QDir::homePath()));
+        }
+    }
+    disconnect(m_placesPanel, &PlacesPanel::storageTearDownSuccessful, nullptr, nullptr);
+}
+
 void DolphinMainWindow::setupActions()
 {
     // setup 'File' menu
@@ -1307,7 +1379,7 @@ void DolphinMainWindow::setupActions()
         "<emphasis>Tab</emphasis> with the current location and view.<nl/>"
         "A tab is an additional view within this window. "
         "You can drag and drop items between tabs."));
-    actionCollection()->setDefaultShortcuts(newTab, {Qt::CTRL + Qt::Key_T, Qt::CTRL + Qt::SHIFT + Qt::Key_N});
+    actionCollection()->setDefaultShortcuts(newTab, {Qt::CTRL | Qt::Key_T, Qt::CTRL | Qt::SHIFT | Qt::Key_N});
     connect(newTab, &QAction::triggered, this, &DolphinMainWindow::openNewActivatedTab);
 
     QAction* addToPlaces = actionCollection()->addAction(QStringLiteral("add_to_places"));
@@ -1366,7 +1438,7 @@ void DolphinMainWindow::setupActions()
         "the <emphasis>active</emphasis> view to the inactive split view."));
     copyToOtherViewAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy")));
     copyToOtherViewAction->setIconText(i18nc("@action:inmenu Edit", "Copy to Inactive Split View"));
-    actionCollection()->setDefaultShortcut(copyToOtherViewAction, Qt::SHIFT + Qt::Key_F5 );
+    actionCollection()->setDefaultShortcut(copyToOtherViewAction, Qt::SHIFT | Qt::Key_F5 );
     connect(copyToOtherViewAction, &QAction::triggered, m_tabWidget, &DolphinTabWidget::copyToInactiveSplitView);
 
     QAction* moveToOtherViewAction = actionCollection()->addAction(QStringLiteral("move_to_inactive_split_view"));
@@ -1375,9 +1447,32 @@ void DolphinMainWindow::setupActions()
         "the <emphasis>active</emphasis> view to the inactive split view."));
     moveToOtherViewAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-cut")));
     moveToOtherViewAction->setIconText(i18nc("@action:inmenu Edit", "Move to Inactive Split View"));
-    actionCollection()->setDefaultShortcut(moveToOtherViewAction, Qt::SHIFT + Qt::Key_F6 );
+    actionCollection()->setDefaultShortcut(moveToOtherViewAction, Qt::SHIFT | Qt::Key_F6 );
     connect(moveToOtherViewAction, &QAction::triggered, m_tabWidget, &DolphinTabWidget::moveToInactiveSplitView);
 
+    QAction* showFilterBar = actionCollection()->addAction(QStringLiteral("show_filter_bar"));
+    showFilterBar->setText(i18nc("@action:inmenu Tools", "Filter..."));
+    showFilterBar->setToolTip(i18nc("@info:tooltip", "Toggle Filter Bar"));
+    showFilterBar->setWhatsThis(xi18nc("@info:whatsthis", "This opens the "
+        "<emphasis>Filter Bar</emphasis> at the bottom of the window.<nl/> "
+        "There you can enter a text to filter the files and folders currently displayed. "
+        "Only those that contain the text in their name will be kept in view."));
+    showFilterBar->setIcon(QIcon::fromTheme(QStringLiteral("view-filter")));
+    actionCollection()->setDefaultShortcuts(showFilterBar, {Qt::CTRL | Qt::Key_I, Qt::Key_Slash});
+    connect(showFilterBar, &QAction::triggered, this, &DolphinMainWindow::showFilterBar);
+
+    // toggle_filter acts as a copy of the main showFilterBar to be used mainly
+    // in the toolbar, with no default shortcut attached, to avoid messing with
+    // existing workflows (filter bar always open and Ctrl-I to focus)
+    QAction *toggleFilter = actionCollection()->addAction(QStringLiteral("toggle_filter"));
+    toggleFilter->setText(i18nc("@action:inmenu", "Toggle Filter Bar"));
+    toggleFilter->setIconText(i18nc("@action:intoolbar", "Filter"));
+    toggleFilter->setIcon(showFilterBar->icon());
+    toggleFilter->setToolTip(showFilterBar->toolTip());
+    toggleFilter->setWhatsThis(showFilterBar->whatsThis());
+    toggleFilter->setCheckable(true);
+    connect(toggleFilter, &QAction::triggered, this, &DolphinMainWindow::toggleFilterBar);
+
     QAction *searchAction = KStandardAction::find(this, &DolphinMainWindow::find, actionCollection());
     searchAction->setText(i18n("Search..."));
     searchAction->setToolTip(i18nc("@info:tooltip", "Search for files and folders"));
@@ -1408,7 +1503,7 @@ void DolphinMainWindow::setupActions()
     invertSelection->setWhatsThis(xi18nc("@info:whatsthis invert", "This selects all "
         "objects that you have currently <emphasis>not</emphasis> selected instead."));
     invertSelection->setIcon(QIcon::fromTheme(QStringLiteral("edit-select-invert")));
-    actionCollection()->setDefaultShortcut(invertSelection, Qt::CTRL + Qt::SHIFT + Qt::Key_A);
+    actionCollection()->setDefaultShortcut(invertSelection, Qt::CTRL | Qt::SHIFT | Qt::Key_A);
     connect(invertSelection, &QAction::triggered, this, &DolphinMainWindow::invertSelection);
 
     // setup 'View' menu
@@ -1423,12 +1518,12 @@ void DolphinMainWindow::setupActions()
     connect(split, &QAction::triggered, this, &DolphinMainWindow::toggleSplitView);
 
     QAction* stashSplit = actionCollection()->addAction(QStringLiteral("split_stash"));
-    actionCollection()->setDefaultShortcut(stashSplit, Qt::CTRL + Qt::Key_S);
+    actionCollection()->setDefaultShortcut(stashSplit, Qt::CTRL | Qt::Key_S);
     stashSplit->setText(i18nc("@action:intoolbar Stash", "Stash"));
     stashSplit->setToolTip(i18nc("@info", "Opens the stash virtual directory in a split window"));
     stashSplit->setIcon(QIcon::fromTheme(QStringLiteral("folder-stash")));
     stashSplit->setCheckable(false);
-    stashSplit->setVisible(KProtocolInfo::isKnownProtocol("stash"));
+    stashSplit->setVisible(QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.kio.StashNotifier")));
     connect(stashSplit, &QAction::triggered, this, &DolphinMainWindow::toggleSplitStash);
 
     KStandardAction::redisplay(this, &DolphinMainWindow::reloadView, actionCollection());
@@ -1458,7 +1553,7 @@ void DolphinMainWindow::setupActions()
     replaceLocation->setWhatsThis(xi18nc("@info:whatsthis",
         "This switches to editing the location and selects it "
         "so you can quickly enter a different location."));
-    actionCollection()->setDefaultShortcut(replaceLocation, Qt::CTRL + Qt::Key_L);
+    actionCollection()->setDefaultShortcut(replaceLocation, Qt::CTRL | Qt::Key_L);
     connect(replaceLocation, &QAction::triggered, this, &DolphinMainWindow::replaceLocation);
 
     // setup 'Go' menu
@@ -1492,7 +1587,7 @@ void DolphinMainWindow::setupActions()
     undoCloseTab->setText(i18nc("@action:inmenu File", "Undo close tab"));
     undoCloseTab->setWhatsThis(i18nc("@info:whatsthis undo close tab",
         "This returns you to the previously closed tab."));
-    actionCollection()->setDefaultShortcut(undoCloseTab, Qt::CTRL + Qt::SHIFT + Qt::Key_T);
+    actionCollection()->setDefaultShortcut(undoCloseTab, Qt::CTRL | Qt::SHIFT | Qt::Key_T);
     undoCloseTab->setIcon(QIcon::fromTheme(QStringLiteral("edit-undo")));
     undoCloseTab->setEnabled(false);
     connect(undoCloseTab, &QAction::triggered, recentTabsMenu, &DolphinRecentTabsMenu::undoCloseTab);
@@ -1533,16 +1628,6 @@ void DolphinMainWindow::setupActions()
         "including folders that contain personal application data."));
 
     // setup 'Tools' menu
-    QAction* showFilterBar = actionCollection()->addAction(QStringLiteral("show_filter_bar"));
-    showFilterBar->setText(i18nc("@action:inmenu Tools", "Show Filter Bar"));
-    showFilterBar->setWhatsThis(xi18nc("@info:whatsthis", "This opens the "
-        "<emphasis>Filter Bar</emphasis> at the bottom of the window.<nl/> "
-        "There you can enter a text to filter the files and folders currently displayed. "
-        "Only those that contain the text in their name will be kept in view."));
-    showFilterBar->setIcon(QIcon::fromTheme(QStringLiteral("view-filter")));
-    actionCollection()->setDefaultShortcuts(showFilterBar, {Qt::CTRL + Qt::Key_I, Qt::Key_Slash});
-    connect(showFilterBar, &QAction::triggered, this, &DolphinMainWindow::showFilterBar);
-
     QAction* compareFiles = actionCollection()->addAction(QStringLiteral("compare_files"));
     compareFiles->setText(i18nc("@action:inmenu Tools", "Compare Files"));
     compareFiles->setIcon(QIcon::fromTheme(QStringLiteral("kompare")));
@@ -1555,7 +1640,7 @@ void DolphinMainWindow::setupActions()
         "<para>This opens a preferred search tool for the viewed location.</para>"
         "<para>Use <emphasis>More Search Tools</emphasis> menu to configure it.</para>"));
     openPreferredSearchTool->setIcon(QIcon::fromTheme(QStringLiteral("search")));
-    actionCollection()->setDefaultShortcut(openPreferredSearchTool, Qt::CTRL + Qt::SHIFT + Qt::Key_F);
+    actionCollection()->setDefaultShortcut(openPreferredSearchTool, Qt::CTRL | Qt::SHIFT | Qt::Key_F);
     connect(openPreferredSearchTool, &QAction::triggered, this, &DolphinMainWindow::openPreferredSearchTool);
 
     if (KAuthorized::authorize(QStringLiteral("shell_access"))) {
@@ -1564,15 +1649,15 @@ void DolphinMainWindow::setupActions()
         openTerminal->setWhatsThis(xi18nc("@info:whatsthis",
             "<para>This opens a <emphasis>terminal</emphasis> application for the viewed location.</para>"
             "<para>To learn more about terminals use the help in the terminal application.</para>"));
-        openTerminal->setIcon(QIcon::fromTheme(QStringLiteral("dialog-scripts")));
-        actionCollection()->setDefaultShortcut(openTerminal, Qt::SHIFT + Qt::Key_F4);
+        openTerminal->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal")));
+        actionCollection()->setDefaultShortcut(openTerminal, Qt::SHIFT | Qt::Key_F4);
         connect(openTerminal, &QAction::triggered, this, &DolphinMainWindow::openTerminal);
 
 #ifdef HAVE_TERMINAL
         QAction* focusTerminalPanel = actionCollection()->addAction(QStringLiteral("focus_terminal_panel"));
         focusTerminalPanel->setText(i18nc("@action:inmenu Tools", "Focus Terminal Panel"));
         focusTerminalPanel->setIcon(QIcon::fromTheme(QStringLiteral("swap-panels")));
-        actionCollection()->setDefaultShortcut(focusTerminalPanel, Qt::CTRL + Qt::SHIFT + Qt::Key_F4);
+        actionCollection()->setDefaultShortcut(focusTerminalPanel, Qt::CTRL | Qt::SHIFT | Qt::Key_F4);
         connect(focusTerminalPanel, &QAction::triggered, this, &DolphinMainWindow::focusTerminalPanel);
 #endif
     }
@@ -1604,10 +1689,10 @@ void DolphinMainWindow::setupActions()
 
     // not in menu actions
     QList<QKeySequence> nextTabKeys = KStandardShortcut::tabNext();
-    nextTabKeys.append(QKeySequence(Qt::CTRL + Qt::Key_Tab));
+    nextTabKeys.append(QKeySequence(Qt::CTRL | Qt::Key_Tab));
 
     QList<QKeySequence> prevTabKeys = KStandardShortcut::tabPrev();
-    prevTabKeys.append(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab));
+    prevTabKeys.append(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Tab));
 
     for (int i = 0; i < MaxActivateTabShortcuts; ++i) {
         QAction* activateTab = actionCollection()->addAction(QStringLiteral("activate_tab_%1").arg(i));
@@ -1625,7 +1710,7 @@ void DolphinMainWindow::setupActions()
     activateLastTab->setText(i18nc("@action:inmenu", "Activate Last Tab"));
     activateLastTab->setEnabled(false);
     connect(activateLastTab, &QAction::triggered, m_tabWidget, &DolphinTabWidget::activateLastTab);
-    actionCollection()->setDefaultShortcut(activateLastTab, Qt::ALT + Qt::Key_0);
+    actionCollection()->setDefaultShortcut(activateLastTab, Qt::ALT | Qt::Key_0);
 
     QAction* activateNextTab = actionCollection()->addAction(QStringLiteral("activate_next_tab"));
     activateNextTab->setIconText(i18nc("@action:inmenu", "Next Tab"));
@@ -1832,14 +1917,14 @@ void DolphinMainWindow::setupDockWidgets()
     connect(this, &DolphinMainWindow::urlChanged,
             m_placesPanel, &PlacesPanel::setUrl);
     connect(placesDock, &DolphinDockWidget::visibilityChanged,
-            m_tabWidget, &DolphinTabWidget::slotPlacesPanelVisibilityChanged);
+            &DolphinUrlNavigatorsController::slotPlacesPanelVisibilityChanged);
     connect(this, &DolphinMainWindow::settingsChanged,
         m_placesPanel, &PlacesPanel::readSettings);
     connect(m_placesPanel, &PlacesPanel::storageTearDownRequested,
             this, &DolphinMainWindow::slotStorageTearDownFromPlacesRequested);
     connect(m_placesPanel, &PlacesPanel::storageTearDownExternallyRequested,
             this, &DolphinMainWindow::slotStorageTearDownExternallyRequested);
-    m_tabWidget->slotPlacesPanelVisibilityChanged(m_placesPanel->isVisible());
+    DolphinUrlNavigatorsController::slotPlacesPanelVisibilityChanged(m_placesPanel->isVisible());
 
     auto actionShowAllPlaces = new QAction(QIcon::fromTheme(QStringLiteral("view-hidden")), i18nc("@item:inmenu", "Show Hidden Places"), this);
     actionShowAllPlaces->setCheckable(true);
@@ -1968,14 +2053,10 @@ void DolphinMainWindow::updateViewActions()
 {
     m_actionHandler->updateViewActions();
 
-    QAction* showFilterBarAction = actionCollection()->action(QStringLiteral("show_filter_bar"));
-    showFilterBarAction->setChecked(m_activeViewContainer->isFilterBarVisible());
+    QAction* toggleFilterBarAction = actionCollection()->action(QStringLiteral("toggle_filter"));
+    toggleFilterBarAction->setChecked(m_activeViewContainer->isFilterBarVisible());
 
     updateSplitAction();
-
-    QAction* editableLocactionAction = actionCollection()->action(QStringLiteral("editable_location"));
-    const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
-    editableLocactionAction->setChecked(urlNavigator->isUrlEditable());
 }
 
 void DolphinMainWindow::updateGoActions()
@@ -2043,7 +2124,8 @@ bool DolphinMainWindow::addActionToMenu(QAction* action, QMenu* menu)
     Q_ASSERT(menu);
 
     const KToolBar* toolBarWidget = toolBar();
-    foreach (const QWidget* widget, action->associatedWidgets()) {
+    const auto associatedWidgets = action->associatedWidgets();
+    for (const QWidget* widget : associatedWidgets) {
         if (widget == toolBarWidget) {
             return false;
         }
@@ -2066,7 +2148,7 @@ void DolphinMainWindow::refreshViews()
         updateWindowTitle();
     }
 
-    emit settingsChanged();
+    Q_EMIT settingsChanged();
 }
 
 void DolphinMainWindow::clearStatusBar()
@@ -2110,15 +2192,26 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
     connect(view, &DolphinView::goUpRequested,
             this, &DolphinMainWindow::goUp);
 
-    const KUrlNavigator* navigator = container->urlNavigator();
+    auto navigators = static_cast<DolphinNavigatorsWidgetAction *>
+        (actionCollection()->action(QStringLiteral("url_navigators")));
+
+    const KUrlNavigator *navigator = m_tabWidget->currentTabPage()->primaryViewActive() ?
+                                     navigators->primaryUrlNavigator() :
+                                     navigators->secondaryUrlNavigator();
+
     connect(navigator, &KUrlNavigator::urlChanged,
             this, &DolphinMainWindow::changeUrl);
-    connect(navigator, &KUrlNavigator::historyChanged,
-            this, &DolphinMainWindow::updateHistory);
+    QAction *editableLocactionAction = actionCollection()->action(QStringLiteral("editable_location"));
+    editableLocactionAction->setChecked(navigator->isUrlEditable());
     connect(navigator, &KUrlNavigator::editableStateChanged,
             this, &DolphinMainWindow::slotEditableStateChanged);
     connect(navigator, &KUrlNavigator::tabRequested,
             this, &DolphinMainWindow::openNewTabAfterLastTab);
+
+    disconnect(m_updateHistoryConnection);
+    m_updateHistoryConnection = connect(
+            container->urlNavigatorInternalWithHistory(), &KUrlNavigator::historyChanged,
+            this, &DolphinMainWindow::updateHistory);
 }
 
 void DolphinMainWindow::updateSplitAction()
@@ -2142,6 +2235,21 @@ void DolphinMainWindow::updateSplitAction()
     }
 }
 
+void DolphinMainWindow::updateAllowedToolbarAreas()
+{
+    auto navigators = static_cast<DolphinNavigatorsWidgetAction *>
+                        (actionCollection()->action(QStringLiteral("url_navigators")));
+    if (toolBar()->actions().contains(navigators)) {
+        toolBar()->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
+        if (toolBarArea(toolBar()) == Qt::LeftToolBarArea ||
+            toolBarArea(toolBar()) == Qt::RightToolBarArea) {
+            addToolBar(Qt::TopToolBarArea, toolBar());
+        }
+    } else {
+        toolBar()->setAllowedAreas(Qt::AllToolBarAreas);
+    }
+}
+
 bool DolphinMainWindow::isKompareInstalled() const
 {
     static bool initialized = false;
@@ -2349,6 +2457,19 @@ bool DolphinMainWindow::eventFilter(QObject* obj, QEvent* event)
     return false;
 }
 
+void DolphinMainWindow::saveNewToolbarConfig()
+{
+    KXmlGuiWindow::saveNewToolbarConfig(); // Applies the new config. This has to be called first
+                                           // because the rest of this method decides things
+                                           // based on the new config.
+    auto navigators = static_cast<DolphinNavigatorsWidgetAction *>
+                        (actionCollection()->action(QStringLiteral("url_navigators")));
+    if (!toolBar()->actions().contains(navigators)) {
+        m_tabWidget->currentTabPage()->insertNavigatorsWidget(navigators);
+    }
+    updateAllowedToolbarAreas();
+}
+
 void DolphinMainWindow::focusTerminalPanel()
 {
     if (m_terminalPanel->isVisible()) {