[utilities/kate] /: Added action to restore previously closed tabs
Christoph Cullmann
null at kde.org
Sun Feb 18 15:05:13 GMT 2024
Git commit 096c66d3352112b9dbb17aa3b6d7ea5fce21fea4 by Christoph Cullmann, on behalf of Ben Gooding.
Committed on 18/02/2024 at 14:54.
Pushed by cullmann into branch 'master'.
Added action to restore previously closed tabs
- Added unit tests class for KateDocManager
- Added tests for document restoration functionality
M +2 -0 apps/lib/autotests/CMakeLists.txt
A +160 -0 apps/lib/autotests/kate_doc_manager_tests.cpp *
A +27 -0 apps/lib/autotests/kate_doc_manager_tests.h *
M +16 -0 apps/lib/katedocmanager.cpp
M +9 -1 apps/lib/katedocmanager.h
M +7 -0 apps/lib/katemainwindow.cpp
M +8 -0 apps/lib/kateviewmanager.cpp
M +1 -0 apps/lib/kateviewmanager.h
M +4 -0 doc/kate/fundamentals.docbook
M +13 -0 doc/kate/menus.docbook
The files marked with a * at the end have a non valid license. Please read: https://community.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.
https://invent.kde.org/utilities/kate/-/commit/096c66d3352112b9dbb17aa3b6d7ea5fce21fea4
diff --git a/apps/lib/autotests/CMakeLists.txt b/apps/lib/autotests/CMakeLists.txt
index b1e1804d58..9cf0b95ab7 100644
--- a/apps/lib/autotests/CMakeLists.txt
+++ b/apps/lib/autotests/CMakeLists.txt
@@ -22,6 +22,7 @@ if (WIN32)
# sessions_action_test
urlinfo_test
json_utils_test
+ kate_doc_manager_tests
# location_history_test
# kate_view_mgmt_tests
bytearraysplitter_tests
@@ -33,6 +34,7 @@ else()
sessions_action_test
urlinfo_test
json_utils_test
+ kate_doc_manager_tests
location_history_test
kate_view_mgmt_tests
bytearraysplitter_tests
diff --git a/apps/lib/autotests/kate_doc_manager_tests.cpp b/apps/lib/autotests/kate_doc_manager_tests.cpp
new file mode 100644
index 0000000000..a7d37f7eb2
--- /dev/null
+++ b/apps/lib/autotests/kate_doc_manager_tests.cpp
@@ -0,0 +1,160 @@
+
+#include "kate_doc_manager_tests.h"
+#include "katedocmanager.h"
+#include "katemainwindow.h"
+
+#include <KLocalizedString>
+
+#include <QCommandLineParser>
+#include <QSignalSpy>
+#include <QTest>
+
+QTEST_MAIN(KateDocManagerTests)
+
+namespace
+{
+QCommandLineParser &GetParser()
+{
+ static QCommandLineParser parser;
+ return parser;
+}
+
+KateDocumentInfo CreateMockDocument(QUrl url = {})
+{
+ KateDocumentInfo mockDocumentInfo;
+ mockDocumentInfo.normalizedUrl = url;
+ return mockDocumentInfo;
+}
+}
+
+KateDocManagerTests::KateDocManagerTests(QObject *)
+{
+ // ensure ui file can be found and the translation domain is set to avoid warnings
+ qApp->setApplicationName(QStringLiteral("kate"));
+ KLocalizedString::setApplicationDomain(QByteArrayLiteral("kate"));
+}
+
+void KateDocManagerTests::setUp()
+{
+ auto tempdir = new QTemporaryDir;
+ QVERIFY(tempdir->isValid());
+
+ // ensure we use some dummy config
+ KConfig::setMainConfigName(tempdir->path() + QStringLiteral("/testconfigfilerc"));
+
+ app = std::make_unique<KateApp>(GetParser(), KateApp::ApplicationKWrite, tempdir->path());
+}
+
+void KateDocManagerTests::tearDown()
+{
+ app.reset(nullptr);
+}
+
+void KateDocManagerTests::canCreateDocument()
+{
+ setUp();
+
+ auto documentManager = app->documentManager();
+
+ QSignalSpy documentCreatedSpy(documentManager, &KateDocManager::documentCreated);
+ const auto document = documentManager->createDoc(CreateMockDocument());
+ Q_ASSERT(document != nullptr);
+ Q_ASSERT(documentCreatedSpy.count() == 1);
+
+ tearDown();
+}
+
+void KateDocManagerTests::popRecentlyClosedURLsClearsRecentlyClosedURLs()
+{
+ setUp();
+
+ constexpr auto FirstTestURL = "Test URL 1";
+ constexpr auto SecondTestURL = "Test URL 2";
+
+ auto documentManager = app->documentManager();
+ documentManager->closeAllDocuments();
+
+ const auto createdDocuments = [&documentManager] {
+ QList<KTextEditor::Document *> createdDocuments;
+ createdDocuments.push_back(documentManager->createDoc(CreateMockDocument(QUrl(i18n(FirstTestURL)))));
+ createdDocuments.push_back(documentManager->createDoc(CreateMockDocument(QUrl(i18n(SecondTestURL)))));
+ return createdDocuments;
+ }();
+
+ documentManager->closeDocuments(createdDocuments, false);
+
+ {
+ const auto recentlyClosedURLs = documentManager->popRecentlyClosedURLs();
+ Q_ASSERT(recentlyClosedURLs.size() == 2);
+ }
+
+ {
+ const auto recentlyClosedURLs = documentManager->popRecentlyClosedURLs();
+ Q_ASSERT(recentlyClosedURLs.size() == 0);
+ }
+
+ tearDown();
+}
+
+void KateDocManagerTests::popRecentlyClosedURLsReturnsNoneIfNoTabsClosedDuringSession()
+{
+ setUp();
+
+ auto documentManager = app->documentManager();
+
+ Q_ASSERT(documentManager->popRecentlyClosedURLs().empty());
+
+ tearDown();
+}
+
+void KateDocManagerTests::popRecentlyClosedURLsReturnsURLIfTabClosedDuringSession()
+{
+ setUp();
+
+ constexpr auto FirstTestURL = "Test URL 1";
+ constexpr auto SecondTestURL = "Test URL 2";
+
+ auto documentManager = app->documentManager();
+ documentManager->closeAllDocuments();
+
+ const auto createdDocuments = [&documentManager] {
+ QList<KTextEditor::Document *> createdDocuments;
+ createdDocuments.push_back(documentManager->createDoc(CreateMockDocument(QUrl(i18n(FirstTestURL)))));
+ createdDocuments.push_back(documentManager->createDoc(CreateMockDocument(QUrl(i18n(SecondTestURL)))));
+ return createdDocuments;
+ }();
+
+ const bool documentClosed = documentManager->closeDocuments({createdDocuments[0]}, false);
+ Q_ASSERT(documentClosed);
+
+ const auto recentlyClosedURLs = documentManager->popRecentlyClosedURLs();
+ Q_ASSERT(recentlyClosedURLs.contains(QUrl(i18n(FirstTestURL))));
+ Q_ASSERT(!recentlyClosedURLs.contains(QUrl(i18n(SecondTestURL))));
+
+ tearDown();
+}
+
+void KateDocManagerTests::closeDocumentsWithEmptyURLsAreNotRestorable()
+{
+ setUp();
+
+ auto documentManager = app->documentManager();
+ documentManager->closeAllDocuments();
+
+ const auto createdDocuments = [&documentManager] {
+ QList<KTextEditor::Document *> createdDocuments;
+ createdDocuments.push_back(documentManager->createDoc(CreateMockDocument()));
+ createdDocuments.push_back(documentManager->createDoc(CreateMockDocument()));
+ return createdDocuments;
+ }();
+
+ const bool documentsClosed = documentManager->closeDocuments(createdDocuments, false);
+ Q_ASSERT(documentsClosed);
+
+ const auto recentlyClosedURLs = documentManager->popRecentlyClosedURLs();
+ Q_ASSERT(recentlyClosedURLs.isEmpty());
+
+ tearDown();
+}
+
+#include "moc_kate_doc_manager_tests.cpp"
\ No newline at end of file
diff --git a/apps/lib/autotests/kate_doc_manager_tests.h b/apps/lib/autotests/kate_doc_manager_tests.h
new file mode 100644
index 0000000000..385d86bc9a
--- /dev/null
+++ b/apps/lib/autotests/kate_doc_manager_tests.h
@@ -0,0 +1,27 @@
+
+#pragma once
+
+#include "kateapp.h"
+
+#include <QObject>
+
+class KateDocManagerTests : public QObject
+{
+ Q_OBJECT
+public:
+ KateDocManagerTests(QObject *parent = nullptr);
+
+private:
+ void setUp();
+ void tearDown();
+
+private Q_SLOTS:
+ void canCreateDocument();
+ void popRecentlyClosedURLsClearsRecentlyClosedURLs();
+ void popRecentlyClosedURLsReturnsNoneIfNoTabsClosedDuringSession();
+ void popRecentlyClosedURLsReturnsURLIfTabClosedDuringSession();
+ void closeDocumentsWithEmptyURLsAreNotRestorable();
+
+private:
+ std::unique_ptr<KateApp> app;
+};
\ No newline at end of file
diff --git a/apps/lib/katedocmanager.cpp b/apps/lib/katedocmanager.cpp
index 2cf4941769..000a8ca4db 100644
--- a/apps/lib/katedocmanager.cpp
+++ b/apps/lib/katedocmanager.cpp
@@ -171,12 +171,28 @@ KTextEditor::Document *KateDocManager::openUrl(const QUrl &url, const QString &e
return doc;
}
+QList<QUrl> KateDocManager::popRecentlyClosedURLs()
+{
+ const auto recentlyClosedURLs = m_recentlyClosedURLs;
+ m_recentlyClosedURLs.clear();
+ return recentlyClosedURLs;
+}
+
bool KateDocManager::closeDocuments(const QList<KTextEditor::Document *> documents, bool closeUrl)
{
if (documents.empty()) {
return false;
}
+ m_recentlyClosedURLs.clear();
+ for (const auto &document : documents) {
+ const auto &docInfo = m_docInfos.at(document);
+
+ if (!docInfo.normalizedUrl.isEmpty()) {
+ m_recentlyClosedURLs.push_back(docInfo.normalizedUrl);
+ }
+ }
+
saveMetaInfos(documents);
Q_EMIT aboutToDeleteDocuments(QList<KTextEditor::Document *>{documents.begin(), documents.end()});
diff --git a/apps/lib/katedocmanager.h b/apps/lib/katedocmanager.h
index 2981ae635c..56c75a61eb 100644
--- a/apps/lib/katedocmanager.h
+++ b/apps/lib/katedocmanager.h
@@ -7,6 +7,8 @@
#pragma once
+#include "kateprivate_export.h"
+
#include <ktexteditor/document.h>
#include <QList>
@@ -37,10 +39,12 @@ public:
QUrl normalizedUrl;
};
-class KateDocManager : public QObject
+class KATE_PRIVATE_EXPORT KateDocManager : public QObject
{
Q_OBJECT
+ friend class KateDocManagerTests;
+
public:
explicit KateDocManager(QObject *parent);
~KateDocManager() override;
@@ -62,6 +66,8 @@ public:
std::vector<KTextEditor::Document *>
openUrls(const QList<QUrl> &, const QString &encoding = QString(), const KateDocumentInfo &docInfo = KateDocumentInfo());
+ QList<QUrl> popRecentlyClosedURLs();
+
bool closeDocument(KTextEditor::Document *, bool closeUrl = true);
bool closeDocuments(const QList<KTextEditor::Document *> documents, bool closeUrl = true);
bool closeDocumentList(const QList<KTextEditor::Document *> &documents, KateMainWindow *window);
@@ -171,6 +177,8 @@ private:
bool m_saveMetaInfos;
int m_daysMetaInfos;
+ QList<QUrl> m_recentlyClosedURLs;
+
private Q_SLOTS:
void documentOpened();
};
diff --git a/apps/lib/katemainwindow.cpp b/apps/lib/katemainwindow.cpp
index bddc4c13b7..53771fc9cd 100644
--- a/apps/lib/katemainwindow.cpp
+++ b/apps/lib/katemainwindow.cpp
@@ -417,6 +417,13 @@ void KateMainWindow::setupActions()
connect(a, &QAction::triggered, this, &KateMainWindow::slotDocumentCloseAll);
a->setWhatsThis(i18n("Close all open documents."));
+ a = actionCollection()->addAction(QStringLiteral("reopen_latest_closed_tab"));
+ a->setIcon(QIcon::fromTheme(QStringLiteral("reopentab")));
+ a->setText(i18n("&Reopen latest closed tab."));
+ actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_T));
+ connect(a, &QAction::triggered, m_viewManager, &KateViewManager::slotRestoreLastClosedDocument);
+ a->setWhatsThis(i18n("Reopen the tab that was most recently closed"));
+
a = actionCollection()->addAction(KStandardAction::Quit, QStringLiteral("file_quit"));
// Qt::QueuedConnection: delay real shutdown, as we are inside menu action handling (bug #185708)
connect(a, &QAction::triggered, this, &KateMainWindow::slotFileQuit, Qt::QueuedConnection);
diff --git a/apps/lib/kateviewmanager.cpp b/apps/lib/kateviewmanager.cpp
index ff152b3c9b..bb3a3d3b2d 100644
--- a/apps/lib/kateviewmanager.cpp
+++ b/apps/lib/kateviewmanager.cpp
@@ -400,6 +400,14 @@ void KateViewManager::slotDocumentClose()
}
}
+void KateViewManager::slotRestoreLastClosedDocument()
+{
+ const auto &documentManager = KateApp::self()->documentManager();
+ const auto recentlyClosedUrls = documentManager->popRecentlyClosedURLs();
+
+ openUrls(recentlyClosedUrls, QString());
+}
+
KTextEditor::Document *
KateViewManager::openUrl(const QUrl &url, const QString &encoding, bool activate, bool ignoreForRecentFiles, const KateDocumentInfo &docInfo)
{
diff --git a/apps/lib/kateviewmanager.h b/apps/lib/kateviewmanager.h
index a9412fdfde..5ef3e14aa8 100644
--- a/apps/lib/kateviewmanager.h
+++ b/apps/lib/kateviewmanager.h
@@ -95,6 +95,7 @@ public Q_SLOTS:
void slotDocumentOpen();
void slotDocumentClose();
void slotDocumentClose(KTextEditor::Document *document);
+ void slotRestoreLastClosedDocument();
void setActiveSpace(KateViewSpace *vs);
diff --git a/doc/kate/fundamentals.docbook b/doc/kate/fundamentals.docbook
index 9572239ac9..5b562cfc84 100644
--- a/doc/kate/fundamentals.docbook
+++ b/doc/kate/fundamentals.docbook
@@ -371,6 +371,10 @@ action="simul">&Ctrl;<keycap>W</keycap></keycombo> /
<entry><para><keycombo action="simul">&Alt;&Left;</keycombo></para></entry>
<entry><para>Previous Tab</para></entry>
</row>
+<row>
+<entry><para><keycombo action="simul">&Ctrl;&Shift;<keycap>T</keycap></keycombo></para></entry>
+<entry><para>Reopen Latest Closed Tab</para></entry>
+</row>
</tbody>
</tgroup>
diff --git a/doc/kate/menus.docbook b/doc/kate/menus.docbook
index 00a26cfe6e..d810c61fa4 100644
--- a/doc/kate/menus.docbook
+++ b/doc/kate/menus.docbook
@@ -748,6 +748,19 @@ The new instance will be identical to your previous instance.
</listitem>
</varlistentry>
+<varlistentry id="reopen-latest-closed-tab">
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;&Shift;<keycap>T</keycap></keycombo>
+</shortcut>
+<guimenu>View</guimenu>
+<guimenuitem>Reopen Latest Closed Tab</guimenuitem>
+</menuchoice></term>
+<listitem>
+<para>Reopens the latest closed tab.</para>
+</listitem>
+</varlistentry>
+
<varlistentry id="view-quick-open">
<term><menuchoice>
<shortcut>
More information about the kde-doc-english
mailing list