[utilities/krusader] krusader: First steps to achieve undo tab closing: add menu items, a hotkey and other resources

Yuri Chornoivan null at kde.org
Tue Jul 6 20:44:37 BST 2021


Git commit df98b1df9d546e057d56efb65fc1158d43dc62d2 by Yuri Chornoivan, on behalf of Toni Asensi Esteve.
Committed on 03/07/2021 at 05:24.
Pushed by asensi into branch 'master'.

First steps to achieve undo tab closing: add menu items, a hotkey and other resources

GUI: New options are seen in the File menu ("Undo Close Tab"), after right-
clicking on a tab ("Undo Close Tab" is also seen) and, as in Dolphin, in
the Go menu ("Recently Closed Tabs") so the user can choose which tab to
restore (not only the last closed one) or choose "Empty Recently Closed Tabs".

Revision: https://invent.kde.org/utilities/krusader/-/merge_requests/49

M  +1    -0    krusader/GUI/CMakeLists.txt
A  +104  -0    krusader/GUI/recentlyclosedtabsmenu.cpp     [License: GPL(v2.0+)]
A  +42   -0    krusader/GUI/recentlyclosedtabsmenu.h     [License: GPL(v2.0+)]
M  +5    -0    krusader/kractions.cpp
M  +3    -0    krusader/kractions.h
M  +2    -0    krusader/krusaderui.rc
M  +13   -0    krusader/panelmanager.cpp
M  +6    -1    krusader/panelmanager.h
M  +1    -0    krusader/paneltabbar.cpp
M  +1    -0    krusader/paneltabbar.h
M  +7    -0    krusader/tabactions.cpp
M  +4    -1    krusader/tabactions.h

https://invent.kde.org/utilities/krusader/commit/df98b1df9d546e057d56efb65fc1158d43dc62d2

diff --git a/krusader/GUI/CMakeLists.txt b/krusader/GUI/CMakeLists.txt
index 82a4082c..be3f4f72 100644
--- a/krusader/GUI/CMakeLists.txt
+++ b/krusader/GUI/CMakeLists.txt
@@ -11,6 +11,7 @@ set(GUI_SRCS
     krlistwidget.cpp
     mediabutton.cpp
     kcmdmodebutton.cpp
+    recentlyclosedtabsmenu.cpp
     terminaldock.cpp)
 
 add_library(GUI STATIC ${GUI_SRCS})
diff --git a/krusader/GUI/recentlyclosedtabsmenu.cpp b/krusader/GUI/recentlyclosedtabsmenu.cpp
new file mode 100644
index 00000000..9e23a5e8
--- /dev/null
+++ b/krusader/GUI/recentlyclosedtabsmenu.cpp
@@ -0,0 +1,104 @@
+/*
+    SPDX-FileCopyrightText: 2005 Csaba Karai <cskarai at freemail.hu>
+    SPDX-FileCopyrightText: 2005-2020 Krusader Krew <https://krusader.org>
+
+    Based on KrRemoteEncodingMenu (© Csaba Karai and Krusader Krew)
+    from Krusader, DolphinRecentTabsMenu (© Emmanuel Pescosta)
+    from Dolphin and PanelManager::slotDuplicateTab() (© Shie Erlich,
+    Rafi Yanai and Krusader Krew) from Krusader.
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "recentlyclosedtabsmenu.h"
+
+#include "../icon.h"
+#include "../kractions.h"
+#include "../krglobal.h"
+#include "../krusaderview.h"
+#include "../panelmanager.h"
+#include "../tabactions.h"
+#include "../Panel/listpanel.h"
+#include "../Panel/PanelView/krview.h"
+
+#include <KConfigCore/KConfig>
+#include <KI18n/KLocalizedString>
+#include <KIO/Global>
+#include <KXmlGui/KActionCollection>
+
+// QtWidgets
+#include <QMenu>
+
+RecentlyClosedTabsMenu::RecentlyClosedTabsMenu(const QString &text, const QString &iconName, KActionCollection *parent) :
+        KActionMenu(Icon(iconName), text, parent)
+{
+    parent->addAction("recently_closed_tabs", this);
+
+    // Construct the Empty Recently Closed Tabs action and add it to the menu
+    actClearTheList = new QAction(i18n("Empty Recently Closed Tabs"), this);
+    actClearTheList->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear-list")));
+    addAction(actClearTheList);
+    // Add a separator after that menu entry
+    addSeparator();
+
+    connect(menu(), &QMenu::triggered, this, &RecentlyClosedTabsMenu::slotTriggered);
+}
+
+QAction *RecentlyClosedTabsMenu::updateAfterClosingATab(const QUrl &urlClosedTab, const QByteArray &backedUpData,
+                                                        TabActions *argTabActions)
+{
+    // Create the related action
+    QAction *actReopenTab = new QAction(menu());
+    actReopenTab->setText(urlClosedTab.path());
+    actReopenTab->setData(backedUpData);
+    const QString iconName = KIO::iconNameForUrl(urlClosedTab);
+    actReopenTab->setIcon(QIcon::fromTheme(iconName));
+
+    // Add a menu entry (related to the closed tab) after the
+    // separator and the "Empty Recently Closed Tabs" entry
+    if (menu()->actions().size() == 2) {
+        addAction(actReopenTab);
+    } else {
+        insertAction(menu()->actions().at(2), actReopenTab);
+    }
+
+    // Remove the last entry of the menu if there are more than
+    // six (8 - 2) closed tabs there
+    if (menu()->actions().size() > 8) {
+        removeAction(menu()->actions().last());
+    }
+
+    // Enable objects
+    setEnabled(true);
+    tabActions = argTabActions;
+    tabActions->actUndoCloseTab->setEnabled(true);
+
+    return actReopenTab;
+}
+
+void RecentlyClosedTabsMenu::slotTriggered(QAction *action)
+{
+    if (!action)
+        return;
+
+    if (action == actClearTheList) {
+        // Remove the actions that follow those two items:
+        // the "Empty Recently Closed Tabs" one and a separator
+        const int quantActions = menu()->actions().size();
+        for (int x = quantActions - 1; x >= 2; x--) {
+            removeAction(menu()->actions().at(x));
+        }
+    } else {
+        ACTIVE_MNG->undoCloseTab(action);
+
+        removeAction(action);
+        delete action;
+        action = nullptr;
+    }
+
+    if (menu()->actions().size() <= 2) {
+        // Disable objects
+        tabActions->actUndoCloseTab->setEnabled(false);
+        setEnabled(false);
+    }
+}
diff --git a/krusader/GUI/recentlyclosedtabsmenu.h b/krusader/GUI/recentlyclosedtabsmenu.h
new file mode 100644
index 00000000..506623b1
--- /dev/null
+++ b/krusader/GUI/recentlyclosedtabsmenu.h
@@ -0,0 +1,42 @@
+/*
+    SPDX-FileCopyrightText: 2005 Csaba Karai <cskarai at freemail.hu>
+    SPDX-FileCopyrightText: 2005-2020 Krusader Krew <https://krusader.org>
+
+    Based on KrRemoteEncodingMenu (© Csaba Karai and Krusader Krew)
+    from Krusader and DolphinRecentTabsMenu (© Emmanuel Pescosta)
+    from Dolphin.
+
+    SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef RECENTLYCLOSEDTABSMENU_H
+#define RECENTLYCLOSEDTABSMENU_H
+
+#include <KWidgetsAddons/KActionMenu>
+
+class KActionCollection;
+class TabActions;
+
+/**
+ * A menu to perform operations with a list of recently closed tabs
+ */
+class RecentlyClosedTabsMenu: public KActionMenu
+{
+    Q_OBJECT
+    friend class PanelManager;
+
+public:
+    explicit RecentlyClosedTabsMenu(const QString &text, const QString &iconName,
+                                    KActionCollection *parent = nullptr);
+
+protected slots:
+    void slotTriggered(QAction *action);
+
+private:
+    QAction *updateAfterClosingATab(const QUrl &urlClosedTab, const QByteArray &backedUpData,
+                                    TabActions *argTabActions);
+    QAction *actClearTheList;
+    TabActions *tabActions = nullptr;
+};
+
+#endif // RECENTLYCLOSEDTABSMENU_H
diff --git a/krusader/kractions.cpp b/krusader/kractions.cpp
index 80389a12..fe981a42 100644
--- a/krusader/kractions.cpp
+++ b/krusader/kractions.cpp
@@ -36,6 +36,7 @@ QAction *KrActions::actCompare = nullptr;
 QAction *KrActions::actDiskUsage = nullptr;
 QAction *KrActions::actHomeTerminal = nullptr;
 QAction *KrActions::actRemoteEncoding = nullptr;
+RecentlyClosedTabsMenu *KrActions::actClosedTabsMenu = nullptr;
 QAction *KrActions::actProfiles = nullptr;
 QAction *KrActions::actMultiRename = nullptr;
 QAction *KrActions::actMountMan = nullptr;
@@ -270,6 +271,9 @@ void KrActions::setupActions(Krusader *krusaderApp)
 
     actRemoteEncoding = new KrRemoteEncodingMenu(i18n("Select Remote Charset"), "character-set", krusaderApp->actionCollection());
 
+    actClosedTabsMenu = new RecentlyClosedTabsMenu(i18n("Recently Closed Tabs"), "edit-undo", krusaderApp->actionCollection());
+    actClosedTabsMenu->setEnabled(false);
+
     NEW_KACTION(actF10Quit, i18n("Quit"), nullptr, Qt::Key_F10, krusaderApp, SLOT(quit()) , "F10_Quit");
     actF10Quit->setToolTip(i18n("Quit Krusader."));
 
@@ -281,6 +285,7 @@ void KrActions::setupActions(Krusader *krusaderApp)
     NEW_KACTION(tmp, i18n("Move Focus Up"), nullptr, Qt::CTRL + Qt::SHIFT + Qt::Key_Up, MAIN_VIEW, SLOT(focusUp()), "move_focus_up");
     NEW_KACTION(tmp, i18n("Move Focus Down"), nullptr, Qt::CTRL + Qt::SHIFT + Qt::Key_Down, MAIN_VIEW, SLOT(focusDown()), "move_focus_down");
 
+
     // job manager actions
     actJobControl = krJobMan->controlAction();
     krusaderApp->actionCollection()->addAction("job control", actJobControl);
diff --git a/krusader/kractions.h b/krusader/kractions.h
index 53af9393..e177a44e 100644
--- a/krusader/kractions.h
+++ b/krusader/kractions.h
@@ -9,6 +9,8 @@
 #ifndef KRACTIONS_H
 #define KRACTIONS_H
 
+#include "GUI/recentlyclosedtabsmenu.h"
+
 // QtCore
 #include <QObject>
 // QtWidgets
@@ -32,6 +34,7 @@ public:
     static QAction *actMountMan, *actNewTool, *actSwapPanels, *actSwapSides;
     static QAction *actKonfigurator, *actToolsSetup, *actFind;
     static QAction *actRemoteEncoding;
+    static RecentlyClosedTabsMenu *actClosedTabsMenu;
     static QAction *actSelectColorMask, *actMultiRename, *actOpenLeftBm, *actOpenRightBm, *actAddBookmark;
     static QAction *actSplit;
     static QAction *actCombine;
diff --git a/krusader/krusaderui.rc b/krusader/krusaderui.rc
index 0256c64e..b512f0cf 100644
--- a/krusader/krusaderui.rc
+++ b/krusader/krusaderui.rc
@@ -6,6 +6,7 @@
    <Action name="edit_new_file" />
    <Action name="F7_Mkdir" />
    <Action name="new symlink" />
+   <Action name="undo_close_tab" />
    <Separator/>
    <Action name="F3_View" />
    <Action name="F4_Edit" />
@@ -87,6 +88,7 @@
    <text>&Go</text>
    <Action name="root" />
    <Action name="Popular_Urls" />
+   <Action name="recently_closed_tabs" />
    <Separator/>
    <Action name="set_jump_back" />
    <Action name="jump_back" />
diff --git a/krusader/panelmanager.cpp b/krusader/panelmanager.cpp
index 49f6705b..da87a898 100644
--- a/krusader/panelmanager.cpp
+++ b/krusader/panelmanager.cpp
@@ -11,6 +11,7 @@
 #include "defaults.h"
 #include "icon.h"
 #include "tabactions.h"
+#include "kractions.h"
 #include "krusaderview.h"
 #include "krmainwindow.h"
 #include "Panel/listpanel.h"
@@ -23,6 +24,7 @@
 // QtGui
 #include <QImage>
 // QtWidgets
+#include <QMenu>
 #include <QStackedWidget>
 #include <QToolButton>
 #include <QGridLayout>
@@ -305,6 +307,17 @@ void PanelManager::slotCloseTab(int index)
     tabsCountChanged();
 }
 
+void PanelManager::slotUndoCloseTab()
+{
+    Q_ASSERT(KrActions::actClosedTabsMenu->menu()->actions().size() > 2);
+    // Performs the same action as when clicking on that menu item
+    KrActions::actClosedTabsMenu->slotTriggered(KrActions::actClosedTabsMenu->menu()->actions().at(2));
+}
+
+void PanelManager::undoCloseTab(const QAction *action)
+{
+}
+
 void PanelManager::updateTabbarPos()
 {
     KConfigGroup group(krConfig, "Look&Feel");
diff --git a/krusader/panelmanager.h b/krusader/panelmanager.h
index ba543a63..430bb3cd 100644
--- a/krusader/panelmanager.h
+++ b/krusader/panelmanager.h
@@ -71,6 +71,11 @@ public:
     void newTab(const QUrl &url, KrPanel *nextTo) override {
         slotNewTab(url, true, nextTo);
     }
+    /**
+     * Undo the closing of a tab. The `action` argument is utilized to
+     * retrieve information about the previously closed tab.
+     */
+    void undoCloseTab(const QAction *action);
 
 signals:
     void draggingTab(PanelManager *from, QMouseEvent*);
@@ -94,10 +99,10 @@ public slots:
     void slotLockTab();
     void slotPinTab();
     void slotNextTab();
-
     void slotPreviousTab();
     void slotCloseTab();
     void slotCloseTab(int index);
+    void slotUndoCloseTab(); //! Undo the last tab closing
     void slotRecreatePanels();
     void slotCloseInactiveTabs();
     void slotCloseDuplicatedTabs();
diff --git a/krusader/paneltabbar.cpp b/krusader/paneltabbar.cpp
index 3890d46f..d32e2a22 100644
--- a/krusader/paneltabbar.cpp
+++ b/krusader/paneltabbar.cpp
@@ -57,6 +57,7 @@ PanelTabBar::PanelTabBar(QWidget *parent, TabActions *actions): QTabBar(parent),
     insertAction(actions->actMoveTabToLeft);
     insertAction(actions->actMoveTabToRight);
     insertAction(actions->actCloseTab);
+    insertAction(actions->actUndoCloseTab);
     insertAction(actions->actCloseInactiveTabs);
     insertAction(actions->actCloseDuplicatedTabs);
 
diff --git a/krusader/paneltabbar.h b/krusader/paneltabbar.h
index b57ffbdb..b7b994f0 100644
--- a/krusader/paneltabbar.h
+++ b/krusader/paneltabbar.h
@@ -93,6 +93,7 @@ private:
     void setIcon(int index, ListPanel *panel);
     void handleDragEvent(int tabIndex);
     void setPanelTextToTab(int tabIndex, ListPanel *panel);
+
     KActionMenu *_panelActionMenu;
     bool _left;
     int _maxTabLength;
diff --git a/krusader/tabactions.cpp b/krusader/tabactions.cpp
index 82002459..bcd4620e 100644
--- a/krusader/tabactions.cpp
+++ b/krusader/tabactions.cpp
@@ -26,6 +26,8 @@ TabActions::TabActions(QObject *parent, KrMainWindow *mainWindow) : ActionsBase(
     actMoveTabToLeft = action(i18n("Move Current Tab to the Left"), nullptr, Qt::CTRL + Qt::SHIFT + Qt::Key_PageUp, SLOT(moveTabToLeft()), "move_tab_to_left");
     actMoveTabToRight = action(i18n("Move Current Tab to the Right"), nullptr, Qt::CTRL + Qt::SHIFT + Qt::Key_PageDown, SLOT(moveTabToRight()), "move_tab_to_right");
     actCloseTab = action(i18n("Close Current Tab"), "tab-close", KStandardShortcut::close(), this, SLOT(closeTab()), "close tab");
+    actUndoCloseTab = action(i18n("Undo Close Tab"), "edit-undo", Qt::CTRL + Qt::SHIFT + Qt::Key_T, this, SLOT(undoCloseTab()), "undo_close_tab");
+    actUndoCloseTab->setEnabled(false);
     actNextTab = action(i18n("Next Tab"), QString(), KStandardShortcut::tabNext(), this, SLOT(nextTab()), "next tab");
     actPreviousTab = action(i18n("Previous Tab"), QString(), KStandardShortcut::tabPrev(), this, SLOT(previousTab()), "previous tab");
     actCloseInactiveTabs = action(i18n("Close Inactive Tabs"), nullptr, 0, SLOT(closeInactiveTabs()), "close inactive tabs");
@@ -100,6 +102,11 @@ void TabActions::closeTab()
     activeManager()->slotCloseTab();
 }
 
+void TabActions::undoCloseTab()
+{
+    activeManager()->slotUndoCloseTab();
+}
+
 void TabActions::closeInactiveTabs()
 {
     activeManager()->slotCloseInactiveTabs();
diff --git a/krusader/tabactions.h b/krusader/tabactions.h
index 2bb7f2ab..20741fd3 100644
--- a/krusader/tabactions.h
+++ b/krusader/tabactions.h
@@ -18,6 +18,7 @@ class PanelManager;
 class TabActions : public ActionsBase
 {
     friend class PanelTabBar;
+    friend class RecentlyClosedTabsMenu;
 
     Q_OBJECT
 
@@ -33,6 +34,7 @@ protected slots:
     void lockTab();
     void pinTab();
     void closeTab();
+    void undoCloseTab();
     void nextTab();
     void previousTab();
     void closeInactiveTabs();
@@ -44,7 +46,8 @@ protected slots:
 protected:
     inline PanelManager *activeManager();
 
-    QAction *actNewTab, *actDupTab, *actCloseTab, *actPreviousTab, *actNextTab, *actMoveTabToOtherSide;
+    QAction *actNewTab, *actDupTab, *actCloseTab, *actUndoCloseTab;
+    QAction *actPreviousTab, *actNextTab, *actMoveTabToOtherSide;
     QAction *actCloseInactiveTabs, *actCloseDuplicatedTabs, *actLockTab, *actPinTab;
     QAction *actMoveTabToLeft, *actMoveTabToRight;
 };



More information about the kde-doc-english mailing list