25 #include <attica/providermanager.h>
26 #include <attica/provider.h>
27 #include <attica/listjob.h>
28 #include <attica/content.h>
29 #include <attica/downloaditem.h>
30 #include <attica/accountbalance.h>
31 #include <attica/person.h>
33 using namespace Attica;
43 foreach (
const QString& category, categories)
44 mCategoryMap.insert(category, Attica::Category());
46 connect(&m_providerManager, SIGNAL(providerAdded(Attica::Provider)), SLOT(providerLoaded(Attica::Provider)));
47 connect(&m_providerManager, SIGNAL(authenticationCredentialsMissing(
Provider)),
48 SLOT(authenticationCredentialsMissing(
Provider)));
56 foreach (
const QString& category, categories) {
57 mCategoryMap.insert(category, Attica::Category());
59 providerLoaded(provider);
64 return m_provider.baseUrl().toString();
67 void AtticaProvider::authenticationCredentialsMissing(
const KNS3::Provider& )
69 kDebug() <<
"Authentication missing!";
75 if (xmldata.tagName() !=
"provider")
79 QDomDocument doc(
"temp");
80 kDebug(550) <<
"setting provider xml" << doc.toString();
82 doc.appendChild(xmldata.cloneNode(
true));
83 m_providerManager.addProviderFromXml(doc.toString());
85 if (!m_providerManager.providers().isEmpty()) {
86 kDebug() <<
"base url of attica provider:" << m_providerManager.providers().last().baseUrl().toString();
88 kError() <<
"Could not load provider.";
96 mCachedEntries = cachedEntries;
99 void AtticaProvider::providerLoaded(
const Attica::Provider& provider)
101 mName = provider.name();
102 kDebug() <<
"Added provider: " << provider.name();
104 m_provider = provider;
106 Attica::ListJob<Attica::Category>* job = m_provider.requestCategories();
107 connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(listOfCategoriesLoaded(Attica::BaseJob*)));
111 void AtticaProvider::listOfCategoriesLoaded(Attica::BaseJob* listJob)
113 if (!jobSuccess(listJob))
return;
115 kDebug() <<
"loading categories: " << mCategoryMap.keys();
117 Attica::ListJob<Attica::Category>* job =
static_cast<Attica::ListJob<Attica::Category>*
>(listJob);
118 Category::List categoryList = job->itemList();
120 foreach(
const Category& category, categoryList) {
121 if (mCategoryMap.contains(category.name())) {
122 kDebug() <<
"Adding category: " << category.name();
123 mCategoryMap[category.name()] = category;
142 mCurrentRequest = request;
144 if (request.
page == 0) {
157 Attica::Provider::SortMode sorting = atticaSortMode(request.
sortMode);
158 Attica::Category::List categoriesToSearch;
162 categoriesToSearch = mCategoryMap.values();
165 categoriesToSearch.append(mCategoryMap.value(categoryName));
169 ListJob<Content>* job = m_provider.searchContents(categoriesToSearch, request.
searchTerm, sorting, request.
page, request.
pageSize);
170 connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(categoryContentsLoaded(Attica::BaseJob*)));
176 void AtticaProvider::checkForUpdates()
179 ItemJob<Content>* job = m_provider.requestContent(e.
uniqueId());
180 connect(job, SIGNAL(finished(Attica::BaseJob*)),
this, SLOT(detailsLoaded(Attica::BaseJob*)));
181 m_updateJobs.insert(job);
183 kDebug() <<
"Checking for update: " << e.
name();
189 ItemJob<Content>* job = m_provider.requestContent(entry.
uniqueId());
190 connect(job, SIGNAL(finished(Attica::BaseJob*)),
this, SLOT(detailsLoaded(Attica::BaseJob*)));
194 void AtticaProvider::detailsLoaded(BaseJob* job)
196 if (jobSuccess(job)) {
197 ItemJob<Content>* contentJob =
static_cast<ItemJob<Content>*
>(job);
198 Content content = contentJob->result();
201 kDebug() <<
"check update finished: " << entry.
name();
204 if (m_updateJobs.remove(job) && m_updateJobs.isEmpty()) {
205 kDebug() <<
"check update finished.";
207 foreach(
const EntryInternal& entry, mCachedEntries) {
209 updatable.append(entry);
216 void AtticaProvider::categoryContentsLoaded(BaseJob* job)
218 if (!jobSuccess(job))
return;
220 ListJob<Content>* listJob =
static_cast<ListJob<Content>*
>(job);
221 Content::List contents = listJob->itemList();
224 Q_FOREACH(
const Content &content, contents) {
225 mCachedContent.insert(content.id(), content);
226 entries.append(entryFromAtticaContent(content));
234 Attica::Provider::SortMode AtticaProvider::atticaSortMode(
const SortMode& sortMode)
237 return Attica::Provider::Newest;
240 return Attica::Provider::Alphabetical;
243 return Attica::Provider::Downloads;
245 return Attica::Provider::Rating;
250 Attica::Content content = mCachedContent.value(entry.
uniqueId());
251 DownloadDescription desc = content.downloadUrlDescription(linkId);
253 if (desc.hasPrice()) {
255 ItemJob<AccountBalance>* job = m_provider.requestAccountBalance();
256 connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(accountBalanceLoaded(Attica::BaseJob*)));
257 mDownloadLinkJobs[job] = qMakePair(entry, linkId);
260 kDebug() <<
"get account balance";
262 ItemJob<DownloadItem>* job = m_provider.downloadLink(entry.
uniqueId(), QString::number(linkId));
263 connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(downloadItemLoaded(Attica::BaseJob*)));
264 mDownloadLinkJobs[job] = qMakePair(entry, linkId);
271 void AtticaProvider::accountBalanceLoaded(Attica::BaseJob* baseJob)
273 if (!jobSuccess(baseJob))
return;
275 ItemJob<AccountBalance>* job =
static_cast<ItemJob<AccountBalance>*
>(baseJob);
276 AccountBalance item = job->result();
280 Content content = mCachedContent.value(entry.uniqueId());
281 if (content.downloadUrlDescription(pair.second).priceAmount() < item.balance()) {
282 kDebug() <<
"Your balance is greather than the price."
283 << content.downloadUrlDescription(pair.second).priceAmount() <<
" balance: " << item.balance();
285 i18nc(
"the price of a download item, parameter 1 is the currency, 2 is the price",
286 "This item costs %1 %2.\nDo you want to buy it?",
287 item.currency(), content.downloadUrlDescription(pair.second).priceAmount()
289 ItemJob<DownloadItem>* job = m_provider.downloadLink(entry.uniqueId(), QString::number(pair.second));
290 connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(downloadItemLoaded(Attica::BaseJob*)));
292 mDownloadLinkJobs[job] = qMakePair(entry, pair.second);
298 kDebug() <<
"You don't have enough money on your account!"
299 << content.downloadUrlDescription(0).priceAmount() <<
" balance: " << item.balance();
301 item.balance(),content.downloadUrlDescription(0).priceAmount()));
305 void AtticaProvider::downloadItemLoaded(BaseJob* baseJob)
307 if (!jobSuccess(baseJob))
return;
309 ItemJob<DownloadItem>* job =
static_cast<ItemJob<DownloadItem>*
>(baseJob);
310 DownloadItem item = job->result();
312 EntryInternal entry = mDownloadLinkJobs.take(job).first;
313 entry.setPayload(
QString(item.url().toString()));
320 foreach (
const EntryInternal& entry, mCachedEntries) {
322 entries.append(entry);
330 PostJob * job = m_provider.voteForContent(entry.
uniqueId(), rating);
331 connect(job, SIGNAL(finished(Attica::BaseJob*)),
this, SLOT(votingFinished(Attica::BaseJob*)));
336 void AtticaProvider::votingFinished(Attica::BaseJob* job)
338 if (!jobSuccess(job))
return;
344 PostJob * job = m_provider.becomeFan(entry.
uniqueId());
345 connect(job, SIGNAL(finished(Attica::BaseJob*)),
this, SLOT(becomeFanFinished(Attica::BaseJob*)));
350 void AtticaProvider::becomeFanFinished(Attica::BaseJob* job)
352 if (!jobSuccess(job))
return;
356 bool AtticaProvider::jobSuccess(Attica::BaseJob* job)
const
358 if (job->metadata().error() == Attica::Metadata::NoError) {
361 kDebug() <<
"job error: " << job->metadata().error() <<
" status code: " << job->metadata().statusCode() << job->metadata().message();
363 if (job->metadata().error() == Attica::Metadata::NetworkError) {
364 emit
signalError(
i18n(
"Network error. (%1)", job->metadata().statusCode()));
366 if (job->metadata().error() == Attica::Metadata::OcsError) {
367 if (job->metadata().statusCode() == 200) {
368 emit
signalError(
i18n(
"Too many requests to server. Please try again in a few minutes."));
370 emit
signalError(
i18n(
"Unknown Open Collaboration Service API error. (%1)", job->metadata().statusCode()));
376 EntryInternal AtticaProvider::entryFromAtticaContent(
const Attica::Content& content)
380 entry.setProviderId(
id());
381 entry.setUniqueId(content.id());
383 entry.setVersion(content.version());
384 entry.setReleaseDate(content.updated().date());
386 int index = mCachedEntries.indexOf(entry);
388 EntryInternal &cacheEntry = mCachedEntries[index];
391 ((cacheEntry.version() != entry.version()) || (cacheEntry.releaseDate() != entry.releaseDate()))) {
393 cacheEntry.setUpdateVersion(entry.version());
394 cacheEntry.setUpdateReleaseDate(entry.releaseDate());
398 mCachedEntries.append(entry);
401 entry.setName(content.name());
402 entry.setHomepage(content.detailpage());
403 entry.setRating(content.rating());
404 entry.setDownloadCount(content.downloads());
405 entry.setNumberFans(content.attribute(
"fans").toInt());
406 entry.setDonationLink(content.attribute(
"donationpage"));
407 entry.setKnowledgebaseLink(content.attribute(
"knowledgebasepage"));
408 entry.setNumberKnowledgebaseEntries(content.attribute(
"knowledgebaseentries").toInt());
418 entry.setLicense(content.license());
420 author.setName(content.author());
421 author.setHomepage(content.attribute(
"profilepage"));
422 entry.setAuthor(author);
425 entry.setSummary(content.description());
426 entry.setChangelog(content.changelog());
428 entry.clearDownloadLinkInformation();
430 foreach (Attica::DownloadDescription desc, descs) {
431 EntryInternal::DownloadLinkInformation info;
432 info.name = desc.name();
433 info.priceAmount = desc.priceAmount();
434 info.distributionType = desc.distributionType();
435 info.descriptionLink = desc.link();
437 info.isDownloadtypeLink = desc.isDownloadtypLink();
438 entry.appendDownloadLinkInformation(info);
447 #include "atticaprovider.moc"
KNewStuff Base Provider class.
QString i18n(const char *text)
QList< EntryInternal > List
KNewStuff data entry container.
QString name() const
Retrieve the name of the data object.
void signalInformation(const QString &) const
static void information(QWidget *parent, const QString &text, const QString &caption=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
virtual QString id() const
A unique Id for this provider (the url in most cases)
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
virtual bool isInitialized() const
virtual void loadEntries(const KNS3::Provider::SearchRequest &request)
load the given search and return given page
virtual bool setProviderXML(const QDomElement &xmldata)
set the provider data xml, to initialize the provider
virtual void loadEntryDetails(const KNS3::EntryInternal &entry)
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
QString i18nc(const char *ctxt, const char *text)
void payloadLinkLoaded(const KNS3::EntryInternal &)
used to keep track of a search
AtticaProvider(const QStringList &categories)
void providerInitialized(KNS3::Provider *)
virtual void loadPayloadLink(const EntryInternal &entry, int linkId)
static int questionYesNo(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const QString &dontAskAgainName=QString(), Options options=Notify)
void loadingFinished(const KNS3::Provider::SearchRequest &, const KNS3::EntryInternal::List &) const
virtual void setCachedEntries(const KNS3::EntryInternal::List &cachedEntries)
void signalError(const QString &) const
virtual void vote(const EntryInternal &entry, uint rating)
QString hashForRequest() const
void entryDetailsLoaded(const KNS3::EntryInternal &)
virtual void becomeFan(const EntryInternal &entry)