+ d->fireRefreshStatus(CatalogRef(), Delegate::STATUS_REFRESHED);
+ d->firePackagesChanged();
+ }
+}
+
+bool Root::removeCatalogById(const std::string& aId)
+{
+ CatalogRef cat;
+
+ CatalogDict::iterator catIt = d->catalogs.find(aId);
+ if (catIt == d->catalogs.end()) {
+ // check the disabled list
+ CatalogList::iterator j = d->disabledCatalogs.begin();
+ for (; j != d->disabledCatalogs.end(); ++j) {
+ if ((*j)->id() == aId) {
+ break;
+ }
+ }
+
+ if (j == d->disabledCatalogs.end()) {
+ SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: no catalog with id:" << aId);
+ return false;
+ }
+
+ cat = *j;
+ d->disabledCatalogs.erase(j);
+ } else {
+ cat = catIt->second;
+ // drop the reference
+ d->catalogs.erase(catIt);
+ }
+
+ bool ok = cat->uninstall();
+ if (!ok) {
+ SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: catalog :" << aId
+ << "failed to uninstall");
+ }
+
+ // notify that a catalog is being removed
+ d->firePackagesChanged();
+
+ return ok;
+}
+
+void Root::requestThumbnailData(const std::string& aUrl)
+{
+ MemThumbnailCache::iterator it = d->thumbnailCache.find(aUrl);
+ if (it == d->thumbnailCache.end()) {
+ // insert into cache to mark as pending
+ d->pendingThumbnails.push_front(aUrl);
+ d->thumbnailCache[aUrl] = std::string();
+ d->downloadNextPendingThumbnail();
+ } else if (!it->second.empty()) {
+ // already loaded, fire data synchronously
+ d->fireDataForThumbnail(aUrl, it->second);
+ } else {
+ // in cache but empty data, still fetching
+ }
+}
+
+InstallRef Root::existingInstallForPackage(PackageRef p) const
+{
+ RootPrivate::InstallCache::const_iterator it =
+ d->m_installs.find(p);
+ if (it == d->m_installs.end()) {
+ // check if it exists on disk, create
+ SGPath path(p->pathOnDisk());
+ if (path.exists()) {
+ // this will add to our cache, and hence, modify m_installs
+ return Install::createFromPath(path, p->catalog());