File indexing completed on 2024-05-05 05:29:12

0001 /*
0002  *   SPDX-FileCopyrightText: 2016 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "FeaturedModel.h"
0008 
0009 #include "discover_debug.h"
0010 #include <KConfigGroup>
0011 #include <KIO/StoredTransferJob>
0012 #include <KSharedConfig>
0013 #include <QDir>
0014 #include <QFile>
0015 #include <QJsonArray>
0016 #include <QJsonDocument>
0017 #include <QStandardPaths>
0018 #include <QtGlobal>
0019 
0020 #include <resources/ResourcesModel.h>
0021 #include <resources/StoredResultsStream.h>
0022 #include <utils.h>
0023 
0024 using namespace Qt::StringLiterals;
0025 
0026 Q_GLOBAL_STATIC(QString, featuredCache)
0027 
0028 static QString featuredFileName()
0029 {
0030     // kwriteconfig5 --file discoverrc --group Software --key FeaturedListingFileName featured-5.9.json
0031     KConfigGroup grp(KSharedConfig::openConfig(), u"Software"_s);
0032     if (grp.hasKey("FeaturedListingFileName")) {
0033         return grp.readEntry("FeaturedListingFileName", QString());
0034     }
0035     static const bool isMobile = QByteArrayList{"1", "true"}.contains(qgetenv("QT_QUICK_CONTROLS_MOBILE"));
0036     return isMobile ? QLatin1String("featured-mobile-5.9.json") : QLatin1String("featured-5.9.json");
0037 }
0038 
0039 FeaturedModel::FeaturedModel()
0040 {
0041     const QString dir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
0042     QDir().mkpath(dir);
0043 
0044     static const QString fileName = featuredFileName();
0045     *featuredCache = dir + QLatin1Char('/') + fileName;
0046     const QUrl featuredUrl(QStringLiteral("https://autoconfig.kde.org/discover/") + fileName);
0047     const bool shouldBlock = !QFileInfo::exists(*featuredCache);
0048     auto *fetchJob = KIO::storedGet(featuredUrl, KIO::NoReload, KIO::HideProgressInfo);
0049     if (shouldBlock) {
0050         acquireFetching(true);
0051     }
0052     connect(fetchJob, &KIO::StoredTransferJob::result, this, [this, fetchJob, shouldBlock]() {
0053         const auto dest = qScopeGuard([this, shouldBlock] {
0054             if (shouldBlock) {
0055                 acquireFetching(false);
0056             }
0057             refresh();
0058         });
0059         if (fetchJob->error() != 0)
0060             return;
0061 
0062         QFile f(*featuredCache);
0063         if (!f.open(QIODevice::WriteOnly))
0064             qCWarning(DISCOVER_LOG) << "could not open" << *featuredCache << f.errorString();
0065         f.write(fetchJob->data());
0066         f.close();
0067     });
0068     if (!shouldBlock) {
0069         refresh();
0070     }
0071 }
0072 
0073 void FeaturedModel::refresh()
0074 {
0075     // usually only useful if launching just fwupd or kns backends
0076     if (!currentApplicationBackend())
0077         return;
0078 
0079     acquireFetching(true);
0080     const auto dest = qScopeGuard([this] {
0081         acquireFetching(false);
0082     });
0083     QFile f(*featuredCache);
0084     if (!f.open(QIODevice::ReadOnly)) {
0085         qCWarning(DISCOVER_LOG) << "couldn't open file" << *featuredCache << f.errorString();
0086         return;
0087     }
0088     QJsonParseError error;
0089     const auto array = QJsonDocument::fromJson(f.readAll(), &error).array();
0090     if (error.error) {
0091         qCWarning(DISCOVER_LOG) << "couldn't parse" << *featuredCache << ". error:" << error.errorString();
0092         return;
0093     }
0094 
0095     const auto uris = kTransform<QVector<QUrl>>(array, [](const QJsonValue &uri) {
0096         return QUrl(uri.toString());
0097     });
0098     setUris(uris);
0099 }
0100 
0101 #include "FeaturedModel.moc"