Use of gcsDebug instead of qDebug
[meego-garage:garage-client-services.git] / src / application.cpp
1 #include "application.h"
2 #include "garageclientservices.h"
3 #include "image.h"
4 #include <QtAlgorithms>
5 #include <QtDebug>
6 #include <QDateTime>
7 #include <QStringList>
8 #include <libxml/tree.h>
9 #include <QPackageKit>
10 #include "garagesettings.h"
11 #include "catalog.h"
12
13 using namespace MeeGoGarage;
14
15 #ifndef HAVE_NO_PACKAGEKIT
16 using namespace PackageKit;
17 #endif
18
19 Application::Application (Catalog *catalog, Category *category, QObject *parent) :
20     QObject(parent),
21     m_catalog(catalog),
22     m_category(category),
23     m_size(0),
24     m_cachedStatus(UnknownStatus),
25     m_lastUpdateStatus(QDateTime::currentDateTime().toUTC()),
26     m_downloads(0),
27     m_userRating(0),
28     m_averageRating(0.0f),
29     m_ratingCount(0),
30     m_reviewsRready(false)
31 {
32     m_applicationIcon[SmallIcon] = 0;
33     m_applicationIcon[MediumIcon] = 0;
34     m_applicationIcon[LargeIcon] = 0;
35 }
36
37 QString Application::name () const
38 {
39     return m_applicationName;
40 }
41
42 #ifndef HAVE_NO_PACKAGEKIT
43 QSharedPointer<PackageKit::Package> Application::package () const
44 {
45     return m_package;
46 }
47
48 QSharedPointer<PackageKit::Package> Application::packageToUpdate () const
49 {
50     return m_packageToUpdate;
51 }
52 #endif
53
54 QString Application::packageName () const
55 {
56     return m_packageName;
57 }
58
59 QString Application::execFilename () const
60 {
61     return m_execFilename;
62 }
63
64 void Application::setName (const QString& name)
65 {
66     m_applicationName = name;
67 }
68
69 void Application::setCategoryName (const QString& name)
70 {
71     m_categoryName = name;
72 }
73
74 QString Application::categoryName () const
75 {
76     return m_categoryName;
77 }
78
79 void Application::setPackageName (const QString& name)
80 {
81     m_packageName = name;
82 }
83
84 void Application::setExecFilename (const QString& execString)
85 {
86     m_execFilename = execString;
87 }
88
89 void Application::setDescription (const QString& desp)
90 {
91     m_description = desp;
92 }
93
94 QString Application::description() const
95 {
96     return m_description;
97 }
98
99 void Application::setLongDescription (const QString& longdesc)
100 {
101     m_longDescription = longdesc;
102 }
103
104 QString Application::longDescription() const
105 {
106     return m_longDescription;
107 }
108
109 Image *Application::iconImage (IconType type) const
110 {
111     if (m_applicationIcon[type]) {
112         m_applicationIcon[type]->requestContent();
113     }
114     return m_applicationIcon[type];
115 }
116
117 QList<Image *> Application::screenshotList() const
118 {
119     return m_screenshotList;
120 }
121
122 QList<QUrl> Application::videoUrlList() const
123 {
124     return m_videoUrlList;
125 }
126
127 QString Application::changelog() const
128 {
129     return m_changelog;
130 }
131
132 QString Application::releaseNotes() const
133 {
134     return m_releaseNotes;
135 }
136
137 QString Application::publisher() const
138 {
139     return m_publisher;
140 }
141
142 QString Application::publisherURL() const
143 {
144     return m_publisherURL;
145 }
146
147 QString Application::supportURL() const
148 {
149     return m_supportURL;
150 }
151
152 QDateTime Application::createdDate() const
153 {
154     return m_createdDate;
155 }
156
157 QDateTime Application::publishDate() const
158 {
159     return m_publishDate;
160 }
161
162 QString Application::version() const
163 {
164     return m_version;
165 }
166
167 void Application::setVersion(const QString& ver)
168 {
169     m_version = ver;
170 }
171
172 QString Application::installedVersion() const
173 {
174     return m_installedVersion;
175 }
176
177 void Application::setInstalledVersion(const QString& ver)
178 {
179     m_installedVersion = ver;
180 }
181
182 QString Application::versionToUpdate() const
183 {
184     return m_versionToUpdate;
185 }
186
187 void Application::setVersionToUpdate(const QString& ver)
188 {
189     m_versionToUpdate = ver;
190 }
191
192 uint64_t Application::size() const
193 {
194     return m_size;
195 }
196
197 QString Application::eula() const
198 {
199     return m_eula;
200 }
201
202 QString Application::id() const
203 {
204     return m_applicationId;
205 }
206
207 void Application::setId(const QString &id)
208 {
209     m_applicationId = id;
210 }
211
212 bool Application::applicationNameLessThan(Application* &a1, Application* &a2)
213 {
214     return a1->name() < a2->name();
215 }
216
217 bool Application::applicationDateLessThan(Application* &a1, Application* &a2)
218 {
219     return a1->publishDate() > a2->publishDate();
220 }
221
222 bool Application::applicationRatingLessThan(Application* &a1, Application* &a2)
223 {
224     return a1->averageRating() > a2->averageRating();
225 }
226
227 /*
228 bool Application::applicationSizeLessThan(Application* &a1, Application* &a2)
229 {
230     return a1->size() < a2->size();
231 }*/
232
233 bool Application::applicationDownloadLessThan(Application* &a1, Application* &a2)
234 {
235     return a1->size() < a2->size();
236 }
237
238 ApplicationList Application::sortApplications(ApplicationList list, MeeGoGarage::ApplicationListSortType sortType)
239 {
240     ApplicationList resultList = list;
241
242     switch(sortType) {
243     case SortByName:
244         qSort(resultList.begin(), resultList.end(), applicationNameLessThan);
245         break;
246     case SortByDate:
247         qSort(resultList.begin(), resultList.end(), applicationDateLessThan);
248         break;
249     case SortByRating:
250         qSort(resultList.begin(), resultList.end(), applicationRatingLessThan);
251         break;
252     //case SortBySize:
253     //    qSort(resultList.begin(), resultList.end(), applicationSizeLessThan);
254         break;
255     case SortByDownloads:
256         qSort(resultList.begin(), resultList.end(), applicationDownloadLessThan);
257         break;
258     case LastSort:
259         Q_ASSERT(false);
260         break;
261     }
262
263     return resultList;
264 }
265
266 #if 0
267 static bool matchKeywordInApplication (const QString& keyword, const Application* application, 
268                                         MeeGoGarage::SearchType type)
269 {
270     QString text = application->name();
271     if (text.contains(keyword, Qt::CaseInsensitive))
272         return true;
273
274     if (type == MeeGoGarage::SearchByName)
275         return false;
276
277     text = application->description();
278     if (text.contains(keyword, Qt::CaseInsensitive))
279         return true;
280
281     if (type == MeeGoGarage::SearchNameAndDescription)
282         return false;
283
284     text = application->categoryName();
285     if (text.contains(keyword, Qt::CaseInsensitive))
286         return true;
287
288     text = application->longDescription();
289     if (text.contains(keyword, Qt::CaseInsensitive))
290         return true;
291
292     text = application->packageName();
293     if (text.contains(keyword, Qt::CaseInsensitive))
294         return true;
295
296     text = application->publisher();
297     if (text.contains(keyword, Qt::CaseInsensitive))
298         return true;
299
300     text = application->releaseNotes();
301     if (text.contains(keyword, Qt::CaseInsensitive))
302         return true;
303
304     return false;
305 }
306
307 ApplicationList Application::searchApplications (QStringList keywordList, ApplicationList srcList,
308                                         MeeGoGarage::SearchType type, MeeGoGarage::SearchMode mode)
309 {
310     ApplicationList list;
311
312     ApplicationList::iterator i;
313     for (i = srcList.begin(); i != srcList.end(); i++) {
314         QList<QString>::iterator j;
315
316         if (mode == MeeGoGarage::SearchAnd) {
317             bool isMatch = true;
318             for (j = keywordList.begin(); j != keywordList.end(); j++) {
319                 if (!matchKeywordInApplication((*j), (*i), type)) {
320                     isMatch = false;
321                     break;
322                 }
323             }
324
325             if (isMatch)
326                 list.append(*i);
327         } else if (mode == MeeGoGarage::SearchOr) {
328             bool isMatch = false;
329             for (j = keywordList.begin(); j != keywordList.end(); j++) {
330                 if (matchKeywordInApplication((*j), (*i), type)) {
331                     isMatch = true;
332                     break;
333                 }
334             }
335
336             if (isMatch)
337                 list.append(*i);
338         } else {
339         }
340     } 
341
342     return list;
343 }
344 #endif
345
346 Application *Application::getApplicationByPackageName(ApplicationList applicationList,  QString str)
347 {
348     // Get all packagenames
349     ApplicationList::const_iterator i;
350     for (i = applicationList.constBegin(); i != applicationList.constEnd(); i++) {
351         Application* application = *i;
352         if (str.contains( application->packageName() )) {
353             return application;
354         }
355     }
356
357     // application not found
358     return 0;
359 }
360
361 void Application::dumpApplication()
362 {
363     qDebug() << "Dump Application: " << m_applicationName;
364 #if 0
365     qDebug() << "       Name: " << m_applicationName;
366     qDebug() << "         ID: " << m_applicationID;
367     qDebug() << "    Package: " << m_packageName;
368     qDebug() << "Description: " << m_description;
369     qDebug() << "       Icon: ";
370     qDebug() << "           Small: " << m_applicationIcon[SmallIcon]->m_imageUrl;
371     qDebug() << "          Medium: " << m_applicationIcon[MediumIcon]->m_imageUrl;
372     qDebug() << "           Large: " << m_applicationIcon[LargeIcon]->m_imageUrl;
373 #endif
374 }
375
376 Application::Status Application::status() const
377 {
378     return m_cachedStatus;
379 }
380
381 void Application::setStatus(Application::Status status)
382 {
383     qDebug() << "Updated status " << name() << " to " << toStatusString(status);
384
385     m_cachedStatus = status;
386     m_lastUpdateStatus = QDateTime::currentDateTime().toUTC();
387
388     emit statusUpdated(m_cachedStatus, false);
389 }
390
391 #ifndef HAVE_NO_PACKAGEKIT
392 Application::Status Application::toStatus(
393         int /*PackageKit::Enum::Info*/ info,
394         Application::Status previousStatus)
395 {
396     Application::Status cachedStatus = previousStatus;
397
398     switch(info) {
399     case Enum::InfoInstalled:
400     case Enum::InfoCollectionInstalled:
401         cachedStatus = InstalledStatus;
402         break;
403     case Enum::InfoAvailable:
404     case Enum::InfoCollectionAvailable:
405         cachedStatus = NotInstalledStatus;
406         break;
407     case Enum::InfoLow:
408     case Enum::InfoEnhancement:
409     case Enum::InfoNormal:
410     case Enum::InfoBugfix:
411     case Enum::InfoImportant:
412     case Enum::InfoSecurity:
413         cachedStatus = UpdateAvailableStatus;
414         break;
415     case Enum::InfoUpdating:
416     case Enum::InfoDowngrading:
417         cachedStatus = UpdatingStatus;
418         break;
419     case Enum::InfoInstalling:
420     case Enum::InfoReinstalling:
421         cachedStatus = InstallingStatus;
422         break;
423     case Enum::InfoRemoving:
424         cachedStatus = RemovingStatus;
425         break;
426     case Enum::UnknownInfo:
427         cachedStatus = UnknownStatus;
428         break;
429     // the following satus are intermediate states and can be shared with different actions.
430     // So better to just keep the last known satus
431     case Enum::InfoFinished:
432     case Enum::InfoDownloading:
433     case Enum::InfoPreparing:
434     case Enum::InfoDecompressing:
435     case Enum::InfoBlocked:
436     case Enum::InfoCleanup:
437     case Enum::InfoObsoleting:
438         break;
439     case Enum::LastInfo:
440         Q_ASSERT(false);
441         break;
442     };
443
444     return cachedStatus;
445 }
446
447 void Application::setPackage(QSharedPointer<PackageKit::Package> package)
448 {
449     m_package = package;
450 }
451
452 void Application::setPackageToUpdate(QSharedPointer<PackageKit::Package> package)
453 {
454     m_packageToUpdate = package;
455 }
456 #endif
457
458 QString Application::toStatusString(Application::Status status)
459 {
460     QString str = tr("Unknown");
461
462     switch(status) {
463     case Application::ResolvingStatus:
464         str = tr("Resolving ...");
465         break;
466     case Application::InstalledStatus:
467         str = tr("Installed");
468         break;
469     case Application::NotInstalledStatus:
470         str = tr("Not Installed");
471         break;
472     case Application::UpdateAvailableStatus:
473         str = tr("Update Available");
474         break;
475     case Application::InstallingStatus:
476         str = tr("Installing ...");
477         break;
478     case Application::RemovingStatus:
479         str = tr("Removing ...");
480         break;
481     case Application::UpdatingStatus:
482         str = tr("Updating ...");
483         break;
484     case Application::UnknownStatus:
485         str = tr("Unknown");
486         break;
487     case Application::ResolveErrorStatus:
488         str = tr("Error");
489         break;
490     case Application::ErrorStatus:
491         str = tr("Error");
492         break;
493     case Application::QueuedInstallStatus:
494         //str = tr("Queued to Install");
495         str = tr("Installing ...");
496         break;
497     case Application::QueuedRemoveStatus:
498         //str = tr("Queued to Remove");
499         str = tr("Removing ...");
500         break;
501     case Application::QueuedUpdateStatus:
502         //str = tr("Queued to Update");
503         str = tr("Updating ...");
504         break;
505     case Application::QueuedResolveStatus:
506         //str = tr("Queued to Resolve");
507         str = tr("Resolving ...");
508         break;
509     }
510
511     return str;
512 }
513
514 void Application::onProgressUpdated()
515 {
516     emit progressUpdated();
517 }
518
519 void Application::onTransactionError(ApplicationManager::ActionType actionType, const QString& errorStr)
520 {
521 #ifndef HAVE_NO_PACKAGEKIT
522     if (actionType == ApplicationManager::ResolveAction || !m_package) {
523         setStatus(Application::ResolveErrorStatus);
524     } else {
525         // set the same status we had before
526         setStatus(toStatus(m_package->info(),status()));
527     }
528
529     emit transactionError(actionType, errorStr);
530 #endif
531 }
532
533 void Application::onTransactionFinished(ApplicationManager::ActionType actionType, bool success)
534 {
535 #ifndef HAVE_NO_PACKAGEKIT
536     if (success) {
537         switch(actionType) {
538         case ApplicationManager::ResolveAction:
539             if (!m_package) {
540                 qDebug() << "Forced status ResolveErrorStatus for " << name();
541                 setStatus(ResolveErrorStatus);
542             }
543             // in this case, the state is set when package resolved
544             //setStatus(toStatus(p->info()));
545             break;
546         case ApplicationManager::InstallAction:
547         case ApplicationManager::UpdateAction:
548             setStatus(InstalledStatus);
549             break;
550         case ApplicationManager::RemoveAction:
551             setStatus(NotInstalledStatus);
552             break;
553         case ApplicationManager::NoAction:
554         //case ApplicationManager::ErrorResolve:
555             Q_ASSERT(false);
556             break;
557         case ApplicationManager::RefreshCacheAction:
558         case ApplicationManager::GetUpdatesAction:
559             // do nothing
560             break;
561         }
562     } else if (status() != ResolveErrorStatus) {
563         if (m_package) {
564             setStatus(toStatus(m_package->info(), status()));
565         } else {
566             setStatus(UnknownStatus);
567         }
568     }
569
570     emit transactionFinished(actionType, success);
571 #endif
572 }
573
574 QDateTime Application::getLastUpdateStatusDateTime() const
575 {
576     return m_lastUpdateStatus;
577 }
578
579 bool Application::updateStatus(Application::Status status, QDateTime dateTime)
580 {
581     if (dateTime > m_lastUpdateStatus ||
582         status == Application::UnknownStatus) {
583         m_cachedStatus = status;
584         m_lastUpdateStatus = dateTime;
585
586         emit statusUpdated(m_cachedStatus, true);
587
588         return true;
589     }
590
591     return false;
592 }
593
594 bool Application::setUserRating(int rating)
595 {
596     m_userRating = rating;
597     return true;
598 }
599
600 int Application::userRating() const
601 {
602     return m_userRating;
603 }
604
605 float Application::averageRating() const
606 {
607     return m_averageRating;
608 }
609
610 int Application::ratingCount() const
611 {
612     return m_ratingCount;
613 }
614
615 bool Application::canRate() const
616 {
617     return (status() == InstalledStatus ||
618             status() == UpdateAvailableStatus);
619 }
620
621 void Application::addReview(Review review)
622 {
623     m_reviews.append(review);
624 }
625
626 bool Application::reviewsReady() const
627 {
628     return m_reviewsRready;
629 }
630
631 ReviewList Application::reviews() const
632 {
633     return m_reviews;
634 }
635
636 int Application::reviewCount() const
637 {
638     return m_reviews.count();
639 }
640
641 bool Application::canReview() const
642 {
643     return (status() == InstalledStatus ||
644             status() == UpdateAvailableStatus);
645 }
646
647 uint Application::downloads() const
648 {
649     return m_downloads;
650 }