katestashmanager.cpp 4.38 KB
Newer Older
Méven Car's avatar
Méven Car committed
1
2
3
/* This file is part of the KDE project
   SPDX-FileCopyrightText: 2021 Méven Car <meven.car@kdemail.net>

4
   SPDX-License-Identifier: LGPL-2.0-or-later
Méven Car's avatar
Méven Car committed
5
6
7
8
9
10
*/

#include "katestashmanager.h"

#include "katedebug.h"

11
#include "kateapp.h"
Méven Car's avatar
Méven Car committed
12
13
14
15
16
17
18
19
20
#include "katedocmanager.h"
#include "kateviewmanager.h"

#include "kconfiggroup.h"
#include "ksharedconfig.h"

#include <QDir>
#include <QFile>
#include <QSaveFile>
21
#include <QTextCodec>
Méven Car's avatar
Méven Car committed
22
23
#include <QUrl>

24
25
KateStashManager::KateStashManager(QObject *parent)
    : QObject(parent)
Méven Car's avatar
Méven Car committed
26
27
28
{
}

29
30
31
32
33
34
35
36
37
38
39
40
41
42
void KateStashManager::clearStashForSession(const KateSession::Ptr session)
{
    const QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir dir(appDataPath);
    if (dir.exists(QStringLiteral("stash"))) {
        dir.cd(QStringLiteral("stash"));
        const QString sessionName = session->name();
        if (dir.exists(sessionName)) {
            dir.cd(sessionName);
            dir.removeRecursively();
        }
    }
}

43
44
45
46
47
48
49
50
51
void KateStashManager::stashDocuments(KConfig *config, const QList<KTextEditor::Document *> &documents)
{
    // prepare stash directory
    const QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir dir(appDataPath);
    dir.mkdir(QStringLiteral("stash"));
    dir.cd(QStringLiteral("stash"));

    const auto session = KateApp::self()->sessionManager()->activeSession();
52
53
54
    if (!session) {
        qDebug(LOG_KATE) << "Could not stash files without a session";
        return;
55
56
    }

57
58
59
60
    const QString sessionName = session->name();
    dir.mkdir(sessionName);
    dir.cd(sessionName);

61
62
63
64
65
66
67
68
69
70
71
72
73
74
    int i = 0;
    for (KTextEditor::Document *doc : qAsConst(documents)) {
        const QString entryName = QStringLiteral("Document %1").arg(i);
        KConfigGroup cg(config, entryName);

        // stash the file content
        if (doc->isModified()) {
            stashDocument(doc, entryName, cg, dir.path());
        }

        i++;
    }
}

75
bool KateStashManager::willStashDoc(KTextEditor::Document *doc)
76
{
77
78
79
80
81
82
83
84
85
86
    if (m_stashUnsaveChanges == 0) {
        return false;
    }
    if (!KateApp::self()->sessionManager()->activeSession()) {
        return false;
    }
    if (doc->text().isEmpty()) {
        return false;
    }
    if (doc->url().isEmpty()) {
87
88
        return true;
    }
89
90
91
92
93
94
95
96
97
98
99
100
101
102
    if (doc->url().isLocalFile()) {
        const QString path = doc->url().toLocalFile();
        if (path.startsWith(QDir::tempPath())) {
            return false; // inside tmp resource, do not stash
        }
    }
    return m_stashUnsaveChanges == 2;
}

void KateStashManager::stashDocument(KTextEditor::Document *doc, const QString &stashfileName, KConfigGroup &kconfig, const QString &path)
{
    if (!willStashDoc(doc)) {
        return;
    }
103
104
105
106
    // Stash changes
    QString stashedFile = path + QStringLiteral("/") + stashfileName;

    // save the current document changes to stash
Méven Car's avatar
Méven Car committed
107
    if (!doc->saveAs(QUrl::fromLocalFile(stashedFile))) {
108
        qCWarning(LOG_KATE) << "Could not write to stash file" << stashedFile;
109
        return;
110
111
112
113
114
    }

    // write stash metadata to config
    kconfig.writeEntry("stashedFile", stashedFile);
    if (doc->url().isValid()) {
115
        // save checksum for already-saved documents
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
        kconfig.writeEntry("checksum", doc->checksum());
    }

    kconfig.sync();
}

bool KateStashManager::popDocument(KTextEditor::Document *doc, const KConfigGroup &kconfig)
{
    if (!(kconfig.hasKey("stashedFile"))) {
        return false;
    }
    qCDebug(LOG_KATE) << "popping stashed document" << doc->url();

    // read metadata
    auto stashedFile = kconfig.readEntry("stashedFile");
    auto url = QUrl(kconfig.readEntry("URL"));

    bool checksumOk = true;
    if (url.isValid()) {
135
        const auto sum = kconfig.readEntry(QStringLiteral("checksum")).toLatin1().constData();
136
137
        checksumOk = sum != doc->checksum();
    }
Méven Car's avatar
Méven Car committed
138

139
    if (checksumOk) {
Méven Car's avatar
Méven Car committed
140
141
142
143
        // open file with stashed content
        QFile file(stashedFile);
        file.open(QIODevice::ReadOnly);
        QTextStream out(&file);
144
145
146
147
148
        const auto codec = QTextCodec::codecForName(kconfig.readEntry("Encoding").toLocal8Bit());
        if (codec != 0) {
            out.setCodec(codec);
        }

Méven Car's avatar
Méven Car committed
149
150
151
        doc->setText(out.readAll());

        // clean stashed file
152
153
154
        if (!file.remove()) {
            qCWarning(LOG_KATE) << "Could not remove stash file" << stashedFile;
        }
155
156
157
158

        return true;
    } else {
        return false;
Méven Car's avatar
Méven Car committed
159
160
    }
}