Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F140396
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/contents/ui/MediaFileMenu.qml b/src/contents/ui/MediaFileMenu.qml
index 3fdf08e..63e02f6 100644
--- a/src/contents/ui/MediaFileMenu.qml
+++ b/src/contents/ui/MediaFileMenu.qml
@@ -1,50 +1,50 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import Qt.labs.platform 1.1 as Platform
import org.kde.kirigami 2.13 as Kirigami
import '.' as Types
TapHandler {
property var kazvIO
property var progressBar
+ property var url
acceptedButtons: Qt.LeftButton | Qt.RightButton
onSingleTapped: {
if (eventPoint.event.button === Qt.RightButton) {
optionMenu.popup(parent)
console.log("clicked")
}
if (eventPoint.event.button === Qt.LeftButton) {
// TODO: Open with default program
}
}
onLongPressed: {
- optionMenu.popup()
+ optionMenu.popup(parent)
}
property var optionMenu: Menu {
Kirigami.Action {
text: l10n.get('menu-option-view')
// shortcut: StandardKey.Open
// TODO: open with default program
}
Kirigami.Action {
text: l10n.get('menu-option-save-as')
// Can't think of a suitable shortcut key
// shortcut: StandardKey.Save
onTriggered: {
fileDialog.open()
}
}
}
property var fileDialog: Platform.FileDialog {
acceptLabel: l10n.get('menu-option-save-as')
fileMode: Platform.FileDialog.SaveFile
onAccepted: {
- kazvIO.fileUrl = file
- kazvIO.download(imageUri)
+ kazvIO.download(url, file)
progressBar.visible = true
}
}
}
diff --git a/src/contents/ui/event-types/Image.qml b/src/contents/ui/event-types/Image.qml
index fe60557..89f4f6e 100644
--- a/src/contents/ui/event-types/Image.qml
+++ b/src/contents/ui/event-types/Image.qml
@@ -1,65 +1,66 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2021 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import moe.kazv.mxc.kazv 0.0 as MK
import org.kde.kirigami 2.13 as Kirigami
import '..' as Kazv
Simple {
id: upper
property var gender: 'neutral'
property var body: event.content.body
property var mxcUri: event.content.url
property var imageUri: matrixSdk.mxcUriToHttp(mxcUri)
property var imageInfo: event.content.info || {}
property var imageWidth: image.implicitWidth || imageInfo.w || 1 // lest we divide by 0
property var imageHeight: image.implicitHeight || imageInfo.h || 1
property var innerContentWidth: upper.contentMaxWidth - bubble.bubbleSpacing
property var kazvIO: MK.KazvIO {
onResult: {
progressBar.visible = false
}
}
Kazv.Bubble {
id: bubble
ColumnLayout {
id: layout
Label {
Layout.fillWidth: false
Layout.maximumWidth: innerContentWidth
wrapMode: Text.Wrap
text: l10n.get('event-message-image-sent', { gender, body })
}
Image {
id: image
source: imageUri
Layout.maximumWidth: innerContentWidth
Layout.preferredWidth: imageWidth
Layout.preferredHeight: imageHeight / imageWidth * width
fillMode: Image.PreserveAspectFit
Kazv.MediaFileMenu {
kazvIO: upper.kazvIO
progressBar: progressBar
+ url: imageUri
}
}
Kazv.ProgressBar {
id: progressBar
kazvIO: upper.kazvIO
}
}
}
}
diff --git a/src/kazv-io.cpp b/src/kazv-io.cpp
index 453dbc4..5898036 100644
--- a/src/kazv-io.cpp
+++ b/src/kazv-io.cpp
@@ -1,95 +1,129 @@
#include <QUrl>
#include <KIO/TransferJob>
#include <QObject>
#include <QString>
#include <QSaveFile>
#include <QIODevice>
#include <QFileDialog>
#include <QDebug>
#include <KIO/TransferJob>
+#include <algorithm>
+#include <execution>
+
#include "kazv-io.hpp"
-struct KazvIOPrivate {
+struct KazvIOJob {
QPointer<KIO::TransferJob> job;
float progress = 0;
- QUrl fileUrl;
- QSaveFile file;
+ QUrl url;
+ QPointer<QSaveFile> file;
+};
+
+struct KazvIOPrivate {
+ QUrl url;
};
+QVector<KazvIOJob> KazvIO::jobs = QVector<KazvIOJob>(MAX_JOB_NUM);
+
KazvIO::KazvIO(QObject *parent)
: QObject(parent)
, m_d(new KazvIOPrivate)
{
}
KazvIO::~KazvIO() = default;
-void KazvIO::download(QUrl url)
+void KazvIO::download(const QUrl url, QUrl localFileUrl)
{
- if (m_d->job) {
- return;
+ auto job = std::find_if(std::execution::seq,
+ jobs.begin(),
+ jobs.end(),
+ [](auto it) {return it.job.isNull();});
+ if (job == jobs.constEnd()) {
+ qDebug() << "KazvIO busy";
+ return;
}
- m_d->job = KIO::get(url);
- m_d->file.setFileName(m_d->fileUrl.path());
- m_d->file.open(QIODevice::WriteOnly);
- connect(m_d->job, &KIO::TransferJob::data, this, &KazvIO::write);
- connect(m_d->job, &KJob::percentChanged, this, &KazvIO::updatePercent);
- connect(m_d->job, &KJob::result, this, &KazvIO::emitResult);
- m_d->job->start();
+ qDebug() << url;
+ job->job = KIO::get(url);
+ job->url = url;
+ m_d->url = url;
+ job->file = new QSaveFile(localFileUrl.path());
+ job->file->open(QIODevice::WriteOnly);
+ connect(job->job, &KIO::TransferJob::data, this, &KazvIO::write);
+ connect(job->job, &KJob::percentChanged, this, &KazvIO::updatePercent);
+ connect(job->job, &KJob::result, this, &KazvIO::emitResult);
+ job->job->start();
}
void KazvIO::suspend()
{
- if (!m_d->job->suspend()) {
- qDebug() << "Suspend job failed";
+ auto job = std::find_if(std::execution::seq,
+ jobs.constBegin(),
+ jobs.constEnd(),
+ [this](auto it) {return it.url == m_d->url;});
+ if (!job->job->suspend()) {
+ qDebug() << "Suspend job failed";
}
}
void KazvIO::resume()
{
- if (!m_d->job->resume()) {
- qDebug() << "Resume job failed";
+ auto job = std::find_if(std::execution::seq,
+ jobs.constBegin(),
+ jobs.constEnd(),
+ [this](auto it) {return it.url == m_d->url;});
+ if (!job->job->resume()) {
+ qDebug() << "Resume job failed";
}
}
void KazvIO::cancel()
{
- if (!m_d->job->kill()) {
- qDebug() << "Cancel job failed";
+ auto job = std::find_if(std::execution::seq,
+ jobs.constBegin(),
+ jobs.constEnd(),
+ [this](auto it) {return it.url == m_d->url;});
+ if (!job->job->kill()) {
+ qDebug() << "Cancel job failed";
}
}
float KazvIO::progress()
{
- return m_d->progress;
-}
-
-QUrl KazvIO::fileUrl()
-{
- return m_d->fileUrl;
-}
-
-void KazvIO::setFileUrl(QUrl fileUrl)
-{
- m_d->fileUrl = fileUrl;
- Q_EMIT fileUrlChanged();
+ auto job = std::find_if(std::execution::seq,
+ jobs.constBegin(),
+ jobs.constEnd(),
+ [this](auto it) {return it.url == m_d->url;});
+ return job->progress;
}
void KazvIO::updatePercent(KJob* job, unsigned long percent)
{
- m_d->progress = 1.0 * percent / 100;
+ auto currentJob = std::find_if(std::execution::seq,
+ jobs.begin(),
+ jobs.end(),
+ [this](auto it) {return it.url == m_d->url;});
+ currentJob->progress = 1.0 * percent / 100;
Q_EMIT progressChanged();
}
void KazvIO::write(KJob* job, const QByteArray& data)
{
- m_d->file.write(data);
+ auto currentJob = std::find_if(std::execution::seq,
+ jobs.begin(),
+ jobs.end(),
+ [this](auto it) {return it.url == m_d->url;});
+ currentJob->file->write(data);
}
void KazvIO::emitResult(KJob * job) {
- if (m_d->job->error())
- qDebug() << job->errorString();
- m_d->file.commit();
+ auto currentJob = std::find_if(std::execution::seq,
+ jobs.begin(),
+ jobs.end(),
+ [this](auto it) {return it.url == m_d->url;});
+ if (currentJob->job->error())
+ qDebug() << currentJob->job->errorString();
+ currentJob->file->commit();
Q_EMIT result();
}
diff --git a/src/kazv-io.hpp b/src/kazv-io.hpp
index b82ad67..19d4217 100644
--- a/src/kazv-io.hpp
+++ b/src/kazv-io.hpp
@@ -1,60 +1,65 @@
#pragma once
#include <QObject>
#include <QUrl>
#include <KIO/Job>
#include <QtQml>
#include <KIO/TransferJob>
#include <QPointer>
#include <QSaveFile>
#include <QByteArray>
#include <QScopedPointer>
+#include <QVector>
+#define MAX_JOB_NUM 10
+
+struct KazvIOJob;
struct KazvIOPrivate;
class KazvIO : public QObject {
Q_OBJECT
QML_ELEMENT
- // Progress in decimal form, from 0 to 1
+ /*
+ * Progress in decimal form, from 0 to 1
+ */
Q_PROPERTY(float progress READ progress NOTIFY progressChanged)
- Q_PROPERTY(QUrl fileUrl READ fileUrl WRITE setFileUrl NOTIFY fileUrlChanged)
+ // Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
private:
+ static QVector<KazvIOJob> jobs;
QScopedPointer<KazvIOPrivate> m_d;
+
public:
explicit KazvIO(QObject *parent = 0);
~KazvIO() override;
/**
* QML should call this function to initiate a download.
* url is the file to download.
- * return job id, QML should restore it to call suspend, cancel, etc.
+ * localFileUrl is the file to store.
*/
- Q_INVOKABLE void download(QUrl url);
+ Q_INVOKABLE void download(QUrl url, QUrl localFileUrl);
/** Pause the download.
- * id is the return value of the download function.
*/
Q_INVOKABLE void suspend();
/**
* Resume the download.
- * id is the return value of the download function.
*/
Q_INVOKABLE void resume();
/**
* Cancel the download.
- * id is the return value of the download function.
*/
Q_INVOKABLE void cancel();
float progress();
- QUrl fileUrl();
- void setFileUrl(QUrl fileUrl);
+ // QUrl url();
+ // void setUrl(QUrl url);
Q_SIGNALS:
void progressChanged();
- void fileUrlChanged();
+ // void urlChanged();
void result();
-public Q_SLOTS:
+private Q_SLOTS:
void updatePercent(KJob* job, unsigned long percent);
void write(KJob* job, const QByteArray& data);
void emitResult(KJob* job);
};
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 7:25 PM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55414
Default Alt Text
(10 KB)
Attached To
Mode
rK kazv
Attached
Detach File
Event Timeline
Log In to Comment