Added Image download functionality

This commit is contained in:
Digital Artifex
2026-08-17 13:05:17 -04:00
parent e6d7d908b1
commit 1d5bcb9365
9 changed files with 665 additions and 180 deletions
@@ -0,0 +1,66 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import KomplexHub
import KomplexHub.Kero
import KomplexHub.Controls
import KomplexHub.Plugin
Item
{
property DownloadManager manager: null
ColumnLayout
{
anchors.fill: parent
VerticalSpacer { }
KeroSuccessAvatar
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredHeight: 512
Layout.maximumHeight: 512
}
RowLayout
{
Layout.fillWidth: true
Layout.preferredHeight: 36
Layout.maximumHeight: 36
Layout.margins: Constants.largeMargin
Item
{
Layout.fillHeight: true
Layout.fillWidth: true
}
SquareButton
{
Layout.preferredWidth: 186
Layout.fillHeight: true
text: qsTr("Okay")
onTriggered: () =>
{
if(manager != null)
{
manager.reset()
}
}
}
SquareButton
{
Layout.preferredWidth: 186
Layout.fillHeight: true
text: qsTr("Set Wallpaper")
icon.source: "qrc:/images/icons/icons8-download.svg"
}
}
VerticalSpacer {}
}
}
+131
View File
@@ -0,0 +1,131 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Effects
import KomplexHub
import KomplexHub.Controls
import KomplexHub.Plugin
import KomplexHub.Kero
Item
{
property string thumbnail
property DownloadManager manager
Rectangle
{
anchors.fill: parent
color: palette.base
BackgroundImage
{
source: thumbnail
}
ColumnLayout
{
anchors.fill: parent
anchors.margins: Constants.largeMargin
Item { Layout.preferredHeight: 64; Layout.fillWidth: true }
KeroBuildingAnimation
{
Layout.fillWidth: true
Layout.fillHeight: true
}
VerticalSpacer {}
Text
{
text: qsTr("Download Progress")
font: Constants.h3Font
color : palette.text
Layout.preferredHeight: Constants.largeMargin
}
RowLayout
{
Layout.fillWidth: true
Layout.preferredHeight: Constants.largeMargin
ProgressBar
{
Layout.fillWidth: true
value: manager.downloadProgress
}
Text
{
text: manager.downloadedBytes
font: Constants.h4Font
color : palette.text
}
Text
{
text: "/"
font: Constants.h4Font
color : palette.text
Layout.preferredHeight: 32
}
Text
{
text: manager.downloadSize
font: Constants.h4Font
color : palette.text
Layout.preferredHeight: 32
}
}
Text
{
text: qsTr("Install Progress")
font: Constants.h3Font
color : palette.text
height: 32
}
RowLayout
{
Layout.fillWidth: true
Layout.preferredHeight: Constants.largeMargin
ProgressBar
{
Layout.fillWidth: true
value: manager.compileProgress
}
Text
{
text: manager.compileStepsCompleted
font: Constants.h4Font
color : palette.text
Layout.preferredHeight: Constants.largeMargin
}
Text
{
text: "/"
font: Constants.h4Font
color : palette.text
Layout.preferredHeight: Constants.largeMargin
}
Text
{
text: manager.compileSteps
font: Constants.h4Font
color : palette.text
Layout.preferredHeight: Constants.largeMargin
}
}
Item { Layout.preferredHeight: Constants.largeMargin * 2; Layout.fillWidth: true }
}
}
}
+64
View File
@@ -0,0 +1,64 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import KomplexHub
import KomplexHub.Kero
import KomplexHub.Controls
import KomplexHub.Plugin
Item
{
property DownloadManager manager: null
ColumnLayout
{
anchors.fill: parent
VerticalSpacer { }
KeroWarningAvatar
{
Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredHeight: 512
Layout.maximumHeight: 512
}
RowLayout
{
Layout.fillWidth: true
Layout.preferredHeight: 36
Layout.maximumHeight: 36
Layout.margins: Constants.largeMargin
Item
{
Layout.fillHeight: true
Layout.fillWidth: true
}
SquareButton
{
Layout.preferredWidth: 186
Layout.fillHeight: true
text: qsTr("Okay")
onTriggered: () =>
{
if(manager != null)
{
manager.reset()
}
}
}
SquareButton
{
Layout.preferredWidth: 186
Layout.fillHeight: true
text: qsTr("Set Wallpaper")
}
}
VerticalSpacer {}
}
}
+188 -44
View File
@@ -6,7 +6,7 @@ import QtQuick.Effects
import KomplexHub import KomplexHub
import KomplexHub.Controls import KomplexHub.Controls
import KomplexHub.Kero import KomplexHub.Kero
import KomplexHubPlugin import KomplexHub.Plugin
Item Item
{ {
@@ -17,7 +17,6 @@ Item
property string thumbnail property string thumbnail
property string portrait property string portrait
property string landscape property string landscape
property string original
property string fullScreen property string fullScreen
property string portraitSize property string portraitSize
property string landscapeSize property string landscapeSize
@@ -30,29 +29,21 @@ Item
id: rootItem id: rootItem
DownloadManager
{
id: downloadManager
}
Rectangle Rectangle
{ {
id: pageView
anchors.fill: parent anchors.fill: parent
color: palette.base color: palette.base
Image BackgroundImage
{ {
id: backgroundImage
source: width > height ? backgroundLandscape : backgroundPortrait
transform: Image.PreserveAspectCrop
anchors.fill: parent anchors.fill: parent
visible: false source: width > height ? backgroundLandscape : backgroundPortrait
}
MultiEffect
{
anchors.fill: backgroundImage
source: backgroundImage
blurEnabled: true
blurMax: 64
blur: 1.0
opacity: 0.25
saturation: -0.8
} }
ColumnLayout ColumnLayout
@@ -61,36 +52,15 @@ Item
anchors.margins: Constants.largeMargin anchors.margins: Constants.largeMargin
spacing: Constants.largeMargin spacing: Constants.largeMargin
RowLayout ImageFrame
{ {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignTop| Qt.AlignHCenter Layout.alignment: Qt.AlignTop| Qt.AlignHCenter
Layout.topMargin: 32 Layout.topMargin: Constants.largeMargin
Layout.preferredHeight: width / 1.77777777778
Layout.maximumWidth: 800
Rectangle source: rootItem.thumbnail
{
Layout.fillWidth: true
Layout.preferredHeight: width / 1.77777777778
Layout.maximumWidth: 800
Layout.alignment: Qt.AlignHCenter
color: palette.base.darker()
Throbber
{
anchors.fill: parent
id: loadingThrobber
visible: viewImage.status === Image.Loading
}
Image
{
id: viewImage
anchors.fill: parent
transform: Image.PreserveAspectCrop
source: rootItem.thumbnail
visible: !(status === Image.Loading)
}
}
} }
Text Text
@@ -158,6 +128,8 @@ Item
Layout.preferredWidth: 128 Layout.preferredWidth: 128
text: qsTr("Download") text: qsTr("Download")
icon.source: "qrc:/images/icons/icons8-download.svg" icon.source: "qrc:/images/icons/icons8-download.svg"
onTriggered: () => rootItem.download()
} }
} }
@@ -191,5 +163,177 @@ Item
} }
} }
} }
states:
[
State
{
name: "downloading"
when: downloadManager.state === DownloadManager.Downloading
PropertyChanges
{
target: pageView
opacity: 0
}
PropertyChanges
{
target: downloadView
opacity: 1
}
PropertyChanges
{
target: completedView
opacity: 0
}
PropertyChanges
{
target: errorView
opacity: 0
}
},
State
{
name: "complete"
when: downloadManager.state === DownloadManager.Complete
PropertyChanges
{
target: pageView
opacity: 0
}
PropertyChanges
{
target: downloadView
opacity: 0
}
PropertyChanges
{
target: completedView
opacity: 1
}
PropertyChanges
{
target: errorView
opacity: 0
}
},
State
{
name: "error"
when: downloadManager.state === DownloadManager.Error
PropertyChanges
{
target: pageView
opacity: 0
}
PropertyChanges
{
target: downloadView
opacity: 0
}
PropertyChanges
{
target: completedView
opacity: 0
}
PropertyChanges
{
target: errorView
opacity: 1
}
},
State
{
name: "idle"
when: downloadManager.state === DownloadManager.Idle
PropertyChanges
{
target: pageView
opacity: 1
}
PropertyChanges
{
target: downloadView
opacity: 0
}
PropertyChanges
{
target: completedView
opacity: 0
}
PropertyChanges
{
target: errorView
opacity: 0
}
}
]
}
DownloadView
{
id: downloadView
anchors.fill: parent
manager: downloadManager
thumbnail: rootItem.thumbnail
opacity: 0
visible: opacity > 0.01
}
CompletedView
{
id: completedView
anchors.fill: parent
opacity: 0
visible: opacity > 0.01
manager: downloadManager
}
ErrorView
{
id: errorView
anchors.fill: parent
opacity: 0
visible: opacity > 0.01
manager: downloadManager
}
function download()
{
let url = ""
switch(downloadSelector.currentIndex)
{
case 1:
url = portrait
break;
case 2:
url = landscape
break;
case 0:
default:
url = fullScreen
break;
}
downloadManager.downloadImage(author, authorUrl, description, url)
} }
} }
+1 -1
View File
@@ -6,7 +6,7 @@ add_library(
qt_add_qml_module( qt_add_qml_module(
KomplexHubPlugin KomplexHubPlugin
URI URI
KomplexHubPlugin "KomplexHub.Plugin"
VERSION VERSION
1.0 1.0
SOURCES SOURCES
+22 -19
View File
@@ -12,28 +12,31 @@ auto CoreServices::networkAccessManager() -> QWeakPointer<QNetworkAccessManager>
if(!s_networkAccessPointer) if(!s_networkAccessPointer)
{ {
s_networkAccessManager = new QNetworkAccessManager(QCoreApplication::instance()); if(!s_networkAccessManager)
s_networkAccessManager->setAutoDeleteReplies(true); {
s_networkAccessManager = new QNetworkAccessManager(QCoreApplication::instance());
s_networkAccessManager->setAutoDeleteReplies(true);
QObject::connect( QObject::connect(
s_networkAccessManager, s_networkAccessManager,
&QNetworkAccessManager::sslErrors, &QNetworkAccessManager::sslErrors,
s_networkAccessManager, s_networkAccessManager,
[] (QNetworkReply *reply, const QList<QSslError> &errors) [] (QNetworkReply *reply, const QList<QSslError> &errors)
{
for(const auto &error : errors)
{ {
LOG_ERROR( for(const auto &error : errors)
"CoreServices::networkAccessManager", {
error.errorString().toStdString().c_str() LOG_ERROR(
); "CoreServices::networkAccessManager",
} error.errorString().toStdString().c_str()
);
}
#ifdef KOMPLEX_LOCAL_DEV #ifdef KOMPLEX_LOCAL_DEV
reply->ignoreSslErrors(); reply->ignoreSslErrors();
#endif #endif
} }
); );
}
s_networkAccessPointer = QSharedPointer<QNetworkAccessManager>( s_networkAccessPointer = QSharedPointer<QNetworkAccessManager>(
s_networkAccessManager, s_networkAccessManager,
+161 -103
View File
@@ -31,6 +31,44 @@ DownloadManager::DownloadManager(QObject *parent)
this, this,
&DownloadManager::compileStepsChanged &DownloadManager::compileStepsChanged
); );
QObject::connect
(
&m_moveProcess,
&QProcess::readyReadStandardOutput,
this,
[this]()
{
QByteArray processData = m_moveProcess.readAllStandardOutput();
if(!processData.isValidUtf8())
{
qWarning() << QStringLiteral("Process output not valid UTF8 data");
return;
}
setCompilerOutput(m_compilerOutput + processData);
}
);
QObject::connect
(
&m_moveProcess,
&QProcess::readyReadStandardError,
this,
[this]()
{
QByteArray processData = m_moveProcess.readAllStandardError();
if(!processData.isValidUtf8())
{
qWarning() << QStringLiteral("Process output not valid UTF8 data");
return;
}
setCompilerOutput(m_compilerOutput + processData);
}
);
} }
/** /**
@@ -39,30 +77,42 @@ DownloadManager::DownloadManager(QObject *parent)
* [3] Optionally ask user if they would like to apply manipulative shader * [3] Optionally ask user if they would like to apply manipulative shader
* [4] Install locally * [4] Install locally
*/ */
auto DownloadManager::downloadImage(const QString &author, const QString &authorId, const QString &description, const QUrl &url) noexcept(false) -> void auto DownloadManager::downloadImage(const QString &author, const QString &authorId, const QString &description, const QUrl &url) -> void
{ {
QFuture future = QtConcurrent::run // QFuture future = QtConcurrent::run
( // (
[this, url, author, authorId, description]() // [this, url, author, authorId, description]()
{ // {
QNetworkRequest request(url); QNetworkRequest request(url);
QString requestUrl = request.url().toString();
QString id = QUuid::createUuidV7().toString(QUuid::WithoutBraces); QString id = QUuid::createUuidV7().toString(QUuid::WithoutBraces);
QFuture<QUrl> downloadUri = download(request, id); setState(Downloading);
downloadUri //QFuture<QUrl> downloadUri = download(request, id, Get);
if(m_downloadFuture.isRunning())
{
m_downloadFuture.cancelChain();
}
m_downloadFuture = download(request, id, Get);
m_downloadFuture
.then .then
( (
[this, author, description, id](QUrl result) -> QUrl [this, author, description, id](QUrl result) -> QUrl
{ {
setState(Installing);
ShaderPack metadata; ShaderPack metadata;
metadata.setAuthor(author); metadata.setAuthor(author);
metadata.setDescription(description); metadata.setDescription(description);
metadata.setName(QStringLiteral("Pexels Image (%1)").arg(id)); metadata.setName(QStringLiteral("Pexels Image (%1)").arg(id));
metadata.setSource(QStringLiteral("./images/%1").arg(result.fileName()));
QUrl packUri QUrl packUri
( (
QStringLiteral("%1/%2").arg QStringLiteral("file://%1/%2").arg
( (
QStandardPaths::writableLocation(QStandardPaths::TempLocation), QStandardPaths::writableLocation(QStandardPaths::TempLocation),
id id
@@ -71,7 +121,7 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author
QUrl packImageUri QUrl packImageUri
( (
QStringLiteral("%1/%2/images/%3").arg QStringLiteral("file://%1/%2/images/%3").arg
( (
QStandardPaths::writableLocation(QStandardPaths::TempLocation), QStandardPaths::writableLocation(QStandardPaths::TempLocation),
id, id,
@@ -80,7 +130,12 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author
); );
QDir packDirectory(packUri.toLocalFile()); QDir packDirectory(packUri.toLocalFile());
packDirectory.mkpath(packUri.toLocalFile());
if(!packDirectory.mkpath(packUri.toLocalFile()))
{
throw FileException(QStringLiteral("Could not create directory"));
}
packDirectory.mkdir(QStringLiteral("images")); packDirectory.mkdir(QStringLiteral("images"));
QFile::rename(result.toLocalFile(), packImageUri.toLocalFile()); QFile::rename(result.toLocalFile(), packImageUri.toLocalFile());
@@ -99,7 +154,7 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author
throw FileException(packFile.errorString()); throw FileException(packFile.errorString());
} }
QByteArray data = metadata.json().toJson(QJsonDocument::Compact); QByteArray data = metadata.json().toJson(QJsonDocument::Indented);
if(packFile.write(data) != data.length()) if(packFile.write(data) != data.length())
{ {
@@ -113,10 +168,18 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author
} }
) )
.then .then
(
[this](QUrl result) -> QUrl
{
return install(result);
}
)
.then
( (
[this](QUrl result) [this](QUrl result)
{ {
install(result); setLastInstalledFile(result.toLocalFile());
setState(Complete);
} }
) )
.onCanceled .onCanceled
@@ -127,17 +190,36 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author
} }
) )
.onFailed .onFailed
(
[this] (const NetworkException &e)
{
reset();
setError(QStringLiteral("Network Exception %1").arg(QString::number(e.errorCode)), e.message);
}
)
.onFailed
(
[this] (const FileException &e)
{
reset();
setError(QStringLiteral("File Exception %1").arg(QString::number(e.errorCode)), e.message);
}
)
.onFailed
( (
[this] () [this] ()
{ {
reset(); reset();
setError(QStringLiteral("Unknown Exception"), QString());
} }
); );
}
); // downloadUri.waitForFinished();
// }
// );
} }
auto DownloadManager::downloadVideo(const QString &author, const QString &authorId, const QString &description, const QUrl &url) noexcept(false) -> void auto DownloadManager::downloadVideo(const QString &author, const QString &authorId, const QString &description, const QUrl &url) -> void
{ {
QFuture future = QtConcurrent::run QFuture future = QtConcurrent::run
( (
@@ -236,7 +318,7 @@ auto DownloadManager::downloadVideo(const QString &author, const QString &author
); );
} }
auto DownloadManager::downloadPack(const QString &id) noexcept(false) -> void auto DownloadManager::downloadPack(const QString &id) -> void
{ {
QFuture aether = QtConcurrent::run QFuture aether = QtConcurrent::run
( (
@@ -267,9 +349,16 @@ auto DownloadManager::downloadPack(const QString &id) noexcept(false) -> void
) )
.then .then
( (
[this](QUrl result) [this](QUrl result) -> QUrl
{ {
install(result); return install(result);
}
)
.then
(
[this] (QUrl result)
{
setState(Complete);
} }
) )
.onFailed .onFailed
@@ -337,6 +426,8 @@ auto DownloadManager::setError(const QString &title, const QString &message) ->
m_errorMessage = std::move(message); m_errorMessage = std::move(message);
m_errorTitle = std::move(title); m_errorTitle = std::move(title);
Q_EMIT errorChanged(); Q_EMIT errorChanged();
setState(Error);
} }
void DownloadManager::setCompilerOutput(const QString &compilerOutput) void DownloadManager::setCompilerOutput(const QString &compilerOutput)
@@ -383,89 +474,45 @@ auto DownloadManager::install(const QUrl &uri) noexcept(false) -> QUrl
QDir tempDirectory(uri.toLocalFile()); QDir tempDirectory(uri.toLocalFile());
QString installLocation = QStringLiteral("%1/.local/share/komplex/packs/%2").arg QUrl installLocation = QStringLiteral("%1/.local/share/komplex/packs/%2").arg
( (
QStandardPaths::writableLocation(QStandardPaths::HomeLocation), QStandardPaths::writableLocation(QStandardPaths::HomeLocation),
tempDirectory.dirName() tempDirectory.dirName()
); );
QDir installDirectory(installLocation); QDir installDirectory(installLocation.toLocalFile());
if(installDirectory.exists()) if(installDirectory.exists())
installDirectory.removeRecursively(); installDirectory.removeRecursively();
QProcess process;
QObject::connect
(
&process,
&QProcess::readyReadStandardOutput,
this,
[this, &process]()
{
QByteArray processData = process.readAllStandardOutput();
if(!processData.isValidUtf8())
{
qWarning() << QStringLiteral("Process output not valid UTF8 data");
return;
}
setCompilerOutput(m_compilerOutput + processData);
}
);
QObject::connect
(
&process,
&QProcess::readyReadStandardError,
this,
[this, &process]()
{
QByteArray processData = process.readAllStandardError();
if(!processData.isValidUtf8())
{
qWarning() << QStringLiteral("Process output not valid UTF8 data");
return;
}
setCompilerOutput(m_compilerOutput + processData);
}
);
QStringList arguments = QStringList QStringList arguments = QStringList
{ {
QStringLiteral("-R"),
uri.toLocalFile(), uri.toLocalFile(),
installLocation installLocation.toLocalFile()
}; };
process.start(QStringLiteral("cp"), arguments); m_moveProcess.start(QStringLiteral("mv"), arguments);
if(!process.waitForStarted(3000)) if(!m_moveProcess.waitForStarted(3000))
{ {
qWarning() << QStringLiteral("Could not start copy process: %1").arg(process.readAllStandardError()); qWarning() << QStringLiteral("Could not start copy process: %1").arg(m_moveProcess.readAllStandardError());
throw FileException(QStringLiteral("Could not start install process")); throw FileException(QStringLiteral("Could not start install process"));
} }
if(!process.waitForFinished()) if(!m_moveProcess.waitForFinished())
{ {
qWarning() << QStringLiteral("Copy process took longer than expected (>30s)"); qWarning() << QStringLiteral("Copy process took longer than expected (>30s)");
throw FileException(QStringLiteral("Install process took longer than expected (>30s)")); throw FileException(QStringLiteral("Install process took longer than expected (>30s)"));
} }
QUrl installUri(installLocation); return installLocation;
installUri.setScheme(QStringLiteral("file://"));
return installUri;
} }
auto DownloadManager::download(const QNetworkRequest &request, const QString &id, RequestType type) -> QFuture<QUrl> auto DownloadManager::download(const QNetworkRequest &request, const QString &id, RequestType type) -> QFuture<QUrl>
{ {
return QtConcurrent::run return QtConcurrent::run
( (
[this, request, id]() -> QUrl [this, request, id, type]() -> QUrl
{ {
QEventLoop loop; QEventLoop loop;
QString filename = id; QString filename = id;
@@ -475,10 +522,10 @@ auto DownloadManager::download(const QNetworkRequest &request, const QString &id
filename = QUuid::createUuidV7().toString(); filename = QUuid::createUuidV7().toString();
} }
QUrl downloadUri = QStringLiteral("%1/%2").arg QUrl downloadUri = QStringLiteral("file://%1/%2").arg
( (
QStandardPaths::writableLocation(QStandardPaths::TempLocation), QStandardPaths::writableLocation(QStandardPaths::TempLocation),
filename request.url().fileName()
); );
auto manager = CoreServices::networkAccessManager().toStrongRef(); auto manager = CoreServices::networkAccessManager().toStrongRef();
@@ -493,20 +540,23 @@ auto DownloadManager::download(const QNetworkRequest &request, const QString &id
QFile downloadFile(downloadUri.toLocalFile()); QFile downloadFile(downloadUri.toLocalFile());
if(!downloadFile.open(QFile::ReadWrite)) if(downloadFile.exists() && !downloadFile.remove())
{ {
throw FileException(QStringLiteral("Could not open temp file location")); throw FileException(downloadFile.errorString());
} }
QNetworkReply *reply = manager->post(request, nullptr); QNetworkReply *reply = nullptr;
QObject::connect switch(type)
( {
reply, case Post:
&QNetworkReply::finished, reply = manager->post(request, nullptr);
&loop, break;
&QEventLoop::quit default:
); case Get:
reply = manager->get(request, nullptr);
break;
}
QObject::connect QObject::connect
( (
@@ -545,40 +595,35 @@ auto DownloadManager::download(const QNetworkRequest &request, const QString &id
reply, reply,
&QNetworkReply::readyRead, &QNetworkReply::readyRead,
this, this,
[this, &downloadFile, &reply]() [this, downloadUri, reply]()
{ {
if(!downloadFile.isOpen()) QFile downloadFile(downloadUri.toLocalFile());
if(!downloadFile.open(QFile::ReadWrite | QFile::Append))
{ {
return; throw FileException(QStringLiteral("Could not open temp file location"));
} }
quint64 bytes = reply->bytesAvailable(); quint64 bytes = reply->bytesAvailable();
quint64 bytesWritten = downloadFile.write(reply->read(bytes)); quint64 bytesWritten = downloadFile.write(reply->readAll()/*bytes)*/);
if(bytesWritten != bytes) downloadFile.close();
{
throw FileException(QStringLiteral("Could not write temp file data"));
}
} }
); );
QObject::connect
(
reply,
&QNetworkReply::finished,
&loop,
&QEventLoop::quit
);
if(!reply->isFinished()) if(!reply->isFinished())
{ {
loop.exec(); loop.exec();
} }
if(reply->bytesAvailable() > 0)
{
quint64 bytes = reply->bytesAvailable();
quint64 bytesWritten = downloadFile.write(reply->read(bytes));
if(bytesWritten != bytes)
{
throw FileException(QStringLiteral("Could not write temp file data"));
}
}
downloadFile.close();
manager.clear(); manager.clear();
return downloadUri; return downloadUri;
@@ -717,6 +762,19 @@ auto DownloadManager::readShaderToyEntry(const QUrl &uri) noexcept(false) -> Sha
return std::move(entry); return std::move(entry);
} }
auto DownloadManager::lastInstalledFile() const -> const QString &
{
return m_lastInstalledFile;
}
auto DownloadManager::setLastInstalledFile(const QString &lastInstalledFile) -> void
{
if (m_lastInstalledFile == lastInstalledFile)
return;
m_lastInstalledFile = lastInstalledFile;
emit lastInstalledFileChanged();
}
auto DownloadManager::setDownloadedBytes(qint64 downloadedBytes) -> void auto DownloadManager::setDownloadedBytes(qint64 downloadedBytes) -> void
{ {
if (m_downloadedBytes == downloadedBytes) if (m_downloadedBytes == downloadedBytes)
+18 -6
View File
@@ -68,13 +68,13 @@ public:
* out of it * out of it
* @param url * @param url
*/ */
auto downloadImage Q_INVOKABLE auto downloadImage
( (
const QString &author, const QString &author,
const QString &authorId, const QString &authorId,
const QString &description, const QString &description,
const QUrl &url const QUrl &url
) noexcept(false) -> void; ) -> void;
/** /**
* @brief downloadVideo * @brief downloadVideo
@@ -85,13 +85,13 @@ public:
* @param description * @param description
* @param url * @param url
*/ */
auto downloadVideo Q_INVOKABLE auto downloadVideo
( (
const QString &author, const QString &author,
const QString &authorId, const QString &authorId,
const QString &description, const QString &description,
const QUrl &url const QUrl &url
) noexcept(false) -> void; ) -> void;
/** /**
* @brief downloadPack * @brief downloadPack
@@ -100,13 +100,13 @@ public:
* @param id * @param id
* @return File info of the installed pack * @return File info of the installed pack
*/ */
auto downloadPack(const QString &id) noexcept(false) -> void; Q_INVOKABLE auto downloadPack(const QString &id) -> void;
auto compilerOutput() const -> const QString & { return m_compilerOutput; } auto compilerOutput() const -> const QString & { return m_compilerOutput; }
auto errorTitle() const -> const QString & { return m_errorTitle; } auto errorTitle() const -> const QString & { return m_errorTitle; }
auto errorMessage() const -> const QString & { return m_errorMessage; } auto errorMessage() const -> const QString & { return m_errorMessage; }
auto state() const -> State { return m_state; } auto state() const -> State { return m_state; }
auto reset() -> void; Q_INVOKABLE auto reset() -> void;
auto downloadProgress() -> qreal { return m_downloadProgress; } auto downloadProgress() -> qreal { return m_downloadProgress; }
auto compileProgress() -> qreal; auto compileProgress() -> qreal;
auto compileSteps() -> qint64; auto compileSteps() -> qint64;
@@ -118,6 +118,9 @@ public:
auto downloadedBytes() const -> qint64 { return m_downloadedBytes; } auto downloadedBytes() const -> qint64 { return m_downloadedBytes; }
auto setDownloadedBytes(qint64 downloadedBytes) -> void; auto setDownloadedBytes(qint64 downloadedBytes) -> void;
auto lastInstalledFile() const -> const QString &;
auto setLastInstalledFile(const QString &lastInstalledFile) -> void;
protected: protected:
auto setError(const QString &title, const QString &message) -> void; auto setError(const QString &title, const QString &message) -> void;
auto setCompilerOutput(const QString &compilerOutput) -> void; auto setCompilerOutput(const QString &compilerOutput) -> void;
@@ -136,12 +139,16 @@ signals:
auto compileStepsChanged() -> void; auto compileStepsChanged() -> void;
auto compileStepsCompletedChanged() -> void; auto compileStepsCompletedChanged() -> void;
auto lastInstalledFileChanged() -> void;
private: private:
auto compile(const QUrl &uri) noexcept(false) -> QUrl; auto compile(const QUrl &uri) noexcept(false) -> QUrl;
auto install(const QUrl &uri) noexcept(false) -> QUrl; auto install(const QUrl &uri) noexcept(false) -> QUrl;
auto download(const QNetworkRequest &request, const QString &id, RequestType type = Get) -> QFuture<QUrl>; auto download(const QNetworkRequest &request, const QString &id, RequestType type = Get) -> QFuture<QUrl>;
auto readShaderToyEntry(const QUrl &uri) noexcept(false) -> ShaderToyEntry; auto readShaderToyEntry(const QUrl &uri) noexcept(false) -> ShaderToyEntry;
QString m_lastInstalledFile;
QString m_compilerOutput; QString m_compilerOutput;
QString m_errorTitle; QString m_errorTitle;
QString m_errorMessage; QString m_errorMessage;
@@ -156,6 +163,10 @@ private:
PackCompiler *m_compiler = nullptr; PackCompiler *m_compiler = nullptr;
QProcess m_moveProcess;
QFuture<QUrl> m_downloadFuture;
Q_PROPERTY(QString compilerOutput READ compilerOutput WRITE setCompilerOutput NOTIFY compilerOutputChanged FINAL) Q_PROPERTY(QString compilerOutput READ compilerOutput WRITE setCompilerOutput NOTIFY compilerOutputChanged FINAL)
Q_PROPERTY(QString errorTitle READ errorTitle NOTIFY errorChanged FINAL) Q_PROPERTY(QString errorTitle READ errorTitle NOTIFY errorChanged FINAL)
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorChanged FINAL) Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorChanged FINAL)
@@ -166,6 +177,7 @@ private:
Q_PROPERTY(qint64 downloadedBytes READ downloadedBytes WRITE setDownloadedBytes NOTIFY downloadedBytesChanged FINAL) Q_PROPERTY(qint64 downloadedBytes READ downloadedBytes WRITE setDownloadedBytes NOTIFY downloadedBytesChanged FINAL)
Q_PROPERTY(qint64 compileSteps READ compileSteps NOTIFY compileStepsChanged FINAL) Q_PROPERTY(qint64 compileSteps READ compileSteps NOTIFY compileStepsChanged FINAL)
Q_PROPERTY(qint64 compileStepsCompleted READ compileStepsCompleted NOTIFY compileStepsCompletedChanged FINAL) Q_PROPERTY(qint64 compileStepsCompleted READ compileStepsCompleted NOTIFY compileStepsCompletedChanged FINAL)
Q_PROPERTY(QString lastInstalledFile READ lastInstalledFile WRITE setLastInstalledFile NOTIFY lastInstalledFileChanged FINAL)
}; };
Q_DECLARE_METATYPE(DownloadManager) Q_DECLARE_METATYPE(DownloadManager)
+14 -7
View File
@@ -5,49 +5,56 @@ FeaturedImagesModel::FeaturedImagesModel(QObject *parent) : QAbstractListModel{p
m_paginator = new FeaturedImagesPaginator(this); m_paginator = new FeaturedImagesPaginator(this);
PaginationNotifier *notifier = static_cast<PaginationNotifier*>(m_paginator); PaginationNotifier *notifier = static_cast<PaginationNotifier*>(m_paginator);
QObject::connect( QObject::connect
(
notifier, notifier,
&PaginationNotifier::resultsPerPageChanged, &PaginationNotifier::resultsPerPageChanged,
this, this,
&FeaturedImagesModel::resultsPerPageChanged &FeaturedImagesModel::resultsPerPageChanged
); );
QObject::connect( QObject::connect
(
notifier, notifier,
&PaginationNotifier::totalResultsChanged, &PaginationNotifier::totalResultsChanged,
this, this,
&FeaturedImagesModel::totalResultsChanged &FeaturedImagesModel::totalResultsChanged
); );
QObject::connect( QObject::connect
(
notifier, notifier,
&PaginationNotifier::totalPagesChanged, &PaginationNotifier::totalPagesChanged,
this, this,
&FeaturedImagesModel::totalPagesChanged &FeaturedImagesModel::totalPagesChanged
); );
QObject::connect( QObject::connect
(
notifier, notifier,
&PaginationNotifier::pageChanged, &PaginationNotifier::pageChanged,
this, this,
&FeaturedImagesModel::pageChanged &FeaturedImagesModel::pageChanged
); );
QObject::connect( QObject::connect
(
notifier, notifier,
&PaginationNotifier::pageChanged, &PaginationNotifier::pageChanged,
this, this,
&FeaturedImagesModel::resetDataModel &FeaturedImagesModel::resetDataModel
); );
QObject::connect( QObject::connect
(
notifier, notifier,
&PaginationNotifier::fetchComplete, &PaginationNotifier::fetchComplete,
this, this,
&FeaturedImagesModel::resetState &FeaturedImagesModel::resetState
); );
QObject::connect( QObject::connect
(
notifier, notifier,
&PaginationNotifier::fetching, &PaginationNotifier::fetching,
this, this,