Added more debug info
[meego-garage:opensuse-appstore-garage-client-services.git] / src / applicationmanager.cpp
1 #include "applicationmanager.h"
2 #include "application.h"
3 #include "catalog.h"
4 #include "applicationstatusstorage.h"
5 #include "garagesettings.h"
6 #include "garageclientservices.h"
7 #include "utils.h"
8
9 #ifndef HAVE_NO_PACKAGEKIT
10 #include <QPackageKit>
11 #endif
12 #include <QMutableListIterator>
13 #include <QDir>
14 #include <QFile>
15 #include <QtDebug>
16
17 using namespace MeeGoGarage;
18
19 Application::Status mapActionToQueuedStatus(ApplicationManager::ActionType actionType);
20 Application::Status mapActionToRunningStatus(ApplicationManager::ActionType actionType);
21 Application::Status mapActionToFinishedStatus(ApplicationManager::ActionType actionType);
22
23 #define PKENUM_DAEMONERROR_STRING(v)   GCS_ENUM_STRING(PackageKit::Client,DaemonError,(v))
24 #define PKENUM_ROLE_STRING(v)       GCS_ENUM_STRING(PackageKit::Enum,Role,(v))
25 #define PKENUM_STATUS_STRING(v)     GCS_ENUM_STRING(PackageKit::Enum,Status,(v))
26 #define PKENUM_EXIT_STRING(v)       GCS_ENUM_STRING(PackageKit::Enum,Exit,(v))
27 #define PKENUM_NETWORK_STRING(v)    GCS_ENUM_STRING(PackageKit::Enum,Network,(v))
28 #define PKENUM_ERROR_STRING(v)      GCS_ENUM_STRING(PackageKit::Enum,Error,(v))
29 #define PKENUM_MESSAGE_STRING(v)    GCS_ENUM_STRING(PackageKit::Enum,Message,(v))
30 #define PKENUM_INFO_STRING(v)       GCS_ENUM_STRING(PackageKit::Enum,Info,(v))
31 #define PKENUM_MEDIATYPE_STRING(v)  GCS_ENUM_STRING(PackageKit::Enum,MediaType,(v))
32 #define PKENUM_RESTART_STRING(v)    GCS_ENUM_STRING(PackageKit::Enum,Restart,(v))
33
34 ApplicationManager* ApplicationManager::m_instance = 0;
35
36 ApplicationManager* ApplicationManager::instance()
37 {
38     if (!m_instance) {
39         m_instance = new ApplicationManager(0);
40         if (!m_instance) {
41             gcsFatal() << tr("Not possible to create ApplicationManager instance");
42             return 0;
43         }
44
45         // configure packagekit
46         QStringList hints;
47         //hints << "locale=en_US.UTF-8";
48         hints << "background=false";
49         hints << "interactive=true";
50         if (!PackageKit::Client::instance()) {
51             gcsFatal() << tr("PackageKit Client not available");
52             return 0;
53         }
54         PackageKit::Client::instance()->setHints(hints);
55     }
56
57     return m_instance;
58 }
59
60 ApplicationManager::ApplicationManager(QObject *parent) :
61     QObject(parent),
62     m_currentTransaction(0),
63     m_statusStorage(new ApplicationStatusStorage())
64 {
65 #ifndef HAVE_NO_PACKAGEKIT
66     PackageKit::Client * client = PackageKit::Client::instance();
67     if (!PackageKit::Client::instance()) {
68         gcsFatal() << tr("PackageKit Client not available");
69         return;
70     }
71     connect(client, SIGNAL(error(PackageKit::Client::DaemonError)),
72             SLOT(onError(PackageKit::Client::DaemonError)));
73 #endif
74
75     Q_ASSERT(GarageClientServices::instance());
76     connect(GarageClientServices::instance(), SIGNAL(onlineStateChanged(bool)), this, SLOT(onOnlineStateChanged(bool)));
77 }
78
79 ApplicationManager::~ApplicationManager()
80 {
81     if (m_statusStorage) {
82         delete m_statusStorage;
83         m_statusStorage = 0;
84     }
85 }
86
87 void ApplicationManager::install(Application * app)
88 {
89     queueAction(InstallAction, app);
90 }
91
92 void ApplicationManager::install(ApplicationList apps)
93 {
94     queueAction(InstallAction, apps);
95 }
96
97 void ApplicationManager::remove(Application * app)
98 {
99     queueAction(RemoveAction, app);
100 }
101
102 void ApplicationManager::remove(ApplicationList apps)
103 {
104     queueAction(RemoveAction, apps);
105 }
106
107 void ApplicationManager::update(Application * app)
108 {
109     queueAction(UpdateAction, app);
110 }
111
112 void ApplicationManager::update(ApplicationList apps)
113 {
114     queueAction(UpdateAction, apps);
115 }
116
117 void ApplicationManager::resolve(Application * app)
118 {
119     queueAction(ResolveAction, app);
120 }
121
122 void ApplicationManager::resolve(ApplicationList apps)
123 {
124 #if 1
125     QListIterator<Application*> i(apps);
126     while(i.hasNext()) {
127         Application * application = i.next();
128         if (application) {
129             resolve(application);
130         }
131     }
132 #else
133     //queueAction(ResolveAction, apps);
134 #endif
135 }
136
137 void ApplicationManager::cancelAll(bool privateActionsToo)
138 {
139     // clear the queue of actions
140     m_actionList.clear();
141
142 #ifndef HAVE_NO_PACKAGEKIT
143     if (privateActionsToo) {
144         m_privateActionList.clear();
145     }
146
147     // cancel current transation
148     if (m_currentTransaction != 0 && m_currentTransaction->allowCancel()) {
149         if (privateActionsToo || !m_isCurrentActionPrivate)
150             m_currentTransaction->cancel();
151     }
152 #endif
153 }
154
155 bool ApplicationManager::canCancel() const
156 {
157     if (! m_actionList.isEmpty()) {
158         return true;
159     }
160
161 #ifndef HAVE_NO_PACKAGEKIT
162     if (m_currentTransaction != 0) {
163         return m_currentTransaction->allowCancel();
164     }
165 #endif
166     return false;
167 }
168
169 ApplicationManager::ActionType ApplicationManager::currentActionType() const
170 {
171     return m_currentAction.actionType;
172 }
173
174 ApplicationList ApplicationManager::currentApplicationList() const
175 {
176     return m_appsInProcess;
177     //return m_currentAction.applicationList;
178 }
179
180 bool ApplicationManager::isCurrentActionPrivate() const
181 {
182     return m_isCurrentActionPrivate;
183 }
184
185 int ApplicationManager::percentage() const
186 {
187     // return invalid if no actions running
188     if (numActionsQueued() <= 0 && m_currentTransaction == 0) {
189         return -1;
190     }
191
192     // returns percentage of total operations in the queue
193     int numTotal = numActionsTotal();
194     if (numTotal <= 0)
195         return 0;
196
197     int numDone = numActionsDone();
198     int percentTransaction = 0;
199
200 #ifndef HAVE_NO_PACKAGEKIT
201     if (m_currentTransaction) {
202         percentTransaction = m_currentTransaction->percentage() / numTotal;
203     }
204 #endif
205
206     return numDone * 100 / numTotal + percentTransaction;
207 }
208
209 int ApplicationManager::elapsedTime() const
210 {
211 #ifndef HAVE_NO_PACKAGEKIT
212     if (m_currentTransaction->elapsedTime()) {
213         return m_currentTransaction->elapsedTime();
214     }
215 #endif
216     return 0;
217 }
218
219 int ApplicationManager::remainingTime() const
220 {
221 #ifndef HAVE_NO_PACKAGEKIT
222     if (m_currentTransaction) {
223         return m_currentTransaction->remainingTime();
224     }
225 #endif
226     return 0;
227 }
228
229 ApplicationManager::ActionType ApplicationManager::actionQueuedForApplication(Application * app, bool includeCurrent) const
230 {
231     if (includeCurrent && m_currentAction.applicationList.contains(app)) {
232         return m_currentAction.actionType;
233     }
234
235     QList<Action>::const_iterator i;
236     for(i = m_actionList.constBegin();i != m_actionList.constEnd();i++) {
237         if ((*i).applicationList.contains(app)) {
238             return (*i).actionType;
239         }
240     }
241
242     for(i = m_privateActionList.begin();i != m_privateActionList.end();i++) {
243         if ((*i).applicationList.contains(app)) {
244             return (*i).actionType;
245         }
246     }
247
248     return NoAction;
249 }
250
251 ApplicationManager::ActionType ApplicationManager::actionQueuedForApplication(QList<Application *> apps, bool includeCurrent) const
252 {
253     ApplicationList::const_iterator i;
254     for(i = apps.constBegin();i != apps.constEnd();i++) {
255         ActionType actionType = actionQueuedForApplication(*i, includeCurrent);
256         if (actionType != NoAction) {
257             return actionType;
258         }
259     }
260
261     return NoAction;
262 }
263
264 void ApplicationManager::queueAction(ApplicationManager::ActionType actionType, Application * application)
265 {
266     Q_ASSERT(actionQueuedForApplication(application) == NoAction);
267
268     ApplicationList appList;
269     appList.append(application);
270     queueAction(actionType, appList);
271 }
272
273 void ApplicationManager::queueAction(ApplicationManager::ActionType actionType, ApplicationList applicationList)
274 {
275     gcsDebug() << "actionType=" << actionTypeAsString(actionType) <<
276             "appList=" << Utils::applicationListAsString(applicationList);
277     //Catalog::dumpApplicationList(applicationList);
278
279     Q_ASSERT(actionQueuedForApplication(applicationList) == NoAction);
280
281     if (actionType != ResolveAction) {
282         resolveIfNeeded(applicationList);
283     }
284
285     if (!m_currentTransaction && m_actionList.isEmpty()) {
286         m_numActionsTotal = 0;
287     }
288
289     ApplicationList::iterator i;
290     for(i = applicationList.begin();i != applicationList.end();i++) {
291         (*i)->setStatus( mapActionToQueuedStatus(actionType) );
292     }
293
294     Action action;
295     action.actionType = actionType;
296     action.applicationList = applicationList;
297     // give priorities to resolve actions
298     if (actionType == ResolveAction) {
299         m_privateActionList.append(action);
300     } else {
301         m_actionList.append(action);
302         m_numActionsTotal++;
303     }
304
305 #ifndef HAVE_NO_PACKAGEKIT
306     processQueue();
307 #endif
308 }
309
310 void ApplicationManager::resolveIfNeeded(ApplicationList appList)
311 {
312     QMutableListIterator<Application*> i(appList);
313     while (i.hasNext()) {
314         Application * app = i.next();
315         if (!app) {
316             gcsWarning() << tr("Error, application to resolve not found");
317             i.remove();
318         }
319         // it is safer to resolve always
320 #if 0
321         // we will resolve just the ones without package
322 #ifndef HAVE_NO_PACKAGEKIT
323         if (app->getPackage() != 0) {
324             i.remove();
325         }
326 #endif
327 #endif
328     }
329
330     resolve(appList);
331 }
332
333 #ifndef HAVE_NO_PACKAGEKIT
334 bool ApplicationManager::takeActionFromQueue()
335 {
336     Q_ASSERT(!m_currentTransaction);
337
338     if (m_privateActionList.count() > 0) {
339         // assuming all private actions are resolve and thus can be done offline
340         m_currentAction = m_privateActionList.takeAt(0);
341         Q_ASSERT(m_currentAction.actionType == ResolveAction);
342         m_isCurrentActionPrivate = true;
343         return true;
344     }
345     if (m_actionList.count() > 0) {
346         if  (GarageClientServices::instance()->isOnline()) {
347             m_currentAction = m_actionList.takeAt(0);
348             m_isCurrentActionPrivate = false;
349             return true;
350         } else {
351             int i;
352             for(i = 0;i < m_actionList.count();i++) {
353                 const Action & action = m_actionList.at(i);
354                 if (action.actionType == RemoveAction ||
355                     action.actionType == ResolveAction) {
356                     // when offline we just process the remove and resolve actions
357                     m_currentAction = m_actionList.takeAt(i);
358                     m_isCurrentActionPrivate = false;
359                     return true;
360                 }
361             }
362         }
363     }
364
365     return false;
366 }
367
368 void ApplicationManager::processQueue()
369 {
370     //gcsDebug();
371
372     PackageKit::Client * packageKitClient = PackageKit::Client::instance();
373     if (!packageKitClient) {
374         gcsError() << tr("Processing queue: PackageKit Client not available");
375         return;
376     }
377
378     dumpDaemon();
379
380     while (!m_currentTransaction && takeActionFromQueue()) {
381
382         gcsDebug() << "processing queue length=" << m_privateActionList.count() << m_actionList.count();
383
384         m_appsInProcess = m_currentAction.applicationList;
385         QList<QSharedPointer<PackageKit::Package> > packages;
386         QList<QString> packageNames;
387
388         gcsDebug() << "processing action=" << actionTypeAsString(m_currentAction.actionType) <<
389                 "appList=" << Utils::applicationListAsString(m_currentAction.applicationList);
390
391         if (m_currentAction.actionType == ResolveAction) {
392
393             // build list of packages names for resolving
394             ApplicationList::const_iterator i = m_currentAction.applicationList.constBegin();
395             while(i != m_currentAction.applicationList.constEnd()) {
396                 Application * application = (*i);
397                 if (application == 0) {
398                     gcsWarning() << tr("Package not available for processing");
399                 } else if (application->packageName().isEmpty()) {
400                     gcsWarning() << tr("Package name not available for processing %1").arg(application->name());
401                 } else {
402                     packageNames.append(application->packageName());
403                     application->setStatus(Application::ResolvingStatus);
404                 }
405                 i++;
406             }
407
408             if (packageNames.isEmpty()) {
409                 m_currentAction.actionType = NoAction;
410                 m_currentAction.applicationList.clear();
411                 m_appsInProcess.clear();
412                 packageNames.clear();
413                 packages.clear();
414                 //TODO emit error for the ones we don't process ...
415
416                 gcsDebug() << "Error: no package names to resolve";
417
418                 continue;
419             }
420
421         } else if (m_currentAction.actionType == InstallAction ||
422                    m_currentAction.actionType == RemoveAction ||
423                    m_currentAction.actionType == UpdateAction) {
424
425             // build list of packages for install, remove, update
426             ApplicationList::const_iterator i = m_currentAction.applicationList.constBegin();
427             while(i != m_currentAction.applicationList.constEnd()) {
428                 Application * application = (*i);
429                 if (application == 0) {
430                     gcsWarning() << tr("Package not available for processing");
431                 } else if (application->package().isNull()) {
432                     gcsWarning() << tr("Package not available for processing %1").arg( application->name() );
433                 } else {
434                     packages.append(application->package());
435                     application->setStatus( mapActionToRunningStatus(m_currentAction.actionType) );
436                 }
437                 i++;
438             }
439
440             if (packages.isEmpty()) {
441                 m_currentAction.actionType = NoAction;
442                 m_currentAction.applicationList.clear();
443                 m_appsInProcess.clear();
444                 packageNames.clear();
445                 packages.clear();
446                 //TODO emit error for the ones we don't process ...
447
448                 gcsDebug() << "Error: no packages for operation";
449
450                 continue;
451             }
452         }
453
454         sendProgressMessage(ActionStartedMessage);
455
456         /// Signaled when an application action is started
457         emit applicationActionStarted(m_currentAction.actionType,m_currentAction.applicationList,
458                                       m_isCurrentActionPrivate);
459
460         // TODO current interface in PackageKit is a bit unsafe, a signal could be launched
461         // between the time of the creation of the transaction and the connect,
462         // so the signal would be lost.
463         // This can get fixed in 0.6.8 PackageKit, but some changes should be done in source code
464         switch(m_currentAction.actionType) {
465         case InstallAction:
466             gcsDebug() << "installPackages count=" << packages.count();
467             m_currentTransaction = packageKitClient->installPackages(false, packages);
468             break;
469         case RemoveAction:
470             gcsDebug() << "removePackages count=" << packages.count();
471             // TODO yum does not support autoremove, check for zypp
472             //m_currentTransaction = packageKitClient->removePackages(packages, true, true);
473             m_currentTransaction = packageKitClient->removePackages(packages, true, false);
474             break;
475         case UpdateAction:
476             gcsDebug() << "updatePackages count=" << packages.count();
477             m_currentTransaction = packageKitClient->updatePackages(false, packages);
478             break;
479         case ResolveAction:
480             gcsDebug() << "resolve count=" << packageNames.count();
481             m_currentTransaction = packageKitClient->resolve(packageNames);
482             break;
483         case ApplicationManager::RefreshCacheAction:
484             gcsDebug() << "refreshCache";
485             m_currentTransaction = packageKitClient->refreshCache(true);
486             break;
487         case ApplicationManager::GetUpdatesAction:
488             gcsDebug() << "getUpdates";
489             m_currentTransaction = packageKitClient->getUpdates();
490             break;
491         case NoAction:
492             Q_ASSERT(false);
493             break;
494         }
495
496         if (!m_currentTransaction) {
497
498             gcsError() << tr("Transaction could not be created: %1")
499                     .arg( PKENUM_DAEMONERROR_STRING(PackageKit::Client::instance()->getLastError()) );
500
501             m_currentAction.actionType = NoAction;
502             m_currentAction.applicationList.clear();
503             m_appsInProcess.clear();
504             packageNames.clear();
505             packages.clear();
506
507             continue;
508         }
509
510         dumpDaemon();
511
512         connect(m_currentTransaction, SIGNAL(package(QSharedPointer<PackageKit::Package>)),
513                 SLOT(onPackageResolved(QSharedPointer<PackageKit::Package>)));
514         connect(m_currentTransaction, SIGNAL(changed()),
515                 SLOT(onTransactionChanged()));
516         connect(m_currentTransaction, SIGNAL(errorCode(PackageKit::Enum::Error, const QString&)),
517                 SLOT(onTransactionError(PackageKit::Enum::Error, const QString&)));
518         connect(m_currentTransaction, SIGNAL(finished(PackageKit::Enum::Exit,uint)),
519                 SLOT(onTransactionFinished(PackageKit::Enum::Exit,uint)));
520         connect(m_currentTransaction, SIGNAL(message(PackageKit::Enum::Message,QString)),
521                 SLOT(onMessage(PackageKit::Enum::Message,QString)));
522
523         connect(m_currentTransaction, SIGNAL(eulaRequired(PackageKit::Client::EulaInfo)),
524                 this, SLOT(onEulaRequired(PackageKit::Client::EulaInfo)));
525         connect(m_currentTransaction, SIGNAL(mediaChangeRequired(PackageKit::Enum::MediaType,QString,QString)),
526                 this, SLOT(onMediaChangeRequired(PackageKit::Enum::MediaType,QString,QString)));
527         connect(m_currentTransaction, SIGNAL(repoSignatureRequired(PackageKit::Client::SignatureInfo)),
528                 this, SLOT(onRepoSignatureRequired(PackageKit::Client::SignatureInfo)));
529         connect(m_currentTransaction, SIGNAL(requireRestart(PackageKit::Enum::Restart,QSharedPointer<PackageKit::Package>)),
530                 this, SLOT(onRequireRestart(PackageKit::Enum::Restart,QSharedPointer<PackageKit::Package>)));
531
532         if (m_currentTransaction && m_currentTransaction->status() == PackageKit::Enum::StatusFinished) {
533             gcsWarning() << "Transaction Finish signal lost";
534             onTransactionFinished(PackageKit::Enum::ExitSuccess, 0);
535         }
536     }
537
538 /*
539     if (!m_currentTransaction && m_actionList.isEmpty()) {
540         m_numActionsTotal = 0;
541     }
542 */
543 }
544
545 void ApplicationManager::onEulaRequired(PackageKit::Client::EulaInfo eula)
546 {
547     QString shortStr;
548
549     if (eula.package.isNull()) {
550         shortStr = tr("EULA required id %1 vendor %2")
551                    .arg(eula.id)
552                    .arg(eula.vendorName);
553     } else {
554         shortStr = tr("EULA required id %1 package %2 vendor %3")
555                    .arg(eula.id)
556                    .arg(eula.package->name())
557                    .arg(eula.vendorName);
558     }
559
560     gcsWarning() << shortStr << eula.licenseAgreement;
561     sendUserMessage(shortStr, eula.licenseAgreement);
562 }
563
564 void ApplicationManager::onMediaChangeRequired(PackageKit::Enum::MediaType type, const QString& id, const QString& text)
565 {
566     QString shortStr = tr("Media change required %1 id %2")
567                        .arg(tr(PKENUM_MEDIATYPE_STRING(type)))
568                        .arg(id);
569
570     gcsWarning() << shortStr << text;
571     sendUserMessage(shortStr, text);
572 }
573
574 void ApplicationManager::onRepoSignatureRequired(PackageKit::Client::SignatureInfo info)
575 {
576     QString shortStr = tr("Repo signature required for %1")
577                        .arg(info.package->name());
578
579     QString detailedStr = tr("repoId=%1 keyUrl=%2 keyUserId=%3 keyId=%4 keyFingerprint=%5 keyTimestamp=%6")
580                           .arg(info.repoId)
581                           .arg(info.keyUrl)
582                           .arg(info.keyUserid)
583                           .arg(info.keyId)
584                           .arg(info.keyFingerprint)
585                           .arg(info.keyTimestamp);
586
587     gcsWarning() << shortStr << detailedStr;
588     sendUserMessage(shortStr, detailedStr);
589 }
590
591 void ApplicationManager::onRequireRestart(PackageKit::Enum::Restart type, QSharedPointer<PackageKit::Package> p)
592 {
593     QString shortStr;
594     if (p.isNull()) {
595         shortStr = tr("Restart required %1")
596                            .arg(tr(PKENUM_RESTART_STRING(type)));
597     } else {
598         shortStr = tr("Restart required %1 for package %2")
599                            .arg(tr(PKENUM_RESTART_STRING(type)))
600                            .arg(p->name());
601     }
602
603     gcsWarning() << shortStr;
604     sendUserMessage(shortStr);
605 }
606
607 void ApplicationManager::onPackageResolved(QSharedPointer<PackageKit::Package> package)
608 {
609     if (package.isNull()) {
610         gcsWarning() << tr("ApplicationManager::onPackageResolved returned invalid package");
611         dumpDaemon();
612         return;
613     }
614
615     sendProgressMessage(ActionInProgressMessage, tr("Resolved %1").arg(package->id()) );
616
617     gcsDebug() << "called for " << package->name() << package->id() << package->info();
618     dumpDaemon();
619     dumpPackage(package);
620
621     Application * application = 0;
622     GarageClientServices * gcs = GarageClientServices::instance();
623     if (gcs && gcs->catalog()) {
624         application = gcs->catalog()->findApplicationByPackageName(package->name());
625     }
626
627     if (!application) {
628         gcsDebug() << tr("Catalog::onPackageResolve not found application with package name %1").arg( package->name() );
629         return;
630     }
631
632     /*
633       We might get this signal for non-resolve transactions as well
634     */
635     if (m_currentAction.actionType == ResolveAction) {
636         m_appsInProcess.removeOne(application);
637     }
638
639     // check if it is an update
640     Application::Status status = Application::toStatus(
641             package->info(),
642             application->status());
643     if (application->package() != 0 &&
644         application->package()->name() ==  package->name() &&
645         application->package()->version() != package->version() &&
646         application->status() == Application::InstalledStatus &&
647         status == Application::NotInstalledStatus ) {
648         status = Application::UpdateAvailableStatus;
649         //application->setUpdatePackage(package);
650         application->setVersionToUpdate(package->version());
651         application->setPackageToUpdate(package);
652         // TODO for version 1.1 manage both package and uninstalled package
653     } else {
654         application->setInstalledVersion(package->version());
655     }
656
657     // set package
658     application->setPackage(package);
659
660     // we will not set the status when the same package is still in the queue waiting for other ops to execute
661     // to avoid spurious changes of state
662     if (actionQueuedForApplication(application, false) == NoAction) {
663         // package resolved succesfully
664         application->setStatus(status);
665     }
666 }
667
668 void ApplicationManager::onTransactionChanged()
669 {
670     gcsDebug();
671     dumpDaemon();
672
673     PackageKit::Transaction * transaction = static_cast<PackageKit::Transaction *> (sender());
674
675     QString transStatus = getTransactionStatusMessage(transaction->status());
676     sendProgressMessage(ActionInProgressMessage, transStatus);
677
678     emit progressUpdated(QString(), m_isCurrentActionPrivate);
679 }
680
681 void ApplicationManager::onTransactionError(PackageKit::Enum::Error error, const QString& errorStr)
682 {
683     gcsDebug() << "error=" << PKENUM_ERROR_STRING(error) << errorStr;
684     dumpDaemon();
685
686     // we keep the list for the signal sent later
687     ApplicationList appsInProcess = m_appsInProcess;
688
689     /*
690       We don't get the package names of the packages which have error.
691       We assume we get them all in string (it happens at least with resolve).
692     */
693     ApplicationList appsError = findApplicationsContainedInString(m_appsInProcess, errorStr);
694     if (appsError.isEmpty()) {
695         // if there are no apps in appsError, we will assume all had error
696         appsError = m_appsInProcess;
697     }
698
699     // sent transaction error to every app with errors and remove from apps in process
700     QListIterator<Application*> i(appsError);
701     while (i.hasNext()) {
702         Application * application = i.next();
703         if (application) {
704             application->onTransactionError(m_currentAction.actionType, errorStr);
705             m_appsInProcess.removeOne(application);
706         }
707     }
708
709     sendProgressMessage(ActionErrorMessage, errorStr + "(" + tr(PKENUM_ERROR_STRING(error)) + ")");
710
711     gcsError() << errorStr << PKENUM_ERROR_STRING(error);
712     emit applicationActionError(m_currentAction.actionType, appsInProcess, errorStr, m_isCurrentActionPrivate);
713 }
714
715 void ApplicationManager::onTransactionFinished(PackageKit::Enum::Exit code, uint time)
716 {
717     gcsDebug() << "status=" << code << PKENUM_EXIT_STRING(code) << time << PKENUM_STATUS_STRING(m_currentTransaction->status());
718     dumpDaemon();
719
720     bool success = (code == PackageKit::Enum::ExitSuccess);
721
722     if (success) {
723         sendProgressMessage(ActionFinishedMessage);
724     } else {
725         sendProgressMessage(ActionFailedMessage, PKENUM_EXIT_STRING(code));
726     }
727
728     // resolve does not send neither error nor success failed if not possible to resolve ...
729     // so we force transaction error if we didn't get the package and success is true
730     // also make the whole transaction not successful
731     if (success && m_currentAction.actionType == ResolveAction) {
732         QListIterator<Application*> i(m_appsInProcess);
733         while (i.hasNext()) {
734             Application * application = i.next();
735             if (application && application->package().isNull()) {
736                 application->onTransactionError(m_currentAction.actionType, tr("Transaction finished without providing packages"));
737                 m_appsInProcess.removeOne(application);
738                 success = false;
739             }
740         }
741     }
742
743     // we keep the list for the resolve issued later
744     ApplicationList appsToResolve;
745     if (!success &&
746         m_currentAction.actionType == ResolveAction &&
747         !m_appsInProcess.isEmpty()) {
748         appsToResolve = m_appsInProcess;
749     }
750
751     // if operation was not resolve and failed, we will try to resolve
752     // it might be due to inconsistent cached application status
753     if (code == PackageKit::Enum::ExitFailed &&
754         m_currentAction.actionType != ResolveAction) {
755         appsToResolve = m_currentAction.applicationList;
756     }
757
758     // emit action finished for every single application
759     QListIterator<Application*> i( m_currentAction.applicationList );
760     while(i.hasNext()) {
761         Application * app = i.next();
762         app->onTransactionFinished(m_currentAction.actionType, success);
763     }
764
765     m_currentTransaction = 0;
766     emit applicationActionCompleted(m_currentAction.actionType, m_currentAction.applicationList, success, m_isCurrentActionPrivate);
767
768     // clean the current action and continue processing
769     m_currentAction.actionType = NoAction;
770     m_currentAction.applicationList.clear();
771     m_appsInProcess.clear();
772
773     /*
774       Special case with resolving. It stops working on error.
775       So we reissue the resolve packages action for the packages that were not resolved.
776       Also resolve -> if current operation was not resolve and failed,
777     */
778     if (!appsToResolve.isEmpty()) {
779         resolve(appsToResolve);
780     }
781
782     // check if something to process in the queue
783     processQueue();
784 }
785 #endif
786
787 Application * ApplicationManager::getApplicationByName(ApplicationList applicationList, QString str) const
788 {
789     // Get all packagenames
790     ApplicationList::const_iterator i;
791     for (i = applicationList.constBegin(); i != applicationList.constEnd(); i++) {
792         Application* application = *i;
793         if (application->name() == str) {
794             return application;
795         }
796     }
797
798     // application not found
799     return 0;
800 }
801
802 Application::Status mapActionToQueuedStatus(ApplicationManager::ActionType actionType)
803 {
804     switch(actionType) {
805     case ApplicationManager::InstallAction:
806         return Application::QueuedInstallStatus;
807         break;
808     case ApplicationManager::RemoveAction:
809         return Application::QueuedRemoveStatus;
810         break;
811     case ApplicationManager::UpdateAction:
812         return Application::QueuedUpdateStatus;
813         break;
814     case ApplicationManager::ResolveAction:
815         return Application::QueuedResolveStatus;
816         break;
817     case ApplicationManager::NoAction:
818     case ApplicationManager::RefreshCacheAction:
819     case ApplicationManager::GetUpdatesAction:
820         Q_ASSERT(false);
821         break;
822     }
823
824     return Application::ErrorStatus;
825 }
826
827 Application::Status mapActionToRunningStatus(ApplicationManager::ActionType actionType)
828 {
829     switch(actionType) {
830     case ApplicationManager::InstallAction:
831         return Application::InstallingStatus;
832         break;
833     case ApplicationManager::RemoveAction:
834         return Application::RemovingStatus;
835         break;
836     case ApplicationManager::UpdateAction:
837         return Application::UpdatingStatus;
838         break;
839     case ApplicationManager::ResolveAction:
840         return Application::ResolvingStatus;
841         break;
842     case ApplicationManager::NoAction:
843     case ApplicationManager::RefreshCacheAction:
844     case ApplicationManager::GetUpdatesAction:
845         Q_ASSERT(false);
846         break;
847     }
848
849     return Application::ErrorStatus;
850 }
851
852 Application::Status mapActionToFinishedStatus(ApplicationManager::ActionType actionType)
853 {
854     switch(actionType) {
855     case ApplicationManager::InstallAction:
856     case ApplicationManager::UpdateAction:
857         return Application::InstalledStatus;
858         break;
859     case ApplicationManager::RemoveAction:
860         return Application::NotInstalledStatus;
861         break;
862     case ApplicationManager::ResolveAction:
863         // it should be obtained from the resolved package
864         Q_ASSERT(false);
865         break;
866     case ApplicationManager::NoAction:
867     case ApplicationManager::RefreshCacheAction:
868     case ApplicationManager::GetUpdatesAction:
869         Q_ASSERT(false);
870         break;
871     }
872
873     return Application::ErrorStatus;
874 }
875
876 Application *ApplicationManager::findApplicationContainedInString(
877         ApplicationList applicationList,
878         QString string) const
879 {
880     if (string.isEmpty()) {
881         return 0;
882     }
883
884     ApplicationList resultingAppList = applicationList;
885     QMutableListIterator<Application*> i(resultingAppList);
886     while (i.hasNext()) {
887         Application* application = i.next();
888         if (string == application->packageName() ||
889             string.contains(" " + application->packageName() + " ") ||
890             string.startsWith(application->packageName() + " ") ||
891             string.endsWith(" " + application->packageName())) {
892             return application;
893         }
894     }
895
896     return 0;
897 }
898
899 ApplicationList ApplicationManager::findApplicationsContainedInString(
900         ApplicationList applicationList,
901         QString string) const
902 {
903     if (string.isEmpty()) {
904         applicationList.clear();
905         return applicationList;
906     }
907
908     ApplicationList resultingAppList = applicationList;
909     QMutableListIterator<Application*> i(resultingAppList);
910     while (i.hasNext()) {
911         Application* application = i.next();
912         if (string != application->packageName() &&
913             !string.contains(" " + application->packageName() + " ") &&
914             !string.startsWith(application->packageName() + " ") &&
915             !string.endsWith(" " + application->packageName())) {
916             i.remove();
917         }
918     }
919
920     return resultingAppList;
921 }
922
923 ApplicationList ApplicationManager::filterAppsToResolve(ApplicationList applicationList)
924 {
925     ApplicationList resultingAppList = applicationList;
926     QMutableListIterator<Application*> i(resultingAppList);
927     while (i.hasNext()) {
928         Application* application = i.next();
929         if (application->status() != Application::UnknownStatus) {
930             i.remove();
931         }
932     }
933
934     return resultingAppList;
935 }
936
937 QString ApplicationManager::actionTypeAsString(ActionType actionType)
938 {
939     switch(actionType) {
940     case ResolveAction:
941         return tr("Resolving");
942         break;
943     case InstallAction:
944         return tr("Installing");
945         break;
946     case RemoveAction:
947         return tr("Removing");
948         break;
949     case UpdateAction:
950         return tr("Updating");
951         break;
952     case RefreshCacheAction:
953         return tr("Refreshing Cache");
954         break;
955     case GetUpdatesAction:
956         return tr("Get Updates Action");
957         break;
958     case NoAction:
959         return tr("No Action");
960         break;
961     }
962
963     return tr("Unknown");
964 }
965
966 int ApplicationManager::numActionsQueued() const
967 {
968     int numQueue = m_actionList.count();
969     return numQueue;
970 }
971
972 int ApplicationManager::numActionsTotal() const
973 {
974     //gcsDebug() << "total=" << m_numActionsTotal;
975
976     return m_numActionsTotal;
977 }
978
979 int ApplicationManager::numActionsDone() const
980 {
981     int numQueue = m_actionList.count();
982
983     if (m_currentTransaction) {
984         numQueue++;
985     }
986
987     int result = numActionsTotal() - numQueue;
988
989     //gcsDebug() << "done=" << result << "queue=" << numQueue << " m_currentTransaction" << m_currentTransaction;
990
991     return result;
992 }
993
994 bool ApplicationManager::isActionQueueEmpty() const
995 {
996     if (m_currentTransaction) {
997         return false;
998     }
999     return (m_actionList.count() + m_privateActionList.count()) <= 0;
1000 }
1001
1002 #ifndef HAVE_NO_PACKAGEKIT
1003 void ApplicationManager::onMessage(PackageKit::Enum::Message type, QString str)
1004 {
1005     gcsDebug() << type << PKENUM_MESSAGE_STRING(type) << str;
1006
1007     emit progressUpdated(str, m_isCurrentActionPrivate);
1008 }
1009 #endif
1010
1011 void ApplicationManager::saveStatus()
1012 {
1013     gcsDebug();
1014
1015     QString dirStr = GarageSettings::configPath();
1016     QDir configDir(dirStr);
1017     configDir.mkpath(dirStr);
1018     QFile file(dirStr + "/appstatus.xml");
1019     file.open(QIODevice::ReadWrite | QIODevice::Truncate);  
1020     m_statusStorage->write(&file);
1021     file.close();
1022 }
1023
1024 void ApplicationManager::loadStatus()
1025 {
1026     gcsDebug();
1027     
1028     QString dirStr = GarageSettings::configPath();
1029     QDir configDir(dirStr);
1030     configDir.mkpath(dirStr);
1031     QFile file(dirStr + "/appstatus.xml");
1032     file.open(QIODevice::ReadOnly);
1033     m_statusStorage->read(&file);
1034     file.close();
1035 }
1036
1037 void ApplicationManager::registerApplications(ApplicationList appList)
1038 {
1039     gcsDebug();
1040
1041     m_statusStorage->registerApplications(appList);
1042
1043     // check which applications need refresh of the status
1044     ApplicationList statusRefreshApps;
1045     QListIterator<Application*> i(appList);
1046     QDateTime now = QDateTime::currentDateTime().toUTC();
1047     while(i.hasNext()) {
1048         Application * app = i.next();
1049         if (app && (
1050                 app->status() == Application::UnknownStatus ||
1051                 app->getLastUpdateStatusDateTime().secsTo(now) >= secsToForceUpdate)) {
1052             statusRefreshApps.append(app);
1053         }
1054     }
1055
1056     resolve(statusRefreshApps);
1057 }
1058
1059 void ApplicationManager::resolveOldOrUnknownApps()
1060 {
1061     gcsDebug();
1062
1063     ApplicationList oldOrUnknownApps = m_statusStorage->oldOrUnknownApps();
1064     resolve(oldOrUnknownApps);
1065 }
1066
1067 void ApplicationManager::dumpDaemon()
1068 {
1069 #ifndef HAVE_NO_PACKAGEKIT
1070     PackageKit::Client * client = PackageKit::Client::instance();
1071     qDebug() << "=== DAEMON" <<
1072             client->distroId() <<
1073             client->backendName() <<
1074             client->versionMajor() << client->versionMinor() << client->versionMicro() <<
1075             PKENUM_NETWORK_STRING(client->networkState()) <<
1076             (!GarageClientServices::instance()->isOnline() ? "OFFLINE" : "") <<
1077             (client->locked() ? "LOCKED" : "") <<
1078             ((client->getLastError() != PackageKit::Client::NoError) ? PKENUM_DAEMONERROR_STRING(client->getLastError()) : "");
1079     QList<PackageKit::Transaction*> transactions = PackageKit::Client::instance()->getTransactions();
1080     QListIterator<PackageKit::Transaction*> i(transactions);
1081     int cnt = 0;
1082
1083     if (m_currentTransaction) {
1084         qDebug() << "=== CURRENT TRANSACTION " <<
1085                 m_currentTransaction->tid() <<
1086                 PKENUM_ROLE_STRING(m_currentTransaction->role()) <<
1087                 ((!m_currentTransaction->lastPackage().isNull()) ? m_currentTransaction->lastPackage()->id() : "");
1088         dumpTransaction(m_currentTransaction);
1089     } else {
1090         qDebug() << "=== CURRENT TRANSACTION None";
1091     }
1092
1093     qDebug() << "=== TRANSACTION QUEUE";
1094     while(i.hasNext()) {
1095         PackageKit::Transaction * transaction = i.next();
1096         if (transaction) {
1097             qDebug() << "TRANSACTION" << cnt <<
1098                     transaction->tid() <<
1099                     PKENUM_ROLE_STRING(transaction->role()) <<
1100                     ((!transaction->lastPackage().isNull()) ? transaction->lastPackage()->id() : "");
1101             dumpTransaction(transaction);
1102         } else {
1103             qDebug() << "\tTransaction " << cnt << "invalid";
1104         }
1105         cnt++;
1106     }
1107
1108     qDebug() << "=== CURRENT ACTION" << actionTypeAsString(currentActionType()) <<
1109             Utils::applicationListAsString(currentApplicationList());
1110
1111     qDebug() << "=== PRIVATE ACTION QUEUE" << m_privateActionList.count() << "actions";
1112     QListIterator<Action> j(m_privateActionList);
1113     cnt = 0;
1114     while (j.hasNext()) {
1115         Action action = j.next();
1116         qDebug() << "ACTION" << cnt++ << actionTypeAsString(action.actionType) <<
1117                 Utils::applicationListAsString(action.applicationList);
1118     }
1119
1120     qDebug() << "=== NORMAL ACTION QUEUE" << m_actionList.count() << "actions";
1121     j = m_actionList;
1122     cnt = 0;
1123     while (j.hasNext()) {
1124         Action action = j.next();
1125         qDebug() << "ACTION" << cnt++ << actionTypeAsString(action.actionType) <<
1126                 Utils::applicationListAsString(action.applicationList);
1127     }
1128 #endif
1129 }
1130
1131 #ifndef HAVE_NO_PACKAGEKIT
1132 void ApplicationManager::dumpTransaction(PackageKit::Transaction * transaction)
1133 {
1134     QSharedPointer<PackageKit::Package> package = transaction->lastPackage();
1135     qDebug() << "=== TRANSACTION" <<
1136             transaction->tid() <<
1137             PKENUM_ROLE_STRING(transaction->role()) <<
1138             ((!package.isNull()) ? package->id() : "") <<
1139             PKENUM_STATUS_STRING(transaction->status()) <<
1140             ((transaction->error() != PackageKit::Client::NoError) ? PKENUM_DAEMONERROR_STRING(transaction->error()) : "") <<
1141             "succeeded=" << transaction->succeeded() <<
1142             QString("%1%").arg( transaction->percentage() ) <<
1143             (!transaction->allowCancel() ? "NotCancellable" : "") <<
1144             (!transaction->callerActive() ? "CallerNotActive" : "");
1145 }
1146
1147 void ApplicationManager::dumpPackage(QSharedPointer<PackageKit::Package> package)
1148 {
1149     qDebug() << "=== PACKAGE id=" << package->id() << "info=" << PKENUM_INFO_STRING( package->info() );
1150     qDebug() << "\tname=" << package->name() << "version=" << package->version() <<
1151             "arch=" << package->arch() << "data=" << package->data();
1152     if (!package->summary().isEmpty()) {
1153         qDebug() << "\tsummary=" << package->summary();
1154     }
1155     if (!package->iconPath().isEmpty()) {
1156         qDebug() << "\ticonPath=" << package->iconPath();
1157     }
1158     gcsDebug();
1159     if (package->hasDetails()) {
1160         PackageKit::Package::Details * details;
1161         details = package->details();
1162         if (!details->license().isEmpty()) {
1163             qDebug() << "\tlicense=" << details->license();
1164         }
1165         qDebug() << "\tgroup=" << details->group();
1166         if (!details->description().isEmpty()) {
1167             qDebug() << "\tdescription=" << details->description();
1168         }
1169         if (!details->url().isEmpty()) {
1170             qDebug() << "\turl=" << details->url();
1171         }
1172         qDebug() << "\tsize" << details->size();
1173     }
1174 }
1175 #endif
1176
1177 void ApplicationManager::refreshCache()
1178 {
1179     queueAction(RefreshCacheAction);
1180 }
1181
1182 void ApplicationManager::getUpdates()
1183 {
1184     queueAction(GetUpdatesAction);
1185 }
1186
1187 void ApplicationManager::sendProgressMessage(MessageType messageType, QString detailedStr)
1188 {
1189     ApplicationManager::ActionType actionType = m_currentAction.actionType;
1190     ApplicationList apps = m_currentAction.applicationList;
1191     bool isActionPrivate = m_isCurrentActionPrivate;
1192
1193     QString appName;
1194     //QString appListNames;
1195     if (apps.size() > 0) {
1196         appName = apps.at(0)->name();
1197         //appListNames = Catalog::applicationListAsString(apps);
1198     }
1199
1200     QString actionStr = getActionMessage(messageType, actionType, appName);
1201
1202     /// send null string instead of repeated one
1203     if (m_lastDetailedStr == detailedStr) {
1204         detailedStr = "";
1205     } else {
1206         m_lastDetailedStr = detailedStr;
1207     }
1208
1209     /// send null string instead of repeated one
1210     if (m_lastActionStr == actionStr) {
1211         actionStr =  "";
1212     } else {
1213         m_lastActionStr = actionStr;
1214     }
1215
1216     emit progressMessage(messageType, actionType, apps, isActionPrivate, actionStr, detailedStr,
1217                          percentage());
1218 }
1219
1220 void ApplicationManager::sendUserMessage(QString shortStr, QString detailedStr)
1221 {
1222     emit progressMessage(UserMessage, NoAction, ApplicationList(), false, shortStr, detailedStr, -1);
1223 }
1224
1225 QString ApplicationManager::getActionMessage(
1226         ApplicationManager::MessageType messageType,
1227         ApplicationManager::ActionType actionType,
1228         QString appName)
1229 {
1230     QString msg;
1231
1232     switch(messageType) {
1233     case ActionStartedMessage:
1234         switch(actionType) {
1235         case ApplicationManager::InstallAction:
1236             msg = tr("Started %1 installation");
1237             break;
1238         case ApplicationManager::RemoveAction:
1239             msg = tr("Started %1 removal");
1240             break;
1241         case ApplicationManager::UpdateAction:
1242             msg = tr("Started %1 update");
1243             break;
1244         case ApplicationManager::ResolveAction:
1245             msg = tr("Started %1 resolve");
1246             break;
1247         case ApplicationManager::RefreshCacheAction:
1248             msg = tr("Started cache refresh");
1249             break;
1250         case ApplicationManager::GetUpdatesAction:
1251             msg = tr("Started getting updates");
1252             break;
1253         case ApplicationManager::NoAction:
1254             msg = tr("Started");
1255         }
1256         break;
1257     case ActionInProgressMessage:
1258         switch(actionType) {
1259         case ApplicationManager::InstallAction:
1260             msg = tr("Installing %1");
1261             break;
1262         case ApplicationManager::RemoveAction:
1263             msg = tr("Removing %1");
1264             break;
1265         case ApplicationManager::UpdateAction:
1266             msg = tr("Updating %1");
1267             break;
1268         case ApplicationManager::ResolveAction:
1269             msg = tr("Resolving %1");
1270             break;
1271         case ApplicationManager::RefreshCacheAction:
1272             msg = tr("Refreshing cache");
1273             break;
1274         case ApplicationManager::GetUpdatesAction:
1275             msg = tr("Getting updates");
1276             break;
1277         case ApplicationManager::NoAction:
1278             msg = tr("Progress");
1279         }
1280         break;
1281     case ActionErrorMessage:
1282         switch(actionType) {
1283         case ApplicationManager::InstallAction:
1284             msg = tr("Error while installing %1");
1285             break;
1286         case ApplicationManager::RemoveAction:
1287             msg = tr("Error while removing %1");
1288             break;
1289         case ApplicationManager::UpdateAction:
1290             msg = tr("Error while updating %1");
1291             break;
1292         case ApplicationManager::ResolveAction:
1293             msg = tr("Error while resolving %1");
1294             break;
1295         case ApplicationManager::RefreshCacheAction:
1296             msg = tr("Error while refreshing cache");
1297             break;
1298         case ApplicationManager::GetUpdatesAction:
1299             msg = tr("Error while getting updates");
1300             break;
1301         case ApplicationManager::NoAction:
1302             msg = tr("Error");
1303             break;
1304         }
1305         break;
1306     case ActionFinishedMessage:
1307         switch(actionType) {
1308         case ApplicationManager::InstallAction:
1309             msg = tr("%1 installed successfully");
1310             break;
1311         case ApplicationManager::RemoveAction:
1312             msg = tr("%1 removed successfully");
1313             break;
1314         case ApplicationManager::UpdateAction:
1315             msg = tr("%1 updated successfully");
1316             break;
1317         case ApplicationManager::ResolveAction:
1318             msg = tr("%1 resolved successfully");
1319             break;
1320         case ApplicationManager::RefreshCacheAction:
1321             msg = tr("Refresh cache successful");
1322             break;
1323         case ApplicationManager::GetUpdatesAction:
1324             msg = tr("Get updates successful");
1325             break;
1326         case ApplicationManager::NoAction:
1327             msg = tr("Success");
1328             break;
1329         }
1330         break;
1331     case ActionFailedMessage:
1332         switch(actionType) {
1333         case ApplicationManager::InstallAction:
1334             msg = tr("%1 install failed");
1335             break;
1336         case ApplicationManager::RemoveAction:
1337             msg = tr("%1 remove failed");
1338             break;
1339         case ApplicationManager::UpdateAction:
1340             msg = tr("%1 update failed");
1341             break;
1342         case ApplicationManager::ResolveAction:
1343             msg = tr("%1 resolve failed");
1344             break;
1345         case ApplicationManager::RefreshCacheAction:
1346             msg = tr("Refresh cache failed");
1347             break;
1348         case ApplicationManager::GetUpdatesAction:
1349             msg = tr("Getting updates failed");
1350             break;
1351         case ApplicationManager::NoAction:
1352             msg = tr("Failed");
1353             break;
1354         }
1355         break;
1356     case UserMessage:
1357         msg = tr("User message");
1358         break;
1359     }
1360
1361     if (msg.contains("%1")) {
1362         return msg.arg(appName);
1363     } else {
1364         return msg;
1365     }
1366 }
1367
1368 #ifndef HAVE_NO_PACKAGEKIT
1369 QString ApplicationManager::getTransactionStatusMessage(PackageKit::Enum::Status status)
1370 {
1371     QString statusStr;
1372
1373     switch(status) {
1374     case PackageKit::Enum::UnknownStatus:
1375         statusStr = tr("Unknown Status");
1376         break;
1377     case PackageKit::Enum::StatusWait:
1378         statusStr = tr("Waiting for other transaction(s)");
1379         break;
1380     case PackageKit::Enum::StatusSetup:
1381         statusStr = tr("Setting up transaction");
1382         break;
1383     case PackageKit::Enum::StatusRunning:
1384         statusStr = tr("Starting transaction");
1385         break;
1386     case PackageKit::Enum::StatusQuery:
1387         statusStr = tr("Querying backend");
1388         break;
1389     case PackageKit::Enum::StatusInfo:
1390         statusStr = tr("Getting info from server");
1391         break;
1392     case PackageKit::Enum::StatusRemove:
1393         statusStr = tr("Removing package(s)");
1394         break;
1395     case PackageKit::Enum::StatusRefreshCache:
1396         statusStr = tr("Refreshing internal cache");
1397         break;
1398     case PackageKit::Enum::StatusDownload:
1399         statusStr = tr("Downloading package(s)");
1400         break;
1401     case PackageKit::Enum::StatusInstall:
1402         statusStr = tr("Installing package(s)");
1403         break;
1404     case PackageKit::Enum::StatusUpdate:
1405         statusStr = tr("Updating package(s)");
1406         break;
1407     case PackageKit::Enum::StatusCleanup:
1408         statusStr = tr("Cleaning up old package(s) and config files");
1409         break;
1410     case PackageKit::Enum::StatusObsolete:
1411         statusStr = tr("Obsoleting old package(s)");
1412         break;
1413     case PackageKit::Enum::StatusDepResolve:
1414         statusStr = tr("Resolving package(s) dependencies");
1415         break;
1416     case PackageKit::Enum::StatusSigCheck:
1417         statusStr = tr("Checking signatures");
1418         break;
1419     case PackageKit::Enum::StatusRollback:
1420         statusStr = tr("Rolling back to previous state");
1421         break;
1422     case PackageKit::Enum::StatusTestCommit:
1423         statusStr = tr("Testing commit to database");
1424         break;
1425     case PackageKit::Enum::StatusCommit:
1426         statusStr = tr("Committing changes to databse");
1427         break;
1428     case PackageKit::Enum::StatusRequest:
1429         statusStr = tr("Requesting data from server");
1430         break;
1431     case PackageKit::Enum::StatusFinished:
1432         statusStr = tr("Transaction finished");
1433         break;
1434     case PackageKit::Enum::StatusCancel:
1435         statusStr = tr("Cancelling transaction");
1436         break;
1437     case PackageKit::Enum::StatusDownloadRepository:
1438         statusStr = tr("Downloading repository information");
1439         break;
1440     case PackageKit::Enum::StatusDownloadPackagelist:
1441         statusStr = tr("Downloading list of packages");
1442         break;
1443     case PackageKit::Enum::StatusDownloadFilelist:
1444         statusStr = tr("Downloading list of files");
1445         break;
1446     case PackageKit::Enum::StatusDownloadChangelog:
1447         statusStr = tr("Downloading list of changes");
1448         break;
1449     case PackageKit::Enum::StatusDownloadGroup:
1450         statusStr = tr("Downloading groups");
1451         break;
1452     case PackageKit::Enum::StatusDownloadUpdateinfo:
1453         statusStr = tr("Downloading update information");
1454         break;
1455     case PackageKit::Enum::StatusRepackaging:
1456         statusStr = tr("Repackaging files");
1457         break;
1458     case PackageKit::Enum::StatusLoadingCache:
1459         statusStr = tr("Loading cache");
1460         break;
1461     case PackageKit::Enum::StatusScanApplications:
1462         statusStr = tr("Scanning installed applications");
1463         break;
1464     case PackageKit::Enum::StatusGeneratePackageList:
1465         statusStr = tr("Generating list of installed packages");
1466         break;
1467     case PackageKit::Enum::StatusWaitingForLock:
1468         statusStr = tr("Waiting for the native installer to finish");
1469         break;
1470     case PackageKit::Enum::StatusWaitingForAuth:
1471         statusStr = tr("Waiting for the user to type the password");
1472         break;
1473     case PackageKit::Enum::StatusScanProcessList:
1474         statusStr = tr("Checking running applications");
1475         break;
1476     case PackageKit::Enum::StatusCheckExecutableFiles:
1477         statusStr = tr("Checkking executable files currently in use");
1478         break;
1479     case PackageKit::Enum::StatusCheckLibraries:
1480         statusStr = tr("Checking libraries currently in use");
1481         break;
1482     case PackageKit::Enum::StatusCopyFiles:
1483         statusStr = tr("Copying files");
1484         break;
1485     case PackageKit::Enum::LastStatus:
1486         Q_ASSERT(false);
1487     }
1488
1489     return statusStr;
1490 }
1491
1492 void ApplicationManager::onError(PackageKit::Client::DaemonError error)
1493 {
1494     gcsDebug();
1495
1496     QString errorMsg = tr("Packagekit daemon error %1").arg(tr(PKENUM_DAEMONERROR_STRING(error)));
1497     sendProgressMessage(UserMessage, errorMsg);
1498     gcsWarning() << errorMsg;
1499
1500     if (error == PackageKit::Client::ErrorDaemonUnreachable) {
1501         m_currentTransaction = 0;
1502
1503         emit applicationActionError(m_currentAction.actionType, m_currentAction.applicationList, tr(PKENUM_DAEMONERROR_STRING(error)), m_isCurrentActionPrivate);
1504
1505         // clean the current action and continue processing
1506         m_currentAction.actionType = NoAction;
1507         m_currentAction.applicationList.clear();
1508         m_appsInProcess.clear();
1509
1510         processQueue();
1511     }
1512 }
1513 #endif
1514
1515 void ApplicationManager::onOnlineStateChanged(bool isOnline)
1516 {
1517     gcsDebug() << "isOnline=" << isOnline;
1518     if (isOnline) {
1519 #ifndef HAVE_NO_PACKAGEKIT
1520         processQueue();
1521 #endif
1522     }
1523 }
1524