]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/dolphinmainwindow.cpp
DolphinView: rename copySelectedItems to copySelectedItemsToClipboard
[dolphin.git] / src / dolphinmainwindow.cpp
index 2cf524bbd7f124c9558474387c1361ac3b95006b..ab41e2d7ff5afff0ce2b1e04b0cdc4271809d6c0 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2006 by Peter Penz <peter.penz@gmx.at>                  *\r
- *   Copyright (C) 2006 by Stefan Monov <logixoul@gmail.com>               *\r
- *   Copyright (C) 2006 by Cvetoslav Ludmiloff <ludmiloff@gmail.com>       *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   This program is distributed in the hope that it will be useful,       *\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
- *   GNU General Public License for more details.                          *\r
- *                                                                         *\r
- *   You should have received a copy of the GNU General Public License     *\r
- *   along with this program; if not, write to the                         *\r
- *   Free Software Foundation, Inc.,                                       *\r
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *\r
- ***************************************************************************/\r
-\r
-#include "dolphinmainwindow.h"\r
-\r
-#include <assert.h>\r
-\r
-#include "dolphinapplication.h"\r
-#include "dolphinnewmenu.h"\r
-#include "dolphinsettings.h"\r
-#include "dolphinsettingsdialog.h"\r
-#include "dolphinstatusbar.h"\r
-#include "dolphinapplication.h"\r
-#include "urlnavigator.h"\r
-#include "dolphinsettings.h"\r
-#include "bookmarkssidebarpage.h"\r
-#include "infosidebarpage.h"\r
-#include "dolphin_generalsettings.h"\r
-#include "viewpropertiesdialog.h"\r
-#include "viewproperties.h"\r
-#include "mainwindowadaptor.h"\r
-\r
-#include <kaction.h>\r
-#include <kactioncollection.h>\r
-#include <kbookmarkmanager.h>\r
-#include <kconfig.h>\r
-#include <kdesktopfile.h>\r
-#include <kdeversion.h>\r
-#include <kfiledialog.h>\r
-#include <kglobal.h>\r
-#include <kicon.h>\r
-#include <kiconloader.h>\r
-#include <kio/netaccess.h>\r
-#include <kio/deletejob.h>\r
-#include <kio/renamedialog.h>\r
-#include <kinputdialog.h>\r
-#include <klocale.h>\r
-#include <kmenu.h>\r
-#include <kmessagebox.h>\r
-#include <konqmimedata.h>\r
-#include <kpropertiesdialog.h>\r
-#include <kprotocolinfo.h>\r
-#include <ktoggleaction.h>\r
-#include <krun.h>\r
-#include <kshell.h>\r
-#include <kstandarddirs.h>\r
-#include <kstatusbar.h>\r
-#include <kstandardaction.h>\r
-#include <kurl.h>\r
-\r
-#include <QCloseEvent>\r
-#include <QClipboard>\r
-#include <QSplitter>\r
-#include <QDockWidget>\r
-\r
-DolphinMainWindow::DolphinMainWindow(int id) :\r
-    KMainWindow(0),\r
-    m_newMenu(0),\r
-    m_splitter(0),\r
-    m_activeView(0),\r
-    m_id(id)\r
-{\r
-    setObjectName("Dolphin");\r
-    m_view[PrimaryIdx] = 0;\r
-    m_view[SecondaryIdx] = 0;\r
-\r
-    new MainWindowAdaptor(this);\r
-    QDBusConnection::sessionBus().registerObject(QString("/dolphin/MainWindow%1").arg(m_id), this);\r
-\r
-    KonqUndoManager::incRef();\r
-\r
-    KonqUndoManager* undoManager = KonqUndoManager::self();\r
-    undoManager->setUiInterface(new UndoUiInterface(this));\r
-\r
-    connect(undoManager, SIGNAL(undoAvailable(bool)),\r
-            this, SLOT(slotUndoAvailable(bool)));\r
-    connect(undoManager, SIGNAL(undoTextChanged(const QString&)),\r
-            this, SLOT(slotUndoTextChanged(const QString&)));\r
-}\r
-\r
-DolphinMainWindow::~DolphinMainWindow()\r
-{\r
-    KonqUndoManager::decRef();\r
-    DolphinApplication::app()->removeMainWindow(this);\r
-}\r
-\r
-void DolphinMainWindow::setActiveView(DolphinView* view)\r
-{\r
-    assert((view == m_view[PrimaryIdx]) || (view == m_view[SecondaryIdx]));\r
-    if (m_activeView == view) {\r
-        return;\r
-    }\r
-\r
-    m_activeView = view;\r
-\r
-    updateHistory();\r
-    updateEditActions();\r
-    updateViewActions();\r
-    updateGoActions();\r
-\r
-    setCaption(m_activeView->url().fileName());\r
-\r
-    emit activeViewChanged();\r
-}\r
-\r
-void DolphinMainWindow::dropUrls(const KUrl::List& urls,\r
-                                 const KUrl& destination)\r
-{\r
-    Qt::DropAction action = Qt::CopyAction;\r
-\r
-    Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();\r
-    const bool shiftPressed   = modifier & Qt::ShiftModifier;\r
-    const bool controlPressed = modifier & Qt::ControlModifier;\r
-    if (shiftPressed && controlPressed) {\r
-        // shortcut for 'Link Here' is used\r
-        action = Qt::LinkAction;\r
-    }\r
-    else if (shiftPressed) {\r
-        // shortcut for 'Move Here' is used\r
-        action = Qt::MoveAction;\r
-    }\r
-    else if (controlPressed) {\r
-        // shortcut for 'Copy Here' is used\r
-        action = Qt::CopyAction;\r
-    }\r
-    else {\r
-        // open a context menu which offers the following actions:\r
-        // - Move Here\r
-        // - Copy Here\r
-        // - Link Here\r
-        // - Cancel\r
-\r
-        KMenu popup(this);\r
-\r
-        QString seq = QKeySequence(Qt::ShiftModifier).toString();\r
-        seq.chop(1); // chop superfluous '+'\r
-        QAction* moveAction = popup.addAction(KIcon("goto"),\r
-                                              i18n("&Move Here") + "\t" + seq);\r
-\r
-        seq = QKeySequence(Qt::ControlModifier).toString();\r
-        seq.chop(1);\r
-        QAction* copyAction = popup.addAction(KIcon("editcopy"),\r
-                                              i18n("&Copy Here") + "\t" + seq);\r
-\r
-        seq = QKeySequence(Qt::ControlModifier + Qt::ShiftModifier).toString();\r
-        seq.chop(1);\r
-        QAction* linkAction = popup.addAction(KIcon("www"),\r
-                                              i18n("&Link Here") + "\t" + seq);\r
-\r
-        popup.addSeparator();\r
-        popup.addAction(KIcon("stop"), i18n("Cancel"));\r
-\r
-        QAction* activatedAction = popup.exec(QCursor::pos());\r
-        if (activatedAction == moveAction) {\r
-            action = Qt::MoveAction;\r
-        }\r
-        else if (activatedAction == copyAction) {\r
-            action = Qt::CopyAction;\r
-        }\r
-        else if (activatedAction == linkAction) {\r
-            action = Qt::LinkAction;\r
-        }\r
-        else {\r
-            return;\r
-        }\r
-    }\r
-\r
-    switch (action) {\r
-        case Qt::MoveAction:\r
-            moveUrls(urls, destination);\r
-            break;\r
-\r
-        case Qt::CopyAction:\r
-            copyUrls(urls, destination);\r
-            break;\r
-\r
-        case Qt::LinkAction:\r
-            linkUrls(urls, destination);\r
-            break;\r
-\r
-        default:\r
-            break;\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::refreshViews()\r
-{\r
-    const bool split = DolphinSettings::instance().generalSettings()->splitView();\r
-    const bool isPrimaryViewActive = (m_activeView == m_view[PrimaryIdx]);\r
-    KUrl url;\r
-    for (int i = PrimaryIdx; i <= SecondaryIdx; ++i) {\r
-       if (m_view[i] != 0) {\r
-            url = m_view[i]->url();\r
-\r
-            // delete view instance...\r
-            m_view[i]->close();\r
-            m_view[i]->deleteLater();\r
-            m_view[i] = 0;\r
-        }\r
-\r
-        if (split || (i == PrimaryIdx)) {\r
-            // ... and recreate it\r
-            ViewProperties props(url);\r
-            m_view[i] = new DolphinView(this,\r
-                                        m_splitter,\r
-                                        url,\r
-                                        props.viewMode(),\r
-                                        props.showHiddenFiles());\r
-            connectViewSignals(i);\r
-            m_view[i]->show();\r
-        }\r
-    }\r
-\r
-    m_activeView = isPrimaryViewActive ? m_view[PrimaryIdx] : m_view[SecondaryIdx];\r
-    assert(m_activeView != 0);\r
-\r
-    updateViewActions();\r
-    emit activeViewChanged();\r
-}\r
-\r
-void DolphinMainWindow::changeUrl(const QString& url)\r
-{\r
-    if (activeView() != 0) {\r
-        activeView()->setUrl(KUrl(url));\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::slotViewModeChanged()\r
-{\r
-    updateViewActions();\r
-}\r
-\r
-void DolphinMainWindow::slotShowHiddenFilesChanged()\r
-{\r
-    KToggleAction* showHiddenFilesAction =\r
-        static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));\r
-    showHiddenFilesAction->setChecked(m_activeView->showHiddenFiles());\r
-}\r
-\r
-void DolphinMainWindow::slotSortingChanged(DolphinView::Sorting sorting)\r
-{\r
-    QAction* action = 0;\r
-    switch (sorting) {\r
-        case DolphinView::SortByName:\r
-            action = actionCollection()->action("by_name");\r
-            break;\r
-        case DolphinView::SortBySize:\r
-            action = actionCollection()->action("by_size");\r
-            break;\r
-        case DolphinView::SortByDate:\r
-            action = actionCollection()->action("by_date");\r
-            break;\r
-        case DolphinView::SortByPermissions:\r
-            action = actionCollection()->action("by_permissions");\r
-            break;\r
-        case DolphinView::SortByOwner:\r
-            action = actionCollection()->action("by_owner");\r
-            break;\r
-        case DolphinView::SortByGroup:\r
-            action = actionCollection()->action("by_group");\r
-            break;\r
-        default:\r
-            break;\r
-    }\r
-\r
-    if (action != 0) {\r
-        KToggleAction* toggleAction = static_cast<KToggleAction*>(action);\r
-        toggleAction->setChecked(true);\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::slotSortOrderChanged(Qt::SortOrder order)\r
-{\r
-    KToggleAction* descending = static_cast<KToggleAction*>(actionCollection()->action("descending"));\r
-    const bool sortDescending = (order == Qt::Descending);\r
-    descending->setChecked(sortDescending);\r
-}\r
-\r
-void DolphinMainWindow::slotSelectionChanged()\r
-{\r
-    updateEditActions();\r
-\r
-    assert(m_view[PrimaryIdx] != 0);\r
-    int selectedUrlsCount = m_view[PrimaryIdx]->selectedUrls().count();\r
-    if (m_view[SecondaryIdx] != 0) {\r
-        selectedUrlsCount += m_view[SecondaryIdx]->selectedUrls().count();\r
-    }\r
-\r
-    QAction* compareFilesAction = actionCollection()->action("compare_files");\r
-    compareFilesAction->setEnabled(selectedUrlsCount == 2);\r
-\r
-    m_activeView->updateStatusBar();\r
-\r
-    emit selectionChanged();\r
-}\r
-\r
-void DolphinMainWindow::slotHistoryChanged()\r
-{\r
-    updateHistory();\r
-}\r
-\r
-void DolphinMainWindow::slotUrlChanged(const KUrl& url)\r
-{\r
-    updateEditActions();\r
-    updateGoActions();\r
-    setCaption(url.fileName());\r
-}\r
-\r
-void DolphinMainWindow::updateFilterBarAction(bool show)\r
-{\r
-    KToggleAction* showFilterBarAction =\r
-        static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));\r
-    showFilterBarAction->setChecked(show);\r
-}\r
-\r
-void DolphinMainWindow::openNewMainWindow()\r
-{\r
-    DolphinApplication::app()->createMainWindow()->show();\r
-}\r
-\r
-void DolphinMainWindow::closeEvent(QCloseEvent* event)\r
-{\r
-    DolphinSettings& settings = DolphinSettings::instance();\r
-    GeneralSettings* generalSettings = settings.generalSettings();\r
-    generalSettings->setFirstRun(false);\r
-\r
-    settings.save();\r
-\r
-    // TODO: I assume there will be a generic way in KDE 4 to store the docks\r
-    // of the main window. In the meantime they are stored manually:\r
-    QString filename = KStandardDirs::locateLocal("data", KGlobal::mainComponent().componentName());\r
-    filename.append("/panels_layout");\r
-    QFile file(filename);\r
-    if (file.open(QIODevice::WriteOnly)) {\r
-        QByteArray data = saveState();\r
-        file.write(data);\r
-        file.close();\r
-    }\r
-\r
-    KMainWindow::closeEvent(event);\r
-}\r
-\r
-void DolphinMainWindow::saveProperties(KConfig* config)\r
-{\r
-    KConfigGroup primaryView = config->group("Primary view");\r
-    primaryView.writeEntry("Url", m_view[PrimaryIdx]->url().url());\r
-    primaryView.writeEntry("Editable Url", m_view[PrimaryIdx]->isUrlEditable());\r
-    if (m_view[SecondaryIdx] != 0) {\r
-        KConfigGroup secondaryView = config->group("Secondary view");\r
-        secondaryView.writeEntry("Url", m_view[SecondaryIdx]->url().url());\r
-        secondaryView.writeEntry("Editable Url", m_view[SecondaryIdx]->isUrlEditable());\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::readProperties(KConfig* config)\r
-{\r
-    const KConfigGroup primaryView = config->group("Primary view");\r
-    m_view[PrimaryIdx]->setUrl(primaryView.readEntry("Url"));\r
-    m_view[PrimaryIdx]->setUrlEditable(primaryView.readEntry("Editable Url", false));\r
-    if (config->hasGroup("Secondary view")) {\r
-        const KConfigGroup secondaryView = config->group("Secondary view");\r
-        if (m_view[SecondaryIdx] == 0) {\r
-            toggleSplitView();\r
-        }\r
-        m_view[SecondaryIdx]->setUrl(secondaryView.readEntry("Url"));\r
-        m_view[SecondaryIdx]->setUrlEditable(secondaryView.readEntry("Editable Url", false));\r
-    }\r
-    else if (m_view[SecondaryIdx] != 0) {\r
-        toggleSplitView();\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::updateNewMenu()\r
-{\r
-    m_newMenu->slotCheckUpToDate();\r
-    m_newMenu->setPopupFiles(activeView()->url());\r
-}\r
-\r
-void DolphinMainWindow::rename()\r
-{\r
-    clearStatusBar();\r
-    m_activeView->renameSelectedItems();\r
-}\r
-\r
-void DolphinMainWindow::moveToTrash()\r
-{\r
-    clearStatusBar();\r
-    const KUrl::List selectedUrls = m_activeView->selectedUrls();\r
-    KonqOperations::del(this, KonqOperations::TRASH, selectedUrls);\r
-    m_undoOperations.append(KonqOperations::TRASH);\r
-}\r
-\r
-void DolphinMainWindow::deleteItems()\r
-{\r
-    clearStatusBar();\r
-\r
-    KUrl::List list = m_activeView->selectedUrls();\r
-    const uint itemCount = list.count();\r
-    assert(itemCount >= 1);\r
-\r
-    QString text;\r
-    if (itemCount > 1) {\r
-        text = i18n("Do you really want to delete the %1 selected items?",itemCount);\r
-    }\r
-    else {\r
-        const KUrl& url = list.first();\r
-        text = i18n("Do you really want to delete '%1'?",url.fileName());\r
-    }\r
-\r
-    const bool del = KMessageBox::warningContinueCancel(this,\r
-                                                        text,\r
-                                                        QString::null,\r
-                                                        KGuiItem(i18n("Delete"), KIcon("editdelete"))\r
-                                                       ) == KMessageBox::Continue;\r
-    if (del) {\r
-        KIO::Job* job = KIO::del(list);\r
-        connect(job, SIGNAL(result(KJob*)),\r
-                this, SLOT(slotHandleJobError(KJob*)));\r
-        connect(job, SIGNAL(result(KJob*)),\r
-                this, SLOT(slotDeleteFileFinished(KJob*)));\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::properties()\r
-{\r
-    const KFileItemList list = m_activeView->selectedItems();\r
-    new KPropertiesDialog(list, this);\r
-}\r
-\r
-void DolphinMainWindow::quit()\r
-{\r
-    close();\r
-}\r
-\r
-void DolphinMainWindow::slotHandleJobError(KJob* job)\r
-{\r
-    if (job->error() != 0) {\r
-        DolphinStatusBar* statusBar = m_activeView->statusBar();\r
-        statusBar->setMessage(job->errorString(),\r
-                              DolphinStatusBar::Error);\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::slotDeleteFileFinished(KJob* job)\r
-{\r
-    if (job->error() == 0) {\r
-        DolphinStatusBar* statusBar = m_activeView->statusBar();\r
-        statusBar->setMessage(i18n("Delete operation completed."),\r
-                              DolphinStatusBar::OperationCompleted);\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::slotUndoAvailable(bool available)\r
-{\r
-    QAction* undoAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Undo));\r
-    if (undoAction != 0) {\r
-        undoAction->setEnabled(available);\r
-    }\r
-\r
-    if (available && (m_undoOperations.count() > 0)) {\r
-        const KonqOperations::Operation op = m_undoOperations.takeFirst();\r
-        DolphinStatusBar* statusBar = m_activeView->statusBar();\r
-        switch (op) {\r
-            case KonqOperations::COPY:\r
-                statusBar->setMessage(i18n("Copy operation completed."),\r
-                                      DolphinStatusBar::OperationCompleted);\r
-                break;\r
-            case KonqOperations::MOVE:\r
-                statusBar->setMessage(i18n("Move operation completed."),\r
-                                      DolphinStatusBar::OperationCompleted);\r
-                break;\r
-            case KonqOperations::LINK:\r
-                statusBar->setMessage(i18n("Link operation completed."),\r
-                                      DolphinStatusBar::OperationCompleted);\r
-                break;\r
-            case KonqOperations::TRASH:\r
-                statusBar->setMessage(i18n("Move to trash operation completed."),\r
-                                      DolphinStatusBar::OperationCompleted);\r
-                break;\r
-            default:\r
-                break;\r
-        }\r
-\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::slotUndoTextChanged(const QString& text)\r
-{\r
-    QAction* undoAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Undo));\r
-    if (undoAction != 0) {\r
-        undoAction->setText(text);\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::undo()\r
-{\r
-    clearStatusBar();\r
-    KonqUndoManager::self()->undo();\r
-}\r
-\r
-void DolphinMainWindow::cut()\r
-{\r
-    QMimeData* mimeData = new QMimeData();\r
-    const KUrl::List kdeUrls = m_activeView->selectedUrls();\r
-    const KUrl::List mostLocalUrls;\r
-    KonqMimeData::populateMimeData(mimeData, kdeUrls, mostLocalUrls, true);\r
-    QApplication::clipboard()->setMimeData(mimeData);\r
-}\r
-\r
-void DolphinMainWindow::copy()\r
-{\r
-    QMimeData* mimeData = new QMimeData();\r
-    const KUrl::List kdeUrls = m_activeView->selectedUrls();\r
-    const KUrl::List mostLocalUrls;\r
-    KonqMimeData::populateMimeData(mimeData, kdeUrls, mostLocalUrls, false);\r
-\r
-    QApplication::clipboard()->setMimeData(mimeData);\r
-}\r
-\r
-void DolphinMainWindow::paste()\r
-{\r
-    QClipboard* clipboard = QApplication::clipboard();\r
-    const QMimeData* mimeData = clipboard->mimeData();\r
-\r
-    clearStatusBar();\r
-\r
-    const KUrl::List sourceUrls = KUrl::List::fromMimeData(mimeData);\r
-\r
-    // per default the pasting is done into the current Url of the view\r
-    KUrl destUrl(m_activeView->url());\r
-\r
-    // check whether the pasting should be done into a selected directory\r
-    KUrl::List selectedUrls = m_activeView->selectedUrls();\r
-    if (selectedUrls.count() == 1) {\r
-        const KFileItem fileItem(S_IFDIR,\r
-                                 KFileItem::Unknown,\r
-                                 selectedUrls.first(),\r
-                                 true);\r
-        if (fileItem.isDir()) {\r
-            // only one item is selected which is a directory, hence paste\r
-            // into this directory\r
-            destUrl = selectedUrls.first();\r
-        }\r
-    }\r
-\r
-    if (KonqMimeData::decodeIsCutSelection(mimeData)) {\r
-        moveUrls(sourceUrls, destUrl);\r
-        clipboard->clear();\r
-    }\r
-    else {\r
-        copyUrls(sourceUrls, destUrl);\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::updatePasteAction()\r
-{\r
-    QAction* pasteAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Paste));\r
-    if (pasteAction == 0) {\r
-        return;\r
-    }\r
-\r
-    QString text(i18n("Paste"));\r
-    QClipboard* clipboard = QApplication::clipboard();\r
-    const QMimeData* mimeData = clipboard->mimeData();\r
-\r
-    KUrl::List urls = KUrl::List::fromMimeData(mimeData);\r
-    if (!urls.isEmpty()) {\r
-        pasteAction->setEnabled(true);\r
-\r
-        const int count = urls.count();\r
-        if (count == 1) {\r
-            pasteAction->setText(i18n("Paste 1 File"));\r
-        }\r
-        else {\r
-            pasteAction->setText(i18n("Paste %1 Files", count));\r
-        }\r
-    }\r
-    else {\r
-        pasteAction->setEnabled(false);\r
-        pasteAction->setText(i18n("Paste"));\r
-    }\r
-\r
-    if (pasteAction->isEnabled()) {\r
-        KUrl::List urls = m_activeView->selectedUrls();\r
-        const uint count = urls.count();\r
-        if (count > 1) {\r
-            // pasting should not be allowed when more than one file\r
-            // is selected\r
-            pasteAction->setEnabled(false);\r
-        }\r
-        else if (count == 1) {\r
-            // Only one file is selected. Pasting is only allowed if this\r
-            // file is a directory.\r
-            // TODO: this doesn't work with remote protocols; instead we need a\r
-            // m_activeView->selectedFileItems() to get the real KFileItems\r
-            const KFileItem fileItem(S_IFDIR,\r
-                                     KFileItem::Unknown,\r
-                                     urls.first(),\r
-                                     true);\r
-            pasteAction->setEnabled(fileItem.isDir());\r
-        }\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::selectAll()\r
-{\r
-    clearStatusBar();\r
-    m_activeView->selectAll();\r
-}\r
-\r
-void DolphinMainWindow::invertSelection()\r
-{\r
-    clearStatusBar();\r
-    m_activeView->invertSelection();\r
-}\r
-void DolphinMainWindow::setIconsView()\r
-{\r
-    m_activeView->setMode(DolphinView::IconsView);\r
-}\r
-\r
-void DolphinMainWindow::setDetailsView()\r
-{\r
-    m_activeView->setMode(DolphinView::DetailsView);\r
-}\r
-\r
-void DolphinMainWindow::sortByName()\r
-{\r
-    m_activeView->setSorting(DolphinView::SortByName);\r
-}\r
-\r
-void DolphinMainWindow::sortBySize()\r
-{\r
-    m_activeView->setSorting(DolphinView::SortBySize);\r
-}\r
-\r
-void DolphinMainWindow::sortByDate()\r
-{\r
-    m_activeView->setSorting(DolphinView::SortByDate);\r
-}\r
-\r
-void DolphinMainWindow::sortByPermissions()\r
-{\r
-    m_activeView->setSorting(DolphinView::SortByPermissions);\r
-}\r
-\r
-void DolphinMainWindow::sortByOwner()\r
-{\r
-    m_activeView->setSorting(DolphinView::SortByOwner);\r
-}\r
-\r
-void DolphinMainWindow::sortByGroup()\r
-{\r
-    m_activeView->setSorting(DolphinView::SortByGroup);\r
-}\r
-\r
-void DolphinMainWindow::toggleSortOrder()\r
-{\r
-    const Qt::SortOrder order = (m_activeView->sortOrder() == Qt::Ascending) ?\r
-                                Qt::Descending :\r
-                                Qt::Ascending;\r
-    m_activeView->setSortOrder(order);\r
-}\r
-\r
-void DolphinMainWindow::toggleSplitView()\r
-{\r
-    if (m_view[SecondaryIdx] == 0) {\r
-        const int newWidth = (m_view[PrimaryIdx]->width() - m_splitter->handleWidth()) / 2;\r
-        // create a secondary view\r
-        m_view[SecondaryIdx] = new DolphinView(this,\r
-                                               0,\r
-                                               m_view[PrimaryIdx]->url(),\r
-                                               m_view[PrimaryIdx]->mode(),\r
-                                               m_view[PrimaryIdx]->showHiddenFiles());\r
-        connectViewSignals(SecondaryIdx);\r
-        m_splitter->addWidget(m_view[SecondaryIdx]);\r
-        m_splitter->setSizes(QList<int>() << newWidth << newWidth);\r
-        m_view[SecondaryIdx]->show();\r
-    }\r
-    else {\r
-        // remove secondary view\r
-        if (m_activeView == m_view[PrimaryIdx]) {\r
-            m_view[SecondaryIdx]->close();\r
-            m_view[SecondaryIdx]->deleteLater();\r
-            m_view[SecondaryIdx] = 0;\r
-            setActiveView(m_view[PrimaryIdx]);\r
-        }\r
-        else {\r
-            // The secondary view is active, hence from the users point of view\r
-            // the content of the secondary view should be moved to the primary view.\r
-            // From an implementation point of view it is more efficient to close\r
-            // the primary view and exchange the internal pointers afterwards.\r
-            m_view[PrimaryIdx]->close();\r
-            delete m_view[PrimaryIdx];\r
-            m_view[PrimaryIdx] = m_view[SecondaryIdx];\r
-            m_view[SecondaryIdx] = 0;\r
-            setActiveView(m_view[PrimaryIdx]);\r
-        }\r
-    }\r
-    emit activeViewChanged();\r
-}\r
-\r
-void DolphinMainWindow::reloadView()\r
-{\r
-    clearStatusBar();\r
-    m_activeView->reload();\r
-}\r
-\r
-void DolphinMainWindow::stopLoading()\r
-{\r
-}\r
-\r
-void DolphinMainWindow::togglePreview()\r
-{\r
-    clearStatusBar();\r
-\r
-    const KToggleAction* showPreviewAction =\r
-        static_cast<KToggleAction*>(actionCollection()->action("show_preview"));\r
-    const bool show = showPreviewAction->isChecked();\r
-    m_activeView->setShowPreview(show);\r
-}\r
-\r
-void DolphinMainWindow::toggleShowHiddenFiles()\r
-{\r
-    clearStatusBar();\r
-\r
-    const KToggleAction* showHiddenFilesAction =\r
-        static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));\r
-    const bool show = showHiddenFilesAction->isChecked();\r
-    m_activeView->setShowHiddenFiles(show);\r
-}\r
-\r
-void DolphinMainWindow::showFilterBar()\r
-{\r
-    const KToggleAction* showFilterBarAction =\r
-        static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));\r
-    const bool show = showFilterBarAction->isChecked();\r
-    m_activeView->showFilterBar(show);\r
-}\r
-\r
-void DolphinMainWindow::zoomIn()\r
-{\r
-    m_activeView->zoomIn();\r
-    updateViewActions();\r
-}\r
-\r
-void DolphinMainWindow::zoomOut()\r
-{\r
-    m_activeView->zoomOut();\r
-    updateViewActions();\r
-}\r
-\r
-void DolphinMainWindow::toggleEditLocation()\r
-{\r
-    clearStatusBar();\r
-\r
-    KToggleAction* action = static_cast<KToggleAction*>(actionCollection()->action("editable_location"));\r
-\r
-    bool editOrBrowse = action->isChecked();\r
-    m_activeView->setUrlEditable(editOrBrowse);\r
-}\r
-\r
-void DolphinMainWindow::editLocation()\r
-{\r
-    m_activeView->setUrlEditable(true);\r
-}\r
-\r
-void DolphinMainWindow::adjustViewProperties()\r
-{\r
-    clearStatusBar();\r
-    ViewPropertiesDialog dlg(m_activeView);\r
-    dlg.exec();\r
-}\r
-\r
-void DolphinMainWindow::goBack()\r
-{\r
-    clearStatusBar();\r
-    m_activeView->goBack();\r
-}\r
-\r
-void DolphinMainWindow::goForward()\r
-{\r
-    clearStatusBar();\r
-    m_activeView->goForward();\r
-}\r
-\r
-void DolphinMainWindow::goUp()\r
-{\r
-    clearStatusBar();\r
-    m_activeView->goUp();\r
-}\r
-\r
-void DolphinMainWindow::goHome()\r
-{\r
-    clearStatusBar();\r
-    m_activeView->goHome();\r
-}\r
-\r
-void DolphinMainWindow::openTerminal()\r
-{\r
-    QString command("konsole --workdir \"");\r
-    command.append(m_activeView->url().path());\r
-    command.append('\"');\r
-\r
-    KRun::runCommand(command, "Konsole", "konsole");\r
-}\r
-\r
-void DolphinMainWindow::findFile()\r
-{\r
-    KRun::run("kfind", m_activeView->url());\r
-}\r
-\r
-void DolphinMainWindow::compareFiles()\r
-{\r
-    // The method is only invoked if exactly 2 files have\r
-    // been selected. The selected files may be:\r
-    // - both in the primary view\r
-    // - both in the secondary view\r
-    // - one in the primary view and the other in the secondary\r
-    //   view\r
-    assert(m_view[PrimaryIdx] != 0);\r
-\r
-    KUrl urlA;\r
-    KUrl urlB;\r
-    KUrl::List urls = m_view[PrimaryIdx]->selectedUrls();\r
-\r
-    switch (urls.count()) {\r
-        case 0: {\r
-            assert(m_view[SecondaryIdx] != 0);\r
-            urls = m_view[SecondaryIdx]->selectedUrls();\r
-            assert(urls.count() == 2);\r
-            urlA = urls[0];\r
-            urlB = urls[1];\r
-            break;\r
-        }\r
-\r
-        case 1: {\r
-            urlA = urls[0];\r
-            assert(m_view[SecondaryIdx] != 0);\r
-            urls = m_view[SecondaryIdx]->selectedUrls();\r
-            assert(urls.count() == 1);\r
-            urlB = urls[0];\r
-            break;\r
-        }\r
-\r
-        case 2: {\r
-            urlA = urls[0];\r
-            urlB = urls[1];\r
-            break;\r
-        }\r
-\r
-        default: {\r
-            // may not happen: compareFiles may only get invoked if 2\r
-            // files are selected\r
-            assert(false);\r
-        }\r
-    }\r
-\r
-    QString command("kompare -c \"");\r
-    command.append(urlA.pathOrUrl());\r
-    command.append("\" \"");\r
-    command.append(urlB.pathOrUrl());\r
-    command.append('\"');\r
-    KRun::runCommand(command, "Kompare", "kompare");\r
-\r
-}\r
-\r
-void DolphinMainWindow::editSettings()\r
-{\r
-    // TODO: make a static method for opening the settings dialog\r
-    DolphinSettingsDialog dlg(this);\r
-    dlg.exec();\r
-}\r
-\r
-void DolphinMainWindow::init()\r
-{\r
-    // Check whether Dolphin runs the first time. If yes then\r
-    // a proper default window size is given at the end of DolphinMainWindow::init().\r
-    GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings();\r
-    const bool firstRun = generalSettings->firstRun();\r
-    if (firstRun) {\r
-        generalSettings->setViewPropsTimestamp(QDateTime::currentDateTime());\r
-    }\r
-\r
-    setAcceptDrops(true);\r
-\r
-    m_splitter = new QSplitter(this);\r
-\r
-    DolphinSettings& settings = DolphinSettings::instance();\r
-\r
-    KBookmarkManager* manager = settings.bookmarkManager();\r
-    assert(manager != 0);\r
-    KBookmarkGroup root = manager->root();\r
-    if (root.first().isNull()) {\r
-        root.addBookmark(manager, i18n("Home"), settings.generalSettings()->homeUrl(), "folder_home");\r
-        root.addBookmark(manager, i18n("Storage Media"), KUrl("media:/"), "blockdevice");\r
-        root.addBookmark(manager, i18n("Network"), KUrl("remote:/"), "network_local");\r
-        root.addBookmark(manager, i18n("Root"), KUrl("/"), "folder_red");\r
-        root.addBookmark(manager, i18n("Trash"), KUrl("trash:/"), "trashcan_full");\r
-    }\r
-\r
-    setupActions();\r
-\r
-    const KUrl& homeUrl = root.first().url();\r
-    setCaption(homeUrl.fileName());\r
-    ViewProperties props(homeUrl);\r
-    m_view[PrimaryIdx] = new DolphinView(this,\r
-                                         m_splitter,\r
-                                         homeUrl,\r
-                                         props.viewMode(),\r
-                                         props.showHiddenFiles());\r
-    connectViewSignals(PrimaryIdx);\r
-    m_view[PrimaryIdx]->show();\r
-\r
-    m_activeView = m_view[PrimaryIdx];\r
-\r
-    setCentralWidget(m_splitter);\r
-    setupDockWidgets();\r
-\r
-    setupGUI(Keys|Save|Create|ToolBar);\r
-    createGUI();\r
-\r
-    stateChanged("new_file");\r
-    setAutoSaveSettings();\r
-\r
-    QClipboard* clipboard = QApplication::clipboard();\r
-    connect(clipboard, SIGNAL(dataChanged()),\r
-            this, SLOT(updatePasteAction()));\r
-    updatePasteAction();\r
-    updateGoActions();\r
-\r
-    loadSettings();\r
-\r
-    if (firstRun) {\r
-        // assure a proper default size if Dolphin runs the first time\r
-        resize(640, 480);\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::loadSettings()\r
-{\r
-    GeneralSettings* settings = DolphinSettings::instance().generalSettings();\r
-\r
-    KToggleAction* splitAction = static_cast<KToggleAction*>(actionCollection()->action("split_view"));\r
-    if (settings->splitView()) {\r
-        splitAction->setChecked(true);\r
-        toggleSplitView();\r
-    }\r
-\r
-    updateViewActions();\r
-\r
-    // TODO: I assume there will be a generic way in KDE 4 to restore the docks\r
-    // of the main window. In the meantime they are restored manually (see also\r
-    // DolphinMainWindow::closeEvent() for more details):\r
-    QString filename = KStandardDirs::locateLocal("data", KGlobal::mainComponent().componentName());   filename.append("/panels_layout");\r
-    QFile file(filename);\r
-    if (file.open(QIODevice::ReadOnly)) {\r
-        QByteArray data = file.readAll();\r
-        restoreState(data);\r
-        file.close();\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::setupActions()\r
-{\r
-    // setup 'File' menu\r
-    m_newMenu = new DolphinNewMenu(this);\r
-    KMenu* menu = m_newMenu->menu();\r
-    menu->setTitle(i18n("Create New..."));\r
-    menu->setIcon(SmallIcon("filenew"));\r
-    connect(menu, SIGNAL(aboutToShow()),\r
-            this, SLOT(updateNewMenu()));\r
-\r
-    QAction* action = actionCollection()->addAction("new_window");\r
-    action->setIcon(KIcon("window_new"));\r
-    action->setText(i18n("New &Window"));\r
-    connect(action, SIGNAL(triggered()), this, SLOT(openNewMainWindow()));\r
-\r
-    QAction* rename = actionCollection()->addAction("rename");\r
-    rename->setText(i18n("Rename"));\r
-    rename->setShortcut(Qt::Key_F2);\r
-    connect(rename, SIGNAL(triggered()), this, SLOT(rename()));\r
-\r
-    QAction* moveToTrash = actionCollection()->addAction("move_to_trash");\r
-    moveToTrash->setText(i18n("Move to Trash"));\r
-    moveToTrash->setIcon(KIcon("edittrash"));\r
-    moveToTrash->setShortcut(QKeySequence::Delete);\r
-    connect(moveToTrash, SIGNAL(triggered()), this, SLOT(moveToTrash()));\r
-\r
-    QAction* deleteAction = actionCollection()->addAction("delete");\r
-    deleteAction->setText(i18n("Delete"));\r
-    deleteAction->setShortcut(Qt::ALT | Qt::Key_Delete);\r
-    deleteAction->setIcon(KIcon("editdelete"));\r
-    connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteItems()));\r
-\r
-    QAction* properties = actionCollection()->addAction("properties");\r
-    properties->setText(i18n("Properties"));\r
-    properties->setShortcut(Qt::ALT | Qt::Key_Return);\r
-    connect(properties, SIGNAL(triggered()), this, SLOT(properties()));\r
-\r
-    KStandardAction::quit(this, SLOT(quit()), actionCollection());\r
-\r
-    // setup 'Edit' menu\r
-    KStandardAction::undo(this,\r
-                          SLOT(undo()),\r
-                          actionCollection());\r
-\r
-    KStandardAction::cut(this, SLOT(cut()), actionCollection());\r
-    KStandardAction::copy(this, SLOT(copy()), actionCollection());\r
-    KStandardAction::paste(this, SLOT(paste()), actionCollection());\r
-\r
-    QAction* selectAll = actionCollection()->addAction("select_all");\r
-    selectAll->setText(i18n("Select All"));\r
-    selectAll->setShortcut(Qt::CTRL + Qt::Key_A);\r
-    connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAll()));\r
-\r
-    QAction* invertSelection = actionCollection()->addAction("invert_selection");\r
-    invertSelection->setText(i18n("Invert Selection"));\r
-    invertSelection->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_A);\r
-    connect(invertSelection, SIGNAL(triggered()), this, SLOT(invertSelection()));\r
-\r
-    // setup 'View' menu\r
-    KStandardAction::zoomIn(this,\r
-                       SLOT(zoomIn()),\r
-                       actionCollection());\r
-\r
-    KStandardAction::zoomOut(this,\r
-                        SLOT(zoomOut()),\r
-                        actionCollection());\r
-\r
-    KToggleAction* iconsView = actionCollection()->add<KToggleAction>("icons");\r
-    iconsView->setText(i18n("Icons"));\r
-    iconsView->setShortcut(Qt::CTRL | Qt::Key_1);\r
-    iconsView->setIcon(KIcon("view_icon"));\r
-    connect(iconsView, SIGNAL(triggered()), this, SLOT(setIconsView()));\r
-\r
-    KToggleAction* detailsView = actionCollection()->add<KToggleAction>("details");\r
-    detailsView->setText(i18n("Details"));\r
-    detailsView->setShortcut(Qt::CTRL | Qt::Key_2);\r
-    detailsView->setIcon(KIcon("view_text"));\r
-    connect(detailsView, SIGNAL(triggered()), this, SLOT(setDetailsView()));\r
-\r
-    QActionGroup* viewModeGroup = new QActionGroup(this);\r
-    viewModeGroup->addAction(iconsView);\r
-    viewModeGroup->addAction(detailsView);\r
-\r
-    KToggleAction* sortByName = actionCollection()->add<KToggleAction>("by_name");\r
-    sortByName->setText(i18n("By Name"));\r
-    connect(sortByName, SIGNAL(triggered()), this, SLOT(sortByName()));\r
-\r
-    KToggleAction* sortBySize = actionCollection()->add<KToggleAction>("by_size");\r
-    sortBySize->setText(i18n("By Size"));\r
-    connect(sortBySize, SIGNAL(triggered()), this, SLOT(sortBySize()));\r
-\r
-    KToggleAction* sortByDate = actionCollection()->add<KToggleAction>("by_date");\r
-    sortByDate->setText(i18n("By Date"));\r
-    connect(sortByDate, SIGNAL(triggered()), this, SLOT(sortByDate()));\r
-\r
-    KToggleAction* sortByPermissions = actionCollection()->add<KToggleAction>("by_permissions");\r
-    sortByPermissions->setText(i18n("By Permissions"));\r
-    connect(sortByPermissions, SIGNAL(triggered()), this, SLOT(sortByPermissions()));\r
-\r
-    KToggleAction* sortByOwner = actionCollection()->add<KToggleAction>("by_owner");\r
-    sortByOwner->setText(i18n("By Owner"));\r
-    connect(sortByOwner, SIGNAL(triggered()), this, SLOT(sortByOwner()));\r
-\r
-    KToggleAction* sortByGroup = actionCollection()->add<KToggleAction>("by_group");\r
-    sortByGroup->setText(i18n("By Group"));\r
-    connect(sortByGroup, SIGNAL(triggered()), this, SLOT(sortByGroup()));\r
-\r
-    QActionGroup* sortGroup = new QActionGroup(this);\r
-    sortGroup->addAction(sortByName);\r
-    sortGroup->addAction(sortBySize);\r
-    sortGroup->addAction(sortByDate);\r
-    sortGroup->addAction(sortByPermissions);\r
-    sortGroup->addAction(sortByOwner);\r
-    sortGroup->addAction(sortByGroup);\r
-\r
-    KToggleAction* sortDescending = actionCollection()->add<KToggleAction>("descending");\r
-    sortDescending->setText(i18n("Descending"));\r
-    connect(sortDescending, SIGNAL(triggered()), this, SLOT(toggleSortOrder()));\r
-\r
-    KToggleAction* showPreview = actionCollection()->add<KToggleAction>("show_preview");\r
-    showPreview->setText(i18n("Show Preview"));\r
-    connect(showPreview, SIGNAL(triggered()), this, SLOT(togglePreview()));\r
-\r
-    KToggleAction* showHiddenFiles = actionCollection()->add<KToggleAction>("show_hidden_files");\r
-    showHiddenFiles->setText(i18n("Show Hidden Files"));\r
-    showHiddenFiles->setShortcut(Qt::ALT | Qt::Key_Period);\r
-    connect(showHiddenFiles, SIGNAL(triggered()), this, SLOT(toggleShowHiddenFiles()));\r
-\r
-    KToggleAction* split = actionCollection()->add<KToggleAction>("split_view");\r
-    split->setText(i18n("Split View"));\r
-    split->setShortcut(Qt::Key_F10);\r
-    split->setIcon(KIcon("view_left_right"));\r
-    connect(split, SIGNAL(triggered()), this, SLOT(toggleSplitView()));\r
-\r
-    QAction* reload = actionCollection()->addAction("reload");\r
-    reload->setText(i18n("Reload"));\r
-    reload->setShortcut(Qt::Key_F5);\r
-    reload->setIcon(KIcon("reload"));\r
-    connect(reload, SIGNAL(triggered()), this, SLOT(reloadView()));\r
-\r
-    QAction* stop = actionCollection()->addAction("stop");\r
-    stop->setText(i18n("Stop"));\r
-    stop->setIcon(KIcon("stop"));\r
-    connect(stop, SIGNAL(triggered()), this, SLOT(stopLoading()));\r
-\r
-    // TODO: the URL navigator must emit a signal if the editable state has been\r
-    // changed, so that the corresponding showFullLocation action is updated. Also\r
-    // the naming "Show full Location" is currently confusing...\r
-    KToggleAction* showFullLocation = actionCollection()->add<KToggleAction>("editable_location");\r
-    showFullLocation->setText(i18n("Show Full Location"));\r
-    showFullLocation->setShortcut(Qt::CTRL | Qt::Key_L);\r
-    connect(showFullLocation, SIGNAL(triggered()), this, SLOT(toggleEditLocation()));\r
-\r
-    QAction* editLocation = actionCollection()->addAction("edit_location");\r
-    editLocation->setText(i18n("Edit Location"));\r
-    editLocation->setShortcut(Qt::Key_F6);\r
-    connect(editLocation, SIGNAL(triggered()), this, SLOT(editLocation()));\r
-\r
-    QAction* adjustViewProps = actionCollection()->addAction("view_properties");\r
-    adjustViewProps->setText(i18n("Adjust View Properties..."));\r
-    connect(adjustViewProps, SIGNAL(triggered()), this, SLOT(adjustViewProperties()));\r
-\r
-    // setup 'Go' menu\r
-    KStandardAction::back(this, SLOT(goBack()), actionCollection());\r
-    KStandardAction::forward(this, SLOT(goForward()), actionCollection());\r
-    KStandardAction::up(this, SLOT(goUp()), actionCollection());\r
-    KStandardAction::home(this, SLOT(goHome()), actionCollection());\r
-\r
-    // setup 'Tools' menu\r
-    QAction* openTerminal = actionCollection()->addAction("open_terminal");\r
-    openTerminal->setText(i18n("Open Terminal"));\r
-    openTerminal->setShortcut(Qt::Key_F4);\r
-    openTerminal->setIcon(KIcon("konsole"));\r
-    connect(openTerminal, SIGNAL(triggered()), this, SLOT(openTerminal()));\r
-\r
-    QAction* findFile = actionCollection()->addAction("find_file");\r
-    findFile->setText(i18n("Find File..."));\r
-    findFile->setShortcut(Qt::Key_F);\r
-    findFile->setIcon(KIcon("filefind"));\r
-    connect(findFile, SIGNAL(triggered()), this, SLOT(findFile()));\r
-\r
-    KToggleAction* showFilterBar = actionCollection()->add<KToggleAction>("show_filter_bar");\r
-    showFilterBar->setText(i18n("Show Filter Bar"));\r
-    showFilterBar->setShortcut(Qt::Key_Slash);\r
-    connect(showFilterBar, SIGNAL(triggered()), this, SLOT(showFilterBar()));\r
-\r
-    QAction* compareFiles = actionCollection()->addAction("compare_files");\r
-    compareFiles->setText(i18n("Compare Files"));\r
-    compareFiles->setIcon(KIcon("kompare"));\r
-    compareFiles->setEnabled(false);\r
-    connect(compareFiles, SIGNAL(triggered()), this, SLOT(compareFiles()));\r
-\r
-    // setup 'Settings' menu\r
-    KStandardAction::preferences(this, SLOT(editSettings()), actionCollection());\r
-}\r
-\r
-void DolphinMainWindow::setupDockWidgets()\r
-{\r
-    QDockWidget* shortcutsDock = new QDockWidget(i18n("Bookmarks"));\r
-    shortcutsDock->setObjectName("bookmarksDock");\r
-    shortcutsDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);\r
-    shortcutsDock->setWidget(new BookmarksSidebarPage(this));\r
-\r
-    shortcutsDock->toggleViewAction()->setText(i18n("Show Bookmarks Panel"));\r
-    actionCollection()->addAction("show_bookmarks_panel", shortcutsDock->toggleViewAction());\r
-\r
-    addDockWidget(Qt::LeftDockWidgetArea, shortcutsDock);\r
-\r
-    QDockWidget* infoDock = new QDockWidget(i18n("Information"));\r
-    infoDock->setObjectName("infoDock");\r
-    infoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);\r
-    infoDock->setWidget(new InfoSidebarPage(this));\r
-\r
-    infoDock->toggleViewAction()->setText(i18n("Show Information Panel"));\r
-    actionCollection()->addAction("show_info_panel", infoDock->toggleViewAction());\r
-\r
-    addDockWidget(Qt::RightDockWidgetArea, infoDock);\r
-}\r
-\r
-void DolphinMainWindow::updateHistory()\r
-{\r
-    int index = 0;\r
-    const QLinkedList<UrlNavigator::HistoryElem> list = m_activeView->urlHistory(index);\r
-\r
-    QAction* backAction = actionCollection()->action("go_back");\r
-    if (backAction != 0) {\r
-        backAction->setEnabled(index < static_cast<int>(list.count()) - 1);\r
-    }\r
-\r
-    QAction* forwardAction = actionCollection()->action("go_forward");\r
-    if (forwardAction != 0) {\r
-        forwardAction->setEnabled(index > 0);\r
-    }\r
-}\r
-\r
-void DolphinMainWindow::updateEditActions()\r
-{\r
-    const KFileItemList list = m_activeView->selectedItems();\r
-    if (list.isEmpty()) {\r
-        stateChanged("has_no_selection");\r
-    }\r
-    else {\r
-        stateChanged("has_selection");\r
-\r
-        QAction* renameAction = actionCollection()->action("rename");\r
-        if (renameAction != 0) {\r
-            renameAction->setEnabled(list.count() >= 1);\r
-        }\r
-\r
-        bool enableMoveToTrash = true;\r
-\r
-        KFileItemList::const_iterator it = list.begin();\r
-        const KFileItemList::const_iterator end = list.end();\r
-        while (it != end) {\r
-            KFileItem* item = *it;\r
-            const KUrl& url = item->url();\r
-            // only enable the 'Move to Trash' action for local files\r
-            if (!url.isLocalFile()) {\r
-                enableMoveToTrash = false;\r
-            }\r
-            ++it;\r
-        }\r
-\r
-        QAction* moveToTrashAction = actionCollection()->action("move_to_trash");\r
-        moveToTrashAction->setEnabled(enableMoveToTrash);\r
-    }\r
-    updatePasteAction();\r
-}\r
-\r
-void DolphinMainWindow::updateViewActions()\r
-{\r
-    QAction* zoomInAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::ZoomIn));\r
-    if (zoomInAction != 0) {\r
-        zoomInAction->setEnabled(m_activeView->isZoomInPossible());\r
-    }\r
-\r
-    QAction* zoomOutAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::ZoomOut));\r
-    if (zoomOutAction != 0) {\r
-        zoomOutAction->setEnabled(m_activeView->isZoomOutPossible());\r
-    }\r
-\r
-    QAction* action = 0;\r
-    switch (m_activeView->mode()) {\r
-        case DolphinView::IconsView:\r
-            action = actionCollection()->action("icons");\r
-            break;\r
-        case DolphinView::DetailsView:\r
-            action = actionCollection()->action("details");\r
-            break;\r
-        default:\r
-            break;\r
-    }\r
-\r
-    if (action != 0) {\r
-        KToggleAction* toggleAction = static_cast<KToggleAction*>(action);\r
-        toggleAction->setChecked(true);\r
-    }\r
-\r
-    slotSortingChanged(m_activeView->sorting());\r
-    slotSortOrderChanged(m_activeView->sortOrder());\r
-\r
-    KToggleAction* showFilterBarAction =\r
-        static_cast<KToggleAction*>(actionCollection()->action("show_filter_bar"));\r
-    showFilterBarAction->setChecked(m_activeView->isFilterBarVisible());\r
-\r
-    KToggleAction* showHiddenFilesAction =\r
-        static_cast<KToggleAction*>(actionCollection()->action("show_hidden_files"));\r
-    showHiddenFilesAction->setChecked(m_activeView->showHiddenFiles());\r
-\r
-    KToggleAction* splitAction = static_cast<KToggleAction*>(actionCollection()->action("split_view"));\r
-    splitAction->setChecked(m_view[SecondaryIdx] != 0);\r
-\r
-    KToggleAction* editableLocactionAction =\r
-        static_cast<KToggleAction*>(actionCollection()->action("editable_location"));\r
-    editableLocactionAction->setChecked(m_activeView->isUrlEditable());\r
-}\r
-\r
-void DolphinMainWindow::updateGoActions()\r
-{\r
-    QAction* goUpAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Up));\r
-    const KUrl& currentUrl = m_activeView->url();\r
-    goUpAction->setEnabled(currentUrl.upUrl() != currentUrl);\r
-}\r
-\r
-void DolphinMainWindow::copyUrls(const KUrl::List& source, const KUrl& dest)\r
-{\r
-    KonqOperations::copy(this, KonqOperations::COPY, source, dest);\r
-    m_undoOperations.append(KonqOperations::COPY);\r
-}\r
-\r
-void DolphinMainWindow::moveUrls(const KUrl::List& source, const KUrl& dest)\r
-{\r
-    KonqOperations::copy(this, KonqOperations::MOVE, source, dest);\r
-    m_undoOperations.append(KonqOperations::MOVE);\r
-}\r
-\r
-void DolphinMainWindow::linkUrls(const KUrl::List& source, const KUrl& dest)\r
-{\r
-    KonqOperations::copy(this, KonqOperations::LINK, source, dest);\r
-    m_undoOperations.append(KonqOperations::LINK);\r
-}\r
-\r
-void DolphinMainWindow::clearStatusBar()\r
-{\r
-    m_activeView->statusBar()->clear();\r
-}\r
-\r
-void DolphinMainWindow::connectViewSignals(int viewIndex)\r
-{\r
-    DolphinView* view = m_view[viewIndex];\r
-    connect(view, SIGNAL(modeChanged()),\r
-            this, SLOT(slotViewModeChanged()));\r
-    connect(view, SIGNAL(showHiddenFilesChanged()),\r
-            this, SLOT(slotShowHiddenFilesChanged()));\r
-    connect(view, SIGNAL(sortingChanged(DolphinView::Sorting)),\r
-            this, SLOT(slotSortingChanged(DolphinView::Sorting)));\r
-    connect(view, SIGNAL(sortOrderChanged(Qt::SortOrder)),\r
-            this, SLOT(slotSortOrderChanged(Qt::SortOrder)));\r
-    connect(view, SIGNAL(selectionChanged()),\r
-            this, SLOT(slotSelectionChanged()));\r
-    connect(view, SIGNAL(showFilterBarChanged(bool)),\r
-            this, SLOT(updateFilterBarAction(bool)));\r
-\r
-    const UrlNavigator* navigator = view->urlNavigator();\r
-    connect(navigator, SIGNAL(urlChanged(const KUrl&)),\r
-            this, SLOT(slotUrlChanged(const KUrl&)));\r
-    connect(navigator, SIGNAL(historyChanged()),\r
-            this, SLOT(slotHistoryChanged()));\r
-\r
-}\r
-\r
-DolphinMainWindow::UndoUiInterface::UndoUiInterface(DolphinMainWindow* mainWin) :\r
-    KonqUndoManager::UiInterface(mainWin),\r
-    m_mainWin(mainWin)\r
-{\r
-    assert(m_mainWin != 0);\r
-}\r
-\r
-DolphinMainWindow::UndoUiInterface::~UndoUiInterface()\r
-{\r
-}\r
-\r
-void DolphinMainWindow::UndoUiInterface::jobError(KIO::Job* job)\r
-{\r
-    DolphinStatusBar* statusBar = m_mainWin->activeView()->statusBar();\r
-    statusBar->setMessage(job->errorString(), DolphinStatusBar::Error);\r
-}\r
-\r
-#include "dolphinmainwindow.moc"\r
+/***************************************************************************
+ *   Copyright (C) 2006 by Peter Penz <peter.penz19@gmail.com>             *
+ *   Copyright (C) 2006 by Stefan Monov <logixoul@gmail.com>               *
+ *   Copyright (C) 2006 by Cvetoslav Ludmiloff <ludmiloff@gmail.com>       *
+ *                                                                         *
+ *   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 "dolphinmainwindow.h"
+
+#include "dolphinmainwindowadaptor.h"
+#include "config-terminal.h"
+#include "global.h"
+#include "dolphinbookmarkhandler.h"
+#include "dolphindockwidget.h"
+#include "dolphincontextmenu.h"
+#include "dolphinnewfilemenu.h"
+#include "dolphinrecenttabsmenu.h"
+#include "dolphinviewcontainer.h"
+#include "dolphintabpage.h"
+#include "middleclickactioneventfilter.h"
+#include "panels/folders/folderspanel.h"
+#include "panels/places/placesitemmodel.h"
+#include "panels/places/placespanel.h"
+#include "panels/information/informationpanel.h"
+#include "panels/terminal/terminalpanel.h"
+#include "settings/dolphinsettingsdialog.h"
+#include "statusbar/dolphinstatusbar.h"
+#include "views/dolphinviewactionhandler.h"
+#include "views/dolphinremoteencoding.h"
+#include "views/draganddrophelper.h"
+#include "views/viewproperties.h"
+#include "views/dolphinnewfilemenuobserver.h"
+#include "dolphin_generalsettings.h"
+
+#include <KActionCollection>
+#include <KActionMenu>
+#include <KAuthorized>
+#include <KConfig>
+#include <KConfigGui>
+#include <KDualAction>
+#include <KFileItemListProperties>
+#include <KHelpMenu>
+#include <KIO/CommandLauncherJob>
+#include <KIO/JobUiDelegate>
+#include <KIO/OpenFileManagerWindowJob>
+#include <KJobWidgets>
+#include <KLocalizedString>
+#include <KMessageBox>
+#include <KNS3/KMoreToolsMenuFactory>
+#include <KProtocolInfo>
+#include <KProtocolManager>
+#include <KRun>
+#include <KShell>
+#include <KStandardAction>
+#include <KStartupInfo>
+#include <KToggleAction>
+#include <KToolBar>
+#include <KToolBarPopupAction>
+#include <KToolInvocation>
+#include <KUrlComboBox>
+#include <KUrlNavigator>
+#include <KWindowSystem>
+
+#include <QApplication>
+#include <QClipboard>
+#include <QCloseEvent>
+#include <QDesktopServices>
+#include <QDialog>
+#include <QFileInfo>
+#include <QLineEdit>
+#include <QMenu>
+#include <QMenuBar>
+#include <QPushButton>
+#include <QShowEvent>
+#include <QStandardPaths>
+#include <QTimer>
+#include <QToolButton>
+#include <QWhatsThisClickedEvent>
+
+namespace {
+    // Used for GeneralSettings::version() to determine whether
+    // an updated version of Dolphin is running.
+    const int CurrentDolphinVersion = 200;
+    // The maximum number of entries in the back/forward popup menu
+    const int MaxNumberOfNavigationentries = 12;
+    // The maximum number of "Activate Tab" shortcuts
+    const int MaxActivateTabShortcuts = 9;
+}
+
+DolphinMainWindow::DolphinMainWindow() :
+    KXmlGuiWindow(nullptr),
+    m_newFileMenu(nullptr),
+    m_helpMenu(nullptr),
+    m_tabWidget(nullptr),
+    m_activeViewContainer(nullptr),
+    m_actionHandler(nullptr),
+    m_remoteEncoding(nullptr),
+    m_settingsDialog(),
+    m_bookmarkHandler(nullptr),
+    m_controlButton(nullptr),
+    m_updateToolBarTimer(nullptr),
+    m_lastHandleUrlStatJob(nullptr),
+    m_terminalPanel(nullptr),
+    m_placesPanel(nullptr),
+    m_tearDownFromPlacesRequested(false),
+    m_backAction(nullptr),
+    m_forwardAction(nullptr)
+{
+    Q_INIT_RESOURCE(dolphin);
+
+    new MainWindowAdaptor(this);
+
+#ifndef Q_OS_WIN
+       setWindowFlags(Qt::WindowContextHelpButtonHint);
+#endif
+    setComponentName(QStringLiteral("dolphin"), QGuiApplication::applicationDisplayName());
+    setObjectName(QStringLiteral("Dolphin#"));
+
+    connect(&DolphinNewFileMenuObserver::instance(), &DolphinNewFileMenuObserver::errorMessage,
+            this, &DolphinMainWindow::showErrorMessage);
+
+    KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
+    undoManager->setUiInterface(new UndoUiInterface());
+
+    connect(undoManager, QOverload<bool>::of(&KIO::FileUndoManager::undoAvailable),
+            this, &DolphinMainWindow::slotUndoAvailable);
+    connect(undoManager, &KIO::FileUndoManager::undoTextChanged,
+            this, &DolphinMainWindow::slotUndoTextChanged);
+    connect(undoManager, &KIO::FileUndoManager::jobRecordingStarted,
+            this, &DolphinMainWindow::clearStatusBar);
+    connect(undoManager, &KIO::FileUndoManager::jobRecordingFinished,
+            this, &DolphinMainWindow::showCommand);
+
+    GeneralSettings* generalSettings = GeneralSettings::self();
+    const bool firstRun = (generalSettings->version() < 200);
+    if (firstRun) {
+        generalSettings->setViewPropsTimestamp(QDateTime::currentDateTime());
+    }
+
+    setAcceptDrops(true);
+
+    m_tabWidget = new DolphinTabWidget(this);
+    m_tabWidget->setObjectName("tabWidget");
+    connect(m_tabWidget, &DolphinTabWidget::activeViewChanged,
+            this, &DolphinMainWindow::activeViewChanged);
+    connect(m_tabWidget, &DolphinTabWidget::tabCountChanged,
+            this, &DolphinMainWindow::tabCountChanged);
+    connect(m_tabWidget, &DolphinTabWidget::currentUrlChanged,
+            this, &DolphinMainWindow::updateWindowTitle);
+    setCentralWidget(m_tabWidget);
+
+    setupActions();
+
+    m_actionHandler = new DolphinViewActionHandler(actionCollection(), this);
+    connect(m_actionHandler, &DolphinViewActionHandler::actionBeingHandled, this, &DolphinMainWindow::clearStatusBar);
+    connect(m_actionHandler, &DolphinViewActionHandler::createDirectoryTriggered, this, &DolphinMainWindow::createDirectory);
+
+    m_remoteEncoding = new DolphinRemoteEncoding(this, m_actionHandler);
+    connect(this, &DolphinMainWindow::urlChanged,
+            m_remoteEncoding, &DolphinRemoteEncoding::slotAboutToOpenUrl);
+
+    setupDockWidgets();
+
+    setupGUI(Keys | Save | Create | ToolBar);
+    stateChanged(QStringLiteral("new_file"));
+
+    QClipboard* clipboard = QApplication::clipboard();
+    connect(clipboard, &QClipboard::dataChanged,
+            this, &DolphinMainWindow::updatePasteAction);
+
+    QAction* showFilterBarAction = actionCollection()->action(QStringLiteral("show_filter_bar"));
+    showFilterBarAction->setChecked(generalSettings->filterBar());
+
+    if (firstRun) {
+        menuBar()->setVisible(false);
+        // Assure a proper default size if Dolphin runs the first time
+        resize(750, 500);
+    }
+
+    const bool showMenu = !menuBar()->isHidden();
+    QAction* showMenuBarAction = actionCollection()->action(KStandardAction::name(KStandardAction::ShowMenubar));
+    showMenuBarAction->setChecked(showMenu);  // workaround for bug #171080
+    if (!showMenu) {
+        createControlButton();
+    }
+
+    // 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);
+    toolBar()->installEventFilter(middleClickEventFilter);
+
+    setupWhatsThis();
+
+    QTimer::singleShot(0, this, &DolphinMainWindow::setupUpdateOpenPreferredSearchToolAction);
+}
+
+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();
+    }
+    return viewContainers;
+}
+
+void DolphinMainWindow::openDirectories(const QList<QUrl>& dirs, bool splitView)
+{
+    m_tabWidget->openDirectories(dirs, splitView);
+}
+
+void DolphinMainWindow::openDirectories(const QStringList& dirs, bool splitView)
+{
+    openDirectories(QUrl::fromStringList(dirs), splitView);
+}
+
+void DolphinMainWindow::openFiles(const QList<QUrl>& files, bool splitView)
+{
+    m_tabWidget->openFiles(files, splitView);
+}
+
+void DolphinMainWindow::openFiles(const QStringList& files, bool splitView)
+{
+    openFiles(QUrl::fromStringList(files), splitView);
+}
+
+void DolphinMainWindow::activateWindow()
+{
+    window()->setAttribute(Qt::WA_NativeWindow, true);
+    KStartupInfo::setNewStartupId(window()->windowHandle(), KStartupInfo::startupId());
+    KWindowSystem::activateWindow(window()->effectiveWinId());
+}
+
+void DolphinMainWindow::showCommand(CommandType command)
+{
+    DolphinStatusBar* statusBar = m_activeViewContainer->statusBar();
+    switch (command) {
+    case KIO::FileUndoManager::Copy:
+        statusBar->setText(i18nc("@info:status", "Successfully copied."));
+        break;
+    case KIO::FileUndoManager::Move:
+        statusBar->setText(i18nc("@info:status", "Successfully moved."));
+        break;
+    case KIO::FileUndoManager::Link:
+        statusBar->setText(i18nc("@info:status", "Successfully linked."));
+        break;
+    case KIO::FileUndoManager::Trash:
+        statusBar->setText(i18nc("@info:status", "Successfully moved to trash."));
+        break;
+    case KIO::FileUndoManager::Rename:
+        statusBar->setText(i18nc("@info:status", "Successfully renamed."));
+        break;
+
+    case KIO::FileUndoManager::Mkdir:
+        statusBar->setText(i18nc("@info:status", "Created folder."));
+        break;
+
+    default:
+        break;
+    }
+}
+
+void DolphinMainWindow::pasteIntoFolder()
+{
+    m_activeViewContainer->view()->pasteIntoFolder();
+}
+
+void DolphinMainWindow::changeUrl(const QUrl &url)
+{
+    if (!KProtocolManager::supportsListing(url)) {
+        // The URL navigator only checks for validity, not
+        // if the URL can be listed. An error message is
+        // shown due to DolphinViewContainer::restoreView().
+        return;
+    }
+
+    m_activeViewContainer->setUrl(url);
+    updateFileAndEditActions();
+    updatePasteAction();
+    updateViewActions();
+    updateGoActions();
+
+    emit urlChanged(url);
+}
+
+void DolphinMainWindow::slotTerminalDirectoryChanged(const QUrl& url)
+{
+    if (m_tearDownFromPlacesRequested && url == QUrl::fromLocalFile(QDir::homePath())) {
+        m_placesPanel->proceedWithTearDown();
+        m_tearDownFromPlacesRequested = false;
+    }
+
+    m_activeViewContainer->setAutoGrabFocus(false);
+    changeUrl(url);
+    m_activeViewContainer->setAutoGrabFocus(true);
+}
+
+void DolphinMainWindow::slotEditableStateChanged(bool editable)
+{
+    KToggleAction* editableLocationAction =
+        static_cast<KToggleAction*>(actionCollection()->action(QStringLiteral("editable_location")));
+    editableLocationAction->setChecked(editable);
+}
+
+void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection)
+{
+    updateFileAndEditActions();
+
+    const int selectedUrlsCount = m_tabWidget->currentTabPage()->selectedItemsCount();
+
+    QAction* compareFilesAction = actionCollection()->action(QStringLiteral("compare_files"));
+    if (selectedUrlsCount == 2) {
+        compareFilesAction->setEnabled(isKompareInstalled());
+    } else {
+        compareFilesAction->setEnabled(false);
+    }
+
+    emit selectionChanged(selection);
+}
+
+void DolphinMainWindow::updateHistory()
+{
+    const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    const int index = urlNavigator->historyIndex();
+
+    QAction* backAction = actionCollection()->action(KStandardAction::name(KStandardAction::Back));
+    if (backAction) {
+        backAction->setToolTip(i18nc("@info", "Go back"));
+        backAction->setWhatsThis(i18nc("@info:whatsthis go back", "Return to the previously viewed folder."));
+        backAction->setEnabled(index < urlNavigator->historySize() - 1);
+    }
+
+    QAction* forwardAction = actionCollection()->action(KStandardAction::name(KStandardAction::Forward));
+    if (forwardAction) {
+        forwardAction->setToolTip(i18nc("@info", "Go forward"));
+        forwardAction->setWhatsThis(xi18nc("@info:whatsthis go forward",
+            "This undoes a <interface>Go|Back</interface> action."));
+        forwardAction->setEnabled(index > 0);
+    }
+}
+
+void DolphinMainWindow::updateFilterBarAction(bool show)
+{
+    QAction* showFilterBarAction = actionCollection()->action(QStringLiteral("show_filter_bar"));
+    showFilterBarAction->setChecked(show);
+}
+
+void DolphinMainWindow::openNewMainWindow()
+{
+    Dolphin::openNewWindow({m_activeViewContainer->url()}, this);
+}
+
+void DolphinMainWindow::openNewActivatedTab()
+{
+    m_tabWidget->openNewActivatedTab();
+}
+
+void DolphinMainWindow::addToPlaces()
+{
+    QUrl url;
+    QString name;
+
+    // If nothing is selected, act on the current dir
+    if (m_activeViewContainer->view()->selectedItems().isEmpty()) {
+        url = m_activeViewContainer->url();
+        name = m_activeViewContainer->placesText();
+    } else {
+        const auto dirToAdd = m_activeViewContainer->view()->selectedItems().first();
+        url = dirToAdd.url();
+        name = dirToAdd.name();
+    }
+    if (url.isValid()) {
+        PlacesItemModel model;
+        QString icon;
+        if (m_activeViewContainer->isSearchModeEnabled()) {
+            icon = QStringLiteral("folder-saved-search-symbolic");
+        } else {
+            icon = KIO::iconNameForUrl(url);
+        }
+        model.createPlacesItem(name, url, icon);
+    }
+}
+
+void DolphinMainWindow::openNewTab(const QUrl& url, DolphinTabWidget::TabPlacement tabPlacement)
+{
+    m_tabWidget->openNewTab(url, QUrl(), tabPlacement);
+}
+
+void DolphinMainWindow::openNewTabAfterCurrentTab(const QUrl& url)
+{
+    m_tabWidget->openNewTab(url, QUrl(), DolphinTabWidget::AfterCurrentTab);
+}
+
+void DolphinMainWindow::openNewTabAfterLastTab(const QUrl& url)
+{
+    m_tabWidget->openNewTab(url, QUrl(), DolphinTabWidget::AfterLastTab);
+}
+
+void DolphinMainWindow::openInNewTab()
+{
+    const KFileItemList& list = m_activeViewContainer->view()->selectedItems();
+    bool tabCreated = false;
+
+    foreach (const KFileItem& item, list) {
+        const QUrl& url = DolphinView::openItemAsFolderUrl(item);
+        if (!url.isEmpty()) {
+            openNewTabAfterCurrentTab(url);
+            tabCreated = true;
+        }
+    }
+
+    // if no new tab has been created from the selection
+    // open the current directory in a new tab
+    if (!tabCreated) {
+        openNewTabAfterCurrentTab(m_activeViewContainer->url());
+    }
+}
+
+void DolphinMainWindow::openInNewWindow()
+{
+    QUrl newWindowUrl;
+
+    const KFileItemList list = m_activeViewContainer->view()->selectedItems();
+    if (list.isEmpty()) {
+        newWindowUrl = m_activeViewContainer->url();
+    } else if (list.count() == 1) {
+        const KFileItem& item = list.first();
+        newWindowUrl = DolphinView::openItemAsFolderUrl(item);
+    }
+
+    if (!newWindowUrl.isEmpty()) {
+        Dolphin::openNewWindow({newWindowUrl}, this);
+    }
+}
+
+void DolphinMainWindow::showTarget()
+{
+    const auto link = m_activeViewContainer->view()->selectedItems().at(0);
+    const auto linkLocationDir = QFileInfo(link.localPath()).absoluteDir();
+    auto linkDestination = link.linkDest();
+    if (QFileInfo(linkDestination).isRelative()) {
+        linkDestination = linkLocationDir.filePath(linkDestination);
+    }
+    if (QFileInfo::exists(linkDestination)) {
+        KIO::highlightInFileManager({QUrl::fromLocalFile(linkDestination).adjusted(QUrl::StripTrailingSlash)});
+    } else {
+        m_activeViewContainer->showMessage(xi18nc("@info", "Could not access <filename>%1</filename>.", linkDestination),
+                                           DolphinViewContainer::Warning);
+    }
+}
+
+void DolphinMainWindow::showEvent(QShowEvent* event)
+{
+    KXmlGuiWindow::showEvent(event);
+
+    if (!event->spontaneous()) {
+        m_activeViewContainer->view()->setFocus();
+    }
+}
+
+void DolphinMainWindow::closeEvent(QCloseEvent* event)
+{
+    // Find out if Dolphin is closed directly by the user or
+    // by the session manager because the session is closed
+    bool closedByUser = true;
+    if (qApp->isSavingSession()) {
+        closedByUser = false;
+    }
+
+    if (m_tabWidget->count() > 1 && GeneralSettings::confirmClosingMultipleTabs() && closedByUser) {
+        // Ask the user if he really wants to quit and close all tabs.
+        // Open a confirmation dialog with 3 buttons:
+        // QDialogButtonBox::Yes    -> Quit
+        // QDialogButtonBox::No     -> Close only the current tab
+        // QDialogButtonBox::Cancel -> do nothing
+        QDialog *dialog = new QDialog(this, Qt::Dialog);
+        dialog->setWindowTitle(i18nc("@title:window", "Confirmation"));
+        dialog->setModal(true);
+        QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Yes | QDialogButtonBox::No | QDialogButtonBox::Cancel);
+        KGuiItem::assign(buttons->button(QDialogButtonBox::Yes), KGuiItem(i18nc("@action:button 'Quit Dolphin' button", "&Quit %1", QGuiApplication::applicationDisplayName()), QIcon::fromTheme(QStringLiteral("application-exit"))));
+        KGuiItem::assign(buttons->button(QDialogButtonBox::No), KGuiItem(i18n("C&lose Current Tab"), QIcon::fromTheme(QStringLiteral("tab-close"))));
+        KGuiItem::assign(buttons->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
+        buttons->button(QDialogButtonBox::Yes)->setDefault(true);
+
+        bool doNotAskAgainCheckboxResult = false;
+
+        const auto result = KMessageBox::createKMessageBox(dialog,
+            buttons,
+            QMessageBox::Warning,
+            i18n("You have multiple tabs open in this window, are you sure you want to quit?"),
+            QStringList(),
+            i18n("Do not ask again"),
+            &doNotAskAgainCheckboxResult,
+            KMessageBox::Notify);
+
+        if (doNotAskAgainCheckboxResult) {
+            GeneralSettings::setConfirmClosingMultipleTabs(false);
+        }
+
+        switch (result) {
+            case QDialogButtonBox::Yes:
+                // Quit
+                break;
+            case QDialogButtonBox::No:
+                // Close only the current tab
+                m_tabWidget->closeTab();
+                Q_FALLTHROUGH();
+            default:
+                event->ignore();
+                return;
+        }
+    }
+
+    if (m_terminalPanel && m_terminalPanel->hasProgramRunning() && GeneralSettings::confirmClosingTerminalRunningProgram() && closedByUser) {
+        // Ask if the user really wants to quit Dolphin with a program that is still running in the Terminal panel
+        // Open a confirmation dialog with 3 buttons:
+        // QDialogButtonBox::Yes    -> Quit
+        // QDialogButtonBox::No     -> Show Terminal Panel
+        // QDialogButtonBox::Cancel -> do nothing
+        QDialog *dialog = new QDialog(this, Qt::Dialog);
+        dialog->setWindowTitle(i18nc("@title:window", "Confirmation"));
+        dialog->setModal(true);
+        auto standardButtons = QDialogButtonBox::Yes | QDialogButtonBox::Cancel;
+        if (!m_terminalPanel->isVisible()) {
+            standardButtons |= QDialogButtonBox::No;
+        }
+        QDialogButtonBox *buttons = new QDialogButtonBox(standardButtons);
+        KGuiItem::assign(buttons->button(QDialogButtonBox::Yes), KStandardGuiItem::quit());
+        if (!m_terminalPanel->isVisible()) {
+            KGuiItem::assign(
+                    buttons->button(QDialogButtonBox::No),
+                    KGuiItem(i18n("Show &Terminal Panel"), QIcon::fromTheme(QStringLiteral("dialog-scripts"))));
+        }
+        KGuiItem::assign(buttons->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
+
+        bool doNotAskAgainCheckboxResult = false;
+
+        const auto result = KMessageBox::createKMessageBox(
+                dialog,
+                buttons,
+                QMessageBox::Warning,
+                i18n("The program '%1' is still running in the Terminal panel. Are you sure you want to quit?", m_terminalPanel->runningProgramName()),
+                QStringList(),
+                i18n("Do not ask again"),
+                &doNotAskAgainCheckboxResult,
+                KMessageBox::Dangerous);
+
+        if (doNotAskAgainCheckboxResult) {
+            GeneralSettings::setConfirmClosingTerminalRunningProgram(false);
+        }
+
+        switch (result) {
+            case QDialogButtonBox::Yes:
+                // Quit
+                break;
+            case QDialogButtonBox::No:
+                actionCollection()->action("show_terminal_panel")->trigger();
+                // Do not quit, ignore quit event
+                Q_FALLTHROUGH();
+            default:
+                event->ignore();
+                return;
+        }
+    }
+
+    if (GeneralSettings::rememberOpenedTabs())  {
+        KConfigGui::setSessionConfig(QStringLiteral("dolphin"), QStringLiteral("dolphin"));
+        KConfig *config = KConfigGui::sessionConfig();
+        saveGlobalProperties(config);
+        savePropertiesInternal(config, 1);
+        config->sync();
+    }
+
+    GeneralSettings::setVersion(CurrentDolphinVersion);
+    GeneralSettings::self()->save();
+
+    KXmlGuiWindow::closeEvent(event);
+}
+
+void DolphinMainWindow::saveProperties(KConfigGroup& group)
+{
+    m_tabWidget->saveProperties(group);
+}
+
+void DolphinMainWindow::readProperties(const KConfigGroup& group)
+{
+    m_tabWidget->readProperties(group);
+}
+
+void DolphinMainWindow::updateNewMenu()
+{
+    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
+    m_newFileMenu->checkUpToDate();
+    m_newFileMenu->setPopupFiles(QList<QUrl>() << activeViewContainer()->url());
+}
+
+void DolphinMainWindow::createDirectory()
+{
+    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
+    m_newFileMenu->setPopupFiles(QList<QUrl>() << activeViewContainer()->url());
+    m_newFileMenu->createDirectory();
+}
+
+void DolphinMainWindow::quit()
+{
+    close();
+}
+
+void DolphinMainWindow::showErrorMessage(const QString& message)
+{
+    m_activeViewContainer->showMessage(message, DolphinViewContainer::Error);
+}
+
+void DolphinMainWindow::slotUndoAvailable(bool available)
+{
+    QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
+    if (undoAction) {
+        undoAction->setEnabled(available);
+    }
+}
+
+void DolphinMainWindow::slotUndoTextChanged(const QString& text)
+{
+    QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
+    if (undoAction) {
+        undoAction->setText(text);
+    }
+}
+
+void DolphinMainWindow::undo()
+{
+    clearStatusBar();
+    KIO::FileUndoManager::self()->uiInterface()->setParentWidget(this);
+    KIO::FileUndoManager::self()->undo();
+}
+
+void DolphinMainWindow::cut()
+{
+    m_activeViewContainer->view()->cutSelectedItems();
+}
+
+void DolphinMainWindow::copy()
+{
+    m_activeViewContainer->view()->copySelectedItemsToClipboard();
+}
+
+void DolphinMainWindow::paste()
+{
+    m_activeViewContainer->view()->paste();
+}
+
+void DolphinMainWindow::find()
+{
+    m_activeViewContainer->setSearchModeEnabled(true);
+}
+
+void DolphinMainWindow::updateSearchAction()
+{
+    QAction* toggleSearchAction = actionCollection()->action(QStringLiteral("toggle_search"));
+    toggleSearchAction->setChecked(m_activeViewContainer->isSearchModeEnabled());
+}
+
+void DolphinMainWindow::updatePasteAction()
+{
+    QAction* pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste));
+    QPair<bool, QString> pasteInfo = m_activeViewContainer->view()->pasteInfo();
+    pasteAction->setEnabled(pasteInfo.first);
+    pasteAction->setText(pasteInfo.second);
+}
+
+void DolphinMainWindow::slotDirectoryLoadingCompleted()
+{
+    updatePasteAction();
+}
+
+void DolphinMainWindow::slotToolBarActionMiddleClicked(QAction *action)
+{
+    if (action == actionCollection()->action(KStandardAction::name(KStandardAction::Back))) {
+        goBackInNewTab();
+    } else if (action == actionCollection()->action(KStandardAction::name(KStandardAction::Forward))) {
+        goForwardInNewTab();
+    } else if (action == actionCollection()->action(QStringLiteral("go_up"))) {
+        goUpInNewTab();
+    } else if (action == actionCollection()->action(QStringLiteral("go_home"))) {
+        goHomeInNewTab();
+    }
+}
+
+void DolphinMainWindow::slotAboutToShowBackPopupMenu()
+{
+    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    int entries = 0;
+    m_backAction->menu()->clear();
+    for (int i = urlNavigator->historyIndex() + 1; i < urlNavigator->historySize() && entries < MaxNumberOfNavigationentries; ++i, ++entries) {
+        QAction* action = new QAction(urlNavigator->locationUrl(i).toString(QUrl::PreferLocalFile), m_backAction->menu());
+        action->setData(i);
+        m_backAction->menu()->addAction(action);
+    }
+}
+
+void DolphinMainWindow::slotGoBack(QAction* action)
+{
+    int gotoIndex = action->data().value<int>();
+    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    for (int i = gotoIndex - urlNavigator->historyIndex(); i > 0; --i) {
+        goBack();
+    }
+}
+
+void DolphinMainWindow::slotBackForwardActionMiddleClicked(QAction* action)
+{
+    if (action) {
+        KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
+        openNewTabAfterCurrentTab(urlNavigator->locationUrl(action->data().value<int>()));
+    }
+}
+
+void DolphinMainWindow::slotAboutToShowForwardPopupMenu()
+{
+    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    int entries = 0;
+    m_forwardAction->menu()->clear();
+    for (int i = urlNavigator->historyIndex() - 1; i >= 0 && entries < MaxNumberOfNavigationentries; --i, ++entries) {
+        QAction* action = new QAction(urlNavigator->locationUrl(i).toString(QUrl::PreferLocalFile), m_forwardAction->menu());
+        action->setData(i);
+        m_forwardAction->menu()->addAction(action);
+    }
+}
+
+void DolphinMainWindow::slotGoForward(QAction* action)
+{
+    int gotoIndex = action->data().value<int>();
+    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    for (int i = urlNavigator->historyIndex() - gotoIndex; i > 0; --i) {
+        goForward();
+    }
+}
+
+void DolphinMainWindow::selectAll()
+{
+    clearStatusBar();
+
+    // if the URL navigator is editable and focused, select the whole
+    // URL instead of all items of the view
+
+    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    QLineEdit* lineEdit = urlNavigator->editor()->lineEdit();
+    const bool selectUrl = urlNavigator->isUrlEditable() &&
+                           lineEdit->hasFocus();
+    if (selectUrl) {
+        lineEdit->selectAll();
+    } else {
+        m_activeViewContainer->view()->selectAll();
+    }
+}
+
+void DolphinMainWindow::invertSelection()
+{
+    clearStatusBar();
+    m_activeViewContainer->view()->invertSelection();
+}
+
+void DolphinMainWindow::toggleSplitView()
+{
+    DolphinTabPage* tabPage = m_tabWidget->currentTabPage();
+    tabPage->setSplitViewEnabled(!tabPage->splitViewEnabled());
+
+    updateViewActions();
+}
+
+void DolphinMainWindow::toggleSplitStash()
+{
+    DolphinTabPage* tabPage = m_tabWidget->currentTabPage();
+    tabPage->setSplitViewEnabled(false);
+    tabPage->setSplitViewEnabled(true, QUrl("stash:/"));
+}
+
+void DolphinMainWindow::reloadView()
+{
+    clearStatusBar();
+    m_activeViewContainer->reload();
+    m_activeViewContainer->statusBar()->updateSpaceInfo();
+}
+
+void DolphinMainWindow::stopLoading()
+{
+    m_activeViewContainer->view()->stopLoading();
+}
+
+void DolphinMainWindow::enableStopAction()
+{
+    actionCollection()->action(QStringLiteral("stop"))->setEnabled(true);
+}
+
+void DolphinMainWindow::disableStopAction()
+{
+    actionCollection()->action(QStringLiteral("stop"))->setEnabled(false);
+}
+
+void DolphinMainWindow::showFilterBar()
+{
+    m_activeViewContainer->setFilterBarVisible(true);
+}
+
+void DolphinMainWindow::toggleEditLocation()
+{
+    clearStatusBar();
+
+    QAction* action = actionCollection()->action(QStringLiteral("editable_location"));
+    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    urlNavigator->setUrlEditable(action->isChecked());
+}
+
+void DolphinMainWindow::replaceLocation()
+{
+    KUrlNavigator* navigator = m_activeViewContainer->urlNavigator();
+    QLineEdit* lineEdit = navigator->editor()->lineEdit();
+
+    // If the text field currently has focus and everything is selected,
+    // pressing the keyboard shortcut returns the whole thing to breadcrumb mode
+    if (navigator->isUrlEditable()
+        && lineEdit->hasFocus()
+        && lineEdit->selectedText() == lineEdit->text() ) {
+        navigator->setUrlEditable(false);
+    } else {
+        navigator->setUrlEditable(true);
+        navigator->setFocus();
+        lineEdit->selectAll();
+    }
+}
+
+void DolphinMainWindow::togglePanelLockState()
+{
+    const bool newLockState = !GeneralSettings::lockPanels();
+    foreach (QObject* child, children()) {
+        DolphinDockWidget* dock = qobject_cast<DolphinDockWidget*>(child);
+        if (dock) {
+            dock->setLocked(newLockState);
+        }
+    }
+
+    GeneralSettings::setLockPanels(newLockState);
+}
+
+void DolphinMainWindow::slotTerminalPanelVisibilityChanged()
+{
+    if (m_terminalPanel->isHiddenInVisibleWindow() && m_activeViewContainer) {
+        m_activeViewContainer->view()->setFocus();
+    }
+}
+
+void DolphinMainWindow::goBack()
+{
+    KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
+    urlNavigator->goBack();
+
+    if (urlNavigator->locationState().isEmpty()) {
+        // An empty location state indicates a redirection URL,
+        // which must be skipped too
+        urlNavigator->goBack();
+    }
+}
+
+void DolphinMainWindow::goForward()
+{
+    m_activeViewContainer->urlNavigator()->goForward();
+}
+
+void DolphinMainWindow::goUp()
+{
+    m_activeViewContainer->urlNavigator()->goUp();
+}
+
+void DolphinMainWindow::goHome()
+{
+    m_activeViewContainer->urlNavigator()->goHome();
+}
+
+void DolphinMainWindow::goBackInNewTab()
+{
+    KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
+    const int index = urlNavigator->historyIndex() + 1;
+    openNewTabAfterCurrentTab(urlNavigator->locationUrl(index));
+}
+
+void DolphinMainWindow::goForwardInNewTab()
+{
+    KUrlNavigator* urlNavigator = activeViewContainer()->urlNavigator();
+    const int index = urlNavigator->historyIndex() - 1;
+    openNewTabAfterCurrentTab(urlNavigator->locationUrl(index));
+}
+
+void DolphinMainWindow::goUpInNewTab()
+{
+    const QUrl currentUrl = activeViewContainer()->urlNavigator()->locationUrl();
+    openNewTabAfterCurrentTab(KIO::upUrl(currentUrl));
+}
+
+void DolphinMainWindow::goHomeInNewTab()
+{
+    openNewTabAfterCurrentTab(Dolphin::homeUrl());
+}
+
+void DolphinMainWindow::compareFiles()
+{
+    const KFileItemList items = m_tabWidget->currentTabPage()->selectedItems();
+    if (items.count() != 2) {
+        // The action is disabled in this case, but it could have been triggered
+        // via D-Bus, see https://bugs.kde.org/show_bug.cgi?id=325517
+        return;
+    }
+
+    QUrl urlA = items.at(0).url();
+    QUrl urlB = items.at(1).url();
+
+    QString command(QStringLiteral("kompare -c \""));
+    command.append(urlA.toDisplayString(QUrl::PreferLocalFile));
+    command.append("\" \"");
+    command.append(urlB.toDisplayString(QUrl::PreferLocalFile));
+    command.append('\"');
+
+    KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob(command, this);
+    job->setDesktopName(QStringLiteral("org.kde.kompare"));
+    job->start();
+}
+
+void DolphinMainWindow::toggleShowMenuBar()
+{
+    const bool visible = menuBar()->isVisible();
+    menuBar()->setVisible(!visible);
+    if (visible) {
+        createControlButton();
+    } else {
+        deleteControlButton();
+    }
+}
+
+QString DolphinMainWindow::activeContainerLocalPath()
+{
+    KIO::StatJob* statJob = KIO::mostLocalUrl(m_activeViewContainer->url());
+    KJobWidgets::setWindow(statJob, this);
+    statJob->exec();
+    QUrl url = statJob->mostLocalUrl();
+    if (url.isLocalFile()) {
+        return url.toLocalFile();
+    }
+    return QDir::homePath();
+}
+
+QPointer<QAction> DolphinMainWindow::preferredSearchTool()
+{
+    m_searchTools.clear();
+    KMoreToolsMenuFactory("dolphin/search-tools").fillMenuFromGroupingNames(
+        &m_searchTools, { "files-find" }, m_activeViewContainer->url()
+    );
+    QList<QAction*> actions = m_searchTools.actions();
+    if (actions.isEmpty()) {
+        return nullptr;
+    }
+    QAction* action = actions.first();
+    if (action->isSeparator()) {
+        return nullptr;
+    }
+    return action;
+}
+
+void DolphinMainWindow::setupUpdateOpenPreferredSearchToolAction()
+{
+    QAction* openPreferredSearchTool = actionCollection()->action(QStringLiteral("open_preferred_search_tool"));
+    const QList<QWidget*> widgets = openPreferredSearchTool->associatedWidgets();
+    for (QWidget* widget : widgets) {
+        QMenu* menu = qobject_cast<QMenu*>(widget);
+        if (menu) {
+            connect(menu, &QMenu::aboutToShow, this, &DolphinMainWindow::updateOpenPreferredSearchToolAction);
+        }
+    }
+
+    // Update the open_preferred_search_tool action *before* the Configure Shortcuts window is shown,
+    // since this action is then listed in that window and it should be up-to-date when it is displayed.
+    // This update is instantaneous if user made no changes to the search tools in the meantime.
+    // Maybe all KStandardActions should defer calls to their slots, so that we could simply connect() to trigger()?
+    connect(
+        actionCollection()->action(KStandardAction::name(KStandardAction::KeyBindings)), &QAction::hovered,
+        this, &DolphinMainWindow::updateOpenPreferredSearchToolAction
+    );
+
+    updateOpenPreferredSearchToolAction();
+}
+
+void DolphinMainWindow::updateOpenPreferredSearchToolAction()
+{
+    QAction* openPreferredSearchTool = actionCollection()->action(QStringLiteral("open_preferred_search_tool"));
+    if (!openPreferredSearchTool) {
+        return;
+    }
+    QPointer<QAction> tool = preferredSearchTool();
+    if (tool) {
+        openPreferredSearchTool->setVisible(true);
+        openPreferredSearchTool->setText(i18nc("@action:inmenu Tools", "Open %1", tool->text()));
+        openPreferredSearchTool->setIcon(tool->icon());
+    } else {
+        openPreferredSearchTool->setVisible(false);
+        // still visible in Shortcuts configuration window
+        openPreferredSearchTool->setText(i18nc("@action:inmenu Tools", "Open Preferred Search Tool"));
+        openPreferredSearchTool->setIcon(QIcon::fromTheme(QStringLiteral("search")));
+    }
+}
+
+void DolphinMainWindow::openPreferredSearchTool()
+{
+    QPointer<QAction> tool = preferredSearchTool();
+    if (tool) {
+        tool->trigger();
+    }
+}
+
+void DolphinMainWindow::openTerminal()
+{
+    KToolInvocation::invokeTerminal(QString(), activeContainerLocalPath());
+}
+
+void DolphinMainWindow::editSettings()
+{
+    if (!m_settingsDialog) {
+        DolphinViewContainer* container = activeViewContainer();
+        container->view()->writeSettings();
+
+        const QUrl url = container->url();
+        DolphinSettingsDialog* settingsDialog = new DolphinSettingsDialog(url, this);
+        connect(settingsDialog, &DolphinSettingsDialog::settingsChanged, this, &DolphinMainWindow::refreshViews);
+        settingsDialog->setAttribute(Qt::WA_DeleteOnClose);
+        settingsDialog->show();
+        m_settingsDialog = settingsDialog;
+    } else {
+        m_settingsDialog.data()->raise();
+    }
+}
+
+void DolphinMainWindow::handleUrl(const QUrl& url)
+{
+    delete m_lastHandleUrlStatJob;
+    m_lastHandleUrlStatJob = nullptr;
+
+    if (url.isLocalFile() && QFileInfo(url.toLocalFile()).isDir()) {
+        activeViewContainer()->setUrl(url);
+    } else if (KProtocolManager::supportsListing(url)) {
+        // stat the URL to see if it is a dir or not
+        m_lastHandleUrlStatJob = KIO::stat(url, KIO::HideProgressInfo);
+        if (m_lastHandleUrlStatJob->uiDelegate()) {
+            KJobWidgets::setWindow(m_lastHandleUrlStatJob, this);
+        }
+        connect(m_lastHandleUrlStatJob, &KIO::Job::result,
+                this, &DolphinMainWindow::slotHandleUrlStatFinished);
+
+    } else {
+        new KRun(url, this); // Automatically deletes itself after being finished
+    }
+}
+
+void DolphinMainWindow::slotHandleUrlStatFinished(KJob* job)
+{
+    m_lastHandleUrlStatJob = nullptr;
+    const KIO::UDSEntry entry = static_cast<KIO::StatJob*>(job)->statResult();
+    const QUrl url = static_cast<KIO::StatJob*>(job)->url();
+    if (entry.isDir()) {
+        activeViewContainer()->setUrl(url);
+    } else {
+        new KRun(url, this);  // Automatically deletes itself after being finished
+    }
+}
+
+void DolphinMainWindow::slotWriteStateChanged(bool isFolderWritable)
+{
+    // trash:/ is writable but we don't want to create new items in it.
+    // TODO: remove the trash check once https://phabricator.kde.org/T8234 is implemented
+    newFileMenu()->setEnabled(isFolderWritable && m_activeViewContainer->url().scheme() != QLatin1String("trash"));
+}
+
+void DolphinMainWindow::openContextMenu(const QPoint& pos,
+                                        const KFileItem& item,
+                                        const QUrl& url,
+                                        const QList<QAction*>& customActions)
+{
+    QPointer<DolphinContextMenu> contextMenu = new DolphinContextMenu(this, pos, item, url);
+    contextMenu.data()->setCustomActions(customActions);
+    const DolphinContextMenu::Command command = contextMenu.data()->open();
+
+    switch (command) {
+    case DolphinContextMenu::OpenParentFolder:
+        changeUrl(KIO::upUrl(item.url()));
+        m_activeViewContainer->view()->markUrlsAsSelected({item.url()});
+        m_activeViewContainer->view()->markUrlAsCurrent(item.url());
+        break;
+
+    case DolphinContextMenu::OpenParentFolderInNewWindow:
+        Dolphin::openNewWindow({item.url()}, this, Dolphin::OpenNewWindowFlag::Select);
+        break;
+
+    case DolphinContextMenu::OpenParentFolderInNewTab:
+        openNewTabAfterLastTab(KIO::upUrl(item.url()));
+        break;
+
+    case DolphinContextMenu::None:
+    default:
+        break;
+    }
+
+    // Delete the menu, unless it has been deleted in its own nested event loop already.
+    if (contextMenu) {
+        contextMenu->deleteLater();
+    }
+}
+
+void DolphinMainWindow::updateControlMenu()
+{
+    QMenu* menu = qobject_cast<QMenu*>(sender());
+    Q_ASSERT(menu);
+
+    // All actions get cleared by QMenu::clear(). This includes the sub-menus
+    // because 'menu' is their parent.
+    menu->clear();
+
+    KActionCollection* ac = actionCollection();
+
+    menu->addMenu(m_newFileMenu->menu());
+    addActionToMenu(ac->action(QStringLiteral("file_new")), menu);
+    addActionToMenu(ac->action(QStringLiteral("new_tab")), menu);
+    addActionToMenu(ac->action(QStringLiteral("closed_tabs")), menu);
+
+    menu->addSeparator();
+
+    // Add "Edit" actions
+    bool added = addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Undo)), menu) |
+                 addActionToMenu(ac->action(KStandardAction::name(KStandardAction::SelectAll)), menu) |
+                 addActionToMenu(ac->action(QStringLiteral("invert_selection")), menu);
+
+    if (added) {
+        menu->addSeparator();
+    }
+
+    // Add "View" actions
+    if (!GeneralSettings::showZoomSlider()) {
+        addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ZoomIn)), menu);
+        addActionToMenu(ac->action(QStringLiteral("view_zoom_reset")), menu);
+        addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ZoomOut)), menu);
+        menu->addSeparator();
+    }
+
+    added = addActionToMenu(ac->action(QStringLiteral("show_preview")), menu) |
+            addActionToMenu(ac->action(QStringLiteral("show_in_groups")), menu) |
+            addActionToMenu(ac->action(QStringLiteral("show_hidden_files")), menu) |
+            addActionToMenu(ac->action(QStringLiteral("additional_info")), menu) |
+            addActionToMenu(ac->action(QStringLiteral("view_properties")), menu);
+
+    if (added) {
+        menu->addSeparator();
+    }
+
+    // Add a curated assortment of items from the "Tools" menu
+    addActionToMenu(ac->action(QStringLiteral("show_filter_bar")), menu);
+    addActionToMenu(ac->action(QStringLiteral("open_preferred_search_tool")), menu);
+    addActionToMenu(ac->action(QStringLiteral("open_terminal")), menu);
+    connect(menu, &QMenu::aboutToShow, this, &DolphinMainWindow::updateOpenPreferredSearchToolAction);
+
+    menu->addSeparator();
+
+    // Add "Show Panels" menu
+    addActionToMenu(ac->action(QStringLiteral("panels")), menu);
+
+    // Add "Settings" menu entries
+    addActionToMenu(ac->action(KStandardAction::name(KStandardAction::KeyBindings)), menu);
+    addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ConfigureToolbars)), menu);
+    addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Preferences)), menu);
+    addActionToMenu(ac->action(KStandardAction::name(KStandardAction::ShowMenubar)), menu);
+
+    // Add "Help" menu
+    auto helpMenu = m_helpMenu->menu();
+    helpMenu->setIcon(QIcon::fromTheme(QStringLiteral("system-help")));
+    menu->addMenu(helpMenu);
+}
+
+void DolphinMainWindow::updateToolBar()
+{
+    if (!menuBar()->isVisible()) {
+        createControlButton();
+    }
+}
+
+void DolphinMainWindow::slotControlButtonDeleted()
+{
+    m_controlButton = nullptr;
+    m_updateToolBarTimer->start();
+}
+
+void DolphinMainWindow::slotPlaceActivated(const QUrl& url)
+{
+    DolphinViewContainer* view = activeViewContainer();
+
+    if (view->url() == url) {
+        // We can end up here if the user clicked a device in the Places Panel
+        // which had been unmounted earlier, see https://bugs.kde.org/show_bug.cgi?id=161385.
+        reloadView();
+    } else {
+        changeUrl(url);
+    }
+}
+
+void DolphinMainWindow::closedTabsCountChanged(unsigned int count)
+{
+    actionCollection()->action(QStringLiteral("undo_close_tab"))->setEnabled(count > 0);
+}
+
+void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer)
+{
+    DolphinViewContainer* oldViewContainer = m_activeViewContainer;
+    Q_ASSERT(viewContainer);
+
+    m_activeViewContainer = viewContainer;
+
+    if (oldViewContainer) {
+        const QAction* toggleSearchAction = actionCollection()->action(QStringLiteral("toggle_search"));
+        toggleSearchAction->disconnect(oldViewContainer);
+
+        // Disconnect all signals between the old view container (container,
+        // view and url navigator) and main window.
+        oldViewContainer->disconnect(this);
+        oldViewContainer->view()->disconnect(this);
+        oldViewContainer->urlNavigator()->disconnect(this);
+
+        // except the requestItemInfo so that on hover the information panel can still be updated
+        connect(oldViewContainer->view(), &DolphinView::requestItemInfo,
+                this, &DolphinMainWindow::requestItemInfo);
+    }
+
+    connectViewSignals(viewContainer);
+
+    m_actionHandler->setCurrentView(viewContainer->view());
+
+    updateHistory();
+    updateFileAndEditActions();
+    updatePasteAction();
+    updateViewActions();
+    updateGoActions();
+    updateSearchAction();
+
+    const QUrl url = viewContainer->url();
+    emit urlChanged(url);
+}
+
+void DolphinMainWindow::tabCountChanged(int count)
+{
+    const bool enableTabActions = (count > 1);
+    for (int i = 0; i < MaxActivateTabShortcuts; ++i) {
+        actionCollection()->action(QStringLiteral("activate_tab_%1").arg(i))->setEnabled(enableTabActions);
+    }
+    actionCollection()->action(QStringLiteral("activate_last_tab"))->setEnabled(enableTabActions);
+    actionCollection()->action(QStringLiteral("activate_next_tab"))->setEnabled(enableTabActions);
+    actionCollection()->action(QStringLiteral("activate_prev_tab"))->setEnabled(enableTabActions);
+}
+
+void DolphinMainWindow::updateWindowTitle()
+{
+    const QString newTitle = m_activeViewContainer->captionWindowTitle();
+    if (windowTitle() != newTitle) {
+        setWindowTitle(newTitle);
+    }
+}
+
+void DolphinMainWindow::slotStorageTearDownFromPlacesRequested(const QString& mountPath)
+{
+    if (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) {
+        m_tearDownFromPlacesRequested = true;
+        m_terminalPanel->goHome();
+        // m_placesPanel->proceedWithTearDown() will be called in slotTerminalDirectoryChanged
+    } else {
+        m_placesPanel->proceedWithTearDown();
+    }
+}
+
+void DolphinMainWindow::slotStorageTearDownExternallyRequested(const QString& mountPath)
+{
+    if (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) {
+        m_tearDownFromPlacesRequested = false;
+        m_terminalPanel->goHome();
+    }
+}
+
+void DolphinMainWindow::setupActions()
+{
+    // setup 'File' menu
+    m_newFileMenu = new DolphinNewFileMenu(actionCollection(), this);
+    QMenu* menu = m_newFileMenu->menu();
+    menu->setTitle(i18nc("@title:menu Create new folder, file, link, etc.", "Create New"));
+    menu->setIcon(QIcon::fromTheme(QStringLiteral("document-new")));
+    m_newFileMenu->setDelayed(false);
+    connect(menu, &QMenu::aboutToShow,
+            this, &DolphinMainWindow::updateNewMenu);
+
+    QAction* newWindow = KStandardAction::openNew(this, &DolphinMainWindow::openNewMainWindow, actionCollection());
+    newWindow->setText(i18nc("@action:inmenu File", "New &Window"));
+    newWindow->setToolTip(i18nc("@info", "Open a new Dolphin window"));
+    newWindow->setWhatsThis(xi18nc("@info:whatsthis", "This opens a new "
+        "window just like this one with the current location and view."
+        "<nl/>You can drag and drop items between windows."));
+    newWindow->setIcon(QIcon::fromTheme(QStringLiteral("window-new")));
+
+    QAction* newTab = actionCollection()->addAction(QStringLiteral("new_tab"));
+    newTab->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
+    newTab->setText(i18nc("@action:inmenu File", "New Tab"));
+    newTab->setWhatsThis(xi18nc("@info:whatsthis", "This opens a new "
+        "<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});
+    connect(newTab, &QAction::triggered, this, &DolphinMainWindow::openNewActivatedTab);
+
+    QAction* addToPlaces = actionCollection()->addAction(QStringLiteral("add_to_places"));
+    addToPlaces->setIcon(QIcon::fromTheme(QStringLiteral("bookmark-new")));
+    addToPlaces->setText(i18nc("@action:inmenu Add current folder to places", "Add to Places"));
+    addToPlaces->setWhatsThis(xi18nc("@info:whatsthis", "This adds the selected folder "
+        "to the Places panel."));
+    connect(addToPlaces, &QAction::triggered, this, &DolphinMainWindow::addToPlaces);
+
+    QAction* closeTab = KStandardAction::close(m_tabWidget, QOverload<>::of(&DolphinTabWidget::closeTab), actionCollection());
+    closeTab->setText(i18nc("@action:inmenu File", "Close Tab"));
+    closeTab->setWhatsThis(i18nc("@info:whatsthis", "This closes the "
+        "currently viewed tab. If no more tabs are left this window "
+        "will close instead."));
+
+    QAction* quitAction = KStandardAction::quit(this, &DolphinMainWindow::quit, actionCollection());
+    quitAction->setWhatsThis(i18nc("@info:whatsthis quit", "This closes this window."));
+
+    // setup 'Edit' menu
+    KStandardAction::undo(this,
+                          &DolphinMainWindow::undo,
+                          actionCollection());
+
+    // i18n: This will be the last paragraph for the whatsthis for all three:
+    // Cut, Copy and Paste
+    const QString cutCopyPastePara = xi18nc("@info:whatsthis", "<para><emphasis>Cut, "
+        "Copy</emphasis> and <emphasis>Paste</emphasis> work between many "
+        "applications and are among the most used commands. That's why their "
+        "<emphasis>keyboard shortcuts</emphasis> are prominently placed right "
+        "next to each other on the keyboard: <shortcut>Ctrl+X</shortcut>, "
+        "<shortcut>Ctrl+C</shortcut> and <shortcut>Ctrl+V</shortcut>.</para>");
+    QAction* cutAction = KStandardAction::cut(this, &DolphinMainWindow::cut, actionCollection());
+    cutAction->setWhatsThis(xi18nc("@info:whatsthis cut", "This copies the items "
+        "in your current selection to the <emphasis>clipboard</emphasis>.<nl/>"
+        "Use the <emphasis>Paste</emphasis> action afterwards to copy them from "
+        "the clipboard to a new location. The items will be removed from their "
+        "initial location.") + cutCopyPastePara);
+    QAction* copyAction = KStandardAction::copy(this, &DolphinMainWindow::copy, actionCollection());
+    copyAction->setWhatsThis(xi18nc("@info:whatsthis copy", "This copies the "
+        "items in your current selection to the <emphasis>clipboard</emphasis>."
+        "<nl/>Use the <emphasis>Paste</emphasis> action afterwards to copy them "
+        "from the clipboard to a new location.") +  cutCopyPastePara);
+    QAction* paste = KStandardAction::paste(this, &DolphinMainWindow::paste, actionCollection());
+    // The text of the paste-action is modified dynamically by Dolphin
+    // (e. g. to "Paste One Folder"). To prevent that the size of the toolbar changes
+    // due to the long text, the text "Paste" is used:
+    paste->setIconText(i18nc("@action:inmenu Edit", "Paste"));
+    paste->setWhatsThis(xi18nc("@info:whatsthis paste", "This copies the items from "
+        "your <emphasis>clipboard</emphasis> to the currently viewed folder.<nl/>"
+        "If the items were added to the clipboard by the <emphasis>Cut</emphasis> "
+        "action they are removed from their old location.") +  cutCopyPastePara);
+
+    QAction *searchAction = KStandardAction::find(this, &DolphinMainWindow::find, actionCollection());
+    searchAction->setText(i18n("Search..."));
+    searchAction->setToolTip(i18nc("@info:tooltip", "Search for files and folders"));
+    searchAction->setWhatsThis(xi18nc("@info:whatsthis find", "<para>This helps you "
+        "find files and folders by opening a <emphasis>find bar</emphasis>. "
+        "There you can enter search terms and specify settings to find the "
+        "objects you are looking for.</para><para>Use this help again on "
+        "the find bar so we can have a look at it while the settings are "
+        "explained.</para>"));
+
+    // toggle_search acts as a copy of the main searchAction to be used mainly
+    // in the toolbar, with no default shortcut attached, to avoid messing with
+    // existing workflows (search bar always open and Ctrl-F to focus)
+    QAction *toggleSearchAction = actionCollection()->addAction(QStringLiteral("toggle_search"));
+    toggleSearchAction->setText(i18nc("@action:inmenu", "Toggle Search Bar"));
+    toggleSearchAction->setIconText(i18nc("@action:intoolbar", "Search"));
+    toggleSearchAction->setIcon(searchAction->icon());
+    toggleSearchAction->setToolTip(searchAction->toolTip());
+    toggleSearchAction->setWhatsThis(searchAction->whatsThis());
+    toggleSearchAction->setCheckable(true);
+
+    QAction* selectAllAction = KStandardAction::selectAll(this, &DolphinMainWindow::selectAll, actionCollection());
+    selectAllAction->setWhatsThis(xi18nc("@info:whatsthis", "This selects all "
+        "files and folders in the current location."));
+
+    QAction* invertSelection = actionCollection()->addAction(QStringLiteral("invert_selection"));
+    invertSelection->setText(i18nc("@action:inmenu Edit", "Invert Selection"));
+    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);
+    connect(invertSelection, &QAction::triggered, this, &DolphinMainWindow::invertSelection);
+
+    // setup 'View' menu
+    // (note that most of it is set up in DolphinViewActionHandler)
+
+    QAction* split = actionCollection()->addAction(QStringLiteral("split_view"));
+    split->setWhatsThis(xi18nc("@info:whatsthis find", "<para>This splits "
+        "the folder view below into two autonomous views.</para><para>This "
+        "way you can see two locations at once and move items between them "
+        "quickly.</para>Click this again afterwards to recombine the views."));
+    actionCollection()->setDefaultShortcut(split, Qt::Key_F3);
+    connect(split, &QAction::triggered, this, &DolphinMainWindow::toggleSplitView);
+
+    QAction* stashSplit = actionCollection()->addAction(QStringLiteral("split_stash"));
+    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"));
+    connect(stashSplit, &QAction::triggered, this, &DolphinMainWindow::toggleSplitStash);
+
+    KStandardAction::redisplay(this, &DolphinMainWindow::reloadView, actionCollection());
+
+    QAction* stop = actionCollection()->addAction(QStringLiteral("stop"));
+    stop->setText(i18nc("@action:inmenu View", "Stop"));
+    stop->setToolTip(i18nc("@info", "Stop loading"));
+    stop->setWhatsThis(i18nc("@info", "This stops the loading of the contents of the current folder."));
+    stop->setIcon(QIcon::fromTheme(QStringLiteral("process-stop")));
+    connect(stop, &QAction::triggered, this, &DolphinMainWindow::stopLoading);
+
+    KToggleAction* editableLocation = actionCollection()->add<KToggleAction>(QStringLiteral("editable_location"));
+    editableLocation->setText(i18nc("@action:inmenu Navigation Bar", "Editable Location"));
+    editableLocation->setWhatsThis(xi18nc("@info:whatsthis",
+        "This toggles the <emphasis>Location Bar</emphasis> to be "
+        "editable so you can directly enter a location you want to go to.<nl/>"
+        "You can also switch to editing by clicking to the right of the "
+        "location and switch back by confirming the edited location."));
+    actionCollection()->setDefaultShortcut(editableLocation, Qt::Key_F6);
+    connect(editableLocation, &KToggleAction::triggered, this, &DolphinMainWindow::toggleEditLocation);
+
+    QAction* replaceLocation = actionCollection()->addAction(QStringLiteral("replace_location"));
+    replaceLocation->setText(i18nc("@action:inmenu Navigation Bar", "Replace Location"));
+    // i18n: "enter" is used both in the meaning of "writing" and "going to" a new location here.
+    // Both meanings are useful but not necessary to understand the use of "Replace Location".
+    // So you might want to be more verbose in your language to convey the meaning but it's up to you.
+    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);
+    connect(replaceLocation, &QAction::triggered, this, &DolphinMainWindow::replaceLocation);
+
+    // setup 'Go' menu
+    {
+        QScopedPointer<QAction> backAction(KStandardAction::back(nullptr, nullptr, nullptr));
+        m_backAction = new KToolBarPopupAction(backAction->icon(), backAction->text(), actionCollection());
+        m_backAction->setObjectName(backAction->objectName());
+        m_backAction->setShortcuts(backAction->shortcuts());
+    }
+    m_backAction->setDelayed(true);
+    m_backAction->setStickyMenu(false);
+    connect(m_backAction, &QAction::triggered, this, &DolphinMainWindow::goBack);
+    connect(m_backAction->menu(), &QMenu::aboutToShow, this, &DolphinMainWindow::slotAboutToShowBackPopupMenu);
+    connect(m_backAction->menu(), &QMenu::triggered, this, &DolphinMainWindow::slotGoBack);
+    actionCollection()->addAction(m_backAction->objectName(), m_backAction);
+
+    auto backShortcuts = m_backAction->shortcuts();
+    backShortcuts.append(QKeySequence(Qt::Key_Backspace));
+    actionCollection()->setDefaultShortcuts(m_backAction, backShortcuts);
+
+    DolphinRecentTabsMenu* recentTabsMenu = new DolphinRecentTabsMenu(this);
+    actionCollection()->addAction(QStringLiteral("closed_tabs"), recentTabsMenu);
+    connect(m_tabWidget, &DolphinTabWidget::rememberClosedTab,
+            recentTabsMenu, &DolphinRecentTabsMenu::rememberClosedTab);
+    connect(recentTabsMenu, &DolphinRecentTabsMenu::restoreClosedTab,
+            m_tabWidget, &DolphinTabWidget::restoreClosedTab);
+    connect(recentTabsMenu, &DolphinRecentTabsMenu::closedTabsCountChanged,
+            this, &DolphinMainWindow::closedTabsCountChanged);
+
+    QAction* undoCloseTab = actionCollection()->addAction(QStringLiteral("undo_close_tab"));
+    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);
+    undoCloseTab->setIcon(QIcon::fromTheme(QStringLiteral("edit-undo")));
+    undoCloseTab->setEnabled(false);
+    connect(undoCloseTab, &QAction::triggered, recentTabsMenu, &DolphinRecentTabsMenu::undoCloseTab);
+
+    auto undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
+    undoAction->setWhatsThis(xi18nc("@info:whatsthis", "This undoes "
+        "the last change you made to files or folders.<nl/>"
+        "Such changes include <interface>creating, renaming</interface> "
+        "and <interface>moving</interface> them to a different location "
+        "or to the <filename>Trash</filename>. <nl/>Changes that can't "
+        "be undone will ask for your confirmation."));
+    undoAction->setEnabled(false); // undo should be disabled by default
+
+    {
+        QScopedPointer<QAction> forwardAction(KStandardAction::forward(nullptr, nullptr, nullptr));
+        m_forwardAction = new KToolBarPopupAction(forwardAction->icon(), forwardAction->text(), actionCollection());
+        m_forwardAction->setObjectName(forwardAction->objectName());
+        m_forwardAction->setShortcuts(forwardAction->shortcuts());
+    }
+    m_forwardAction->setDelayed(true);
+    m_forwardAction->setStickyMenu(false);
+    connect(m_forwardAction, &QAction::triggered, this, &DolphinMainWindow::goForward);
+    connect(m_forwardAction->menu(), &QMenu::aboutToShow, this, &DolphinMainWindow::slotAboutToShowForwardPopupMenu);
+    connect(m_forwardAction->menu(), &QMenu::triggered, this, &DolphinMainWindow::slotGoForward);
+    actionCollection()->addAction(m_forwardAction->objectName(), m_forwardAction);
+    actionCollection()->setDefaultShortcuts(m_forwardAction, m_forwardAction->shortcuts());
+
+    // enable middle-click to open in a new tab
+    auto *middleClickEventFilter = new MiddleClickActionEventFilter(this);
+    connect(middleClickEventFilter, &MiddleClickActionEventFilter::actionMiddleClicked, this, &DolphinMainWindow::slotBackForwardActionMiddleClicked);
+    m_backAction->menu()->installEventFilter(middleClickEventFilter);
+    m_forwardAction->menu()->installEventFilter(middleClickEventFilter);
+    KStandardAction::up(this, &DolphinMainWindow::goUp, actionCollection());
+    QAction* homeAction = KStandardAction::home(this, &DolphinMainWindow::goHome, actionCollection());
+    homeAction->setWhatsThis(xi18nc("@info:whatsthis", "Go to your "
+        "<filename>Home</filename> folder.<nl/>Every user account "
+        "has their own <filename>Home</filename> that contains their data "
+        "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")));
+    compareFiles->setEnabled(false);
+    connect(compareFiles, &QAction::triggered, this, &DolphinMainWindow::compareFiles);
+
+    QAction* openPreferredSearchTool = actionCollection()->addAction(QStringLiteral("open_preferred_search_tool"));
+    openPreferredSearchTool->setText(i18nc("@action:inmenu Tools", "Open Preferred Search Tool"));
+    openPreferredSearchTool->setWhatsThis(xi18nc("@info:whatsthis",
+        "<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);
+    connect(openPreferredSearchTool, &QAction::triggered, this, &DolphinMainWindow::openPreferredSearchTool);
+
+#ifdef HAVE_TERMINAL
+    if (KAuthorized::authorize(QStringLiteral("shell_access"))) {
+        QAction* openTerminal = actionCollection()->addAction(QStringLiteral("open_terminal"));
+        openTerminal->setText(i18nc("@action:inmenu Tools", "Open Terminal"));
+        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);
+        connect(openTerminal, &QAction::triggered, this, &DolphinMainWindow::openTerminal);
+
+        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);
+        connect(focusTerminalPanel, &QAction::triggered, this, &DolphinMainWindow::focusTerminalPanel);
+    }
+#endif
+
+    // setup 'Bookmarks' menu
+    KActionMenu *bookmarkMenu = new KActionMenu(i18nc("@title:menu", "&Bookmarks"), this);
+    bookmarkMenu->setIcon(QIcon::fromTheme(QStringLiteral("bookmarks")));
+    // Make the toolbar button version work properly on click
+    bookmarkMenu->setDelayed(false);
+    m_bookmarkHandler = new DolphinBookmarkHandler(this, actionCollection(), bookmarkMenu->menu(), this);
+    actionCollection()->addAction(QStringLiteral("bookmarks"), bookmarkMenu);
+
+    // setup 'Settings' menu
+    KToggleAction* showMenuBar = KStandardAction::showMenubar(nullptr, nullptr, actionCollection());
+    showMenuBar->setWhatsThis(xi18nc("@info:whatsthis",
+            "This switches between having a <emphasis>Menubar</emphasis> "
+            "and having a <interface>Control</interface> button. Both "
+            "contain mostly the same commands and configuration options."));
+    connect(showMenuBar, &KToggleAction::triggered,                   // Fixes #286822
+            this, &DolphinMainWindow::toggleShowMenuBar, Qt::QueuedConnection);
+    KStandardAction::preferences(this, &DolphinMainWindow::editSettings, actionCollection());
+
+    // setup 'Help' menu for the m_controlButton. The other one is set up in the base class.
+    m_helpMenu = new KHelpMenu(nullptr);
+    m_helpMenu->menu()->installEventFilter(this);
+    // remove duplicate shortcuts
+    m_helpMenu->action(KHelpMenu::menuHelpContents)->setShortcut(QKeySequence());
+    m_helpMenu->action(KHelpMenu::menuWhatsThis)->setShortcut(QKeySequence());
+
+    // not in menu actions
+    QList<QKeySequence> nextTabKeys = KStandardShortcut::tabNext();
+    nextTabKeys.append(QKeySequence(Qt::CTRL + Qt::Key_Tab));
+
+    QList<QKeySequence> prevTabKeys = KStandardShortcut::tabPrev();
+    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));
+        activateTab->setText(i18nc("@action:inmenu", "Activate Tab %1", i + 1));
+        activateTab->setEnabled(false);
+        connect(activateTab, &QAction::triggered, this, [this, i]() { m_tabWidget->activateTab(i); });
+
+        // only add default shortcuts for the first 9 tabs regardless of MaxActivateTabShortcuts
+        if (i < 9) {
+            actionCollection()->setDefaultShortcut(activateTab, QStringLiteral("Alt+%1").arg(i + 1));
+        }
+    }
+
+    QAction* activateLastTab = actionCollection()->addAction(QStringLiteral("activate_last_tab"));
+    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);
+
+    QAction* activateNextTab = actionCollection()->addAction(QStringLiteral("activate_next_tab"));
+    activateNextTab->setIconText(i18nc("@action:inmenu", "Next Tab"));
+    activateNextTab->setText(i18nc("@action:inmenu", "Activate Next Tab"));
+    activateNextTab->setEnabled(false);
+    connect(activateNextTab, &QAction::triggered, m_tabWidget, &DolphinTabWidget::activateNextTab);
+    actionCollection()->setDefaultShortcuts(activateNextTab, nextTabKeys);
+
+    QAction* activatePrevTab = actionCollection()->addAction(QStringLiteral("activate_prev_tab"));
+    activatePrevTab->setIconText(i18nc("@action:inmenu", "Previous Tab"));
+    activatePrevTab->setText(i18nc("@action:inmenu", "Activate Previous Tab"));
+    activatePrevTab->setEnabled(false);
+    connect(activatePrevTab, &QAction::triggered, m_tabWidget, &DolphinTabWidget::activatePrevTab);
+    actionCollection()->setDefaultShortcuts(activatePrevTab, prevTabKeys);
+
+    // for context menu
+    QAction* showTarget = actionCollection()->addAction(QStringLiteral("show_target"));
+    showTarget->setText(i18nc("@action:inmenu", "Show Target"));
+    showTarget->setIcon(QIcon::fromTheme(QStringLiteral("document-open-folder")));
+    showTarget->setEnabled(false);
+    connect(showTarget, &QAction::triggered, this, &DolphinMainWindow::showTarget);
+
+    QAction* openInNewTab = actionCollection()->addAction(QStringLiteral("open_in_new_tab"));
+    openInNewTab->setText(i18nc("@action:inmenu", "Open in New Tab"));
+    openInNewTab->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
+    connect(openInNewTab, &QAction::triggered, this, &DolphinMainWindow::openInNewTab);
+
+    QAction* openInNewTabs = actionCollection()->addAction(QStringLiteral("open_in_new_tabs"));
+    openInNewTabs->setText(i18nc("@action:inmenu", "Open in New Tabs"));
+    openInNewTabs->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
+    connect(openInNewTabs, &QAction::triggered, this, &DolphinMainWindow::openInNewTab);
+
+    QAction* openInNewWindow = actionCollection()->addAction(QStringLiteral("open_in_new_window"));
+    openInNewWindow->setText(i18nc("@action:inmenu", "Open in New Window"));
+    openInNewWindow->setIcon(QIcon::fromTheme(QStringLiteral("window-new")));
+    connect(openInNewWindow, &QAction::triggered, this, &DolphinMainWindow::openInNewWindow);
+}
+
+void DolphinMainWindow::setupDockWidgets()
+{
+    const bool lock = GeneralSettings::lockPanels();
+
+    KDualAction* lockLayoutAction = actionCollection()->add<KDualAction>(QStringLiteral("lock_panels"));
+    lockLayoutAction->setActiveText(i18nc("@action:inmenu Panels", "Unlock Panels"));
+    lockLayoutAction->setActiveIcon(QIcon::fromTheme(QStringLiteral("object-unlocked")));
+    lockLayoutAction->setInactiveText(i18nc("@action:inmenu Panels", "Lock Panels"));
+    lockLayoutAction->setInactiveIcon(QIcon::fromTheme(QStringLiteral("object-locked")));
+    lockLayoutAction->setWhatsThis(xi18nc("@info:whatsthis", "This "
+        "switches between having panels <emphasis>locked</emphasis> or "
+        "<emphasis>unlocked</emphasis>.<nl/>Unlocked panels can be "
+        "dragged to the other side of the window and have a close "
+        "button.<nl/>Locked panels are embedded more cleanly."));
+    lockLayoutAction->setActive(lock);
+    connect(lockLayoutAction, &KDualAction::triggered, this, &DolphinMainWindow::togglePanelLockState);
+
+    // Setup "Information"
+    DolphinDockWidget* infoDock = new DolphinDockWidget(i18nc("@title:window", "Information"));
+    infoDock->setLocked(lock);
+    infoDock->setObjectName(QStringLiteral("infoDock"));
+    infoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+
+#ifdef HAVE_BALOO
+    InformationPanel* infoPanel = new InformationPanel(infoDock);
+    infoPanel->setCustomContextMenuActions({lockLayoutAction});
+    connect(infoPanel, &InformationPanel::urlActivated, this, &DolphinMainWindow::handleUrl);
+    infoDock->setWidget(infoPanel);
+
+    QAction* infoAction = infoDock->toggleViewAction();
+    createPanelAction(QIcon::fromTheme(QStringLiteral("dialog-information")), Qt::Key_F11, infoAction, QStringLiteral("show_information_panel"));
+
+    addDockWidget(Qt::RightDockWidgetArea, infoDock);
+    connect(this, &DolphinMainWindow::urlChanged,
+            infoPanel, &InformationPanel::setUrl);
+    connect(this, &DolphinMainWindow::selectionChanged,
+            infoPanel, &InformationPanel::setSelection);
+    connect(this, &DolphinMainWindow::requestItemInfo,
+            infoPanel, &InformationPanel::requestDelayedItemInfo);
+#endif
+
+    // i18n: This is the last paragraph for the "What's This"-texts of all four panels.
+    const QString panelWhatsThis = xi18nc("@info:whatsthis", "<para>To show or "
+        "hide panels like this go to <interface>Control|Panels</interface> "
+        "or <interface>View|Panels</interface>.</para>");
+#ifdef HAVE_BALOO
+    actionCollection()->action(QStringLiteral("show_information_panel"))
+        ->setWhatsThis(xi18nc("@info:whatsthis", "<para> This toggles the "
+        "<emphasis>information</emphasis> panel at the right side of the "
+        "window.</para><para>The panel provides in-depth information "
+        "about the items your mouse is hovering over or about the selected "
+        "items. Otherwise it informs you about the currently viewed folder.<nl/>"
+        "For single items a preview of their contents is provided.</para>"));
+#endif
+    infoDock->setWhatsThis(xi18nc("@info:whatsthis", "<para>This panel "
+        "provides in-depth information about the items your mouse is "
+        "hovering over or about the selected items. Otherwise it informs "
+        "you about the currently viewed folder.<nl/>For single items a "
+        "preview of their contents is provided.</para><para>You can configure "
+        "which and how details are given here by right-clicking.</para>") + panelWhatsThis);
+
+    // Setup "Folders"
+    DolphinDockWidget* foldersDock = new DolphinDockWidget(i18nc("@title:window", "Folders"));
+    foldersDock->setLocked(lock);
+    foldersDock->setObjectName(QStringLiteral("foldersDock"));
+    foldersDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+    FoldersPanel* foldersPanel = new FoldersPanel(foldersDock);
+    foldersPanel->setCustomContextMenuActions({lockLayoutAction});
+    foldersDock->setWidget(foldersPanel);
+
+    QAction* foldersAction = foldersDock->toggleViewAction();
+    createPanelAction(QIcon::fromTheme(QStringLiteral("folder")), Qt::Key_F7, foldersAction, QStringLiteral("show_folders_panel"));
+
+    addDockWidget(Qt::LeftDockWidgetArea, foldersDock);
+    connect(this, &DolphinMainWindow::urlChanged,
+            foldersPanel, &FoldersPanel::setUrl);
+    connect(foldersPanel, &FoldersPanel::folderActivated,
+            this, &DolphinMainWindow::changeUrl);
+    connect(foldersPanel, &FoldersPanel::folderMiddleClicked,
+            this, &DolphinMainWindow::openNewTabAfterCurrentTab);
+    connect(foldersPanel, &FoldersPanel::errorMessage,
+            this, &DolphinMainWindow::showErrorMessage);
+
+    actionCollection()->action(QStringLiteral("show_folders_panel"))
+        ->setWhatsThis(xi18nc("@info:whatsthis", "This toggles the "
+        "<emphasis>folders</emphasis> panel at the left side of the window."
+        "<nl/><nl/>It shows the folders of the <emphasis>file system"
+        "</emphasis> in a <emphasis>tree view</emphasis>."));
+    foldersDock->setWhatsThis(xi18nc("@info:whatsthis", "<para>This panel "
+        "shows the folders of the <emphasis>file system</emphasis> in a "
+        "<emphasis>tree view</emphasis>.</para><para>Click a folder to go "
+        "there. Click the arrow to the left of a folder to see its subfolders. "
+        "This allows quick switching between any folders.</para>") + panelWhatsThis);
+
+    // Setup "Terminal"
+#ifdef HAVE_TERMINAL
+    if (KAuthorized::authorize(QStringLiteral("shell_access"))) {
+        DolphinDockWidget* terminalDock = new DolphinDockWidget(i18nc("@title:window Shell terminal", "Terminal"));
+        terminalDock->setLocked(lock);
+        terminalDock->setObjectName(QStringLiteral("terminalDock"));
+        m_terminalPanel = new TerminalPanel(terminalDock);
+        m_terminalPanel->setCustomContextMenuActions({lockLayoutAction});
+        terminalDock->setWidget(m_terminalPanel);
+
+        connect(m_terminalPanel, &TerminalPanel::hideTerminalPanel, terminalDock, &DolphinDockWidget::hide);
+        connect(m_terminalPanel, &TerminalPanel::changeUrl, this, &DolphinMainWindow::slotTerminalDirectoryChanged);
+        connect(terminalDock, &DolphinDockWidget::visibilityChanged,
+                m_terminalPanel, &TerminalPanel::dockVisibilityChanged);
+        connect(terminalDock, &DolphinDockWidget::visibilityChanged,
+                this, &DolphinMainWindow::slotTerminalPanelVisibilityChanged);
+
+        QAction* terminalAction = terminalDock->toggleViewAction();
+        createPanelAction(QIcon::fromTheme(QStringLiteral("dialog-scripts")), Qt::Key_F4, terminalAction, QStringLiteral("show_terminal_panel"));
+
+        addDockWidget(Qt::BottomDockWidgetArea, terminalDock);
+        connect(this, &DolphinMainWindow::urlChanged,
+                m_terminalPanel, &TerminalPanel::setUrl);
+
+        if (GeneralSettings::version() < 200) {
+            terminalDock->hide();
+        }
+
+        actionCollection()->action(QStringLiteral("show_terminal_panel"))
+            ->setWhatsThis(xi18nc("@info:whatsthis", "<para>This toggles the "
+            "<emphasis>terminal</emphasis> panel at the bottom of the window."
+            "<nl/>The location in the terminal will always match the folder "
+            "view so you can navigate using either.</para><para>The terminal "
+            "panel is not needed for basic computer usage but can be useful "
+            "for advanced tasks. To learn more about terminals use the help "
+            "in a standalone terminal application like Konsole.</para>"));
+        terminalDock->setWhatsThis(xi18nc("@info:whatsthis", "<para>This is "
+            "the <emphasis>terminal</emphasis> panel. It behaves like a "
+            "normal terminal but will match the location of the folder view "
+            "so you can navigate using either.</para><para>The terminal panel "
+            "is not needed for basic computer usage but can be useful for "
+            "advanced tasks. To learn more about terminals use the help in a "
+            "standalone terminal application like Konsole.</para>") + panelWhatsThis);
+    }
+#endif
+
+    if (GeneralSettings::version() < 200) {
+        infoDock->hide();
+        foldersDock->hide();
+    }
+
+    // Setup "Places"
+    DolphinDockWidget* placesDock = new DolphinDockWidget(i18nc("@title:window", "Places"));
+    placesDock->setLocked(lock);
+    placesDock->setObjectName(QStringLiteral("placesDock"));
+    placesDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+
+    m_placesPanel = new PlacesPanel(placesDock);
+    m_placesPanel->setCustomContextMenuActions({lockLayoutAction});
+    placesDock->setWidget(m_placesPanel);
+
+    QAction *placesAction = placesDock->toggleViewAction();
+    createPanelAction(QIcon::fromTheme(QStringLiteral("bookmarks")), Qt::Key_F9, placesAction, QStringLiteral("show_places_panel"));
+
+    addDockWidget(Qt::LeftDockWidgetArea, placesDock);
+    connect(m_placesPanel, &PlacesPanel::placeActivated,
+            this, &DolphinMainWindow::slotPlaceActivated);
+    connect(m_placesPanel, &PlacesPanel::placeMiddleClicked,
+            this, &DolphinMainWindow::openNewTabAfterCurrentTab);
+    connect(m_placesPanel, &PlacesPanel::errorMessage,
+            this, &DolphinMainWindow::showErrorMessage);
+    connect(this, &DolphinMainWindow::urlChanged,
+            m_placesPanel, &PlacesPanel::setUrl);
+    connect(placesDock, &DolphinDockWidget::visibilityChanged,
+            m_tabWidget, &DolphinTabWidget::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());
+
+    auto actionShowAllPlaces = new QAction(QIcon::fromTheme(QStringLiteral("view-hidden")), i18nc("@item:inmenu", "Show Hidden Places"), this);
+    actionShowAllPlaces->setCheckable(true);
+    actionShowAllPlaces->setDisabled(true);
+    actionShowAllPlaces->setWhatsThis(i18nc("@info:whatsthis", "This displays "
+        "all places in the places panel that have been hidden. They will "
+        "appear semi-transparent unless you uncheck their hide property."));
+
+    connect(actionShowAllPlaces, &QAction::triggered, this, [actionShowAllPlaces, this](bool checked){
+        actionShowAllPlaces->setIcon(QIcon::fromTheme(checked ? QStringLiteral("view-visible") : QStringLiteral("view-hidden")));
+        m_placesPanel->showHiddenEntries(checked);
+    });
+
+    connect(m_placesPanel, &PlacesPanel::showHiddenEntriesChanged, this, [actionShowAllPlaces] (bool checked){
+        actionShowAllPlaces->setChecked(checked);
+        actionShowAllPlaces->setIcon(QIcon::fromTheme(checked ? QStringLiteral("view-visible") : QStringLiteral("view-hidden")));
+   });
+
+    actionCollection()->action(QStringLiteral("show_places_panel"))
+        ->setWhatsThis(xi18nc("@info:whatsthis", "<para>This toggles the "
+        "<emphasis>places</emphasis> panel at the left side of the window."
+        "</para><para>It allows you to go to locations you have "
+        "bookmarked and to access disk or media attached to the computer "
+        "or to the network. It also contains sections to find recently "
+        "saved files or files of a certain type.</para>"));
+    placesDock->setWhatsThis(xi18nc("@info:whatsthis", "<para>This is the "
+        "<emphasis>Places</emphasis> panel. It allows you to go to locations "
+        "you have bookmarked and to access disk or media attached to the "
+        "computer or to the network. It also contains sections to find "
+        "recently saved files or files of a certain type.</para><para>"
+        "Click on an entry to go there. Click with the right mouse button "
+        "instead to open any entry in a new tab or new window.</para>"
+        "<para>New entries can be added by dragging folders onto this panel. "
+        "Right-click any section or entry to hide it. Right-click an empty "
+        "space on this panel and select <interface>Show Hidden Places"
+        "</interface> to display it again.</para>") + panelWhatsThis);
+
+    // Add actions into the "Panels" menu
+    KActionMenu* panelsMenu = new KActionMenu(i18nc("@action:inmenu View", "Show Panels"), this);
+    actionCollection()->addAction(QStringLiteral("panels"), panelsMenu);
+    panelsMenu->setIcon(QIcon::fromTheme(QStringLiteral("view-sidetree")));
+    panelsMenu->setDelayed(false);
+    const KActionCollection* ac = actionCollection();
+    panelsMenu->addAction(ac->action(QStringLiteral("show_places_panel")));
+#ifdef HAVE_BALOO
+    panelsMenu->addAction(ac->action(QStringLiteral("show_information_panel")));
+#endif
+    panelsMenu->addAction(ac->action(QStringLiteral("show_folders_panel")));
+    panelsMenu->addAction(ac->action(QStringLiteral("show_terminal_panel")));
+    panelsMenu->addSeparator();
+    panelsMenu->addAction(actionShowAllPlaces);
+    panelsMenu->addAction(lockLayoutAction);
+
+    connect(panelsMenu->menu(), &QMenu::aboutToShow, this, [actionShowAllPlaces, this]{
+        actionShowAllPlaces->setEnabled(m_placesPanel->hiddenListCount());
+    });
+}
+
+
+void DolphinMainWindow::updateFileAndEditActions()
+{
+    const KFileItemList list = m_activeViewContainer->view()->selectedItems();
+    const KActionCollection* col = actionCollection();
+    QAction* addToPlacesAction = col->action(QStringLiteral("add_to_places"));
+
+    if (list.isEmpty()) {
+        stateChanged(QStringLiteral("has_no_selection"));
+
+        addToPlacesAction->setEnabled(true);
+    } else {
+        stateChanged(QStringLiteral("has_selection"));
+
+        QAction* renameAction            = col->action(KStandardAction::name(KStandardAction::RenameFile));
+        QAction* moveToTrashAction       = col->action(KStandardAction::name(KStandardAction::MoveToTrash));
+        QAction* deleteAction            = col->action(KStandardAction::name(KStandardAction::DeleteFile));
+        QAction* cutAction               = col->action(KStandardAction::name(KStandardAction::Cut));
+        QAction* deleteWithTrashShortcut = col->action(QStringLiteral("delete_shortcut")); // see DolphinViewActionHandler
+        QAction* showTarget              = col->action(QStringLiteral("show_target"));
+        QAction* duplicateAction         = col->action(QStringLiteral("duplicate")); // see DolphinViewActionHandler
+
+        if (list.length() == 1 && list.first().isDir()) {
+            addToPlacesAction->setEnabled(true);
+        } else {
+            addToPlacesAction->setEnabled(false);
+        }
+
+        KFileItemListProperties capabilities(list);
+        const bool enableMoveToTrash = capabilities.isLocal() && capabilities.supportsMoving();
+
+        renameAction->setEnabled(capabilities.supportsMoving());
+        moveToTrashAction->setEnabled(enableMoveToTrash);
+        deleteAction->setEnabled(capabilities.supportsDeleting());
+        deleteWithTrashShortcut->setEnabled(capabilities.supportsDeleting() && !enableMoveToTrash);
+        cutAction->setEnabled(capabilities.supportsMoving());
+        showTarget->setEnabled(list.length() == 1 && list.at(0).isLink());
+        duplicateAction->setEnabled(capabilities.supportsWriting());
+    }
+}
+
+void DolphinMainWindow::updateViewActions()
+{
+    m_actionHandler->updateViewActions();
+
+    QAction* showFilterBarAction = actionCollection()->action(QStringLiteral("show_filter_bar"));
+    showFilterBarAction->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()
+{
+    QAction* goUpAction = actionCollection()->action(KStandardAction::name(KStandardAction::Up));
+    const QUrl currentUrl = m_activeViewContainer->url();
+    // I think this is one of the best places to firstly be confronted
+    // with a file system and its hierarchy. Talking about the root
+    // directory might seem too much here but it is the question that
+    // naturally arises in this context.
+    goUpAction->setWhatsThis(xi18nc("@info:whatsthis", "<para>Go to "
+        "the folder that contains the currently viewed one.</para>"
+        "<para>All files and folders are organized in a hierarchical "
+        "<emphasis>file system</emphasis>. At the top of this hierarchy is "
+        "a directory that contains all data connected to this computer"
+        "—the <emphasis>root directory</emphasis>.</para>"));
+    goUpAction->setEnabled(KIO::upUrl(currentUrl) != currentUrl);
+}
+
+void DolphinMainWindow::createControlButton()
+{
+    if (m_controlButton) {
+        return;
+    }
+    Q_ASSERT(!m_controlButton);
+
+    m_controlButton = new QToolButton(this);
+    m_controlButton->setAccessibleName(i18nc("@action:intoolbar", "Control"));
+    m_controlButton->setIcon(QIcon::fromTheme(QStringLiteral("application-menu")));
+    m_controlButton->setToolTip(i18nc("@action", "Show menu"));
+    m_controlButton->setAttribute(Qt::WidgetAttribute::WA_CustomWhatsThis);
+    m_controlButton->setPopupMode(QToolButton::InstantPopup);
+
+    QMenu* controlMenu = new QMenu(m_controlButton);
+    connect(controlMenu, &QMenu::aboutToShow, this, &DolphinMainWindow::updateControlMenu);
+    controlMenu->installEventFilter(this);
+
+    m_controlButton->setMenu(controlMenu);
+
+    toolBar()->addWidget(m_controlButton);
+    connect(toolBar(), &KToolBar::iconSizeChanged,
+            m_controlButton, &QToolButton::setIconSize);
+
+    // The added widgets are owned by the toolbar and may get deleted when e.g. the toolbar
+    // gets edited. In this case we must add them again. The adding is done asynchronously by
+    // m_updateToolBarTimer.
+    connect(m_controlButton, &QToolButton::destroyed, this, &DolphinMainWindow::slotControlButtonDeleted);
+    m_updateToolBarTimer = new QTimer(this);
+    m_updateToolBarTimer->setInterval(500);
+    connect(m_updateToolBarTimer, &QTimer::timeout, this, &DolphinMainWindow::updateToolBar);
+}
+
+void DolphinMainWindow::deleteControlButton()
+{
+    delete m_controlButton;
+    m_controlButton = nullptr;
+
+    delete m_updateToolBarTimer;
+    m_updateToolBarTimer = nullptr;
+}
+
+bool DolphinMainWindow::addActionToMenu(QAction* action, QMenu* menu)
+{
+    Q_ASSERT(action);
+    Q_ASSERT(menu);
+
+    const KToolBar* toolBarWidget = toolBar();
+    foreach (const QWidget* widget, action->associatedWidgets()) {
+        if (widget == toolBarWidget) {
+            return false;
+        }
+    }
+
+    menu->addAction(action);
+    return true;
+}
+
+void DolphinMainWindow::refreshViews()
+{
+    m_tabWidget->refreshViews();
+
+    if (GeneralSettings::modifiedStartupSettings()) {
+        // The startup settings have been changed by the user (see bug #254947).
+        // Synchronize the split-view setting with the active view:
+        const bool splitView = GeneralSettings::splitView();
+        m_tabWidget->currentTabPage()->setSplitViewEnabled(splitView);
+        updateSplitAction();
+        updateWindowTitle();
+    }
+
+    emit settingsChanged();
+}
+
+void DolphinMainWindow::clearStatusBar()
+{
+    m_activeViewContainer->statusBar()->resetToDefaultText();
+}
+
+void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
+{
+    connect(container, &DolphinViewContainer::showFilterBarChanged,
+            this, &DolphinMainWindow::updateFilterBarAction);
+    connect(container, &DolphinViewContainer::writeStateChanged,
+            this, &DolphinMainWindow::slotWriteStateChanged);
+    connect(container, &DolphinViewContainer::searchModeEnabledChanged,
+            this, &DolphinMainWindow::updateSearchAction);
+
+    const QAction* toggleSearchAction = actionCollection()->action(QStringLiteral("toggle_search"));
+    connect(toggleSearchAction, &QAction::triggered, container, &DolphinViewContainer::setSearchModeEnabled);
+
+    const DolphinView* view = container->view();
+    connect(view, &DolphinView::selectionChanged,
+            this, &DolphinMainWindow::slotSelectionChanged);
+    connect(view, &DolphinView::requestItemInfo,
+            this, &DolphinMainWindow::requestItemInfo);
+    connect(view, &DolphinView::tabRequested,
+            this, &DolphinMainWindow::openNewTab);
+    connect(view, &DolphinView::requestContextMenu,
+            this, &DolphinMainWindow::openContextMenu);
+    connect(view, &DolphinView::directoryLoadingStarted,
+            this, &DolphinMainWindow::enableStopAction);
+    connect(view, &DolphinView::directoryLoadingCompleted,
+            this, &DolphinMainWindow::disableStopAction);
+    connect(view, &DolphinView::directoryLoadingCompleted,
+            this, &DolphinMainWindow::slotDirectoryLoadingCompleted);
+    connect(view, &DolphinView::goBackRequested,
+            this, &DolphinMainWindow::goBack);
+    connect(view, &DolphinView::goForwardRequested,
+            this, &DolphinMainWindow::goForward);
+    connect(view, &DolphinView::urlActivated,
+            this, &DolphinMainWindow::handleUrl);
+
+    const KUrlNavigator* navigator = container->urlNavigator();
+    connect(navigator, &KUrlNavigator::urlChanged,
+            this, &DolphinMainWindow::changeUrl);
+    connect(navigator, &KUrlNavigator::historyChanged,
+            this, &DolphinMainWindow::updateHistory);
+    connect(navigator, &KUrlNavigator::editableStateChanged,
+            this, &DolphinMainWindow::slotEditableStateChanged);
+    connect(navigator, &KUrlNavigator::tabRequested,
+            this, &DolphinMainWindow::openNewTabAfterLastTab);
+}
+
+void DolphinMainWindow::updateSplitAction()
+{
+    QAction* splitAction = actionCollection()->action(QStringLiteral("split_view"));
+    const DolphinTabPage* tabPage = m_tabWidget->currentTabPage();
+    if (tabPage->splitViewEnabled()) {
+        if (GeneralSettings::closeActiveSplitView() ? tabPage->primaryViewActive() : !tabPage->primaryViewActive()) {
+            splitAction->setText(i18nc("@action:intoolbar Close left view", "Close"));
+            splitAction->setToolTip(i18nc("@info", "Close left view"));
+            splitAction->setIcon(QIcon::fromTheme(QStringLiteral("view-left-close")));
+        } else {
+            splitAction->setText(i18nc("@action:intoolbar Close right view", "Close"));
+            splitAction->setToolTip(i18nc("@info", "Close right view"));
+            splitAction->setIcon(QIcon::fromTheme(QStringLiteral("view-right-close")));
+        }
+    } else {
+        splitAction->setText(i18nc("@action:intoolbar Split view", "Split"));
+        splitAction->setToolTip(i18nc("@info", "Split view"));
+        splitAction->setIcon(QIcon::fromTheme(QStringLiteral("view-right-new")));
+    }
+}
+
+bool DolphinMainWindow::isKompareInstalled() const
+{
+    static bool initialized = false;
+    static bool installed = false;
+    if (!initialized) {
+        // TODO: maybe replace this approach later by using a menu
+        // plugin like kdiff3plugin.cpp
+        installed = !QStandardPaths::findExecutable(QStringLiteral("kompare")).isEmpty();
+        initialized = true;
+    }
+    return installed;
+}
+
+void DolphinMainWindow::createPanelAction(const QIcon& icon,
+                                          const QKeySequence& shortcut,
+                                          QAction* dockAction,
+                                          const QString& actionName)
+{
+    QAction* panelAction = actionCollection()->addAction(actionName);
+    panelAction->setCheckable(true);
+    panelAction->setChecked(dockAction->isChecked());
+    panelAction->setText(dockAction->text());
+    panelAction->setIcon(icon);
+    actionCollection()->setDefaultShortcut(panelAction, shortcut);
+
+    connect(panelAction, &QAction::triggered, dockAction, &QAction::trigger);
+    connect(dockAction, &QAction::toggled, panelAction, &QAction::setChecked);
+}
+
+void DolphinMainWindow::setupWhatsThis()
+{
+    // main widgets
+    menuBar()->setWhatsThis(xi18nc("@info:whatsthis", "<para>This is the "
+        "<emphasis>Menubar</emphasis>. It provides access to commands and "
+        "configuration options. Left-click on any of the menus on this "
+        "bar to see its contents.</para><para>The Menubar can be hidden "
+        "by unchecking <interface>Settings|Show Menubar</interface>. Then "
+        "most of its contents become available through a <interface>Control"
+        "</interface> button on the <emphasis>Toolbar</emphasis>.</para>"));
+    toolBar()->setWhatsThis(xi18nc("@info:whatsthis", "<para>This is the "
+        "<emphasis>Toolbar</emphasis>. It allows quick access to "
+        "frequently used actions.</para><para>It is highly customizable. "
+        "All items you see in the <interface>Control</interface> menu or "
+        "in the <interface>Menubar</interface> can be placed on the "
+        "Toolbar. Just right-click on it and select <interface>Configure "
+        "Toolbars…</interface> or find this action in the <interface>"
+        "Control</interface> or <interface>Settings</interface> menu."
+        "</para><para>The location of the bar and the style of its "
+        "buttons can also be changed in the right-click menu. Right-click "
+        "a button if you want to show or hide its text.</para>"));
+    m_tabWidget->setWhatsThis(xi18nc("@info:whatsthis main view",
+        "<para>Here you can see the <emphasis>folders</emphasis> and "
+        "<emphasis>files</emphasis> that are at the location described in "
+        "the <interface>Location Bar</interface> above. This area is the "
+        "central part of this application where you navigate to the files "
+        "you want to use.</para><para>For an elaborate and general "
+        "introduction to this application <link "
+        "url='https://userbase.kde.org/Dolphin/File_Management#Introduction_to_Dolphin'>"
+        "click here</link>. This will open an introductory article from "
+        "the <emphasis>KDE UserBase Wiki</emphasis>.</para><para>For brief "
+        "explanations of all the features of this <emphasis>view</emphasis> "
+        "<link url='help:/dolphin/dolphin-view.html'>click here</link> "
+        "instead. This will open a page from the <emphasis>Handbook"
+        "</emphasis> that covers the basics.</para>"));
+
+    // Settings menu
+    actionCollection()->action(KStandardAction::name(KStandardAction::KeyBindings))
+        ->setWhatsThis(xi18nc("@info:whatsthis","<para>This opens a window "
+        "that lists the <emphasis>keyboard shortcuts</emphasis>.<nl/>"
+        "There you can set up key combinations to trigger an action when "
+        "they are pressed simultaneously. All commands in this application can "
+        "be triggered this way.</para>"));
+    actionCollection()->action(KStandardAction::name(KStandardAction::ConfigureToolbars))
+        ->setWhatsThis(xi18nc("@info:whatsthis","<para>This opens a window in which "
+        "you can change which buttons appear on the <emphasis>Toolbar</emphasis>.</para>"
+        "<para>All items you see in the <interface>Control</interface> menu "
+        "or in the <interface>Menubar</interface> can also be placed on the Toolbar.</para>"));
+    actionCollection()->action(KStandardAction::name(KStandardAction::Preferences))
+        ->setWhatsThis(xi18nc("@info:whatsthis","This opens a window where you can "
+        "change a multitude of settings for this application. For an explanation "
+        "of the various settings go to the chapter <emphasis>Configuring Dolphin"
+        "</emphasis> in <interface>Help|Dolphin Handbook</interface>."));
+
+    // Help menu
+    // The whatsthis has to be set for the m_helpMenu and for the
+    // StandardAction separately because both are used in different locations.
+    // m_helpMenu is only used for createControlButton() button.
+
+    // Links do not work within the Menubar so texts without links are provided there.
+
+    // i18n: If the external link isn't available in your language you should
+    // probably state the external link language at least in brackets to not
+    // frustrate the user. If there are multiple languages that the user might
+    // know with a reasonable chance you might want to have 2 external links.
+    // The same is in my opinion true for every external link you translate.
+    const QString whatsThisHelpContents = xi18nc("@info:whatsthis handbook",
+        "<para>This opens the Handbook for this application. It provides "
+        "explanations for every part of <emphasis>Dolphin</emphasis>.</para>");
+    actionCollection()->action(KStandardAction::name(KStandardAction::HelpContents))
+        ->setWhatsThis(whatsThisHelpContents
+        + xi18nc("@info:whatsthis second half of handbook hb text without link",
+        "<para>If you want more elaborate introductions to the "
+        "different features of <emphasis>Dolphin</emphasis> "
+        "go to the KDE UserBase Wiki.</para>"));
+    m_helpMenu->action(KHelpMenu::menuHelpContents)->setWhatsThis(whatsThisHelpContents
+        + xi18nc("@info:whatsthis second half of handbook text with link",
+        "<para>If you want more elaborate introductions to the "
+        "different features of <emphasis>Dolphin</emphasis> "
+        "<link url='https://userbase.kde.org/Dolphin/File_Management'>click here</link>. "
+        "It will open the dedicated page in the KDE UserBase Wiki.</para>"));
+
+    const QString whatsThisWhatsThis = xi18nc("@info:whatsthis whatsthis button",
+        "<para>This is the button that invokes the help feature you are "
+        "using right now! Click it, then click any component of this "
+        "application to ask \"What's this?\" about it. The mouse cursor "
+        "will change appearance if no help is available for a spot.</para>");
+    actionCollection()->action(KStandardAction::name(KStandardAction::WhatsThis))
+       ->setWhatsThis(whatsThisWhatsThis
+        + xi18nc("@info:whatsthis second half of whatsthis button text without link",
+        "<para>There are two other ways to get help for this application: The "
+        "<interface>Dolphin Handbook</interface> in the <interface>Help"
+        "</interface> menu and the <emphasis>KDE UserBase Wiki</emphasis> "
+        "article about <emphasis>File Management</emphasis> online."
+        "</para><para>The \"What's this?\" help is "
+        "missing in most other windows so don't get too used to this.</para>"));
+    m_helpMenu->action(KHelpMenu::menuWhatsThis)->setWhatsThis(whatsThisWhatsThis
+        + xi18nc("@info:whatsthis second half of whatsthis button text with link",
+        "<para>There are two other ways to get help: "
+        "The <link url='help:/dolphin/index.html'>Dolphin Handbook</link> and "
+        "the <link url='https://userbase.kde.org/Dolphin/File_Management'>KDE "
+        "UserBase Wiki</link>.</para><para>The \"What's this?\" help is "
+        "missing in most other windows so don't get too used to this.</para>"));
+
+    const QString whatsThisReportBug = xi18nc("@info:whatsthis","<para>This opens a "
+        "window that will guide you through reporting errors or flaws "
+        "in this application or in other KDE software.</para>");
+    actionCollection()->action(KStandardAction::name(KStandardAction::ReportBug))
+       ->setWhatsThis(whatsThisReportBug);
+    m_helpMenu->action(KHelpMenu::menuReportBug)->setWhatsThis(whatsThisReportBug
+        + xi18nc("@info:whatsthis second half of reportbug text with link",
+        "<para>High-quality bug reports are much appreciated. To learn "
+        "how to make your bug report as effective as possible "
+        "<link url='https://community.kde.org/Get_Involved/Bug_Reporting'>"
+        "click here</link>.</para>"));
+
+    const QString whatsThisDonate = xi18nc("@info:whatsthis","<para>This opens a "
+        "<emphasis>web page</emphasis> where you can donate to "
+        "support the continued work on this application and many "
+        "other projects by the <emphasis>KDE</emphasis> community.</para>"
+        "<para>Donating is the easiest and fastest way to efficiently "
+        "support KDE and its projects. KDE projects are available for "
+        "free therefore your donation is needed to cover things that "
+        "require money like servers, contributor meetings, etc.</para>"
+        "<para><emphasis>KDE e.V.</emphasis> is the non-profit "
+        "organization behind the KDE community.</para>");
+    actionCollection()->action(KStandardAction::name(KStandardAction::Donate))
+       ->setWhatsThis(whatsThisDonate);
+    m_helpMenu->action(KHelpMenu::menuDonate)->setWhatsThis(whatsThisDonate);
+
+    const QString whatsThisSwitchLanguage = xi18nc("@info:whatsthis",
+        "With this you can change the language this application uses."
+        "<nl/>You can even set secondary languages which will be used "
+        "if texts are not available in your preferred language.");
+    actionCollection()->action(KStandardAction::name(KStandardAction::SwitchApplicationLanguage))
+       ->setWhatsThis(whatsThisSwitchLanguage);
+    m_helpMenu->action(KHelpMenu::menuSwitchLanguage)->setWhatsThis(whatsThisSwitchLanguage);
+
+    const QString whatsThisAboutApp = xi18nc("@info:whatsthis","This opens a "
+        "window that informs you about the version, license, "
+        "used libraries and maintainers of this application.");
+    actionCollection()->action(KStandardAction::name(KStandardAction::AboutApp))
+       ->setWhatsThis(whatsThisAboutApp);
+    m_helpMenu->action(KHelpMenu::menuAboutApp)->setWhatsThis(whatsThisAboutApp);
+
+    const QString whatsThisAboutKDE = xi18nc("@info:whatsthis","This opens a "
+        "window with information about <emphasis>KDE</emphasis>. "
+        "The KDE community are the people behind this free software."
+        "<nl/>If you like using this application but don't know "
+        "about KDE or want to see a cute dragon have a look!");
+    actionCollection()->action(KStandardAction::name(KStandardAction::AboutKDE))
+       ->setWhatsThis(whatsThisAboutKDE);
+    m_helpMenu->action(KHelpMenu::menuAboutKDE)->setWhatsThis(whatsThisAboutKDE);
+}
+
+bool DolphinMainWindow::event(QEvent *event)
+{
+    if (event->type() == QEvent::WhatsThisClicked) {
+        event->accept();
+        QWhatsThisClickedEvent* whatsThisEvent = dynamic_cast<QWhatsThisClickedEvent*>(event);
+        QDesktopServices::openUrl(QUrl(whatsThisEvent->href()));
+        return true;
+    }
+    return KXmlGuiWindow::event(event);
+}
+
+bool DolphinMainWindow::eventFilter(QObject* obj, QEvent* event)
+{
+    Q_UNUSED(obj)
+    if (event->type() == QEvent::WhatsThisClicked) {
+        event->accept();
+        QWhatsThisClickedEvent* whatsThisEvent = dynamic_cast<QWhatsThisClickedEvent*>(event);
+        QDesktopServices::openUrl(QUrl(whatsThisEvent->href()));
+        return true;
+    }
+    return false;
+}
+
+void DolphinMainWindow::focusTerminalPanel()
+{
+    if (m_terminalPanel->isVisible()) {
+        if (m_terminalPanel->terminalHasFocus()) {
+            m_activeViewContainer->view()->setFocus(Qt::FocusReason::ShortcutFocusReason);
+            actionCollection()->action(QStringLiteral("focus_terminal_panel"))->setText(i18nc("@action:inmenu Tools", "Focus Terminal Panel"));
+        } else {
+            m_terminalPanel->setFocus(Qt::FocusReason::ShortcutFocusReason);
+            actionCollection()->action(QStringLiteral("focus_terminal_panel"))->setText(i18nc("@action:inmenu Tools", "Defocus Terminal Panel"));
+        }
+    } else {
+        actionCollection()->action(QStringLiteral("show_terminal_panel"))->trigger();
+        actionCollection()->action(QStringLiteral("focus_terminal_panel"))->setText(i18nc("@action:inmenu Tools", "Defocus Terminal Panel"));
+    }
+}
+
+DolphinMainWindow::UndoUiInterface::UndoUiInterface() :
+    KIO::FileUndoManager::UiInterface()
+{
+}
+
+DolphinMainWindow::UndoUiInterface::~UndoUiInterface()
+{
+}
+
+void DolphinMainWindow::UndoUiInterface::jobError(KIO::Job* job)
+{
+    DolphinMainWindow* mainWin= qobject_cast<DolphinMainWindow *>(parentWidget());
+    if (mainWin) {
+        DolphinViewContainer* container = mainWin->activeViewContainer();
+        container->showMessage(job->errorString(), DolphinViewContainer::Error);
+    } else {
+        KIO::FileUndoManager::UiInterface::jobError(job);
+    }
+}
+
+bool DolphinMainWindow::isUrlOpen(const QString& url)
+{
+    return m_tabWidget->isUrlOpen(QUrl::fromUserInput((url)));
+}
+