diff --git a/qml/components/AppInformation.qml b/qml/components/AppInformation.qml index 01ef74e5..9fd577d0 100644 --- a/qml/components/AppInformation.qml +++ b/qml/components/AppInformation.qml @@ -87,6 +87,13 @@ MouseArea { visible: pkg.packageName } + ChumDetailItem { + //% "Package last updated:" + label: qsTrId("chum-pkg-package-mtime") + value: pkg.packageMTime + visible: pkg.packageMTime + } + ChumDetailItem { //% "Download size:" label: qsTrId("chum-pkg-download-size") diff --git a/qml/pages/PackagesListPage.qml b/qml/pages/PackagesListPage.qml index fbd29a43..81c8ab35 100644 --- a/qml/pages/PackagesListPage.qml +++ b/qml/pages/PackagesListPage.qml @@ -18,6 +18,13 @@ Page { allowedOrientations: Orientation.All + BusyIndicator { + size: BusyIndicatorSize.Large + anchors.centerIn: parent + running: chumModel.busy == true + visible: running + } + SilicaListView { id: view anchors.fill: parent @@ -78,7 +85,7 @@ Page { } onClicked: pageStack.push(Qt.resolvedUrl("../pages/PackagePage.qml"), { - pkg: Chum.package(model.packageId) + pkg: Chum.package(model.packageId), }) onDownChanged: { diff --git a/src/chum.cpp b/src/chum.cpp index 327bb191..16987cb8 100644 --- a/src/chum.cpp +++ b/src/chum.cpp @@ -4,6 +4,13 @@ #include #include +#include +#include +#include +#include +#include + +static char* apiUrl = "http://piggz.co.uk:8081"; using namespace PackageKit; @@ -37,10 +44,7 @@ Chum::Chum(QObject *parent) m_show_apps_by_default = (settings.value(s_config_showapps, 1).toInt() != 0); m_manualVersion = (settings.value(s_config_manualversion, QString()).toString()); - m_busy = true; - //% "Loading SailfishOS:Chum repository" - setStatus(qtTrId("chum-load-repositories")); - m_ssu.loadRepos(); + getChumCache(); } Chum* Chum::instance() { @@ -450,3 +454,86 @@ void Chum::setStatus(QString status) { m_status = status; emit statusChanged(); } + +void Chum::getChumCache() +{ + if (!m_busy) { + m_busy = true; + emit busyChanged(); + } + + //% "Receiving the chum package cache" + setStatus(qtTrId("chum-update-cache")); + + QNetworkAccessManager *netManager = new QNetworkAccessManager(); + + QObject::connect(netManager,&QNetworkAccessManager::finished,[=](QNetworkReply *reply) { + if (reply->error()){ + qDebug() << "Unable to get package build times" << reply->errorString(); + } + else { + m_chumPackageCache = QJsonDocument::fromJson(reply->readAll()); + qDebug() << "Received chum package cache"; + } + m_busy = false; + //% "Loading SailfishOS:Chum repository" + setStatus(qtTrId("chum-load-repositories")); + m_ssu.loadRepos(); + }); + + // Start the network request + QNetworkRequest request=QNetworkRequest(QUrl(apiUrl)); + m_busy = true; + emit busyChanged(); + netManager->get(request); +} + +QDateTime Chum::findPackageMTime(const QString &rpm) const +{ + qDebug() << Q_FUNC_INFO << rpm << Chum::instance()->repoName() << Chum::instance()->repoVersion(); + + QString repo = Chum::instance()->repoVersion() + "_aarch64"; //TODO need to determine device architecture + QString projectName = Chum::instance()->repoName().replace("-", ":"); + QString packageName; + QDateTime mtime = QDateTime::fromMSecsSinceEpoch(0); + bool found = false; + + QJsonArray projects = m_chumPackageCache.object().value("projects").toArray(); + + for (auto project : projects) { + //qDebug() << project.toObject()["name"]; + if (project.toObject()["name"].toString() == projectName) { + QJsonArray repos = project.toObject()["repositories"].toArray(); + for (auto repo : repos) { + //qDebug() << repo.toObject()["name"]; + QJsonArray packages = repo.toObject()["packages"].toArray(); + for (auto package : packages) { + //qDebug() << package.toObject()["name"].toString(); + QJsonArray binaries = package.toObject()["binaries"].toArray(); + for (auto binary : binaries) { + //qDebug() << binary.toString(); + if (binary.toString().startsWith(rpm)) { + packageName = package.toObject()["name"].toString(); + found = true; + } + } + } + } + + if (found) { + //loop the source projects + QJsonArray packages = project.toObject()["packages"].toArray(); + for (auto package : packages) { + //qDebug() << package.toObject()["name"]; + if (package.toObject()["name"].toString() == packageName) { + int mt = package.toObject()["mtime"].toString().toInt(); + mtime = QDateTime::fromMSecsSinceEpoch(1000L * mt); + qDebug() << "Found binary " << rpm << " in source package " << packageName << mt << mtime; + } + } + } + } + } + return mtime; + +} diff --git a/src/chum.h b/src/chum.h index e8cff67f..ab73c50d 100644 --- a/src/chum.h +++ b/src/chum.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "chumpackage.h" #include "ssu.h" @@ -45,10 +46,14 @@ class Chum : public QObject { void setRepoTesting(bool testing); void setShowAppsByDefault(bool v); void setManualVersion(const QString &v); + QString repoName() { return m_ssu.repoName();} + QString repoVersion() { return m_manualVersion.isEmpty() ? m_ssu.deviceVersion() : m_manualVersion; } const QList packages() const { return m_packages.values(); } Q_INVOKABLE ChumPackage* package(const QString &id) const { return m_packages.value(id, nullptr); } + QDateTime findPackageMTime(const QString &rpm) const; + // static public methods static Chum* instance(); @@ -92,6 +97,8 @@ public slots: void startOperation(PackageKit::Transaction *pktr, const QString &pkg_id); void setStatus(QString status); + void getChumCache(); + private: Ssu m_ssu; bool m_busy{false}; @@ -100,6 +107,7 @@ public slots: quint32 m_updates_count{0}; bool m_show_apps_by_default{false}; QString m_manualVersion; + QJsonDocument m_chumPackageCache; QHash m_packages; QSet m_packages_last_refresh; diff --git a/src/chumpackage.cpp b/src/chumpackage.cpp index ec4f960f..8b9da029 100644 --- a/src/chumpackage.cpp +++ b/src/chumpackage.cpp @@ -1,4 +1,5 @@ #include "chumpackage.h" +#include "chum.h" #include "projectgithub.h" #include "projectgitlab.h" @@ -122,6 +123,8 @@ void ChumPackage::setDetails(const PackageKit::Details &v) { // derive name QString pname = Daemon::packageName(m_pkid_latest); m_package_name = pname; + m_package_mtime = Chum::instance()->findPackageMTime(m_package_name); + m_name = QString{}; QStringList nparts = pname.split('-'); bool is_app = false; @@ -261,6 +264,12 @@ void ChumPackage::setPackagerLogin(const QString &login) { SET_IF_EMPTY(m_packager_login, PackagePackagerRole, login); } +void ChumPackage::setPackageMTime(const QDateTime &mtime) +{ + m_package_mtime = mtime; + emit updated(m_id, PackageMTime); +} + void ChumPackage::setPackagerName(const QString &name) { SET_IF_EMPTY(m_packager_name, PackagePackagerRole, name); } diff --git a/src/chumpackage.h b/src/chumpackage.h index 2774d741..5615a808 100644 --- a/src/chumpackage.h +++ b/src/chumpackage.h @@ -24,6 +24,7 @@ class ChumPackage : public QObject { Q_PROPERTY(int issuesCount READ issuesCount NOTIFY updated) Q_PROPERTY(QString license READ license NOTIFY updated) Q_PROPERTY(QString name READ name NOTIFY updated) + Q_PROPERTY(QDateTime packageMTime READ packageMTime NOTIFY updated) Q_PROPERTY(QString packageName READ packageName NOTIFY updated) Q_PROPERTY(QString packager READ packager NOTIFY updated) Q_PROPERTY(QString packagingUrl READ packagingUrl NOTIFY updated) @@ -55,6 +56,7 @@ class ChumPackage : public QObject { PackageSummaryRole, PackageTypeRole, PackageUpdateAvailableRole, + PackageMTime, PackageOtherRole, PackageRefreshRole // used for updates of many parameters @@ -93,6 +95,7 @@ class ChumPackage : public QObject { int issuesCount() const { return m_issues_count; } QString license() const { return m_license; } QString name() const { return m_name; } + QDateTime packageMTime() const { return m_package_mtime; } QString packageName() const { return m_package_name; } QString packager() const; QString packagingUrl() const { return m_packaging_repo_url; } @@ -119,6 +122,7 @@ class ChumPackage : public QObject { void setForksCount(int count); void setIssuesCount(int count); void setPackagerLogin(const QString &login); + void setPackageMTime(const QDateTime &mtime); void setPackagerName(const QString &name); void setReleasesCount(int count); void setStarsCount(int count); @@ -161,6 +165,7 @@ class ChumPackage : public QObject { int m_issues_count{-1}; QString m_license; QString m_name; + QDateTime m_package_mtime; QString m_package_name; QString m_packager_login; QString m_packager_name; diff --git a/src/chumpackagesmodel.cpp b/src/chumpackagesmodel.cpp index 9a6ba38f..03517d62 100644 --- a/src/chumpackagesmodel.cpp +++ b/src/chumpackagesmodel.cpp @@ -44,6 +44,8 @@ QVariant ChumPackagesModel::data(const QModelIndex &index, int role) const { return p->type(); case ChumPackage::PackageUpdateAvailableRole: return p->updateAvailable(); + case ChumPackage::PackageMTime: + return p->packageMTime(); default: return QVariant{}; } @@ -62,6 +64,7 @@ QHash ChumPackagesModel::roleNames() const { {ChumPackage::PackageStarsCountRole, QByteArrayLiteral("packageStarsCount")}, {ChumPackage::PackageTypeRole, QByteArrayLiteral("packageType")}, {ChumPackage::PackageUpdateAvailableRole, QByteArrayLiteral("packageUpdateAvailable")}, + {ChumPackage::PackageMTime, QByteArrayLiteral("packageMTime")}, }; } diff --git a/src/chumpackagesmodel.h b/src/chumpackagesmodel.h index 8325f19d..ce9ba26d 100644 --- a/src/chumpackagesmodel.h +++ b/src/chumpackagesmodel.h @@ -49,6 +49,7 @@ class ChumPackagesModel void filterUpdatesOnlyChanged(); void searchChanged(); void showCategoryChanged(); + void busyChanged(); private: void updatePackage(QString packageId, ChumPackage::Role role); diff --git a/src/ssu.cpp b/src/ssu.cpp index ba4dff0c..cb1b3bfd 100644 --- a/src/ssu.cpp +++ b/src/ssu.cpp @@ -2,6 +2,7 @@ #include #include +#include #include static QString s_repo_regular( @@ -25,6 +26,9 @@ Ssu::Ssu(QObject *parent) : QDBusConnection::systemBus(), parent ) { + QDBusReply version = call(QStringLiteral("release"), false); + m_device_version = version; + qDebug() << "Device version:" << m_device_version; } void Ssu::loadRepos() { diff --git a/src/ssu.h b/src/ssu.h index d7adde1c..0ed878d0 100644 --- a/src/ssu.h +++ b/src/ssu.h @@ -16,6 +16,7 @@ class Ssu : public QDBusAbstractInterface bool repoAvailable() const { return m_manage_repo && !m_repo_name.isEmpty(); } bool repoTesting() const { return m_manage_repo && m_repo_testing; } QString repoName() const { return m_manage_repo ? m_repo_name : QString{}; } + QString deviceVersion() const {return m_device_version;} void loadRepos(); void setRepo(const QString &version=QString(), bool testing=false); @@ -30,6 +31,7 @@ class Ssu : public QDBusAbstractInterface bool m_manage_repo{false}; bool m_repo_testing{false}; QString m_repo_name; + QString m_device_version; QList< std::pair > m_repos; QString m_added_repo_name;