Page MenuHomePhorge

No OneTemporary

Size
15 KB
Referenced Files
None
Subscribers
None
diff --git a/src/contents/ui/KazvIOMenu.qml b/src/contents/ui/KazvIOMenu.qml
index 48e678f..5538758 100644
--- a/src/contents/ui/KazvIOMenu.qml
+++ b/src/contents/ui/KazvIOMenu.qml
@@ -1,121 +1,130 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022 nannanko <nannanko@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.13 as Kirigami
import moe.kazv.mxc.kazv 0.0 as MK
ColumnLayout {
id: kazvIOProgressBar
required property var kazvIOJob
property var jobId
property bool isUpload
visible: kazvIOJob ? true : false
onKazvIOJobChanged: {
if (kazvIOJob == null) {
return
}
+ if (kazvIOJob.isResulted()) {
+ if (kazvIOJob.error()) {
+ jobSlots.onFailure()
+ } else {
+ jobSlots.onSuccess()
+ }
+ return
+ }
if (kazvIOJob.isSuspended()) {
pauseAction.suspended = true
}
}
Connections {
+ id: jobSlots
target: kazvIOJob
function onSuccess() {
// Successful upload job don't need prompt
if (isUpload) {
return
}
progressBarLayout.visible = false
promptMsgLayout.visible = true
promptMsg.text = l10n.get('kazv-io-download-success-prompt')
}
function onFailure() {
progressBarLayout.visible = false
promptMsgLayout.visible = true
if (isUpload) {
promptMsg.text = l10n.get('kazv-io-upload-failure-prompt')
} else {
promptMsg.text = l10n.get('kazv-io-download-failure-prompt')
}
}
}
Label {
text: kazvIOJob ? kazvIOJob.fileName() : ''
}
RowLayout {
id: progressBarLayout
visible: true
Layout.preferredWidth: parent.width
ProgressBar {
id: progressBar
Layout.fillWidth: true
value: kazvIOJob ? kazvIOJob.progress : 0
}
Kirigami.Action {
id: pauseAction
iconName: suspended ? "media-playback-start" : "media-playback-pause"
property var suspended: false
onTriggered: {
if (pauseAction.suspended) {
kazvIOJob.resume()
} else {
kazvIOJob.suspend()
}
suspended = !suspended
}
}
Kirigami.Action {
id: cancelAction
iconName: "dialog-cancel"
onTriggered: {
pauseAction.suspended = false
kazvIOJob.cancel()
}
}
RoundButton {
id: pauseBtn
Accessible.name: pauseAction.suspended ? l10n.get('kazv-io-resume') : l10n.get('kazv-io-pause')
icon.name: pauseAction.suspended ? "media-playback-start" : "media-playback-pause"
onClicked: pauseAction.trigger()
}
RoundButton {
icon.name: "dialog-cancel"
Accessible.name: l10n.get('kazv-io-cancel')
onClicked: cancelAction.trigger()
}
}
RowLayout {
id: promptMsgLayout
visible: false
Text {
id: promptMsg
}
Button {
text: l10n.get('kazv-io-prompt-close')
onClicked: {
if (isUpload) {
kazvIOManager.deleteUploadJob(jobId, kazvIOJob)
} else {
kazvIOManager.deleteDownloadJob(jobId)
+ promptMsgLayout.visible = false
+ progressBarLayout.visible = true
+ kazvIOJob = null
}
- promptMsgLayout.visible = false
- progressBarLayout.visible = true
- kazvIOJob = null
}
}
}
}
diff --git a/src/kazv-io-job.cpp b/src/kazv-io-job.cpp
index 4aa7371..d9da263 100644
--- a/src/kazv-io-job.cpp
+++ b/src/kazv-io-job.cpp
@@ -1,224 +1,233 @@
#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<bool> 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)
{
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()
{
m_d->job->suspend();
}
void KazvIOBaseJob::resume()
{
m_d->job->resume();
}
void KazvIOBaseJob::cancel()
{
m_d->job->kill(KJob::EmitResult);
}
bool KazvIOBaseJob::isSuspended()
{
return m_d->job->isSuspended();
}
bool KazvIOBaseJob::isResulted()
{
return m_d->result.has_value();
}
+bool KazvIOBaseJob::error()
+{
+ if (m_d->result.has_value()) {
+ return !m_d->result.value();
+ }
+ // Shouldn't call this function before result are emited
+ return false;
+}
+
void KazvIOBaseJob::connectJob()
{
connect(m_d->job, &KJob::result, this, [this](KJob *job) {
Q_EMIT result();
if (job->error()) {
m_d->result = false;
Q_EMIT failure();
} else {
m_d->result = true;
Q_EMIT success();
}
});
connect(m_d->job, &KJob::percentChanged, this, &KazvIOBaseJob::emitProgressChanged);
}
void KazvIOBaseJob::emitProgressChanged(KJob * /* job */, unsigned long /* percent */) {
Q_EMIT progressChanged();
}
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)
{
if (!file->isOpen()) {
file->open(QIODevice::WriteOnly);
}
m_d->file.reset(file.data());
Q_EMIT fileChanged();
}
QString KazvIODownloadJob::fileName() {
return m_d->file->fileName();
}
void KazvIODownloadJob::connectJob()
{
KazvIOBaseJob::connectJob();
connect(this->job(), &KIO::TransferJob::data, this, [this](KJob * /* job */, const QByteArray &data) {
m_d->file->write(data);
});
connect(this->job(), &KJob::result, this, [this](KJob *job) {
if (job->error()) {
m_d->file->cancelWriting();
}
m_d->file->commit();
});
}
struct KazvIOUploadJobPrivate
{
QSharedPointer<QFile> file;
QString response;
QPointer<MatrixRoom> room;
QUrl localFileUrl; // For send media file message
};
KazvIOUploadJob::KazvIOUploadJob(QObject *parent)
: KazvIOBaseJob(parent)
, m_d(new KazvIOUploadJobPrivate)
{
}
KazvIOUploadJob::~KazvIOUploadJob() = default;
QPointer<QFile> KazvIOUploadJob::file()
{
return m_d->file.data();
}
void KazvIOUploadJob::setFile(QPointer<QFile> file)
{
if (!file->isOpen()) {
file->open(QIODevice::ReadOnly);
}
m_d->file.reset(file.data());
Q_EMIT fileChanged();
}
QString KazvIOUploadJob::response()
{
return m_d->response;
}
QPointer<MatrixRoom> KazvIOUploadJob::room()
{
return m_d->room;
}
void KazvIOUploadJob::setRoom(QPointer<MatrixRoom> room)
{
m_d->room = 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()
{
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(data);
Q_EMIT responseChanged();
});
connect(this->job(), &KJob::result, this, [this](KJob *job) {
m_d->file->close();
if (job->error()) {
m_d->response.clear();
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()));
});
}
diff --git a/src/kazv-io-job.hpp b/src/kazv-io-job.hpp
index b884b46..0296ec1 100644
--- a/src/kazv-io-job.hpp
+++ b/src/kazv-io-job.hpp
@@ -1,120 +1,121 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022 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;
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:
KazvIOBaseJob(QObject *parent = 0);
~KazvIOBaseJob();
QPointer<KIO::TransferJob> job();
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 bool error();
Q_SIGNALS:
void jobChanged();
void progressChanged();
void result();
void success();
void failure();
protected Q_SLOTS:
virtual void connectJob();
void emitProgressChanged(KJob * job, unsigned long percent);
};
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;
};
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();
void result();
protected Q_SLOTS:
void connectJob() override;
};
diff --git a/src/kazv-io-manager.cpp b/src/kazv-io-manager.cpp
index 5a9b959..f7e8966 100644
--- a/src/kazv-io-manager.cpp
+++ b/src/kazv-io-manager.cpp
@@ -1,108 +1,109 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022 nannanko <nannanko@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include "kazv-io-manager.hpp"
#include "kazv-io-job.hpp"
#include "matrix-room.hpp"
#include "upload-job-model.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 <string>
struct KazvIOManagerPrivate
{
QMap<QString, QPointer<KazvIODownloadJob>> downloadJobs;
QMap<QString, QPointer<UploadJobModel>> uploadJobs;
};
KazvIOManager::KazvIOManager(QObject *parent)
: QObject(parent)
, m_d(new KazvIOManagerPrivate)
{
}
KazvIOManager::~KazvIOManager() = default;
KazvIOBaseJob *KazvIOManager::startNewDownloadJob(const QUrl &serverUrl, const QUrl &localFileUrl, const QString &jobId)
{
auto downloadJob = QPointer<KazvIODownloadJob>(new KazvIODownloadJob());
downloadJob->setJob(KIO::get(serverUrl));
downloadJob->setFile(new QSaveFile(localFileUrl.path(), downloadJob.data()));
m_d->downloadJobs[jobId] = downloadJob;
return downloadJob.data();
}
KazvIOBaseJob *KazvIOManager::startNewUploadJob(const QUrl &serverUrl, const QUrl &localFileUrl, const QString &token, MatrixRoom *room)
{
auto uploadJob = QPointer<KazvIOUploadJob>(new KazvIOUploadJob());
uploadJob->setFile(new QFile(localFileUrl.path(), uploadJob.data()));
auto kazvUploadJob = Kazv::Api::UploadContentJob(serverUrl.toString().toStdString(), token.toStdString(), Kazv::FileDesc(std::string()));
uploadJob->setJob(KIO::http_post(QString(kazvUploadJob.url().data()), uploadJob->file().data()));
uploadJob->job()->addMetaData(QString("content-type") , QMimeDatabase().mimeTypeForFile(localFileUrl.path()).name());
uploadJob->job()->addMetaData("customHTTPHeader", QStringLiteral("Authorization: ").append(kazvUploadJob.requestHeader()->at("Authorization").data()));
uploadJob->job()->addMetaData("PropagateHttpHeader", "true");
uploadJob->setRoom(room);
uploadJob->setLocalFileUrl(localFileUrl);
auto roomId = room->roomId();
connect(uploadJob.data(), &KazvIOBaseJob::success, this, [this, roomId, uploadJob]() {
m_d->uploadJobs[roomId]->removeJob(uploadJob);
});
if (!m_d->uploadJobs.contains(roomId) || m_d->uploadJobs[roomId].isNull()) {
m_d->uploadJobs[roomId] = new UploadJobModel(this);
}
m_d->uploadJobs[roomId]->addJob(uploadJob);
return uploadJob.data();
}
KazvIOBaseJob *KazvIOManager::getDownloadJob(const QString &jobId)
{
auto targetJob = m_d->downloadJobs.find(jobId);
if (targetJob == m_d->downloadJobs.end()) {
return nullptr;
}
return targetJob.value().data();
}
void KazvIOManager::deleteDownloadJob(const QString &jobId)
{
m_d->downloadJobs[jobId]->deleteLater();
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] = new UploadJobModel(this);
}
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)));
+ qDebug() << m_d->uploadJobs[roomId]->rowCount();
}
void KazvIOManager::deleteModelIfEmpty(const QString &roomId)
{
if (!m_d->uploadJobs.contains(roomId)) {
return;
} else if (m_d->uploadJobs[roomId]->rowCount() == 0) {
m_d->uploadJobs[roomId]->deleteLater();
m_d->uploadJobs.remove(roomId);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 9:04 PM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55448
Default Alt Text
(15 KB)

Event Timeline