/* * SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL */ #include "KNSResource.h" #include "KNSBackend.h" #include #include #include #include #include #include #include "ReviewsBackend/Rating.h" #include #include #include KNSResource::KNSResource(const KNSCore::Entry &entry, QStringList categories, KNSBackend *parent) : AbstractResource(parent) , m_categories(std::move(categories)) , m_entry(entry) , m_lastStatus(entry.status()) { connect(this, &KNSResource::stateChanged, parent, &KNSBackend::updatesCountChanged); } KNSResource::~KNSResource() = default; AbstractResource::State KNSResource::state() { switch (m_entry.status()) { case KNSCore::Entry::Invalid: return Broken; case KNSCore::Entry::Downloadable: return None; case KNSCore::Entry::Installed: return Installed; case KNSCore::Entry::Updateable: return Upgradeable; case KNSCore::Entry::Deleted: case KNSCore::Entry::Installing: case KNSCore::Entry::Updating: return None; } return None; } KNSBackend *KNSResource::knsBackend() const { return qobject_cast(parent()); } QVariant KNSResource::icon() const { const QString thumbnail = m_entry.previewUrl(KNSCore::Entry::PreviewSmall1); return thumbnail.isEmpty() ? knsBackend()->iconName() : m_entry.previewUrl(KNSCore::Entry::PreviewSmall1); } QString KNSResource::comment() { QString ret = m_entry.shortSummary(); if (ret.isEmpty()) { ret = m_entry.summary(); int newLine = ret.indexOf(QLatin1Char('\n')); if (newLine > 0) { ret.truncate(newLine); } ret.remove(QRegularExpression(QStringLiteral("\\[\\/?[a-z]*\\]"))); ret.remove(QRegularExpression(QStringLiteral("<[^>]*>"))); } return ret; } QString KNSResource::longDescription() { QString ret = m_entry.summary(); if (m_entry.shortSummary().isEmpty()) { const int newLine = ret.indexOf(QLatin1Char('\n')); if (newLine < 0) ret.clear(); else ret = ret.mid(newLine + 1).trimmed(); } ret.remove(QLatin1Char('\r')); ret.replace(QStringLiteral("[li]"), QStringLiteral("\n* ")); // Get rid of all BBCode markup we don't handle above ret.remove(QRegularExpression(QStringLiteral("\\[\\/?[a-z]*\\]"))); // Find anything that looks like a link (but which also is not some html // tag value or another already) and make it a link static const QRegularExpression urlRegExp( QStringLiteral("(^|\\s)(http[-a-zA-Z0-9@:%_\\+.~#?&//=]{2,256}\\.[a-z]{2,4}\\b(\\/[-a-zA-Z0-9@:;%_\\+.~#?&//=]*)?)"), QRegularExpression::CaseInsensitiveOption); ret.replace(urlRegExp, QStringLiteral("\\2")); return ret; } QString KNSResource::name() const { return m_entry.name(); } QString KNSResource::packageName() const { return m_entry.uniqueId(); } bool KNSResource::hasCategory(const QString &category) const { return m_categories.contains(category); } QUrl KNSResource::homepage() { return m_entry.homepage(); } void KNSResource::setEntry(const KNSCore::Entry &entry) { const bool diff = entry.status() != m_lastStatus; m_entry = entry; if (diff) { m_lastStatus = entry.status(); Q_EMIT stateChanged(); } } KNSCore::Entry KNSResource::entry() const { return m_entry; } QJsonArray KNSResource::licenses() { return {{AppStreamUtils::license(m_entry.license())}}; } quint64 KNSResource::size() { const auto downloadInfo = m_entry.downloadLinkInformationList(); return downloadInfo.isEmpty() ? 0 : downloadInfo.at(0).size * 1024; } QString KNSResource::installedVersion() const { return !m_entry.version().isEmpty() ? m_entry.version() : m_entry.releaseDate().toString(); } QString KNSResource::availableVersion() const { return !m_entry.updateVersion().isEmpty() ? m_entry.updateVersion() : !m_entry.updateReleaseDate().isNull() ? m_entry.updateReleaseDate().toString() : !m_entry.version().isEmpty() ? m_entry.version() : releaseDate().toString(); } QString KNSResource::origin() const { return m_entry.providerId(); } QString KNSResource::displayOrigin() const { if (auto providers = knsBackend()->engine()->atticaProviders(); !providers.isEmpty()) { auto provider = providers.constFirst(); if (provider->name() == QLatin1String("api.kde-look.org")) { return i18nc("The name of the KDE Store", "KDE Store"); } return providers.constFirst()->name(); } return QUrl(m_entry.providerId()).host(); } QString KNSResource::section() { return m_entry.category(); } static bool isAnimated(const QString &path) { static const QVector s_extensions = {QLatin1String(".gif"), QLatin1String(".apng"), QLatin1String(".webp"), QLatin1String(".avif")}; return kContains(s_extensions, [path](const QLatin1String &postfix) { return path.endsWith(postfix); }); } static void appendIfValid(Screenshots &list, const QUrl &thumbnail, const QUrl &screenshot) { if (thumbnail.isEmpty() || screenshot.isEmpty()) { return; } list += {thumbnail, screenshot, isAnimated(thumbnail.path())}; } void KNSResource::fetchScreenshots() { Screenshots ret; appendIfValid(ret, QUrl(m_entry.previewUrl(KNSCore::Entry::PreviewSmall1)), QUrl(m_entry.previewUrl(KNSCore::Entry::PreviewBig1))); appendIfValid(ret, QUrl(m_entry.previewUrl(KNSCore::Entry::PreviewSmall2)), QUrl(m_entry.previewUrl(KNSCore::Entry::PreviewBig2))); appendIfValid(ret, QUrl(m_entry.previewUrl(KNSCore::Entry::PreviewSmall3)), QUrl(m_entry.previewUrl(KNSCore::Entry::PreviewBig3))); Q_EMIT screenshotsFetched(ret); } void KNSResource::fetchChangelog() { Q_EMIT changelogFetched(m_entry.changelog()); } QStringList KNSResource::extends() const { return knsBackend()->extends(); } QUrl KNSResource::url() const { return QUrl(QStringLiteral("kns://") + knsBackend()->name() + QLatin1Char('/') + m_entry.uniqueId()); } bool KNSResource::canExecute() const { return knsBackend()->engine()->hasAdoptionCommand(); } void KNSResource::invokeApplication() const { KNSCore::Transaction::adopt(knsBackend()->engine(), m_entry); } QString KNSResource::executeLabel() const { return knsBackend()->engine()->useLabel(); } QDate KNSResource::releaseDate() const { return m_entry.updateReleaseDate().isNull() ? m_entry.releaseDate() : m_entry.updateReleaseDate(); } QVector KNSResource::linkIds() const { QVector ids; const auto linkInfo = m_entry.downloadLinkInformationList(); for (const auto &e : linkInfo) { if (e.isDownloadtypeLink) ids << e.id; } return ids; } QUrl KNSResource::donationURL() { return QUrl(m_entry.donationLink()); } Rating KNSResource::rating() const { if (!m_rating.has_value()) { const int noc = m_entry.numberOfComments(); const int rating = m_entry.rating(); Q_ASSERT(rating <= 100); m_rating = Rating(packageName(), noc, rating / 10); } return m_rating.value(); } QString KNSResource::author() const { return m_entry.author().name(); } #include "moc_KNSResource.cpp"