diff --git a/KomplexHubModule/Controls/CompletedView.qml b/KomplexHubModule/Controls/CompletedView.qml new file mode 100644 index 0000000..8ab29ec --- /dev/null +++ b/KomplexHubModule/Controls/CompletedView.qml @@ -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 {} + } +} diff --git a/KomplexHubModule/Controls/DownloadView.qml b/KomplexHubModule/Controls/DownloadView.qml new file mode 100644 index 0000000..3020970 --- /dev/null +++ b/KomplexHubModule/Controls/DownloadView.qml @@ -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 } + } + } +} diff --git a/KomplexHubModule/Controls/ErrorView.qml b/KomplexHubModule/Controls/ErrorView.qml new file mode 100644 index 0000000..a447293 --- /dev/null +++ b/KomplexHubModule/Controls/ErrorView.qml @@ -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 {} + } +} diff --git a/KomplexHubModule/Controls/ImageView.qml b/KomplexHubModule/Controls/ImageView.qml index dfa9ecc..8afd277 100644 --- a/KomplexHubModule/Controls/ImageView.qml +++ b/KomplexHubModule/Controls/ImageView.qml @@ -6,7 +6,7 @@ import QtQuick.Effects import KomplexHub import KomplexHub.Controls import KomplexHub.Kero -import KomplexHubPlugin +import KomplexHub.Plugin Item { @@ -17,7 +17,6 @@ Item property string thumbnail property string portrait property string landscape - property string original property string fullScreen property string portraitSize property string landscapeSize @@ -30,29 +29,21 @@ Item id: rootItem + DownloadManager + { + id: downloadManager + } + Rectangle { + id: pageView anchors.fill: parent color: palette.base - Image + BackgroundImage { - id: backgroundImage - source: width > height ? backgroundLandscape : backgroundPortrait - transform: Image.PreserveAspectCrop anchors.fill: parent - visible: false - } - - MultiEffect - { - anchors.fill: backgroundImage - source: backgroundImage - blurEnabled: true - blurMax: 64 - blur: 1.0 - opacity: 0.25 - saturation: -0.8 + source: width > height ? backgroundLandscape : backgroundPortrait } ColumnLayout @@ -61,36 +52,15 @@ Item anchors.margins: Constants.largeMargin spacing: Constants.largeMargin - RowLayout + ImageFrame { Layout.fillWidth: true Layout.alignment: Qt.AlignTop| Qt.AlignHCenter - Layout.topMargin: 32 + Layout.topMargin: Constants.largeMargin + Layout.preferredHeight: width / 1.77777777778 + Layout.maximumWidth: 800 - Rectangle - { - 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) - } - } + source: rootItem.thumbnail } Text @@ -158,6 +128,8 @@ Item Layout.preferredWidth: 128 text: qsTr("Download") 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) } } diff --git a/KomplexHubPlugin/CMakeLists.txt b/KomplexHubPlugin/CMakeLists.txt index 52a4d4d..79e09a0 100644 --- a/KomplexHubPlugin/CMakeLists.txt +++ b/KomplexHubPlugin/CMakeLists.txt @@ -6,7 +6,7 @@ add_library( qt_add_qml_module( KomplexHubPlugin URI - KomplexHubPlugin + "KomplexHub.Plugin" VERSION 1.0 SOURCES diff --git a/KomplexHubPlugin/common/coreservices.cpp b/KomplexHubPlugin/common/coreservices.cpp index 8e541e3..58e88b3 100644 --- a/KomplexHubPlugin/common/coreservices.cpp +++ b/KomplexHubPlugin/common/coreservices.cpp @@ -12,28 +12,31 @@ auto CoreServices::networkAccessManager() -> QWeakPointer if(!s_networkAccessPointer) { - s_networkAccessManager = new QNetworkAccessManager(QCoreApplication::instance()); - s_networkAccessManager->setAutoDeleteReplies(true); + if(!s_networkAccessManager) + { + s_networkAccessManager = new QNetworkAccessManager(QCoreApplication::instance()); + s_networkAccessManager->setAutoDeleteReplies(true); - QObject::connect( - s_networkAccessManager, - &QNetworkAccessManager::sslErrors, - s_networkAccessManager, - [] (QNetworkReply *reply, const QList &errors) - { - for(const auto &error : errors) + QObject::connect( + s_networkAccessManager, + &QNetworkAccessManager::sslErrors, + s_networkAccessManager, + [] (QNetworkReply *reply, const QList &errors) { - LOG_ERROR( - "CoreServices::networkAccessManager", - error.errorString().toStdString().c_str() - ); - } + for(const auto &error : errors) + { + LOG_ERROR( + "CoreServices::networkAccessManager", + error.errorString().toStdString().c_str() + ); + } -#ifdef KOMPLEX_LOCAL_DEV - reply->ignoreSslErrors(); -#endif - } - ); + #ifdef KOMPLEX_LOCAL_DEV + reply->ignoreSslErrors(); + #endif + } + ); + } s_networkAccessPointer = QSharedPointer( s_networkAccessManager, diff --git a/KomplexHubPlugin/downloadmanager.cpp b/KomplexHubPlugin/downloadmanager.cpp index 599daf3..6d94b9a 100644 --- a/KomplexHubPlugin/downloadmanager.cpp +++ b/KomplexHubPlugin/downloadmanager.cpp @@ -31,6 +31,44 @@ DownloadManager::DownloadManager(QObject *parent) this, &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 * [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 - ( - [this, url, author, authorId, description]() - { + // QFuture future = QtConcurrent::run + // ( + // [this, url, author, authorId, description]() + // { QNetworkRequest request(url); + QString requestUrl = request.url().toString(); QString id = QUuid::createUuidV7().toString(QUuid::WithoutBraces); - QFuture downloadUri = download(request, id); + setState(Downloading); - downloadUri + //QFuture downloadUri = download(request, id, Get); + if(m_downloadFuture.isRunning()) + { + m_downloadFuture.cancelChain(); + } + + m_downloadFuture = download(request, id, Get); + + m_downloadFuture .then ( [this, author, description, id](QUrl result) -> QUrl { + setState(Installing); + ShaderPack metadata; metadata.setAuthor(author); metadata.setDescription(description); metadata.setName(QStringLiteral("Pexels Image (%1)").arg(id)); + metadata.setSource(QStringLiteral("./images/%1").arg(result.fileName())); QUrl packUri ( - QStringLiteral("%1/%2").arg + QStringLiteral("file://%1/%2").arg ( QStandardPaths::writableLocation(QStandardPaths::TempLocation), id @@ -71,7 +121,7 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author QUrl packImageUri ( - QStringLiteral("%1/%2/images/%3").arg + QStringLiteral("file://%1/%2/images/%3").arg ( QStandardPaths::writableLocation(QStandardPaths::TempLocation), id, @@ -80,7 +130,12 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author ); QDir packDirectory(packUri.toLocalFile()); - packDirectory.mkpath(packUri.toLocalFile()); + + if(!packDirectory.mkpath(packUri.toLocalFile())) + { + throw FileException(QStringLiteral("Could not create directory")); + } + packDirectory.mkdir(QStringLiteral("images")); QFile::rename(result.toLocalFile(), packImageUri.toLocalFile()); @@ -99,7 +154,7 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author throw FileException(packFile.errorString()); } - QByteArray data = metadata.json().toJson(QJsonDocument::Compact); + QByteArray data = metadata.json().toJson(QJsonDocument::Indented); if(packFile.write(data) != data.length()) { @@ -113,10 +168,18 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author } ) .then + ( + [this](QUrl result) -> QUrl + { + return install(result); + } + ) + .then ( [this](QUrl result) { - install(result); + setLastInstalledFile(result.toLocalFile()); + setState(Complete); } ) .onCanceled @@ -127,17 +190,36 @@ auto DownloadManager::downloadImage(const QString &author, const QString &author } ) .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] () { 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 ( @@ -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 ( @@ -267,9 +349,16 @@ auto DownloadManager::downloadPack(const QString &id) noexcept(false) -> void ) .then ( - [this](QUrl result) + [this](QUrl result) -> QUrl { - install(result); + return install(result); + } + ) + .then + ( + [this] (QUrl result) + { + setState(Complete); } ) .onFailed @@ -337,6 +426,8 @@ auto DownloadManager::setError(const QString &title, const QString &message) -> m_errorMessage = std::move(message); m_errorTitle = std::move(title); Q_EMIT errorChanged(); + + setState(Error); } void DownloadManager::setCompilerOutput(const QString &compilerOutput) @@ -383,89 +474,45 @@ auto DownloadManager::install(const QUrl &uri) noexcept(false) -> QUrl 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), tempDirectory.dirName() ); - QDir installDirectory(installLocation); + QDir installDirectory(installLocation.toLocalFile()); if(installDirectory.exists()) 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 { - QStringLiteral("-R"), 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")); } - if(!process.waitForFinished()) + if(!m_moveProcess.waitForFinished()) { qWarning() << QStringLiteral("Copy process took longer than expected (>30s)"); throw FileException(QStringLiteral("Install process took longer than expected (>30s)")); } - QUrl installUri(installLocation); - installUri.setScheme(QStringLiteral("file://")); - - return installUri; + return installLocation; } auto DownloadManager::download(const QNetworkRequest &request, const QString &id, RequestType type) -> QFuture { return QtConcurrent::run ( - [this, request, id]() -> QUrl + [this, request, id, type]() -> QUrl { QEventLoop loop; QString filename = id; @@ -475,10 +522,10 @@ auto DownloadManager::download(const QNetworkRequest &request, const QString &id filename = QUuid::createUuidV7().toString(); } - QUrl downloadUri = QStringLiteral("%1/%2").arg + QUrl downloadUri = QStringLiteral("file://%1/%2").arg ( QStandardPaths::writableLocation(QStandardPaths::TempLocation), - filename + request.url().fileName() ); auto manager = CoreServices::networkAccessManager().toStrongRef(); @@ -493,20 +540,23 @@ auto DownloadManager::download(const QNetworkRequest &request, const QString &id 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 - ( - reply, - &QNetworkReply::finished, - &loop, - &QEventLoop::quit - ); + switch(type) + { + case Post: + reply = manager->post(request, nullptr); + break; + default: + case Get: + reply = manager->get(request, nullptr); + break; + } QObject::connect ( @@ -545,40 +595,35 @@ auto DownloadManager::download(const QNetworkRequest &request, const QString &id reply, &QNetworkReply::readyRead, 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 bytesWritten = downloadFile.write(reply->read(bytes)); + quint64 bytesWritten = downloadFile.write(reply->readAll()/*bytes)*/); - if(bytesWritten != bytes) - { - throw FileException(QStringLiteral("Could not write temp file data")); - } + downloadFile.close(); } ); + QObject::connect + ( + reply, + &QNetworkReply::finished, + &loop, + &QEventLoop::quit + ); + if(!reply->isFinished()) { 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(); return downloadUri; @@ -717,6 +762,19 @@ auto DownloadManager::readShaderToyEntry(const QUrl &uri) noexcept(false) -> Sha 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 { if (m_downloadedBytes == downloadedBytes) diff --git a/KomplexHubPlugin/downloadmanager.h b/KomplexHubPlugin/downloadmanager.h index 128f8c2..cd0a95c 100644 --- a/KomplexHubPlugin/downloadmanager.h +++ b/KomplexHubPlugin/downloadmanager.h @@ -68,13 +68,13 @@ public: * out of it * @param url */ - auto downloadImage + Q_INVOKABLE auto downloadImage ( const QString &author, const QString &authorId, const QString &description, const QUrl &url - ) noexcept(false) -> void; + ) -> void; /** * @brief downloadVideo @@ -85,13 +85,13 @@ public: * @param description * @param url */ - auto downloadVideo + Q_INVOKABLE auto downloadVideo ( const QString &author, const QString &authorId, const QString &description, const QUrl &url - ) noexcept(false) -> void; + ) -> void; /** * @brief downloadPack @@ -100,13 +100,13 @@ public: * @param id * @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 errorTitle() const -> const QString & { return m_errorTitle; } auto errorMessage() const -> const QString & { return m_errorMessage; } auto state() const -> State { return m_state; } - auto reset() -> void; + Q_INVOKABLE auto reset() -> void; auto downloadProgress() -> qreal { return m_downloadProgress; } auto compileProgress() -> qreal; auto compileSteps() -> qint64; @@ -118,6 +118,9 @@ public: auto downloadedBytes() const -> qint64 { return m_downloadedBytes; } auto setDownloadedBytes(qint64 downloadedBytes) -> void; + auto lastInstalledFile() const -> const QString &; + auto setLastInstalledFile(const QString &lastInstalledFile) -> void; + protected: auto setError(const QString &title, const QString &message) -> void; auto setCompilerOutput(const QString &compilerOutput) -> void; @@ -136,12 +139,16 @@ signals: auto compileStepsChanged() -> void; auto compileStepsCompletedChanged() -> void; + auto lastInstalledFileChanged() -> void; + private: auto compile(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; auto readShaderToyEntry(const QUrl &uri) noexcept(false) -> ShaderToyEntry; + QString m_lastInstalledFile; + QString m_compilerOutput; QString m_errorTitle; QString m_errorMessage; @@ -156,6 +163,10 @@ private: PackCompiler *m_compiler = nullptr; + QProcess m_moveProcess; + + QFuture m_downloadFuture; + Q_PROPERTY(QString compilerOutput READ compilerOutput WRITE setCompilerOutput NOTIFY compilerOutputChanged FINAL) Q_PROPERTY(QString errorTitle READ errorTitle 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 compileSteps READ compileSteps NOTIFY compileStepsChanged 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) diff --git a/KomplexHubPlugin/featuredimagesmodel.cpp b/KomplexHubPlugin/featuredimagesmodel.cpp index 07d590f..9a347b1 100644 --- a/KomplexHubPlugin/featuredimagesmodel.cpp +++ b/KomplexHubPlugin/featuredimagesmodel.cpp @@ -5,49 +5,56 @@ FeaturedImagesModel::FeaturedImagesModel(QObject *parent) : QAbstractListModel{p m_paginator = new FeaturedImagesPaginator(this); PaginationNotifier *notifier = static_cast(m_paginator); - QObject::connect( + QObject::connect + ( notifier, &PaginationNotifier::resultsPerPageChanged, this, &FeaturedImagesModel::resultsPerPageChanged ); - QObject::connect( + QObject::connect + ( notifier, &PaginationNotifier::totalResultsChanged, this, &FeaturedImagesModel::totalResultsChanged ); - QObject::connect( + QObject::connect + ( notifier, &PaginationNotifier::totalPagesChanged, this, &FeaturedImagesModel::totalPagesChanged ); - QObject::connect( + QObject::connect + ( notifier, &PaginationNotifier::pageChanged, this, &FeaturedImagesModel::pageChanged ); - QObject::connect( + QObject::connect + ( notifier, &PaginationNotifier::pageChanged, this, &FeaturedImagesModel::resetDataModel ); - QObject::connect( + QObject::connect + ( notifier, &PaginationNotifier::fetchComplete, this, &FeaturedImagesModel::resetState ); - QObject::connect( + QObject::connect + ( notifier, &PaginationNotifier::fetching, this,