]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Add navigation history to forward/back buttons
authorDavid Hallas <david@davidhallas.dk>
Thu, 11 Apr 2019 17:21:41 +0000 (19:21 +0200)
committerDavid Hallas <david@davidhallas.dk>
Sun, 29 Sep 2019 12:16:11 +0000 (14:16 +0200)
Summary:
Adds navigation history to forward/back buttons in the toolbar. This
changes the forward/back buttons in the toolbar to use the
KToolBarPopupAction class which provides access to a drop down menu.

Test Plan:
Browse some folders
Click the back drop down menu and navigate somewhere
Click the forward drop down menu and navigate somewhere

FEATURE: 157819
FIXED-IN: 19.12.0

Reviewers: #dolphin, ngraham, elvisangelaccio, #vdg

Reviewed By: #dolphin, ngraham, elvisangelaccio, #vdg

Subscribers: felixernst, nerdopolist, mart, richardl, ognarb, david.fontanals, abetts, kfm-devel

Tags: #dolphin

Differential Revision: https://phabricator.kde.org/D19311

src/dolphinmainwindow.cpp
src/dolphinmainwindow.h
src/middleclickactioneventfilter.cpp

index c69567e2684f570c4b344ff75520a264d99db4b0..5f7a8e72801148d8262c3fda6b2d24e84d4ef5cb 100644 (file)
@@ -65,6 +65,7 @@
 #include <KStartupInfo>
 #include <KToggleAction>
 #include <KToolBar>
+#include <KToolBarPopupAction>
 #include <KToolInvocation>
 #include <KUrlComboBox>
 #include <KUrlNavigator>
@@ -90,6 +91,8 @@ 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;
 }
 
 DolphinMainWindow::DolphinMainWindow() :
@@ -107,7 +110,9 @@ DolphinMainWindow::DolphinMainWindow() :
     m_lastHandleUrlStatJob(nullptr),
     m_terminalPanel(nullptr),
     m_placesPanel(nullptr),
-    m_tearDownFromPlacesRequested(false)
+    m_tearDownFromPlacesRequested(false),
+    m_backAction(nullptr),
+    m_forwardAction(nullptr)
 {
     Q_INIT_RESOURCE(dolphin);
     setComponentName(QStringLiteral("dolphin"), QGuiApplication::applicationDisplayName());
@@ -676,6 +681,56 @@ void DolphinMainWindow::slotToolBarActionMiddleClicked(QAction *action)
     }
 }
 
+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();
@@ -1313,10 +1368,22 @@ void DolphinMainWindow::setupActions()
     connect(replaceLocation, &QAction::triggered, this, &DolphinMainWindow::replaceLocation);
 
     // setup 'Go' menu
-    QAction* backAction = KStandardAction::back(this, &DolphinMainWindow::goBack, actionCollection());
-    auto backShortcuts = backAction->shortcuts();
+    {
+        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(backAction, backShortcuts);
+    actionCollection()->setDefaultShortcuts(m_backAction, backShortcuts);
 
     DolphinRecentTabsMenu* recentTabsMenu = new DolphinRecentTabsMenu(this);
     actionCollection()->addAction(QStringLiteral("closed_tabs"), recentTabsMenu);
@@ -1345,7 +1412,23 @@ void DolphinMainWindow::setupActions()
         "be undone will ask for your confirmation."));
     undoAction->setEnabled(false); // undo should be disabled by default
 
-    KStandardAction::forward(this, &DolphinMainWindow::goForward, actionCollection());
+    {
+        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);
+    // 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 "
index 253fc74d4ebc9c358f5c54bbbc471fdc3772e04e..3d86340d6a9ed4b11dcc4d8489a9a04953bd06f2 100644 (file)
@@ -47,6 +47,7 @@ class KFileItemList;
 class KJob;
 class KNewFileMenu;
 class KHelpMenu;
+class KToolBarPopupAction;
 class QToolButton;
 class QIcon;
 class PlacesPanel;
@@ -509,6 +510,36 @@ private slots:
      */
     void slotToolBarActionMiddleClicked(QAction *action);
 
+    /**
+     * Is called before the Back popup menu is shown. This slot will populate
+     * the menu with history data
+     */
+    void slotAboutToShowBackPopupMenu();
+
+    /**
+      * This slot is used by the Back Popup Menu to go back to a specific
+      * history index. The QAction::data will carry an int with the index
+      * to go to.
+      */
+    void slotGoBack(QAction* action);
+
+    /**
+     * Middle clicking Back/Forward will open the resulting folder in a new tab.
+     */
+    void slotBackForwardActionMiddleClicked(QAction *action);
+
+    /**
+     * Is called before the Forward popup menu is shown. This slot will populate
+     * the menu with history data
+     */
+    void slotAboutToShowForwardPopupMenu();
+
+    /**
+      * This slot is used by the Forward Popup Menu to go forward to a specific
+      * history index. The QAction::data will carry an int with the index
+      * to go to.
+      */
+    void slotGoForward(QAction* action);
 private:
     /**
      * Sets up the various menus and actions and connects them.
@@ -599,6 +630,9 @@ private:
     TerminalPanel* m_terminalPanel;
     PlacesPanel* m_placesPanel;
     bool m_tearDownFromPlacesRequested;
+
+    KToolBarPopupAction* m_backAction;
+    KToolBarPopupAction* m_forwardAction;
 };
 
 inline DolphinViewContainer* DolphinMainWindow::activeViewContainer() const
index e0917850a0ea36e754b4e2c8235c36f234c643e5..293e16e0caf7cc0c5d6a25076f96388a1c9763cb 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <QAction>
 #include <QEvent>
+#include <QMenu>
 #include <QMouseEvent>
 #include <QToolBar>
 
@@ -39,16 +40,32 @@ bool MiddleClickActionEventFilter::eventFilter(QObject *watched, QEvent *event)
 
         if (me->button() == Qt::MiddleButton) {
             QToolBar *toolBar = qobject_cast<QToolBar *>(watched);
-
-            QAction *action = toolBar->actionAt(me->pos());
-            if (action) {
-                if (event->type() == QEvent::MouseButtonPress) {
-                    m_lastMiddlePressedAction = action;
-                } else if (event->type() == QEvent::MouseButtonRelease) {
-                    if (m_lastMiddlePressedAction == action) {
-                        emit actionMiddleClicked(action);
+            if (toolBar) {
+                QAction *action = toolBar->actionAt(me->pos());
+                if (action) {
+                    if (event->type() == QEvent::MouseButtonPress) {
+                        m_lastMiddlePressedAction = action;
+                    } else if (event->type() == QEvent::MouseButtonRelease) {
+                        if (m_lastMiddlePressedAction == action) {
+                            emit actionMiddleClicked(action);
+                        }
+                        m_lastMiddlePressedAction = nullptr;
+                    }
+                }
+            }
+            QMenu *menu = qobject_cast<QMenu *>(watched);
+            if (menu) {
+                QAction *action = menu->actionAt(me->pos());
+                if (action) {
+                    if (event->type() == QEvent::MouseButtonPress) {
+                        m_lastMiddlePressedAction = action;
+                    } else if (event->type() == QEvent::MouseButtonRelease) {
+                        if (m_lastMiddlePressedAction == action) {
+                            emit actionMiddleClicked(action);
+                            return true;
+                        }
+                        m_lastMiddlePressedAction = nullptr;
                     }
-                    m_lastMiddlePressedAction = nullptr;
                 }
             }
         }