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"
33Attica::Provider::SortMode atticaSortMode(KNSCore::Provider::SortMode sortMode)
36 case KNSCore::Provider::SortMode::Newest:
37 return Attica::Provider::Newest;
38 case KNSCore::Provider::SortMode::Alphabetical:
39 return Attica::Provider::Alphabetical;
40 case KNSCore::Provider::SortMode::Downloads:
41 return Attica::Provider::Downloads;
42 case KNSCore::Provider::SortMode::Rating:
43 return Attica::Provider::Rating;
45 qWarning() <<
"Unmapped sortMode" << sortMode;
46 return Attica::Provider::Rating;
56 , m_provider(provider)
60void AtticaRequester::detailsLoaded(
BaseJob *job)
62 if (m_provider->jobSuccess(job)) {
64 Content content = contentJob->result();
65 auto entry = entryFromAtticaContent(content);
67 Q_EMIT entryDetailsLoaded(entry);
68 qCDebug(KNEWSTUFFCORE) <<
"check update finished: " << entry.name();
71 if (m_updateJobs.remove(job) && m_updateJobs.isEmpty()) {
72 qCDebug(KNEWSTUFFCORE) <<
"check update finished.";
74 for (
const Entry &entry : std::as_const(m_provider->mCachedEntries)) {
75 if (entry.status() == KNSCore::Entry::Updateable) {
79 qDebug() <<
"UPDATABLE" << updatable;
80 Q_EMIT loadingFinished(updatable);
84void AtticaRequester::checkForUpdates()
86 if (m_provider->mCachedEntries.isEmpty()) {
87 Q_EMIT loadingFinished({});
91 for (
const Entry &entry : std::as_const(m_provider->mCachedEntries)) {
92 ItemJob<Content> *job = m_provider->m_provider.requestContent(entry.uniqueId());
93 connect(job, &BaseJob::finished,
this, &AtticaRequester::detailsLoaded);
94 m_updateJobs.insert(job);
96 qCDebug(KNEWSTUFFCORE) <<
"Checking for update: " << entry.name();
100Entry::List AtticaRequester::installedEntries()
const
103 for (
const Entry &entry : std::as_const(m_provider->mCachedEntries)) {
104 if (entry.status() == KNSCore::Entry::Installed || entry.status() == KNSCore::Entry::Updateable) {
105 entries.append(entry);
111void AtticaRequester::start()
116void AtticaRequester::categoryContentsLoaded(
BaseJob *job)
118 if (!m_provider->jobSuccess(job)) {
123 const Content::List contents = listJob->itemList();
126 TagsFilterChecker checker(m_provider->tagFilter());
127 TagsFilterChecker downloadschecker(m_provider->downloadTagFilter());
128 for (
const Content &content : contents) {
129 if (!content.isValid()) {
130 qCDebug(KNEWSTUFFCORE)
131 <<
"Filtered out an invalid entry. This suggests something is not right on the originating server. Please contact the administrators of"
132 << m_provider->name() <<
"and inform them there is an issue with content in the category or categories" << m_request.categories;
135 if (checker.filterAccepts(content.tags())) {
136 bool filterAcceptsDownloads =
true;
137 if (content.downloads() > 0) {
138 filterAcceptsDownloads =
false;
141 if (downloadschecker.filterAccepts(dli.tags())) {
142 filterAcceptsDownloads =
true;
147 if (filterAcceptsDownloads) {
148 m_provider->mCachedContent.insert(content.id(), content);
149 entries.append(entryFromAtticaContent(content));
151 qCDebug(KNEWSTUFFCORE) <<
"Filter has excluded" << content.name() <<
"on download filter" << m_provider->downloadTagFilter();
154 qCDebug(KNEWSTUFFCORE) <<
"Filter has excluded" << content.name() <<
"on entry filter" << m_provider->tagFilter();
158 qCDebug(KNEWSTUFFCORE) <<
"loaded: " << m_request.hashForRequest() <<
" count: " << entries.size();
159 Q_EMIT loadingFinished(entries);
162void AtticaRequester::startInternal()
164 switch (m_request.filter) {
165 case KNSCore::Provider::None:
167 case KNSCore::Provider::ExactEntryId: {
168 ItemJob<Content> *job = m_provider->m_provider.requestContent(m_request.searchTerm);
169 job->
setProperty(
"providedEntryId", m_request.searchTerm);
170 connect(job, &BaseJob::finished,
this, &AtticaRequester::detailsLoaded);
174 case KNSCore::Provider::Installed:
175 if (m_request.page == 0) {
176 Q_EMIT loadingFinished(installedEntries());
178 Q_EMIT loadingFinished({});
181 case KNSCore::Provider::Updates:
186 Attica::Provider::SortMode sorting = atticaSortMode(m_request.sortMode);
187 Attica::Category::List categoriesToSearch;
189 if (m_request.categories.isEmpty()) {
191 categoriesToSearch = m_provider->mCategoryMap.values();
193 categoriesToSearch.reserve(m_request.categories.size());
194 for (
const QString &categoryName : std::as_const(m_request.categories)) {
195 categoriesToSearch.append(m_provider->mCategoryMap.values(categoryName));
199 ListJob<Content> *job = m_provider->m_provider.searchContents(categoriesToSearch, m_request.searchTerm, sorting, m_request.page, m_request.pageSize);
201 connect(job, &BaseJob::finished,
this, &AtticaRequester::categoryContentsLoaded);
205Entry AtticaRequester::entryFromAtticaContent(
const Attica::Content &content)
209 entry.setProviderId(m_provider->id());
210 entry.setUniqueId(content.
id());
211 entry.setStatus(KNSCore::Entry::Downloadable);
212 entry.setVersion(content.version());
214 entry.setCategory(content.
attribute(QStringLiteral(
"typeid")));
216 qDebug() <<
"looking for cache entry";
217 auto index = m_provider->mCachedEntries.indexOf(entry);
218 qDebug() <<
"looking for cache entry" << index;
220 Entry &cacheEntry = m_provider->mCachedEntries[index];
221 qDebug() <<
"cache entry" << cacheEntry << cacheEntry.version() << entry.version();
223 if (((cacheEntry.status() == KNSCore::Entry::Installed) || (cacheEntry.status() == KNSCore::Entry::Updateable))
224 && ((cacheEntry.version() != entry.version()) || (cacheEntry.releaseDate() != entry.releaseDate()))) {
225 cacheEntry.setStatus(KNSCore::Entry::Updateable);
226 cacheEntry.setUpdateVersion(entry.version());
227 cacheEntry.setUpdateReleaseDate(entry.releaseDate());
231 m_provider->mCachedEntries.append(entry);
234 entry.setName(content.
name());
236 entry.setRating(content.
rating());
238 entry.setDownloadCount(content.
downloads());
239 entry.setNumberFans(content.
attribute(QStringLiteral(
"fans")).toInt());
240 entry.setDonationLink(content.
attribute(QStringLiteral(
"donationpage")));
241 entry.setKnowledgebaseLink(content.
attribute(QStringLiteral(
"knowledgebasepage")));
242 entry.setNumberKnowledgebaseEntries(content.
attribute(QStringLiteral(
"knowledgebaseentries")).toInt());
245 entry.setPreviewUrl(content.smallPreviewPicture(QStringLiteral(
"1")), Entry::PreviewSmall1);
246 entry.setPreviewUrl(content.smallPreviewPicture(QStringLiteral(
"2")), Entry::PreviewSmall2);
247 entry.setPreviewUrl(content.smallPreviewPicture(QStringLiteral(
"3")), Entry::PreviewSmall3);
249 entry.setPreviewUrl(content.previewPicture(QStringLiteral(
"1")), Entry::PreviewBig1);
250 entry.setPreviewUrl(content.previewPicture(QStringLiteral(
"2")), Entry::PreviewBig2);
251 entry.setPreviewUrl(content.previewPicture(QStringLiteral(
"3")), Entry::PreviewBig3);
253 entry.setLicense(content.license());
255 author.setId(content.author());
256 author.setName(content.author());
257 author.setHomepage(content.
attribute(QStringLiteral(
"profilepage")));
258 entry.setAuthor(author);
260 entry.setSource(Entry::Online);
262 entry.setShortSummary(content.
summary());
263 entry.setChangelog(content.changelog());
264 entry.setTags(content.
tags());
267 entry.d->mDownloadLinkInformationList.clear();
268 entry.d->mDownloadLinkInformationList.reserve(descs.
size());
270 entry.d->mDownloadLinkInformationList.append({.name = desc.name(),
271 .priceAmount = desc.priceAmount(),
272 .distributionType = desc.distributionType(),
273 .descriptionLink = desc.link(),
275 .isDownloadtypeLink = desc.type() == Attica::DownloadDescription::LinkDownload,
278 .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
used to keep track of a search