Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85802964
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
26 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/kazv-io-job.cpp b/src/kazv-io-job.cpp
index ee675ff..0d75e31 100644
--- a/src/kazv-io-job.cpp
+++ b/src/kazv-io-job.cpp
@@ -1,353 +1,357 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022-2023 nannanko <nannanko@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <kazv-defs.hpp>
#include "kazv-io-job.hpp"
#include "matrix-room.hpp"
#include "kazv-log.hpp"
#include <QObject>
#include <QPointer>
#include <QSharedPointer>
#include <QSaveFile>
#include <QFile>
#include <QString>
#include <QMimeDatabase>
#include <QCryptographicHash>
#include <QLoggingCategory>
#include <KJob>
#include <KIO/TransferJob>
#include <nlohmann/json.hpp>
#include <optional>
#include <string>
using namespace Qt::Literals::StringLiterals;
struct KazvIOBaseJobPrivate
{
QPointer<KIO::TransferJob> job;
std::optional<KazvIOBaseJob::ErrorCode> result = std::nullopt;
std::optional<Kazv::AES256CTRDesc> aes = std::nullopt;
};
KazvIOBaseJob::KazvIOBaseJob(std::optional<Kazv::AES256CTRDesc> aes, QObject *parent)
: QObject(parent)
, m_d(new KazvIOBaseJobPrivate)
{
/**
* For unknown reasons, if a new AES256CTRDesc is not constructed here,
* it will cause the program to crash.
*/
if (aes != std::nullopt) {
m_d->aes = Kazv::AES256CTRDesc{aes.value().key(), aes.value().iv()};
}
// m_d->aes = aes;
connect(this, &KazvIOBaseJob::jobChanged, this, &KazvIOBaseJob::connectJob);
}
KazvIOBaseJob::~KazvIOBaseJob() = default;
float KazvIOBaseJob::progress() {
if (m_d->job.isNull()) {
return 0;
}
return static_cast<float>(m_d->job->percent()) / 100;
}
void KazvIOBaseJob::suspend()
{
if (m_d->job.isNull()) {
emitResult(KazvError);
return;
}
m_d->job->suspend();
}
void KazvIOBaseJob::resume()
{
if (m_d->job.isNull()) {
emitResult(KazvError);
return;
}
m_d->job->resume();
}
void KazvIOBaseJob::cancel()
{
if (m_d->job.isNull()) {
emitResult(KazvError);
return;
}
emitResult(UserCancel);
m_d->job->kill();
}
bool KazvIOBaseJob::isSuspended()
{
if (m_d->job.isNull()) {
return false;
}
return m_d->job->isSuspended();
}
bool KazvIOBaseJob::isResulted()
{
return m_d->result.has_value();
}
KazvIOBaseJob::ErrorCode KazvIOBaseJob::error()
{
if (m_d->result.has_value()) {
return m_d->result.value();
}
// Shouldn't call this function before result are emited
return NoError;
}
void KazvIOBaseJob::connectJob()
{
connect(m_d->job, &KJob::result, this, [this](KJob *job) {
if (job->error()) {
emitResult(KIOError);
}
});
connect(m_d->job, &KJob::percentChanged, this,
[this](KJob * /* job */, unsigned long /* percent */) { Q_EMIT progressChanged(); });
}
QPointer<KIO::TransferJob> KazvIOBaseJob::job()
{
return m_d->job;
}
void KazvIOBaseJob::setJob(QPointer<KIO::TransferJob> job)
{
m_d->job = job;
Q_EMIT jobChanged();
}
void KazvIOBaseJob::emitResult(ErrorCode ec, QString data)
{
if (m_d->result.has_value()) {
return;
}
m_d->result = ec;
Q_EMIT result(m_d->result.value(), data);
}
std::optional<Kazv::AES256CTRDesc> KazvIOBaseJob::aes()
{
return m_d->aes;
}
void KazvIOBaseJob::setAes(Kazv::AES256CTRDesc aes)
{
m_d->aes = aes;
}
struct KazvIODownloadJobPrivate
{
QSharedPointer<KazvSaveFile> file;
QString hash;
};
KazvIODownloadJob::KazvIODownloadJob(const QString &hash, std::optional<Kazv::AES256CTRDesc> aes, QObject *parent)
: KazvIOBaseJob(aes, parent)
, m_d(new KazvIODownloadJobPrivate)
{
m_d->hash = hash;
}
-KazvIODownloadJob::KazvIODownloadJob(const QString &fileName, const QUrl &serverUrl,
+KazvIODownloadJob::KazvIODownloadJob(const QString &fileName, const QUrl &serverUrl, bool showProgressBar,
const QString &hash, std::optional<Kazv::AES256CTRDesc> aes, QObject *parent)
: KazvIOBaseJob(aes, parent)
, m_d(new KazvIODownloadJobPrivate)
{
if (setFile(fileName)) {
- setJob(KIO::get(serverUrl));
+ auto flag = showProgressBar ? KIO::DefaultFlags : KIO::HideProgressInfo;
+ setJob(KIO::get(serverUrl, KIO::NoReload, flag));
}
m_d->hash = hash;
}
KazvIODownloadJob::~KazvIODownloadJob() = default;
QString KazvIODownloadJob::fileName() {
if (m_d->file.isNull()) {
return QStringLiteral("");
}
return m_d->file->fileName();
}
void KazvIODownloadJob::connectJob()
{
KazvIOBaseJob::connectJob();
connect(this->job(), &KIO::TransferJob::data, this, &KazvIODownloadJob::writeFile);
connect(this->job(), &KJob::result, this, &KazvIODownloadJob::closeFile);
}
bool KazvIODownloadJob::setFile(QString fileName)
{
m_d->file.reset(new KazvSaveFile(fileName, this->aes()));
if (m_d->file->open(QIODevice::WriteOnly)) {
return true;
}
emitResult(KazvIOBaseJob::OpenFileError);
return false;
}
void KazvIODownloadJob::writeFile(KJob *job, const QByteArray &data)
{
if (m_d->file.isNull() || !m_d->file->isOpen()) {
emitResult(KazvError);
job->kill();
return;
}
auto len = m_d->file->write(data);
if (len == -1) {
KazvIOBaseJob::emitResult(WriteFileError);
job->kill();
}
}
void KazvIODownloadJob::closeFile(KJob *job)
{
if (m_d->file.isNull()) {
emitResult(KazvError);
return;
}
if (job->error()) {
m_d->file->cancelWriting();
return;
}
if (!m_d->hash.isEmpty() && QString::fromUtf8(m_d->file->hash()) != m_d->hash) {
emitResult(HashError);
return;
}
m_d->file->commit();
emitResult(NoError);
}
struct KazvIOUploadJobPrivate
{
QSharedPointer<KazvFile> file;
QString response;
QSharedPointer<MatrixRoom> room;
QString mimeType;
QString mxcUri;
QString relType;
QString relatedTo;
};
KazvIOUploadJob::KazvIOUploadJob(std::optional<Kazv::AES256CTRDesc> aes,
const QString &relType, const QString &relatedTo, QObject *parent)
: KazvIOBaseJob(aes, parent)
, m_d(new KazvIOUploadJobPrivate)
{
m_d->relType = relType;
m_d->relatedTo = relatedTo;
}
KazvIOUploadJob::KazvIOUploadJob(const QString fileName, const QUrl serverUrl,
- MatrixRoomList *roomList, const QString &roomId, const QString token,
- std::optional<Kazv::AES256CTRDesc> aes,
+ const bool showProgressBar, MatrixRoomList *roomList, const QString &roomId,
+ const QString token, std::optional<Kazv::AES256CTRDesc> aes,
const QString &relType, const QString &relatedTo, QObject *parent)
: KazvIOBaseJob(aes, parent)
, m_d(new KazvIOUploadJobPrivate)
{
m_d->relType = relType;
m_d->relatedTo = relatedTo;
if (setFile(fileName)) {
auto kazvUploadJob = Kazv::Api::UploadContentJob(serverUrl.toString().toStdString(),
token.toStdString(), Kazv::FileDesc(std::string()));
- auto job = KIO::http_post(QUrl(QString::fromStdString(kazvUploadJob.url())), m_d->file.data());
+ auto jobFlag = showProgressBar ? KIO::DefaultFlags : KIO::HideProgressInfo;
+ auto job = KIO::http_post(
+ QUrl(QString::fromStdString(kazvUploadJob.url())),
+ m_d->file.data(), jobFlag);
job->addMetaData(u"customHTTPHeader"_s, QStringLiteral("Authorization: ")
.append(QString::fromStdString(kazvUploadJob.requestHeader()->at("Authorization"))));
job->addMetaData(u"PropagateHttpHeader"_s, u"true"_s);
setJob(job);
if (roomList) {
m_d->room.reset(roomList->room(roomId));
}
}
}
KazvIOUploadJob::~KazvIOUploadJob() = default;
QString KazvIOUploadJob::fileName()
{
if (m_d->file.isNull()) {
return QStringLiteral("");
}
return m_d->file->fileName();
}
void KazvIOUploadJob::connectJob()
{
KazvIOBaseJob::connectJob();
connect(this->job(), &KIO::TransferJob::data, this,
[this](KJob * /* job */, const QByteArray &data) { m_d->response.append(QString::fromUtf8(data)); });
connect(this->job(), &KJob::result, this, &KazvIOUploadJob::handleResult);
connect(this->job(), &KIO::TransferJob::mimeTypeFound, this,
[this](KJob * /* job */, const QString &mimeType) { m_d->mimeType = mimeType; });
}
void KazvIOUploadJob::handleResult(KJob *job)
{
if (m_d->file.isNull()) {
emitResult(KazvError);
return;
}
m_d->file->close();
if (job->error()) {
return;
}
nlohmann::json j;
try {
j = nlohmann::json::parse(m_d->response.toStdString());
} catch(...) {
emitResult(ResponseError);
qCWarning(kazvLog) << "Get a invaild response from server.";
return;
}
QString mxcUri{};
if (j.contains("content_uri") && j["content_uri"].is_string()) {
mxcUri = QString::fromStdString(j["content_uri"].template get<std::string>());
} else {
emitResult(ResponseError);
qCWarning(kazvLog) << "There is no \"content_uri\" field in response.";
return;
}
auto shouldSendMessage = !!m_d->room;
if (shouldSendMessage) {
auto aes = this->aes();
if (aes.has_value()) {
m_d->room->sendEncryptedFileMessage(QUrl::fromLocalFile(m_d->file->fileName()).fileName(),
QMimeDatabase().mimeTypeForFile(m_d->file.data()->fileName()).name(),
m_d->file->size(), mxcUri,
QString::fromStdString(aes.value().key()), QString::fromStdString(aes.value().iv()),
m_d->file->hash(), m_d->relType, m_d->relatedTo);
} else {
m_d->room->sendMediaFileMessage(QUrl::fromLocalFile(m_d->file->fileName()).fileName(),
QMimeDatabase().mimeTypeForData(m_d->file.data()).name(),
m_d->file->size(), mxcUri, m_d->relType, m_d->relatedTo);
}
}
KazvIOBaseJob::emitResult(NoError, mxcUri);
}
bool KazvIOUploadJob::setFile(const QString fileName)
{
m_d->file.reset(new KazvFile(fileName, this->aes()));
if (m_d->file->open(QIODevice::ReadOnly)) {
return true;
}
emitResult(KazvIOBaseJob::OpenFileError);
return false;
}
diff --git a/src/kazv-io-job.hpp b/src/kazv-io-job.hpp
index bb42234..a9a374e 100644
--- a/src/kazv-io-job.hpp
+++ b/src/kazv-io-job.hpp
@@ -1,164 +1,165 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022-2023 nannanko <nannanko@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#pragma once
#include <kazv-defs.hpp>
#include "matrix-room.hpp"
#include "matrix-room-list.hpp"
#include "kazv-file.hpp"
#include <aes-256-ctr.hpp>
#include <QObject>
#include <QPointer>
#include <QString>
#include <QUrl>
#include <KIO/TransferJob>
#include <memory>
#include <optional>
struct KazvIOBaseJobPrivate;
class KazvIOBaseJob : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("")
Q_PROPERTY(float progress READ progress NOTIFY progressChanged)
std::unique_ptr<KazvIOBaseJobPrivate> m_d;
public:
enum ErrorCode {
/**
* No Error or the signal result has not been emitted yet.
*/
NoError = 0,
/**
* The user actively canceled the job.
*/
UserCancel,
/**
* Open File Error.
*/
OpenFileError,
/**
* Write File Error
*/
WriteFileError,
/**
* Errors caused by KIO, such network error.
*/
KIOError,
/**
* Error caused by hash error
*/
HashError,
/**
* Error caused by invalid response.
* KIO reported no error, but got an invalid JSON response.
*/
ResponseError,
/**
* Errors caused by bad code, means the bug is somewhere.
*/
KazvError
};
Q_ENUM(ErrorCode)
KazvIOBaseJob(std::optional<Kazv::AES256CTRDesc> aes = std::nullopt, QObject *parent = 0);
~KazvIOBaseJob();
float progress();
Q_INVOKABLE void suspend();
Q_INVOKABLE void resume();
Q_INVOKABLE void cancel();
Q_INVOKABLE bool isSuspended();
Q_INVOKABLE bool isResulted();
/**
* Only use it after emitted the result signal
*/
Q_INVOKABLE ErrorCode error();
Q_SIGNALS:
void jobChanged();
void progressChanged();
/**
* @param data the mxcUri if this is an upload job.
*/
void result(ErrorCode ec, QString data);
protected Q_SLOTS:
virtual void connectJob();
protected:
QPointer<KIO::TransferJob> job();
void setJob(QPointer<KIO::TransferJob> job);
std::optional<Kazv::AES256CTRDesc> aes();
void setAes(Kazv::AES256CTRDesc);
void emitResult(ErrorCode ec, QString data = QString());
};
struct KazvIODownloadJobPrivate;
class KazvIODownloadJob : public KazvIOBaseJob
{
Q_OBJECT
std::unique_ptr<KazvIODownloadJobPrivate> m_d;
bool setFile(QString fileName);
public:
KazvIODownloadJob(const QString &hash, std::optional<Kazv::AES256CTRDesc> aes = std::nullopt, QObject *parent = 0);
- KazvIODownloadJob(const QString &fileName, const QUrl &serverUrl, const QString &hash,
+ KazvIODownloadJob(const QString &fileName, const QUrl &serverUrl, const bool showProgressBar, const QString &hash,
std::optional<Kazv::AES256CTRDesc> aes = std::nullopt, QObject *parent = 0);
~KazvIODownloadJob();
Q_INVOKABLE QString fileName();
private Q_SLOTS:
void writeFile(KJob *job, const QByteArray &data);
void closeFile(KJob *job);
protected Q_SLOTS:
void connectJob() override;
};
struct KazvIOUploadJobPrivate;
class KazvIOUploadJob : public KazvIOBaseJob
{
Q_OBJECT
std::unique_ptr<KazvIOUploadJobPrivate> m_d;
bool setFile(const QString fileName);
public:
KazvIOUploadJob(std::optional<Kazv::AES256CTRDesc> aes = std::nullopt,
const QString &relType = QStringLiteral(""),
const QString &relatedTo = QStringLiteral(""), QObject *parent = 0);
- KazvIOUploadJob(const QString fileName, const QUrl serverUrl, MatrixRoomList *roomList,
+ KazvIOUploadJob(const QString fileName, const QUrl serverUrl,
+ const bool showProgressBar, MatrixRoomList *roomList,
const QString &roomId, const QString token,
std::optional<Kazv::AES256CTRDesc> aes = std::nullopt,
const QString &relType = QStringLiteral(""),
const QString &relatedTo = QStringLiteral(""), QObject *parent = 0);
~KazvIOUploadJob();
Q_INVOKABLE QString fileName();
private Q_SLOTS:
void handleResult(KJob *job);
protected Q_SLOTS:
void connectJob() override;
};
diff --git a/src/kazv-io-manager.cpp b/src/kazv-io-manager.cpp
index 328a839..0e6f5cc 100644
--- a/src/kazv-io-manager.cpp
+++ b/src/kazv-io-manager.cpp
@@ -1,223 +1,229 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022-2023 nannanko <nannanko@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <kazv-defs.hpp>
#include "kazv-io-manager.hpp"
#include "kazv-io-job.hpp"
#include "matrix-room.hpp"
#include "upload-job-model.hpp"
#include "qt-rand-adapter.hpp"
#include <api/csapi/content-repo.hpp>
#include <file-desc.hpp>
#include <QObject>
#include <QIODevice>
#include <QFile>
#include <QSaveFile>
#include <QPointer>
#include <QSharedPointer>
#include <QUrl>
#include <QMap>
#include <QMultiMap>
#include <QTemporaryDir>
#include <string>
#include <algorithm>
using namespace Qt::Literals::StringLiterals;
static const QString ROOMLESS = QStringLiteral("not-a-room");
struct KazvIOManagerPrivate
{
/**
* Used to store various temporary files.
* If the user does not specify a cache directory,
* this directory is also used as a cache directory.
*/
QTemporaryDir tmpDir = QTemporaryDir{};
/**
* Stores files that need to be previewed (e.g. in a timeline)
* and are not downloaded by the user, such as images, audio, video covers, and videos.
*/
QDir cacheDir{tmpDir.path()};
Kazv::RandomInterface randomGenerator = QtRandAdapter{};
QMap<QString, QPointer<KazvIODownloadJob>> cacheJobs;
QMap<QString, QSharedPointer<KazvIODownloadJob>> downloadJobs;
QMap<QString, QSharedPointer<UploadJobModel>> uploadJobs;
};
KazvIOManager::KazvIOManager(QObject *parent)
: QObject(parent)
, m_d(new KazvIOManagerPrivate)
{
}
KazvIOManager::~KazvIOManager() = default;
QPointer<KazvIODownloadJob> KazvIOManager::makeDownloadJob(
- const QUrl &serverUrl, const QUrl &localFileUrl, const QString &hash,
+ const QUrl &serverUrl, const QUrl &localFileUrl,
+ const bool showPrograssBar, const QString &hash,
const QString &key, const QString &iv) const
{
QPointer<KazvIODownloadJob> job{};
if (key.isEmpty()) {
- job = new KazvIODownloadJob{localFileUrl.toLocalFile(), serverUrl, hash, std::nullopt};
+ job = new KazvIODownloadJob{localFileUrl.toLocalFile(),
+ serverUrl, showPrograssBar, hash, std::nullopt};
} else {
auto aes = Kazv::AES256CTRDesc{key.toStdString(), iv.toStdString()};
- job = new KazvIODownloadJob{localFileUrl.toLocalFile(), serverUrl, hash, aes};
+ job = new KazvIODownloadJob{localFileUrl.toLocalFile(),
+ serverUrl, showPrograssBar, hash, aes};
}
return job;
}
QUrl KazvIOManager::cacheFile(const QUrl &fileUrl, const QString &id, const QString &hash,
const QString &key, const QString &iv)
{
const QString filePath = m_d->cacheDir.filePath(id);
QDir dir(m_d->cacheDir.path());
if (!dir.exists(id) && this->getCacheJob(id) == nullptr) {
- auto job = this->makeDownloadJob(fileUrl, QUrl::fromLocalFile(filePath), hash, key, iv);
+ auto job = this->makeDownloadJob(fileUrl,
+ QUrl::fromLocalFile(filePath),
+ /* showProgressBar = */ false, hash, key, iv);
m_d->cacheJobs[id] = job;
connect(job, &KazvIOBaseJob::result, this, [this, id](auto /* result */) {
m_d->cacheJobs[id]->deleteLater();
m_d->cacheJobs.remove(id);
});
}
return QUrl::fromLocalFile(filePath);
}
KazvIOBaseJob *KazvIOManager::startNewDownloadJob(const QUrl &serverUrl, const QUrl &localFileUrl,
const QString &jobId, const QString &hash, const QString &key, const QString &iv)
{
- auto downloadJob = this->makeDownloadJob(serverUrl, localFileUrl, hash, key, iv);
+ auto downloadJob = this->makeDownloadJob(serverUrl, localFileUrl,
+ /* showProgressBar = */ true, hash, key, iv);
m_d->downloadJobs[jobId].reset(downloadJob);
QQmlEngine::setObjectOwnership(downloadJob.data(), QQmlEngine::CppOwnership);
return downloadJob.data();
}
KazvIOBaseJob *KazvIOManager::startNewUploadJob(
const QUrl &serverUrl, const QUrl &localFileUrl, const QString &token,
const QString &roomId, MatrixRoomList *roomList, const bool encrypted,
const QString &relType, const QString &relatedTo)
{
auto uploadJob = QPointer<KazvIOUploadJob>();
if (encrypted) {
auto aes = Kazv::AES256CTRDesc::fromRandom(
m_d->randomGenerator.generateRange<Kazv::RandomData>(Kazv::AES256CTRDesc::randomSize));
uploadJob = new KazvIOUploadJob(localFileUrl.toLocalFile(), serverUrl,
- roomList, roomId, token, aes, relType, relatedTo);
+ /* showProgressBar = */ true, roomList, roomId, token, aes, relType, relatedTo);
} else {
uploadJob = new KazvIOUploadJob(localFileUrl.toLocalFile(), serverUrl,
- roomList, roomId, token, std::nullopt, relType, relatedTo);
+ /* showProgressBar = */ true, roomList, roomId, token, std::nullopt, relType, relatedTo);
}
if (!m_d->uploadJobs.contains(roomId) || m_d->uploadJobs[roomId].isNull()) {
m_d->uploadJobs[roomId].reset(new UploadJobModel());
}
m_d->uploadJobs[roomId]->addJob(uploadJob);
QQmlEngine::setObjectOwnership(uploadJob.data(), QQmlEngine::CppOwnership);
return uploadJob.data();
}
KazvIOBaseJob *KazvIOManager::startNewRoomlessUploadJob(const QUrl &serverUrl, const QUrl &localFileUrl, const QString &token)
{
return startNewUploadJob(
serverUrl, localFileUrl, token, ROOMLESS, 0, false,
QStringLiteral(""), QStringLiteral(""));
}
KazvIOBaseJob *KazvIOManager::getCacheJob(const QString &jobId) const
{
auto targetJob = m_d->cacheJobs.find(jobId);
if (targetJob == m_d->cacheJobs.end()) {
return nullptr;
}
QQmlEngine::setObjectOwnership(targetJob.value().data(), QQmlEngine::CppOwnership);
return targetJob.value().data();
}
KazvIOBaseJob *KazvIOManager::getDownloadJob(const QString &jobId)
{
auto targetJob = m_d->downloadJobs.find(jobId);
if (targetJob == m_d->downloadJobs.end()) {
return nullptr;
}
QQmlEngine::setObjectOwnership(targetJob.value().data(), QQmlEngine::CppOwnership);
return targetJob.value().data();
}
void KazvIOManager::deleteDownloadJob(const QString &jobId)
{
m_d->downloadJobs.remove(jobId);
}
UploadJobModel *KazvIOManager::getUploadJobs(const QString &roomId)
{
if (!m_d->uploadJobs.contains(roomId) || m_d->uploadJobs[roomId].isNull()) {
m_d->uploadJobs[roomId].reset(new UploadJobModel());
}
QQmlEngine::setObjectOwnership(m_d->uploadJobs[roomId].data(), QQmlEngine::CppOwnership);
return m_d->uploadJobs[roomId].data();
}
void KazvIOManager::deleteUploadJob(const QString &roomId, KazvIOBaseJob *job)
{
m_d->uploadJobs[roomId]->removeJob(QPointer<KazvIOUploadJob>(qobject_cast<KazvIOUploadJob*>(job)));
}
void KazvIOManager::deleteRoomlessUploadJob(KazvIOBaseJob *job)
{
deleteUploadJob(ROOMLESS, job);
}
void KazvIOManager::deleteModelIfEmpty(const QString &roomId)
{
if (!m_d->uploadJobs.contains(roomId)) {
return;
}
if (m_d->uploadJobs[roomId]->rowCount() == 0) {
m_d->uploadJobs.remove(roomId);
}
}
void KazvIOManager::clearJobs()
{
/**
* KazvIOBaseJob::cancel() for cache jobs will remove itself from cacheJobs,
* so iterators and loops for m_d->cacheJobs cannot be used reliably.
*/
for (auto key : m_d->cacheJobs.keys()) {
m_d->cacheJobs[key]->cancel();
}
std::for_each(m_d->downloadJobs.begin(), m_d->downloadJobs.end(), [this](auto job){
job->cancel();
});
std::for_each(m_d->uploadJobs.begin(), m_d->uploadJobs.end(), [this](auto room) {
room->clearJobs();
});
m_d->downloadJobs.clear();
m_d->uploadJobs.clear();
}
QString KazvIOManager::cacheDirectory() const
{
return m_d->cacheDir.path();
}
void KazvIOManager::setCacheDirectory(QString cacheDirectory)
{
if (cacheDirectory.isEmpty()) {
m_d->cacheDir = QDir{m_d->tmpDir.path()};
} else {
auto cacheDir = QDir{QUrl{cacheDirectory}.toLocalFile()};
if (!cacheDir.mkpath(u"."_s)) {
return;
}
m_d->cacheDir = cacheDir;
}
m_d->downloadJobs.clear();
Q_EMIT cacheDirectoryChanged();
}
diff --git a/src/kazv-io-manager.hpp b/src/kazv-io-manager.hpp
index f0e6c4f..dead687 100644
--- a/src/kazv-io-manager.hpp
+++ b/src/kazv-io-manager.hpp
@@ -1,73 +1,74 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022-2023 nannanko <nannanko@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#pragma once
#include <kazv-defs.hpp>
#include "kazv-io-job.hpp"
#include "matrix-room.hpp"
#include "upload-job-model.hpp"
#include "matrix-room-list.hpp"
#include "matrix-sdk.hpp"
#include <QObject>
#include <QtQml>
#include <QUrl>
#include <QString>
#include <KIO/TransferJob>
#include <QPointer>
#include <memory>
struct KazvIOManagerPrivate;
class KazvIOManager : public QObject
{
Q_OBJECT
QML_ELEMENT
std::unique_ptr<KazvIOManagerPrivate> m_d;
Q_PROPERTY(QString cacheDirectory READ cacheDirectory WRITE setCacheDirectory NOTIFY cacheDirectoryChanged)
QPointer<KazvIODownloadJob> makeDownloadJob(
- const QUrl &serverUrl, const QUrl &localFileUrl, const QString &hash,
+ const QUrl &serverUrl, const QUrl &localFileUrl,
+ const bool showPrograssBar, const QString &hash,
const QString &key = QStringLiteral(""),
const QString &iv = QStringLiteral("")) const;
public:
explicit KazvIOManager(QObject *parent = 0);
~KazvIOManager() override;
/**
* Cache the file specified by fileUrl into a temporary folder
* Multiple calls do not repeat downloads
* Returns the local url of the cached file.
*/
Q_INVOKABLE QUrl cacheFile(const QUrl &fileUrl, const QString &id, const QString &hash = QStringLiteral(""),
const QString &key = QStringLiteral(""), const QString &iv = QStringLiteral(""));
Q_INVOKABLE KazvIOBaseJob *startNewDownloadJob(const QUrl &serverUrl, const QUrl &localFileName,
const QString &jobId, const QString &hash,
const QString &key = QStringLiteral(""), const QString &iv = QStringLiteral(""));
Q_INVOKABLE KazvIOBaseJob *startNewUploadJob(
const QUrl &serverUrl, const QUrl &localFileName, const QString &token,
const QString &roomId, MatrixRoomList *roomList, const bool encrypted,
const QString &relType, const QString &relatedTo);
Q_INVOKABLE KazvIOBaseJob *startNewRoomlessUploadJob(const QUrl &serverUrl, const QUrl &localFileName, const QString &token);
Q_INVOKABLE KazvIOBaseJob *getCacheJob(const QString &jobId) const;
Q_INVOKABLE KazvIOBaseJob *getDownloadJob(const QString &jobId);
Q_INVOKABLE void deleteDownloadJob(const QString &jobId);
Q_INVOKABLE UploadJobModel *getUploadJobs(const QString &roomId);
Q_INVOKABLE void deleteUploadJob(const QString &roomId, KazvIOBaseJob *job);
Q_INVOKABLE void deleteRoomlessUploadJob(KazvIOBaseJob *job);
Q_INVOKABLE void deleteModelIfEmpty(const QString &roomId);
Q_INVOKABLE void clearJobs();
QString cacheDirectory() const;
void setCacheDirectory(QString cacheDirectory);
Q_SIGNALS:
void cacheDirectoryChanged();
};
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Oct 8, 10:11 PM (13 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1784314
Default Alt Text
(26 KB)
Attached To
Mode
rK kazv
Attached
Detach File
Event Timeline
Log In to Comment