5#include "atticarequester_p.h"
7#include "commentsmodel.h"
10#include "tagsfilterchecker.h"
13#include <KLocalizedString>
15#include <QDomDocument>
16#include <knewstuffcore_debug.h>
18#include <attica/accountbalance.h>
19#include <attica/config.h>
20#include <attica/content.h>
21#include <attica/downloaditem.h>
22#include <attica/listjob.h>
23#include <attica/person.h>
24#include <attica/provider.h>
25#include <attica/providermanager.h>
27#include "atticaprovider_p.h"
28#include "searchrequest_p.h"
34Attica::Provider::SortMode atticaSortMode(KNSCore::SortMode sortMode)
37 case KNSCore::SortMode::Newest:
38 return Attica::Provider::Newest;
39 case KNSCore::SortMode::Alphabetical:
40 return Attica::Provider::Alphabetical;
41 case KNSCore::SortMode::Downloads:
42 return Attica::Provider::Downloads;
43 case KNSCore::SortMode::Rating:
44 return Attica::Provider::Rating;
46 qWarning() <<
"Unmapped sortMode" << sortMode;
47 return Attica::Provider::Rating;
57 , m_provider(provider)
61void AtticaRequester::detailsLoaded(
BaseJob *job)
63 if (m_provider->jobSuccess(job)) {
65 Content content = contentJob->result();
66 auto entry = entryFromAtticaContent(content);
68 Q_EMIT entryDetailsLoaded(entry);
69 qCDebug(KNEWSTUFFCORE) <<
"check update finished: " << entry.name();
72 if (m_updateJobs.remove(job) && m_updateJobs.isEmpty()) {
73 qCDebug(KNEWSTUFFCORE) <<
"check update finished.";
75 for (
const Entry &entry : std::as_const(m_provider->mCachedEntries)) {
76 if (entry.status() == KNSCore::Entry::Updateable) {
80 qDebug() <<
"UPDATABLE" << updatable;
81 Q_EMIT entriesLoaded(updatable);
86void AtticaRequester::checkForUpdates()
88 if (m_provider->mCachedEntries.isEmpty()) {
93 for (
const Entry &entry : std::as_const(m_provider->mCachedEntries)) {
94 ItemJob<Content> *job = m_provider->m_provider.requestContent(entry.uniqueId());
95 connect(job, &BaseJob::finished,
this, &AtticaRequester::detailsLoaded);
96 m_updateJobs.insert(job);
98 qCDebug(KNEWSTUFFCORE) <<
"Checking for update: " << entry.name();
102Entry::List AtticaRequester::installedEntries()
const
105 for (
const Entry &entry : std::as_const(m_provider->mCachedEntries)) {
106 if (entry.status() == KNSCore::Entry::Installed || entry.status() == KNSCore::Entry::Updateable) {
107 entries.append(entry);
113void AtticaRequester::start()
118void AtticaRequester::categoryContentsLoaded(
BaseJob *job)
120 if (!m_provider->jobSuccess(job)) {
125 const Content::List contents = listJob->itemList();
128 TagsFilterChecker checker(m_provider->tagFilter());
129 TagsFilterChecker downloadschecker(m_provider->downloadTagFilter());
130 for (
const Content &content : contents) {
131 if (!content.isValid()) {
132 qCDebug(KNEWSTUFFCORE)
133 <<
"Filtered out an invalid entry. This suggests something is not right on the originating server. Please contact the administrators of"
134 << m_provider->name() <<
"and inform them there is an issue with content in the category or categories" << m_request.d->categories;
137 if (checker.filterAccepts(content.tags())) {
138 bool filterAcceptsDownloads =
true;
139 if (content.downloads() > 0) {
140 filterAcceptsDownloads =
false;
143 if (downloadschecker.filterAccepts(dli.tags())) {
144 filterAcceptsDownloads =
true;
149 if (filterAcceptsDownloads) {
150 m_provider->mCachedContent.insert(content.id(), content);
151 entries.append(entryFromAtticaContent(content));
153 qCDebug(KNEWSTUFFCORE) <<
"Filter has excluded" << content.name() <<
"on download filter" << m_provider->downloadTagFilter();
156 qCDebug(KNEWSTUFFCORE) <<
"Filter has excluded" << content.name() <<
"on entry filter" << m_provider->tagFilter();
160 qCDebug(KNEWSTUFFCORE) <<
"loaded: " << m_request.d->hashForRequest() <<
" count: " << entries.size();
161 Q_EMIT entriesLoaded(entries);
162 Q_EMIT loadingDone();
165void AtticaRequester::startInternal()
167 switch (m_request.d->filter) {
168 case KNSCore::Filter::None:
170 case KNSCore::Filter::ExactEntryId: {
171 ItemJob<Content> *job = m_provider->m_provider.requestContent(m_request.d->searchTerm);
172 job->
setProperty(
"providedEntryId", m_request.d->searchTerm);
173 connect(job, &BaseJob::finished,
this, &AtticaRequester::detailsLoaded);
177 case KNSCore::Filter::Installed:
178 if (m_request.d->page == 0) {
179 Q_EMIT entriesLoaded(installedEntries());
180 Q_EMIT loadingDone();
182 Q_EMIT loadingDone();
185 case KNSCore::Filter::Updates:
190 Attica::Provider::SortMode sorting = atticaSortMode(m_request.d->sortMode);
191 Attica::Category::List categoriesToSearch;
193 if (m_request.d->categories.isEmpty()) {
195 categoriesToSearch = m_provider->mCategoryMap.values();
197 categoriesToSearch.reserve(m_request.d->categories.size());
198 for (
const QString &categoryName : std::as_const(m_request.d->categories)) {
199 categoriesToSearch.append(m_provider->mCategoryMap.values(categoryName));
204 m_provider->m_provider.searchContents(categoriesToSearch, m_request.d->searchTerm, sorting, m_request.d->page, m_request.d->pageSize);
206 connect(job, &BaseJob::finished,
this, &AtticaRequester::categoryContentsLoaded);
210Entry AtticaRequester::entryFromAtticaContent(
const Attica::Content &content)
214 entry.setProviderId(m_provider->id());
215 entry.setUniqueId(content.
id());
216 entry.setStatus(KNSCore::Entry::Downloadable);
217 entry.setVersion(content.version());
219 entry.setCategory(content.
attribute(QStringLiteral(
"typeid")));
221 qDebug() <<
"looking for cache entry";
222 auto index = m_provider->mCachedEntries.indexOf(entry);
223 qDebug() <<
"looking for cache entry" << index;
225 Entry &cacheEntry = m_provider->mCachedEntries[index];
226 qDebug() <<
"cache entry" << cacheEntry << cacheEntry.version() << entry.version();
228 if (((cacheEntry.status() == KNSCore::Entry::Installed) || (cacheEntry.status() == KNSCore::Entry::Updateable))
229 && ((cacheEntry.version() != entry.version()) || (cacheEntry.releaseDate() != entry.releaseDate()))) {
230 cacheEntry.setStatus(KNSCore::Entry::Updateable);
231 cacheEntry.setUpdateVersion(entry.version());
232 cacheEntry.setUpdateReleaseDate(entry.releaseDate());
236 m_provider->mCachedEntries.append(entry);
239 entry.setName(content.
name());
241 entry.setRating(content.
rating());
243 entry.setDownloadCount(content.
downloads());
244 entry.setNumberFans(content.
attribute(QStringLiteral(
"fans")).toInt());
245 entry.setDonationLink(content.
attribute(QStringLiteral(
"donationpage")));
246 entry.setKnowledgebaseLink(content.
attribute(QStringLiteral(
"knowledgebasepage")));
247 entry.setNumberKnowledgebaseEntries(content.
attribute(QStringLiteral(
"knowledgebaseentries")).toInt());
250 entry.setPreviewUrl(content.smallPreviewPicture(QStringLiteral(
"1")), Entry::PreviewSmall1);
251 entry.setPreviewUrl(content.smallPreviewPicture(QStringLiteral(
"2")), Entry::PreviewSmall2);
252 entry.setPreviewUrl(content.smallPreviewPicture(QStringLiteral(
"3")), Entry::PreviewSmall3);
254 entry.setPreviewUrl(content.previewPicture(QStringLiteral(
"1")), Entry::PreviewBig1);
255 entry.setPreviewUrl(content.previewPicture(QStringLiteral(
"2")), Entry::PreviewBig2);
256 entry.setPreviewUrl(content.previewPicture(QStringLiteral(
"3")), Entry::PreviewBig3);
258 entry.setLicense(content.license());
260 author.setId(content.author());
261 author.setName(content.author());
262 author.setHomepage(content.
attribute(QStringLiteral(
"profilepage")));
263 entry.setAuthor(author);
265 entry.setSource(Entry::Online);
267 entry.setShortSummary(content.
summary());
268 entry.setChangelog(content.changelog());
269 entry.setTags(content.
tags());
272 entry.d->mDownloadLinkInformationList.clear();
273 entry.d->mDownloadLinkInformationList.reserve(descs.
size());
275 entry.d->mDownloadLinkInformationList.append({.name = desc.name(),
276 .priceAmount = desc.priceAmount(),
277 .distributionType = desc.distributionType(),
278 .descriptionLink = desc.link(),
280 .isDownloadtypeLink = desc.type() == Attica::DownloadDescription::LinkDownload,
283 .version = desc.version()});
QString description() const
QList< DownloadDescription > downloadUrlDescriptions() const
QString attribute(const QString &key) const
int numberOfComments() const
QDateTime updated() const
void append(QList< T > &&value)
qsizetype size() const const
QVariant property(const char *name) const const
bool setProperty(const char *name, QVariant &&value)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QVariant fromValue(T &&value)
QString toString() const const