KIO

kioexecd.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2017 Elvis Angelaccio <elvis.angelaccio@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#include "kioexecd.h"
9#include "kioexecdadaptor.h"
10#include "kioexecdebug.h"
11
12#include <KDirWatch>
13#include <KIO/CopyJob>
14#include <KLocalizedString>
15#include <KMessageBox>
16#include <KPluginFactory>
17
18#include <QDir>
19#include <QFileInfo>
20#include <QStandardPaths>
21
22static const int predefinedTimeout = 30000; // 30s
23
24K_PLUGIN_CLASS_WITH_JSON(KIOExecd, "kioexecd.json")
25
26KIOExecd::KIOExecd(QObject *parent, const QList<QVariant> &)
27 : KDEDModule(parent)
28{
29 qCDebug(KIOEXEC) << "kioexecd started";
30
31 new KIOExecdAdaptor(this);
32 m_watcher = new KDirWatch(this);
33
34 connect(m_watcher, &KDirWatch::dirty, this, &KIOExecd::slotDirty);
35 connect(m_watcher, &KDirWatch::created, this, &KIOExecd::slotCreated);
36 connect(m_watcher, &KDirWatch::deleted, this, &KIOExecd::slotDeleted);
37 m_timer.setSingleShot(true);
38 m_timer.setInterval(predefinedTimeout);
39 connect(&m_timer, &QTimer::timeout, this, &KIOExecd::slotCheckDeletedFiles);
40}
41
42KIOExecd::~KIOExecd()
43{
44 // Remove the remaining temporary files and if possible their parent directories
45 for (auto it = m_watched.constBegin(); it != m_watched.constEnd(); ++it) {
46 QFileInfo info(it.key());
47 const auto parentDir = info.path();
48 qCDebug(KIOEXEC) << "About to delete" << parentDir << "containing" << info.fileName();
49 QFile::remove(it.key());
50 QDir().rmdir(parentDir);
51 }
52}
53
54void KIOExecd::watch(const QString &path, const QString &destUrl)
55{
56 if (m_watched.contains(path)) {
57 qCDebug(KIOEXEC) << "Already watching" << path;
58 return;
59 }
60
61 qCDebug(KIOEXEC) << "Going to watch" << path << "for changes, remote destination is" << destUrl;
62
63 // Watch the temporary file for modifications, creations or deletions
64 m_watcher->addFile(path);
65 m_watched.insert(path, QUrl(destUrl));
66}
67
68void KIOExecd::slotCreated(const QString &path)
69{
70 m_deleted.remove(path);
71
72 // When the file is recreated, it is not signaled as dirty.
73 slotDirty(path);
74}
75
76void KIOExecd::slotDirty(const QString &path)
77{
78 if (!m_watched.contains(path)) {
79 return;
80 }
81
82 const auto dest = m_watched.value(path);
83
84 const auto result = KMessageBox::questionTwoActions(
85 nullptr,
86 xi18nc("@info", "The file <filename>%1</filename><nl/>has been modified. Do you want to upload the changes?", dest.toDisplayString()),
87 i18n("File Changed"),
88 KGuiItem(i18n("Upload"), QLatin1String("cloud-upload-symbolic")),
89 KGuiItem(i18n("Do Not Upload"), QLatin1String("dialog-cancel-symbolic")));
90 if (result != KMessageBox::PrimaryAction) {
91 return;
92 }
93
94 qCDebug(KIOEXEC) << "Uploading" << path << "to" << dest;
95 auto job = KIO::copy(QUrl::fromLocalFile(path), dest);
96 connect(job, &KJob::result, this, [](KJob *job) {
97 if (job->error()) {
98 KMessageBox::error(nullptr, job->errorString());
99 }
100 });
101}
102
103void KIOExecd::slotDeleted(const QString &path)
104{
105 if (!m_watched.contains(path)) {
106 return;
107 }
108
109 m_deleted.insert(path, QDateTime::currentDateTimeUtc());
110 m_timer.start();
111}
112
113void KIOExecd::slotCheckDeletedFiles()
114{
115 const QDateTime currentDateTime = QDateTime::currentDateTimeUtc();
116 // check if the deleted (and not recreated) files where deleted 30s ago or more
117 for (auto it = m_deleted.begin(); it != m_deleted.end();) {
118 if (it.value().msecsTo(currentDateTime) >= predefinedTimeout) {
119 qCDebug(KIOEXEC) << "Going to forget" << it.key();
120 m_watcher->removeFile(it.key());
121 m_watched.remove(it.key());
122 QFileInfo info(it.key());
123 const auto parentDir = info.path();
124 qCDebug(KIOEXEC) << "About to delete" << parentDir;
125 QDir().rmdir(parentDir);
126 it = m_deleted.erase(it);
127 } else {
128 ++it;
129 }
130 }
131 if (!m_deleted.isEmpty()) {
132 m_timer.start();
133 }
134}
135
136#include "kioexecd.moc"
137#include "moc_kioexecd.cpp"
void addFile(const QString &file)
void removeFile(const QString &file)
void deleted(const QString &path)
void dirty(const QString &path)
void created(const QString &path)
virtual QString errorString() const
int error() const
void result(KJob *job)
#define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile)
QString xi18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KIOCORE_EXPORT CopyJob * copy(const QUrl &src, const QUrl &dest, JobFlags flags=DefaultFlags)
Copy a file or directory src into the destination dest, which can be a file (including the final file...
Definition copyjob.cpp:2635
QString path(const QString &relativePath)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
ButtonCode questionTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Notify)
QDateTime currentDateTimeUtc()
bool rmdir(const QString &dirName) const const
bool remove()
iterator begin()
const_iterator constBegin() const const
const_iterator constEnd() const const
bool contains(const Key &key) const const
iterator end()
iterator erase(const_iterator first, const_iterator last)
iterator insert(const Key &key, const T &value)
bool isEmpty() const const
size_type remove(const Key &key)
T value(const Key &key, const T &defaultValue) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void start()
void timeout()
QUrl fromLocalFile(const QString &localFile)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 22 2024 12:04:58 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.