]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/dolphinmainwindow.cpp
Interface cleanups to prepare the return of "grouped sorting"
[dolphin.git] / src / dolphinmainwindow.cpp
index e5cc9901f2603e2e4b74df910307a6a45b1defdf..34ff8b71bf1e125456b06ce7601985b41d07b1c8 100644 (file)
@@ -28,7 +28,6 @@
 #include "dolphincontextmenu.h"
 #include "dolphinnewfilemenu.h"
 #include "dolphinviewcontainer.h"
-#include "mainwindowadaptor.h"
 #ifdef HAVE_NEPOMUK
     #include "panels/search/searchpanel.h"
     #include <Nepomuk/ResourceManager>
 #include "panels/folders/folderspanel.h"
 #include "panels/places/placespanel.h"
 #include "panels/information/informationpanel.h"
+#include "search/dolphinsearchbox.h"
 #include "search/dolphinsearchinformation.h"
 #include "settings/dolphinsettings.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"
 
 #ifndef Q_OS_WIN
@@ -50,7 +49,6 @@
 #endif
 
 #include "dolphin_generalsettings.h"
-#include "dolphin_iconsmodesettings.h"
 #include "dolphin_searchsettings.h"
 
 #include <KAcceleratorManager>
 #include <KUrlComboBox>
 #include <KToolInvocation>
 
+#include <QDesktopWidget>
 #include <QDBusMessage>
 #include <QKeyEvent>
 #include <QClipboard>
 #include <QToolButton>
 #include <QSplitter>
 
+namespace {
+    // Used for GeneralSettings::version() to determine whether
+    // an updated version of Dolphin is running.
+    const int CurrentDolphinVersion = 200;
+};
+
+/*
+ * Menu shown when pressing the configure-button in the toolbar.
+ */
+class ToolBarMenu : public KMenu
+{
+public:
+    ToolBarMenu(QWidget* parent);
+    virtual ~ToolBarMenu();
+protected:
+    virtual void showEvent(QShowEvent* event);
+};
+
 /*
  * Remembers the tab configuration if a tab has been closed.
  * Each closed tab can be restored by the menu
@@ -109,21 +126,19 @@ struct ClosedTab
 };
 Q_DECLARE_METATYPE(ClosedTab)
 
-DolphinMainWindow::DolphinMainWindow(int id) :
+DolphinMainWindow::DolphinMainWindow() :
     KXmlGuiWindow(0),
     m_newFileMenu(0),
     m_tabBar(0),
     m_activeViewContainer(0),
     m_centralWidgetLayout(0),
-    m_id(id),
     m_tabIndex(0),
     m_viewTab(),
     m_actionHandler(0),
     m_remoteEncoding(0),
-    m_settingsDialog(0),
+    m_settingsDialog(),
     m_toolBarSpacer(0),
     m_openToolBarMenuButton(0),
-    m_toolBarMenu(),
     m_updateToolBarTimer(0),
     m_lastHandleUrlStatJob(0),
     m_searchDockIsTemporaryVisible(false)
@@ -137,29 +152,121 @@ DolphinMainWindow::DolphinMainWindow(int id) :
 
     m_viewTab.append(ViewTab());
 
-    new MainWindowAdaptor(this);
-    QDBusConnection::sessionBus().registerObject(QString("/dolphin/MainWindow%1").arg(m_id), this);
-
     KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
     undoManager->setUiInterface(new UndoUiInterface());
 
     connect(undoManager, SIGNAL(undoAvailable(bool)),
             this, SLOT(slotUndoAvailable(bool)));
-    connect(undoManager, SIGNAL(undoTextChanged(const QString&)),
-            this, SLOT(slotUndoTextChanged(const QString&)));
+    connect(undoManager, SIGNAL(undoTextChanged(QString)),
+            this, SLOT(slotUndoTextChanged(QString)));
     connect(undoManager, SIGNAL(jobRecordingStarted(CommandType)),
             this, SLOT(clearStatusBar()));
     connect(undoManager, SIGNAL(jobRecordingFinished(CommandType)),
             this, SLOT(showCommand(CommandType)));
-    connect(DolphinSettings::instance().placesModel(), SIGNAL(errorMessage(const QString&)),
-            this, SLOT(showErrorMessage(const QString&)));
-    connect(&DragAndDropHelper::instance(), SIGNAL(errorMessage(const QString&)),
-            this, SLOT(showErrorMessage(const QString&)));
+    connect(DolphinSettings::instance().placesModel(), SIGNAL(errorMessage(QString)),
+            this, SLOT(showErrorMessage(QString)));
+    //connect(&DragAndDropHelper::instance(), SIGNAL(errorMessage(QString)),
+    //        this, SLOT(showErrorMessage(QString)));
+
+    const DolphinSettings& settings = DolphinSettings::instance();
+
+    GeneralSettings* generalSettings = settings.generalSettings();
+    const bool firstRun = (generalSettings->version() < 200);
+    if (firstRun) {
+        generalSettings->setViewPropsTimestamp(QDateTime::currentDateTime());
+    }
+
+    setAcceptDrops(true);
+
+    m_viewTab[m_tabIndex].splitter = new QSplitter(this);
+    m_viewTab[m_tabIndex].splitter->setChildrenCollapsible(false);
+
+    setupActions();
+
+    const KUrl homeUrl(generalSettings->homeUrl());
+    setUrlAsCaption(homeUrl);
+    m_actionHandler = new DolphinViewActionHandler(actionCollection(), this);
+    connect(m_actionHandler, SIGNAL(actionBeingHandled()), SLOT(clearStatusBar()));
+    connect(m_actionHandler, SIGNAL(createDirectory()), SLOT(createDirectory()));
+
+    m_viewTab[m_tabIndex].primaryView = createViewContainer(homeUrl, m_viewTab[m_tabIndex].splitter);
+
+    m_activeViewContainer = m_viewTab[m_tabIndex].primaryView;
+    connectViewSignals(m_activeViewContainer);
+    DolphinView* view = m_activeViewContainer->view();
+    m_activeViewContainer->show();
+    m_actionHandler->setCurrentView(view);
+
+    m_remoteEncoding = new DolphinRemoteEncoding(this, m_actionHandler);
+    connect(this, SIGNAL(urlChanged(KUrl)),
+            m_remoteEncoding, SLOT(slotAboutToOpenUrl()));
+
+    m_tabBar = new KTabBar(this);
+    m_tabBar->setMovable(true);
+    m_tabBar->setTabsClosable(true);
+    connect(m_tabBar, SIGNAL(currentChanged(int)),
+            this, SLOT(setActiveTab(int)));
+    connect(m_tabBar, SIGNAL(tabCloseRequested(int)),
+            this, SLOT(closeTab(int)));
+    connect(m_tabBar, SIGNAL(contextMenu(int,QPoint)),
+            this, SLOT(openTabContextMenu(int,QPoint)));
+    connect(m_tabBar, SIGNAL(newTabRequest()),
+            this, SLOT(openNewTab()));
+    connect(m_tabBar, SIGNAL(testCanDecode(const QDragMoveEvent*,bool&)),
+            this, SLOT(slotTestCanDecode(const QDragMoveEvent*,bool&)));
+    connect(m_tabBar, SIGNAL(mouseMiddleClick(int)),
+            this, SLOT(closeTab(int)));
+    connect(m_tabBar, SIGNAL(tabMoved(int,int)),
+            this, SLOT(slotTabMoved(int,int)));
+    connect(m_tabBar, SIGNAL(receivedDropEvent(int,QDropEvent*)),
+            this, SLOT(tabDropEvent(int,QDropEvent*)));
+
+    m_tabBar->blockSignals(true);  // signals get unblocked after at least 2 tabs are open
+
+    QWidget* centralWidget = new QWidget(this);
+    m_centralWidgetLayout = new QVBoxLayout(centralWidget);
+    m_centralWidgetLayout->setSpacing(0);
+    m_centralWidgetLayout->setMargin(0);
+    m_centralWidgetLayout->addWidget(m_tabBar);
+    m_centralWidgetLayout->addWidget(m_viewTab[m_tabIndex].splitter, 1);
+
+    setCentralWidget(centralWidget);
+    setupDockWidgets();
+    emit urlChanged(homeUrl);
+
+    setupGUI(Keys | Save | Create | ToolBar);
+    stateChanged("new_file");
+
+    QClipboard* clipboard = QApplication::clipboard();
+    connect(clipboard, SIGNAL(dataChanged()),
+            this, SLOT(updatePasteAction()));
+
+    if (generalSettings->splitView()) {
+        toggleSplitView();
+    }
+    updateEditActions();
+    updateViewActions();
+    updateGoActions();
+
+    QAction* showFilterBarAction = actionCollection()->action("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) {
+        createToolBarMenuButton();
+    }
 }
 
 DolphinMainWindow::~DolphinMainWindow()
 {
-    DolphinApplication::app()->removeMainWindow(this);
 }
 
 void DolphinMainWindow::openDirectories(const QList<KUrl>& dirs)
@@ -192,7 +299,7 @@ void DolphinMainWindow::openDirectories(const QList<KUrl>& dirs)
         }
     }
 
-    // remove the previously opened tabs
+    // Remove the previously opened tabs
     for (int i = 0; i < oldOpenTabsCount; ++i) {
         closeTab(0);
     }
@@ -223,8 +330,10 @@ void DolphinMainWindow::openFiles(const QList<KUrl>& files)
     const int tabCount = m_viewTab.count();
     for (int i = 0; i < tabCount; ++i) {
         m_viewTab[i].primaryView->view()->markUrlsAsSelected(files);
+        m_viewTab[i].primaryView->view()->markUrlAsCurrent(files.at(0));
         if (m_viewTab[i].secondaryView) {
             m_viewTab[i].secondaryView->view()->markUrlsAsSelected(files);
+            m_viewTab[i].secondaryView->view()->markUrlAsCurrent(files.at(0));
         }
     }
 }
@@ -264,39 +373,6 @@ void DolphinMainWindow::showCommand(CommandType command)
     }
 }
 
-void DolphinMainWindow::refreshViews()
-{
-    Q_ASSERT(m_viewTab[m_tabIndex].primaryView);
-
-    // remember the current active view, as because of
-    // the refreshing the active view might change to
-    // the secondary view
-    DolphinViewContainer* activeViewContainer = m_activeViewContainer;
-
-    const int tabCount = m_viewTab.count();
-    for (int i = 0; i < tabCount; ++i) {
-        m_viewTab[i].primaryView->refresh();
-        if (m_viewTab[i].secondaryView) {
-            m_viewTab[i].secondaryView->refresh();
-        }
-    }
-
-    setActiveViewContainer(activeViewContainer);
-
-    const GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings();
-    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();
-        const ViewTab& activeTab = m_viewTab[m_tabIndex];
-        const bool toggle =    ( splitView && !activeTab.secondaryView)
-                            || (!splitView &&  activeTab.secondaryView);
-        if (toggle) {
-            toggleSplitView();
-        }
-    }
-}
-
 void DolphinMainWindow::pasteIntoFolder()
 {
     m_activeViewContainer->view()->pasteIntoFolder();
@@ -365,14 +441,14 @@ void DolphinMainWindow::updateHistory()
     const int index = urlNavigator->historyIndex();
 
     QAction* backAction = actionCollection()->action("go_back");
-    backAction->setToolTip(i18nc("@info", "Go back"));
     if (backAction) {
+        backAction->setToolTip(i18nc("@info", "Go back"));
         backAction->setEnabled(index < urlNavigator->historySize() - 1);
     }
 
     QAction* forwardAction = actionCollection()->action("go_forward");
-    forwardAction->setToolTip(i18nc("@info", "Go forward"));
     if (forwardAction) {
+        forwardAction->setToolTip(i18nc("@info", "Go forward"));
         forwardAction->setEnabled(index > 0);
     }
 }
@@ -385,7 +461,7 @@ void DolphinMainWindow::updateFilterBarAction(bool show)
 
 void DolphinMainWindow::openNewMainWindow()
 {
-    DolphinApplication::app()->createMainWindow()->show();
+    KRun::run("dolphin", KUrl::List(), this);
 }
 
 void DolphinMainWindow::openNewTab()
@@ -495,9 +571,7 @@ void DolphinMainWindow::openInNewWindow()
     }
 
     if (!newWindowUrl.isEmpty()) {
-        DolphinMainWindow* window = DolphinApplication::app()->createMainWindow();
-        window->changeUrl(newWindowUrl);
-        window->show();
+        KRun::run("dolphin", KUrl::List() << newWindowUrl, this);
     }
 }
 
@@ -579,8 +653,7 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event)
         }
     }
 
-    generalSettings->setFirstRun(false);
-
+    generalSettings->setVersion(CurrentDolphinVersion);
     settings.save();
 
     if (m_searchDockIsTemporaryVisible) {
@@ -657,14 +730,14 @@ void DolphinMainWindow::readProperties(const KConfigGroup& group)
 
 void DolphinMainWindow::updateNewMenu()
 {
-    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->showHiddenFiles());
+    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
     m_newFileMenu->checkUpToDate();
     m_newFileMenu->setPopupFiles(activeViewContainer()->url());
 }
 
 void DolphinMainWindow::createDirectory()
 {
-    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->showHiddenFiles());
+    m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
     m_newFileMenu->setPopupFiles(activeViewContainer()->url());
     m_newFileMenu->createDirectory();
 }
@@ -754,6 +827,23 @@ void DolphinMainWindow::find()
     m_activeViewContainer->setSearchModeEnabled(true);
 }
 
+void DolphinMainWindow::slotSearchLocationChanged()
+{
+#ifdef HAVE_NEPOMUK
+    QDockWidget* searchDock = findChild<QDockWidget*>("searchDock");
+    if (!searchDock) {
+        return;
+    }
+
+    SearchPanel* searchPanel = qobject_cast<SearchPanel*>(searchDock->widget());
+    if (searchPanel) {
+        searchPanel->setSearchLocation(SearchSettings::location() == QLatin1String("FromHere")
+                                       ? SearchPanel::FromCurrentDir
+                                       : SearchPanel::Everywhere);
+    }
+#endif
+}
+
 void DolphinMainWindow::updatePasteAction()
 {
     QAction* pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste));
@@ -891,8 +981,6 @@ void DolphinMainWindow::slotPlacesPanelVisibilityChanged(bool visible)
 
 void DolphinMainWindow::goBack()
 {
-    clearStatusBar();
-
     KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
     urlNavigator->goBack();
 
@@ -905,16 +993,19 @@ void DolphinMainWindow::goBack()
 
 void DolphinMainWindow::goForward()
 {
-    clearStatusBar();
     m_activeViewContainer->urlNavigator()->goForward();
 }
 
 void DolphinMainWindow::goUp()
 {
-    clearStatusBar();
     m_activeViewContainer->urlNavigator()->goUp();
 }
 
+void DolphinMainWindow::goHome()
+{
+    m_activeViewContainer->urlNavigator()->goHome();
+}
+
 void DolphinMainWindow::goBack(Qt::MouseButtons buttons)
 {
     // The default case (left button pressed) is handled in goBack().
@@ -1029,11 +1120,13 @@ void DolphinMainWindow::editSettings()
 {
     if (!m_settingsDialog) {
         const KUrl url = activeViewContainer()->url();
-        m_settingsDialog = new DolphinSettingsDialog(url, this);
-        m_settingsDialog->setAttribute(Qt::WA_DeleteOnClose);
-        m_settingsDialog->show();
+        DolphinSettingsDialog* settingsDialog = new DolphinSettingsDialog(url, this);
+        connect(settingsDialog, SIGNAL(settingsChanged()), this, SLOT(refreshViews()));
+        settingsDialog->setAttribute(Qt::WA_DeleteOnClose);
+        settingsDialog->show();
+        m_settingsDialog = settingsDialog;
     } else {
-        m_settingsDialog->raise();
+        m_settingsDialog.data()->raise();
     }
 }
 
@@ -1140,25 +1233,20 @@ void DolphinMainWindow::openTabContextMenu(int index, const QPoint& pos)
         openNewTab(url);
         m_tabBar->setCurrentIndex(m_viewTab.count() - 1);
     } else if (selectedAction == detachTabAction) {
+        const QString separator(QLatin1Char(' '));
+        QString command = QLatin1String("dolphin");
+
         const ViewTab& tab = m_viewTab[index];
         Q_ASSERT(tab.primaryView);
-        const KUrl primaryUrl = tab.primaryView->url();
-        DolphinMainWindow* window = DolphinApplication::app()->createMainWindow();
-        window->changeUrl(primaryUrl);
 
+        command += separator + tab.primaryView->url().url();
         if (tab.secondaryView) {
-            const KUrl secondaryUrl = tab.secondaryView->url();
-            if (!window->m_viewTab[0].secondaryView) {
-                window->toggleSplitView();
-            }
-            window->m_viewTab[0].secondaryView->setUrl(secondaryUrl);
-            if (tab.primaryView->isActive()) {
-                window->m_viewTab[0].primaryView->setActive(true);
-            } else {
-                window->m_viewTab[0].secondaryView->setActive(true);
-            }
+            command += separator + tab.secondaryView->url().url();
+            command += separator + QLatin1String("-split");
         }
-        window->show();
+
+        KRun::runCommand(command, this);
+
         closeTab(index);
     } else if (selectedAction == closeOtherTabsAction) {
         const int count = m_tabBar->count();
@@ -1230,7 +1318,8 @@ void DolphinMainWindow::tabDropEvent(int tab, QDropEvent* event)
     if (!urls.isEmpty() && tab != -1) {
         const ViewTab& viewTab = m_viewTab[tab];
         const KUrl destPath = viewTab.isPrimaryViewActive ? viewTab.primaryView->url() : viewTab.secondaryView->url();
-        DragAndDropHelper::instance().dropUrls(KFileItem(), destPath, event, m_tabBar);
+        Q_UNUSED(destPath);
+        //DragAndDropHelper::instance().dropUrls(KFileItem(), destPath, event, m_tabBar);
     }
 }
 
@@ -1242,9 +1331,8 @@ void DolphinMainWindow::slotWriteStateChanged(bool isFolderWritable)
 void DolphinMainWindow::slotSearchModeChanged(bool enabled)
 {
 #ifdef HAVE_NEPOMUK
-    const KUrl url = m_activeViewContainer->url();
     const DolphinSearchInformation& searchInfo = DolphinSearchInformation::instance();
-    if (!searchInfo.isIndexingEnabled() || !searchInfo.isPathIndexed(url)) {
+    if (!searchInfo.isIndexingEnabled()) {
         return;
     }
 
@@ -1266,36 +1354,38 @@ void DolphinMainWindow::slotSearchModeChanged(bool enabled)
     }
 
     SearchPanel* searchPanel = qobject_cast<SearchPanel*>(searchDock->widget());
-    if (searchPanel) {
-        // Per default any search-operation triggered by the Search Panel is done
-        // "Everywhere".
-        SearchPanel::SearchMode searchMode = SearchPanel::Everywhere;
-
-        if (enabled && (SearchSettings::location() == QLatin1String("FromHere"))) {
-            // Only if the search-mode is enabled it is visible for the user whether
-            // a searching is done "Everywhere" or "From Here" (= current directory).
-            searchMode = SearchPanel::FromCurrentDir;
+    if (!searchPanel) {
+        return;
+    }
+
+    if (enabled) {
+        SearchPanel::SearchLocation searchLocation = SearchPanel::Everywhere;
+        const KUrl url = m_activeViewContainer->url();
+        const bool isSearchUrl = (url.protocol() == QLatin1String("nepomuksearch"));
+        if ((SearchSettings::location() == QLatin1String("FromHere") && !isSearchUrl)) {
+            searchLocation = SearchPanel::FromCurrentDir;
         }
-        searchPanel->setSearchMode(searchMode);
+        searchPanel->setSearchLocation(searchLocation);
+    } else {
+        searchPanel->setSearchLocation(SearchPanel::Everywhere);
     }
 #else
     Q_UNUSED(enabled);
 #endif
 }
 
-void DolphinMainWindow::openContextMenu(const KFileItem& item,
+void DolphinMainWindow::openContextMenu(const QPoint& pos,
+                                        const KFileItem& item,
                                         const KUrl& url,
                                         const QList<QAction*>& customActions)
 {
-    QPointer<DolphinContextMenu> contextMenu = new DolphinContextMenu(this, item, url);
-    contextMenu->setCustomActions(customActions);
-    const DolphinContextMenu::Command command = contextMenu->open();
+    QWeakPointer<DolphinContextMenu> contextMenu = new DolphinContextMenu(this, pos, item, url);
+    contextMenu.data()->setCustomActions(customActions);
+    const DolphinContextMenu::Command command = contextMenu.data()->open();
 
     switch (command) {
     case DolphinContextMenu::OpenParentFolderInNewWindow: {
-        DolphinMainWindow* window = DolphinApplication::app()->createMainWindow();
-        window->changeUrl(item.url().upUrl());
-        window->show();
+        KRun::run("dolphin", KUrl::List() << item.url().upUrl(), this);
         break;
     }
 
@@ -1308,27 +1398,17 @@ void DolphinMainWindow::openContextMenu(const KFileItem& item,
         break;
     }
 
-    delete contextMenu;
-}
-
-void DolphinMainWindow::openToolBarMenu()
-{
-    const int height = m_openToolBarMenuButton->height();
-    const QPoint pos = m_openToolBarMenuButton->mapToGlobal(QPoint(0, height));
-
-    m_toolBarMenu = new KMenu(m_openToolBarMenuButton);
-    m_toolBarMenu.data()->setAttribute(Qt::WA_DeleteOnClose);
-    connect(m_toolBarMenu.data(), SIGNAL(aboutToShow()), this, SLOT(updateToolBarMenu()));
-
-    m_toolBarMenu.data()->exec(pos);
+    delete contextMenu.data();
 }
 
 void DolphinMainWindow::updateToolBarMenu()
 {
-    KMenu* menu = m_toolBarMenu.data();
-    if (!menu) {
-        return;
-    }
+    KMenu* menu = qobject_cast<KMenu*>(sender());
+    Q_ASSERT(menu);
+
+    // All actions get cleared by KMenu::clear(). The sub-menus are deleted
+    // by connecting to the aboutToHide() signal from the parent-menu.
+    menu->clear();
 
     const GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings();
 
@@ -1379,14 +1459,17 @@ void DolphinMainWindow::updateToolBarMenu()
 
     // Add "Go" menu
     KMenu* goMenu = new KMenu(i18nc("@action:inmenu", "Go"), menu);
+    connect(menu, SIGNAL(aboutToHide()), goMenu, SLOT(deleteLater()));
     goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Back)));
     goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Forward)));
     goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Up)));
+    goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Home)));
     goMenu->addAction(ac->action("closed_tabs"));
     menu->addMenu(goMenu);
 
     // Add "Tool" menu
     KMenu* toolsMenu = new KMenu(i18nc("@action:inmenu", "Tools"), menu);
+    connect(menu, SIGNAL(aboutToHide()), toolsMenu, SLOT(deleteLater()));
     toolsMenu->addAction(ac->action("show_filter_bar"));
     toolsMenu->addAction(ac->action("compare_files"));
     toolsMenu->addAction(ac->action("open_terminal"));
@@ -1400,8 +1483,14 @@ void DolphinMainWindow::updateToolBarMenu()
 
     // Add "Help" menu
     KMenu* helpMenu = new KMenu(i18nc("@action:inmenu", "Help"), menu);
+    connect(menu, SIGNAL(aboutToHide()), helpMenu, SLOT(deleteLater()));
     helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::HelpContents)));
     helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::WhatsThis)));
+    helpMenu->addSeparator();
+    helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::ReportBug)));
+    helpMenu->addSeparator();
+    helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::SwitchApplicationLanguage)));
+    helpMenu->addSeparator();
     helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::AboutApp)));
     helpMenu->addAction(ac->action(KStandardAction::name(KStandardAction::AboutKDE)));
     menu->addMenu(helpMenu);
@@ -1436,107 +1525,6 @@ void DolphinMainWindow::slotToolBarIconSizeChanged(const QSize& iconSize)
     }
 }
 
-void DolphinMainWindow::init()
-{
-    DolphinSettings& settings = DolphinSettings::instance();
-
-    // Check whether Dolphin runs the first time. If yes then
-    // a proper default window size is given at the end of DolphinMainWindow::init().
-    GeneralSettings* generalSettings = settings.generalSettings();
-    const bool firstRun = generalSettings->firstRun();
-    if (firstRun) {
-        generalSettings->setViewPropsTimestamp(QDateTime::currentDateTime());
-    }
-
-    setAcceptDrops(true);
-
-    m_viewTab[m_tabIndex].splitter = new QSplitter(this);
-    m_viewTab[m_tabIndex].splitter->setChildrenCollapsible(false);
-
-    setupActions();
-
-    const KUrl homeUrl(generalSettings->homeUrl());
-    setUrlAsCaption(homeUrl);
-    m_actionHandler = new DolphinViewActionHandler(actionCollection(), this);
-    connect(m_actionHandler, SIGNAL(actionBeingHandled()), SLOT(clearStatusBar()));
-    connect(m_actionHandler, SIGNAL(createDirectory()), SLOT(createDirectory()));
-
-    m_viewTab[m_tabIndex].primaryView = createViewContainer(homeUrl, m_viewTab[m_tabIndex].splitter);
-
-    m_activeViewContainer = m_viewTab[m_tabIndex].primaryView;
-    connectViewSignals(m_activeViewContainer);
-    DolphinView* view = m_activeViewContainer->view();
-    m_activeViewContainer->show();
-    m_actionHandler->setCurrentView(view);
-
-    m_remoteEncoding = new DolphinRemoteEncoding(this, m_actionHandler);
-    connect(this, SIGNAL(urlChanged(const KUrl&)),
-            m_remoteEncoding, SLOT(slotAboutToOpenUrl()));
-
-    m_tabBar = new KTabBar(this);
-    m_tabBar->setMovable(true);
-    m_tabBar->setTabsClosable(true);
-    connect(m_tabBar, SIGNAL(currentChanged(int)),
-            this, SLOT(setActiveTab(int)));
-    connect(m_tabBar, SIGNAL(tabCloseRequested(int)),
-            this, SLOT(closeTab(int)));
-    connect(m_tabBar, SIGNAL(contextMenu(int, const QPoint&)),
-            this, SLOT(openTabContextMenu(int, const QPoint&)));
-    connect(m_tabBar, SIGNAL(newTabRequest()),
-            this, SLOT(openNewTab()));
-    connect(m_tabBar, SIGNAL(testCanDecode(const QDragMoveEvent*, bool&)),
-            this, SLOT(slotTestCanDecode(const QDragMoveEvent*, bool&)));
-    connect(m_tabBar, SIGNAL(mouseMiddleClick(int)),
-            this, SLOT(closeTab(int)));
-    connect(m_tabBar, SIGNAL(tabMoved(int, int)),
-            this, SLOT(slotTabMoved(int, int)));
-    connect(m_tabBar, SIGNAL(receivedDropEvent(int, QDropEvent*)),
-            this, SLOT(tabDropEvent(int, QDropEvent*)));
-
-    m_tabBar->blockSignals(true);  // signals get unblocked after at least 2 tabs are open
-
-    QWidget* centralWidget = new QWidget(this);
-    m_centralWidgetLayout = new QVBoxLayout(centralWidget);
-    m_centralWidgetLayout->setSpacing(0);
-    m_centralWidgetLayout->setMargin(0);
-    m_centralWidgetLayout->addWidget(m_tabBar);
-    m_centralWidgetLayout->addWidget(m_viewTab[m_tabIndex].splitter, 1);
-
-    setCentralWidget(centralWidget);
-    setupDockWidgets();
-    emit urlChanged(homeUrl);
-
-    setupGUI(Keys | Save | Create | ToolBar);
-    stateChanged("new_file");
-
-    QClipboard* clipboard = QApplication::clipboard();
-    connect(clipboard, SIGNAL(dataChanged()),
-            this, SLOT(updatePasteAction()));
-
-    if (generalSettings->splitView()) {
-        toggleSplitView();
-    }
-    updateEditActions();
-    updateViewActions();
-    updateGoActions();
-
-    QAction* showFilterBarAction = actionCollection()->action("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) {
-        createToolBarMenuButton();
-    }
-}
-
 void DolphinMainWindow::setActiveViewContainer(DolphinViewContainer* viewContainer)
 {
     Q_ASSERT(viewContainer);
@@ -1678,7 +1666,7 @@ void DolphinMainWindow::setupActions()
 
     // setup 'Go' menu
     KAction* backAction = KStandardAction::back(this, SLOT(goBack()), actionCollection());
-    connect(backAction, SIGNAL(triggered(Qt::MouseButtons, Qt::KeyboardModifiers)), this, SLOT(goBack(Qt::MouseButtons)));
+    connect(backAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goBack(Qt::MouseButtons)));
     KShortcut backShortcut = backAction->shortcut();
     backShortcut.setAlternate(Qt::Key_Backspace);
     backAction->setShortcut(backShortcut);
@@ -1686,10 +1674,10 @@ void DolphinMainWindow::setupActions()
     m_recentTabsMenu = new KActionMenu(i18n("Recently Closed Tabs"), this);
     m_recentTabsMenu->setIcon(KIcon("edit-undo"));
     actionCollection()->addAction("closed_tabs", m_recentTabsMenu);
-    connect(m_recentTabsMenu->menu(), SIGNAL(triggered(QAction *)),
-            this, SLOT(restoreClosedTab(QAction *)));
+    connect(m_recentTabsMenu->menu(), SIGNAL(triggered(QAction*)),
+            this, SLOT(restoreClosedTab(QAction*)));
 
-    QAction* action = new QAction("Empty Recently Closed Tabs", m_recentTabsMenu);
+    QAction* action = new QAction(i18n("Empty Recently Closed Tabs"), m_recentTabsMenu);
     action->setIcon(KIcon("edit-clear-list"));
     action->setData(QVariant::fromValue(true));
     m_recentTabsMenu->addAction(action);
@@ -1697,10 +1685,12 @@ void DolphinMainWindow::setupActions()
     m_recentTabsMenu->setEnabled(false);
 
     KAction* forwardAction = KStandardAction::forward(this, SLOT(goForward()), actionCollection());
-    connect(forwardAction, SIGNAL(triggered(Qt::MouseButtons, Qt::KeyboardModifiers)), this, SLOT(goForward(Qt::MouseButtons)));
+    connect(forwardAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goForward(Qt::MouseButtons)));
 
     KAction* upAction = KStandardAction::up(this, SLOT(goUp()), actionCollection());
-    connect(upAction, SIGNAL(triggered(Qt::MouseButtons, Qt::KeyboardModifiers)), this, SLOT(goUp(Qt::MouseButtons)));
+    connect(upAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(goUp(Qt::MouseButtons)));
+
+    KStandardAction::home(this, SLOT(goHome()), actionCollection());
 
     // setup 'Tools' menu
     KAction* showFilterBar = actionCollection()->addAction("show_filter_bar");
@@ -1779,9 +1769,7 @@ void DolphinMainWindow::setupDockWidgets()
     infoDock->setWidget(infoPanel);
 
     QAction* infoAction = infoDock->toggleViewAction();
-    infoAction->setIcon(KIcon("dialog-information"));
-    infoAction->setShortcut(Qt::Key_F11);
-    addActionCloneToCollection(infoAction, "show_information_panel");
+    createPanelAction(KIcon("dialog-information"), Qt::Key_F11, infoAction, "show_information_panel");
 
     addDockWidget(Qt::RightDockWidgetArea, infoDock);
     connect(this, SIGNAL(urlChanged(KUrl)),
@@ -1801,15 +1789,13 @@ void DolphinMainWindow::setupDockWidgets()
     foldersDock->setWidget(foldersPanel);
 
     QAction* foldersAction = foldersDock->toggleViewAction();
-    foldersAction->setShortcut(Qt::Key_F7);
-    foldersAction->setIcon(KIcon("folder"));
-    addActionCloneToCollection(foldersAction, "show_folders_panel");
+    createPanelAction(KIcon("folder"), Qt::Key_F7, foldersAction, "show_folders_panel");
 
     addDockWidget(Qt::LeftDockWidgetArea, foldersDock);
     connect(this, SIGNAL(urlChanged(KUrl)),
             foldersPanel, SLOT(setUrl(KUrl)));
-    connect(foldersPanel, SIGNAL(changeUrl(KUrl, Qt::MouseButtons)),
-            this, SLOT(handlePlacesClick(KUrl, Qt::MouseButtons)));
+    connect(foldersPanel, SIGNAL(changeUrl(KUrl,Qt::MouseButtons)),
+            this, SLOT(handlePlacesClick(KUrl,Qt::MouseButtons)));
 
     // Setup "Terminal"
 #ifndef Q_OS_WIN
@@ -1822,11 +1808,11 @@ void DolphinMainWindow::setupDockWidgets()
     terminalDock->setWidget(terminalPanel);
 
     connect(terminalPanel, SIGNAL(hideTerminalPanel()), terminalDock, SLOT(hide()));
+    connect(terminalDock, SIGNAL(visibilityChanged(bool)),
+            terminalPanel, SLOT(dockVisibilityChanged()));
 
     QAction* terminalAction = terminalDock->toggleViewAction();
-    terminalAction->setShortcut(Qt::Key_F4);
-    terminalAction->setIcon(KIcon("utilities-terminal"));
-    addActionCloneToCollection(terminalAction, "show_terminal_panel");
+    createPanelAction(KIcon("utilities-terminal"), Qt::Key_F4, terminalAction, "show_terminal_panel");
 
     addDockWidget(Qt::BottomDockWidgetArea, terminalDock);
     connect(this, SIGNAL(urlChanged(KUrl)),
@@ -1845,16 +1831,13 @@ void DolphinMainWindow::setupDockWidgets()
     searchDock->setWidget(searchPanel);
 
     QAction* searchAction = searchDock->toggleViewAction();
-    searchAction->setShortcut(Qt::Key_F12);
-    searchAction->setIcon(KIcon("system-search"));
-    addActionCloneToCollection(searchAction, "show_search_panel");
+    createPanelAction(KIcon("system-search"), Qt::Key_F12, searchAction, "show_search_panel");
     addDockWidget(Qt::RightDockWidgetArea, searchDock);
     connect(this, SIGNAL(urlChanged(KUrl)),
             searchPanel, SLOT(setUrl(KUrl)));
 #endif
 
-    const bool firstRun = DolphinSettings::instance().generalSettings()->firstRun();
-    if (firstRun) {
+    if (DolphinSettings::instance().generalSettings()->version() < 200) {
         infoDock->hide();
         foldersDock->hide();
 #ifndef Q_OS_WIN
@@ -1883,13 +1866,11 @@ void DolphinMainWindow::setupDockWidgets()
     placesDock->setWidget(placesPanel);
 
     QAction* placesAction = placesDock->toggleViewAction();
-    placesAction->setShortcut(Qt::Key_F9);
-    placesAction->setIcon(KIcon("bookmarks"));
-    addActionCloneToCollection(placesAction, "show_places_panel");
+    createPanelAction(KIcon("bookmarks"), Qt::Key_F9, placesAction, "show_places_panel");
 
     addDockWidget(Qt::LeftDockWidgetArea, placesDock);
-    connect(placesPanel, SIGNAL(urlChanged(KUrl, Qt::MouseButtons)),
-            this, SLOT(handlePlacesClick(KUrl, Qt::MouseButtons)));
+    connect(placesPanel, SIGNAL(urlChanged(KUrl,Qt::MouseButtons)),
+            this, SLOT(handlePlacesClick(KUrl,Qt::MouseButtons)));
     connect(this, SIGNAL(urlChanged(KUrl)),
             placesPanel, SLOT(setUrl(KUrl)));
     connect(placesDock, SIGNAL(visibilityChanged(bool)),
@@ -1973,10 +1954,13 @@ void DolphinMainWindow::createToolBarMenuButton()
 
     m_openToolBarMenuButton = new QToolButton(this);
     m_openToolBarMenuButton->setIcon(KIcon("configure"));
+    m_openToolBarMenuButton->setPopupMode(QToolButton::InstantPopup);
+    m_openToolBarMenuButton->setToolTip(i18nc("@info:tooltip", "Configure and control Dolphin"));
+
+    KMenu* toolBarMenu = new ToolBarMenu(m_openToolBarMenuButton);
+    connect(toolBarMenu, SIGNAL(aboutToShow()), this, SLOT(updateToolBarMenu()));
 
-    // Instead of using QPushButton::setMenu() the opening of the menu is done manually
-    // to prevent the "clutter" of the down-arrow drawn by the style.
-    connect(m_openToolBarMenuButton, SIGNAL(clicked()), this, SLOT(openToolBarMenu()));
+    m_openToolBarMenuButton->setMenu(toolBarMenu);
 
     toolBar()->addWidget(m_toolBarSpacer);
     toolBar()->addWidget(m_openToolBarMenuButton);
@@ -2058,6 +2042,39 @@ void DolphinMainWindow::rememberClosedTab(int index)
     KAcceleratorManager::manage(tabsMenu);
 }
 
+void DolphinMainWindow::refreshViews()
+{
+    Q_ASSERT(m_viewTab[m_tabIndex].primaryView);
+
+    // remember the current active view, as because of
+    // the refreshing the active view might change to
+    // the secondary view
+    DolphinViewContainer* activeViewContainer = m_activeViewContainer;
+
+    const int tabCount = m_viewTab.count();
+    for (int i = 0; i < tabCount; ++i) {
+        m_viewTab[i].primaryView->refresh();
+        if (m_viewTab[i].secondaryView) {
+            m_viewTab[i].secondaryView->refresh();
+        }
+    }
+
+    setActiveViewContainer(activeViewContainer);
+
+    const GeneralSettings* generalSettings = DolphinSettings::instance().generalSettings();
+    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();
+        const ViewTab& activeTab = m_viewTab[m_tabIndex];
+        const bool toggle =    ( splitView && !activeTab.secondaryView)
+                            || (!splitView &&  activeTab.secondaryView);
+        if (toggle) {
+            toggleSplitView();
+        }
+    }
+}
+
 void DolphinMainWindow::clearStatusBar()
 {
     m_activeViewContainer->statusBar()->clear();
@@ -2072,6 +2089,10 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
     connect(container, SIGNAL(searchModeChanged(bool)),
             this, SLOT(slotSearchModeChanged(bool)));
 
+    const DolphinSearchBox* searchBox = container->searchBox();
+    connect(searchBox, SIGNAL(searchLocationChanged(SearchLocation)),
+            this, SLOT(slotSearchLocationChanged()));
+
     DolphinView* view = container->view();
     connect(view, SIGNAL(selectionChanged(KFileItemList)),
             this, SLOT(slotSelectionChanged(KFileItemList)));
@@ -2079,23 +2100,23 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
             this, SLOT(slotRequestItemInfo(KFileItem)));
     connect(view, SIGNAL(activated()),
             this, SLOT(toggleActiveView()));
-    connect(view, SIGNAL(tabRequested(const KUrl&)),
-            this, SLOT(openNewTab(const KUrl&)));
-    connect(view, SIGNAL(requestContextMenu(KFileItem, const KUrl&, const QList<QAction*>&)),
-            this, SLOT(openContextMenu(KFileItem, const KUrl&, const QList<QAction*>&)));
+    connect(view, SIGNAL(tabRequested(KUrl)),
+            this, SLOT(openNewTab(KUrl)));
+    connect(view, SIGNAL(requestContextMenu(QPoint,KFileItem,KUrl,QList<QAction*>)),
+            this, SLOT(openContextMenu(QPoint,KFileItem,KUrl,QList<QAction*>)));
     connect(view, SIGNAL(startedPathLoading(KUrl)),
             this, SLOT(enableStopAction()));
     connect(view, SIGNAL(finishedPathLoading(KUrl)),
             this, SLOT(disableStopAction()));
 
     const KUrlNavigator* navigator = container->urlNavigator();
-    connect(navigator, SIGNAL(urlChanged(const KUrl&)),
-            this, SLOT(changeUrl(const KUrl&)));
+    connect(navigator, SIGNAL(urlChanged(KUrl)),
+            this, SLOT(changeUrl(KUrl)));
     connect(navigator, SIGNAL(historyChanged()),
             this, SLOT(updateHistory()));
     connect(navigator, SIGNAL(editableStateChanged(bool)),
             this, SLOT(slotEditableStateChanged(bool)));
-    connect(navigator, SIGNAL(tabRequested(const KUrl&)),
+    connect(navigator, SIGNAL(tabRequested(KUrl)),
             this, SLOT(openNewTab(KUrl)));
 }
 
@@ -2156,7 +2177,7 @@ void DolphinMainWindow::createSecondaryView(int tabIndex)
     const int newWidth = (m_viewTab[tabIndex].primaryView->width() - splitter->handleWidth()) / 2;
 
     const DolphinView* view = m_viewTab[tabIndex].primaryView->view();
-    m_viewTab[tabIndex].secondaryView = createViewContainer(view->rootUrl(), 0);
+    m_viewTab[tabIndex].secondaryView = createViewContainer(view->url(), 0);
     splitter->addWidget(m_viewTab[tabIndex].secondaryView);
     splitter->setSizes(QList<int>() << newWidth << newWidth);
     connectViewSignals(m_viewTab[tabIndex].secondaryView);
@@ -2191,12 +2212,18 @@ QString DolphinMainWindow::squeezedText(const QString& text) const
     return fm.elidedText(text, Qt::ElideMiddle, fm.maxWidth() * 10);
 }
 
-void DolphinMainWindow::addActionCloneToCollection(QAction* action, const QString& actionName)
+void DolphinMainWindow::createPanelAction(const KIcon& icon,
+                                          const QKeySequence& shortcut,
+                                          QAction* dockAction,
+                                          const QString& actionName)
 {
-    KAction* actionClone = actionCollection()->addAction(actionName);
-    actionClone->setText(action->text());
-    actionClone->setIcon(action->icon());
-    connect(actionClone, SIGNAL(triggered()), action, SLOT(trigger()));
+    KAction* panelAction = actionCollection()->addAction(actionName);
+    panelAction->setText(dockAction->text());
+    panelAction->setIcon(icon);
+    panelAction->setShortcut(shortcut);
+
+    dockAction->setIcon(icon);
+    connect(panelAction, SIGNAL(triggered()), dockAction, SLOT(trigger()));
 }
 
 DolphinMainWindow::UndoUiInterface::UndoUiInterface() :
@@ -2219,4 +2246,47 @@ void DolphinMainWindow::UndoUiInterface::jobError(KIO::Job* job)
     }
 }
 
+ToolBarMenu::ToolBarMenu(QWidget* parent) :
+    KMenu(parent)
+{
+}
+
+ToolBarMenu::~ToolBarMenu()
+{
+}
+
+void ToolBarMenu::showEvent(QShowEvent* event)
+{
+    KMenu::showEvent(event);
+
+    // Adjust the position of the menu to be shown within the
+    // Dolphin window to reduce the cases that sub-menus might overlap
+    // the right screen border.
+    QPoint pos;
+    QWidget* button = parentWidget();
+    if (layoutDirection() == Qt::RightToLeft) {
+        pos = button->mapToGlobal(QPoint(0, button->height()));
+    } else {
+        pos = button->mapToGlobal(QPoint(button->width(), button->height()));
+        pos.rx() -= width();
+    }
+
+    // Assure that the menu is not shown outside the screen boundaries and
+    // that it does not overlap with the parent button.
+    const QRect screen = QApplication::desktop()->screenGeometry(QCursor::pos());
+    if (pos.x() < screen.x()) {
+        pos.rx() = screen.x();
+    } else if (pos.x() + width() > screen.x() + screen.width()) {
+        pos.rx() = screen.x() + screen.width() - width();
+    }
+
+    if (pos.y() < screen.y()) {
+        pos.ry() = screen.y();
+    } else if (pos.y() + height() > screen.y() + screen.height()) {
+        pos.ry() = button->mapToGlobal(QPoint(0, 0)).y() - height();
+    }
+
+    move(pos);
+}
+
 #include "dolphinmainwindow.moc"