Page MenuHomePhorge

No OneTemporary

Size
13 KB
Referenced Files
None
Subscribers
None
diff --git a/src/kazv-io-job.cpp b/src/kazv-io-job.cpp
index 06f9c51..bf1ec74 100644
--- a/src/kazv-io-job.cpp
+++ b/src/kazv-io-job.cpp
@@ -1,316 +1,328 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022-2023 nannanko <nannanko@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include "kazv-io-job.hpp"
#include "matrix-room.hpp"
#include <QObject>
#include <QPointer>
#include <QSharedPointer>
#include <QSaveFile>
#include <QFile>
#include <QByteArray>
#include <QIODevice>
#include <QString>
#include <KJob>
#include <KIO/TransferJob>
#include <nlohmann/json.hpp>
#include <optional>
#include <string>
using json = nlohmann::json;
struct KazvIOBaseJobPrivate
{
QPointer<KIO::TransferJob> job;
std::optional<KazvIOBaseJob::ErrorCode> result = std::nullopt;
};
KazvIOBaseJob::KazvIOBaseJob(QObject *parent)
: QObject(parent)
, m_d(new KazvIOBaseJobPrivate)
{
connect(this, &KazvIOBaseJob::jobChanged, this, &KazvIOBaseJob::connectJob);
}
KazvIOBaseJob::~KazvIOBaseJob() = default;
QPointer<KIO::TransferJob> KazvIOBaseJob::job()
{
return m_d->job;
}
void KazvIOBaseJob::setJob(QPointer<KIO::TransferJob> job)
{
resetResult();
if (!m_d->job.isNull()) {
m_d->job->disconnect(this);
}
m_d->job = job;
Q_EMIT jobChanged();
}
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 (m_d->result.has_value()) {
return;
}
if (job->error()) {
emitResult(KIOError);
}
});
connect(m_d->job, &KJob::percentChanged, this,
[this](KJob * /* job */, unsigned long /* percent */) { Q_EMIT progressChanged(); });
}
void KazvIOBaseJob::emitResult(ErrorCode ec)
{
m_d->result = ec;
Q_EMIT result(m_d->result.value());
}
void KazvIOBaseJob::resetResult()
{
m_d->result = std::nullopt;
}
struct KazvIODownloadJobPrivate
{
QSharedPointer<QSaveFile> file;
};
KazvIODownloadJob::KazvIODownloadJob(QObject *parent)
: KazvIOBaseJob(parent)
, m_d(new KazvIODownloadJobPrivate)
{
}
KazvIODownloadJob::~KazvIODownloadJob() = default;
QPointer<QSaveFile> KazvIODownloadJob::file()
{
return m_d->file.data();
}
void KazvIODownloadJob::setFile(QPointer<QSaveFile> file)
{
resetResult();
if (!file->isOpen()) {
auto succ = file->open(QIODevice::WriteOnly);
if (!succ) {
KazvIOBaseJob::emitResult(QtError);
return;
}
}
m_d->file.reset(file.data());
Q_EMIT fileChanged();
}
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, [this](KJob *job, const QByteArray &data) {
- if (!m_d->file.isNull()) {
- auto len = m_d->file->write(data);
- if (len == -1) {
- if (!this->isResulted()){
- KazvIOBaseJob::emitResult(QtError);
- }
- job->kill();
+ connect(this->job(), &KIO::TransferJob::data, this, &KazvIODownloadJob::writeFile);
+ connect(this->job(), &KJob::result, this, &KazvIODownloadJob::closeFile);
+}
+
+void KazvIODownloadJob::writeFile(KJob *job, const QByteArray &data)
+{
+ if (!m_d->file.isNull()) {
+ auto len = m_d->file->write(data);
+ if (len == -1) {
+ if (!this->isResulted()){
+ KazvIOBaseJob::emitResult(QtError);
}
- return;
- }
- if (!this->isResulted()) {
- KazvIOBaseJob::emitResult(KazvError);
- }
- job->kill();
- });
- connect(this->job(), &KJob::result, this, [this](KJob *job) {
- if (m_d->file.isNull()) {
- return;
- }
- if (job->error()) {
- m_d->file->cancelWriting();
+ job->kill();
}
- m_d->file->commit();
- KazvIOBaseJob::emitResult(NoError);
- });
+ return;
+ }
+ if (!this->isResulted()) {
+ KazvIOBaseJob::emitResult(KazvError);
+ }
+ job->kill();
+}
+
+void KazvIODownloadJob::closeFile(KJob *job)
+{
+ if (m_d->file.isNull()) {
+ return;
+ }
+ if (job->error()) {
+ m_d->file->cancelWriting();
+ }
+ m_d->file->commit();
+ KazvIOBaseJob::emitResult(NoError);
}
struct KazvIOUploadJobPrivate
{
QSharedPointer<QFile> file;
QString response;
QSharedPointer<MatrixRoom> room;
QUrl localFileUrl; // For send media file message
};
KazvIOUploadJob::KazvIOUploadJob(QObject *parent)
: KazvIOBaseJob(parent)
, m_d(new KazvIOUploadJobPrivate)
{
connect(this, &KazvIOBaseJob::jobChanged, [this]() { m_d->response.clear(); });
}
KazvIOUploadJob::~KazvIOUploadJob() = default;
QPointer<QFile> KazvIOUploadJob::file()
{
return m_d->file.data();
}
void KazvIOUploadJob::setFile(QPointer<QFile> file)
{
resetResult();
m_d->response.clear();
if (!file->isOpen()) {
auto succ = file->open(QIODevice::ReadOnly);
if (!succ) {
KazvIOBaseJob::emitResult(QtError);
return;
}
}
m_d->file.reset(file.data());
Q_EMIT fileChanged();
}
QString KazvIOUploadJob::response()
{
return m_d->response;
}
QPointer<MatrixRoom> KazvIOUploadJob::room()
{
return m_d->room.data();
}
void KazvIOUploadJob::setRoom(QPointer<MatrixRoom> room)
{
m_d->room.reset(room);
Q_EMIT roomChanged();
}
QUrl KazvIOUploadJob::localFileUrl()
{
return m_d->localFileUrl;
}
void KazvIOUploadJob::setLocalFileUrl(QUrl localFileUrl)
{
m_d->localFileUrl = localFileUrl;
Q_EMIT localFileUrlChanged();
}
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) {
- if (!m_d->file.isNull()) {
- m_d->response.append(data);
- Q_EMIT responseChanged();
- return;
- }
+ connect(this->job(), &KIO::TransferJob::data, this, &KazvIOUploadJob::writeFile);
+ connect(this->job(), &KJob::result, this, &KazvIOUploadJob::closeFile);
+}
+
+void KazvIOUploadJob::writeFile(KJob *job, const QByteArray &data)
+{
+ if (!m_d->file.isNull()) {
+ m_d->response.append(data);
+ Q_EMIT responseChanged();
+ return;
+ }
+ if (!this->isResulted()) {
+ KazvIOBaseJob::emitResult(KazvError);
+ }
+ job->kill();
+}
+
+void KazvIOUploadJob::closeFile(KJob *job)
+{
+ if (m_d->file.isNull()) {
if (!this->isResulted()) {
KazvIOBaseJob::emitResult(KazvError);
}
- job->kill();
- });
- connect(this->job(), &KJob::result, this, [this](KJob *job) {
- if (m_d->file.isNull()) {
- if (!this->isResulted()) {
- KazvIOBaseJob::emitResult(KazvError);
- }
- return;
- }
- m_d->file->close();
- if (job->error()) {
- m_d->response.clear();
- if (!this->isResulted()) {
- KazvIOBaseJob::emitResult(KIOError);
- }
- return;
+ return;
+ }
+ m_d->file->close();
+ if (job->error()) {
+ m_d->response.clear();
+ if (!this->isResulted()) {
+ KazvIOBaseJob::emitResult(KIOError);
}
- json j = json::parse(m_d->response.toStdString());
- auto mxcUri = j["content_uri"].get<std::string>();
- m_d->room->sendMediaFileMessage(m_d->localFileUrl, QString(mxcUri.data()));
- KazvIOBaseJob::emitResult(NoError);
- });
+ return;
+ }
+ json j = json::parse(m_d->response.toStdString());
+ auto mxcUri = j["content_uri"].get<std::string>();
+ m_d->room->sendMediaFileMessage(m_d->localFileUrl, QString(mxcUri.data()));
+ KazvIOBaseJob::emitResult(NoError);
}
diff --git a/src/kazv-io-job.hpp b/src/kazv-io-job.hpp
index 9ec316e..19e5487 100644
--- a/src/kazv-io-job.hpp
+++ b/src/kazv-io-job.hpp
@@ -1,163 +1,167 @@
/*
* 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 "matrix-room.hpp"
#include <QObject>
#include <QPointer>
#include <QSaveFile>
#include <QFile>
#include <QString>
#include <QByteArray>
#include <QUrl>
#include <KIO/TransferJob>
#include <memory>
#include <optional>
struct KazvIOBaseJobPrivate;
/**
* This is considered for an object to perform a job only once,
* but it is also designed to be able to use an object to perform multiple job (just when the previous job has ended.)
* to deal with possible future needs.
* Resetting file, job, etc. will reset the object to prepare for the next job.
* As a suggestion, make sure the file is opened normally before calling setJob to avoid strange problems.
*/
class KazvIOBaseJob : public QObject
{
Q_OBJECT
Q_PROPERTY(QPointer<KIO::TransferJob> job READ job WRITE setJob NOTIFY jobChanged)
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,
/**
* Errors caused by various reasons such as file read and write failures, open failures, etc.
*/
QtError,
/**
* Errors caused by KIO, such network error.
*/
KIOError,
/**
* Errors caused by bad code, means the bug is somewhere.
*/
KazvError
};
Q_ENUM(ErrorCode)
KazvIOBaseJob(QObject *parent = 0);
~KazvIOBaseJob();
QPointer<KIO::TransferJob> job();
/**
* Before calling this function, make sure to use the setFile of the subclass to set a file that has been opened normally
*/
void setJob(QPointer<KIO::TransferJob> job);
float progress();
/**
* Only use it after emitted the result signal
*/
Q_INVOKABLE void suspend();
Q_INVOKABLE void resume();
Q_INVOKABLE void cancel();
Q_INVOKABLE bool isSuspended();
Q_INVOKABLE bool isResulted();
Q_INVOKABLE ErrorCode error();
Q_SIGNALS:
void jobChanged();
void progressChanged();
void result(ErrorCode ec);
protected Q_SLOTS:
virtual void connectJob();
protected:
/**
* If m_d->job needs to be killed before this function is called, then this function should be called first
* Unless you know what you are doing, it is recommended to use the isResulted function to check whether
* the object has emitted a result signal before calling this function
*/
void emitResult(ErrorCode ec);
void resetResult();
};
struct KazvIODownloadJobPrivate;
class KazvIODownloadJob : public KazvIOBaseJob
{
Q_OBJECT
Q_PROPERTY(QPointer<QSaveFile> file READ file WRITE setFile NOTIFY fileChanged)
std::unique_ptr<KazvIODownloadJobPrivate> m_d;
public:
KazvIODownloadJob(QObject *parent = 0);
~KazvIODownloadJob();
QPointer<QSaveFile> file();
void setFile(QPointer<QSaveFile> file);
Q_INVOKABLE QString fileName();
Q_SIGNALS:
void fileChanged();
protected Q_SLOTS:
void connectJob() override;
protected:
void emitResult(ErrorCode ec);
+ void writeFile(KJob *job, const QByteArray &data);
+ void closeFile(KJob *job);
};
struct KazvIOUploadJobPrivate;
class KazvIOUploadJob : public KazvIOBaseJob
{
Q_OBJECT
Q_PROPERTY(QPointer<QFile> file READ file WRITE setFile NOTIFY fileChanged)
Q_PROPERTY(QString response READ response NOTIFY responseChanged)
Q_PROPERTY(QPointer<MatrixRoom> room READ room WRITE setRoom NOTIFY roomChanged)
Q_PROPERTY(QUrl localFileUrl READ localFileUrl WRITE setLocalFileUrl NOTIFY localFileUrlChanged)
std::unique_ptr<KazvIOUploadJobPrivate> m_d;
public:
KazvIOUploadJob(QObject *parent = 0);
~KazvIOUploadJob();
QPointer<QFile> file();
void setFile(QPointer<QFile> file);
QString response();
QPointer<MatrixRoom> room();
void setRoom(QPointer<MatrixRoom> room);
QUrl localFileUrl();
void setLocalFileUrl(QUrl localFileUrl);
Q_INVOKABLE QString fileName();
Q_SIGNALS:
void fileChanged();
void responseChanged();
void roomChanged();
void localFileUrlChanged();
protected Q_SLOTS:
void connectJob() override;
+ void writeFile(KJob *job, const QByteArray &data);
+ void closeFile(KJob *job);
};

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 7:07 PM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55405
Default Alt Text
(13 KB)

Event Timeline