File indexing completed on 2024-04-28 05:49:32
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2021 Méven Car <meven.car@kdemail.net> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "katestashmanager.h" 0008 0009 #include "katedebug.h" 0010 0011 #include "kateapp.h" 0012 #include "kateviewmanager.h" 0013 0014 #include <QDir> 0015 #include <QFile> 0016 #include <QStringDecoder> 0017 #include <QUrl> 0018 0019 KateStashManager::KateStashManager(QObject *parent) 0020 : QObject(parent) 0021 { 0022 } 0023 0024 void KateStashManager::clearStashForSession(const KateSession::Ptr session) 0025 { 0026 const QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); 0027 QDir dir(appDataPath); 0028 if (dir.exists(QStringLiteral("stash"))) { 0029 dir.cd(QStringLiteral("stash")); 0030 const QString sessionName = session->name(); 0031 if (dir.exists(sessionName)) { 0032 dir.cd(sessionName); 0033 dir.removeRecursively(); 0034 } 0035 } 0036 } 0037 0038 void KateStashManager::stashDocuments(KConfig *config, const QList<KTextEditor::Document *> &documents) const 0039 { 0040 if (!canStash()) { 0041 return; 0042 } 0043 0044 // prepare stash directory 0045 const QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); 0046 QDir dir(appDataPath); 0047 dir.mkdir(QStringLiteral("stash")); 0048 dir.cd(QStringLiteral("stash")); 0049 0050 const QString sessionName = KateApp::self()->sessionManager()->activeSession()->name(); 0051 dir.mkdir(sessionName); 0052 dir.cd(sessionName); 0053 0054 int i = 0; 0055 for (KTextEditor::Document *doc : documents) { 0056 // stash the file content 0057 if (doc->isModified()) { 0058 const QString entryName = QStringLiteral("Document %1").arg(i); 0059 KConfigGroup cg(config, entryName); 0060 stashDocument(doc, entryName, cg, dir.path()); 0061 } 0062 0063 i++; 0064 } 0065 } 0066 0067 bool KateStashManager::willStashDoc(KTextEditor::Document *doc) const 0068 { 0069 Q_ASSERT(canStash()); 0070 0071 if (doc->isEmpty()) { 0072 return false; 0073 } 0074 if (doc->url().isEmpty()) { 0075 return m_stashNewUnsavedFiles; 0076 } 0077 if (doc->isModified() && doc->url().isLocalFile()) { 0078 const QString path = doc->url().toLocalFile(); 0079 if (path.startsWith(QDir::tempPath())) { 0080 return false; // inside tmp resource, do not stash 0081 } 0082 return m_stashUnsavedChanges; 0083 } 0084 return false; 0085 } 0086 0087 void KateStashManager::stashDocument(KTextEditor::Document *doc, const QString &stashfileName, KConfigGroup &kconfig, const QString &path) const 0088 { 0089 if (!willStashDoc(doc)) { 0090 return; 0091 } 0092 // Stash changes 0093 QString stashedFile = path + QStringLiteral("/") + stashfileName; 0094 0095 // save the current document changes to stash 0096 if (!doc->saveAs(QUrl::fromLocalFile(stashedFile))) { 0097 qCWarning(LOG_KATE) << "Could not write to stash file" << stashedFile; 0098 return; 0099 } 0100 0101 // write stash metadata to config 0102 kconfig.writeEntry("stashedFile", stashedFile); 0103 if (doc->url().isValid()) { 0104 // save checksum for already-saved documents 0105 kconfig.writeEntry("checksum", doc->checksum()); 0106 } 0107 0108 kconfig.sync(); 0109 } 0110 0111 bool KateStashManager::canStash() const 0112 { 0113 const auto activeSession = KateApp::self()->sessionManager()->activeSession(); 0114 return activeSession && !activeSession->isAnonymous() && !activeSession->name().isEmpty(); 0115 } 0116 0117 void KateStashManager::popDocument(KTextEditor::Document *doc, const KConfigGroup &kconfig) 0118 { 0119 if (!(kconfig.hasKey("stashedFile"))) { 0120 return; 0121 } 0122 qCDebug(LOG_KATE) << "popping stashed document" << doc->url(); 0123 0124 // read metadata 0125 const auto stashedFile = kconfig.readEntry("stashedFile"); 0126 const auto url = QUrl(kconfig.readEntry("URL")); 0127 0128 bool checksumOk = true; 0129 if (url.isValid()) { 0130 const auto sum = kconfig.readEntry(QStringLiteral("checksum")).toLatin1().constData(); 0131 checksumOk = sum != doc->checksum(); 0132 } 0133 0134 if (checksumOk) { 0135 // open file with stashed content 0136 QFile input(stashedFile); 0137 input.open(QIODevice::ReadOnly); 0138 0139 auto decoder = QStringDecoder(kconfig.readEntry("Encoding").toUtf8().constData()); 0140 QString text = decoder.isValid() ? decoder.decode(input.readAll()) : QString::fromLocal8Bit(input.readAll()); 0141 0142 // normalize line endings, to e.g. catch issues with \r\n on Windows 0143 text.replace(QRegularExpression(QStringLiteral("\r\n?")), QStringLiteral("\n")); 0144 0145 doc->setText(text); 0146 0147 // clean stashed file 0148 if (!input.remove()) { 0149 qCWarning(LOG_KATE) << "Could not remove stash file" << stashedFile; 0150 } 0151 } 0152 } 0153 0154 #include "moc_katestashmanager.cpp"