Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F140385
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
13 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 7:07 PM (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55405
Default Alt Text
(13 KB)
Attached To
Mode
rK kazv
Attached
Detach File
Event Timeline
Log In to Comment