diff --git a/src/apps/haikudepot/Model.cpp b/src/apps/haikudepot/Model.cpp index 1cee127531..440907f35d 100644 --- a/src/apps/haikudepot/Model.cpp +++ b/src/apps/haikudepot/Model.cpp @@ -6,11 +6,18 @@ #include "Model.h" +#include #include #include +#include #include #include +#include +#include +#include +#include +#include #include "WebAppInterface.h" @@ -564,13 +571,14 @@ int32 Model::_PopulateAllPackagesEntry(void* cookie) { Model* model = static_cast(cookie); - model->_PopulateAllPackagesThread(); + model->_PopulateAllPackagesThread(true); + model->_PopulateAllPackagesThread(false); return 0; } void -Model::_PopulateAllPackagesThread() +Model::_PopulateAllPackagesThread(bool fromCacheOnly) { int32 depotIndex = 0; int32 packageIndex = 0; @@ -601,7 +609,7 @@ Model::_PopulateAllPackagesThread() if (package.Get() == NULL) continue; - _PopulatePackageIcon(package); + _PopulatePackageIcon(package, fromCacheOnly); // TODO: Average user rating. It needs to be shown in the // list view, so without the user clicking the package. } @@ -609,8 +617,41 @@ Model::_PopulateAllPackagesThread() void -Model::_PopulatePackageIcon(const PackageInfoRef& package) +Model::_PopulatePackageIcon(const PackageInfoRef& package, bool fromCacheOnly) { + // See if there is a cached icon file + BFile iconFile; + BPath iconCachePath; + bool fileExists = false; + BString iconName(package->Title()); + iconName << ".hvif"; + time_t modifiedTime; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &iconCachePath) == B_OK + && iconCachePath.Append("HaikuDepot/IconCache") == B_OK + && create_directory(iconCachePath.Path(), 0777) == B_OK + && iconCachePath.Append(iconName) == B_OK) { + // Try opening the file in read-only mode, which will fail if its + // not a file or does not exist. + fileExists = iconFile.SetTo(iconCachePath.Path(), B_READ_ONLY) == B_OK; + if (fileExists) + iconFile.GetModificationTime(&modifiedTime); + } + + if (fileExists) { + time_t now; + time(&now); + if (fromCacheOnly || now - modifiedTime < 60 * 60) { + // Cache file is recent enough, just use it and return. + BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(iconFile), true); + package->SetIcon(bitmapRef); + return; + } + } + + if (fromCacheOnly) + return; + + // Retrieve icon from web-app WebAppInterface interface; BMallocIO buffer; @@ -618,5 +659,9 @@ Model::_PopulatePackageIcon(const PackageInfoRef& package) if (status == B_OK) { BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(buffer), true); package->SetIcon(bitmapRef); + if (iconFile.SetTo(iconCachePath.Path(), + B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) == B_OK) { + iconFile.Write(buffer.Buffer(), buffer.BufferLength()); + } } } diff --git a/src/apps/haikudepot/Model.h b/src/apps/haikudepot/Model.h index a03b667196..6a4041fd0e 100644 --- a/src/apps/haikudepot/Model.h +++ b/src/apps/haikudepot/Model.h @@ -91,10 +91,11 @@ public: private: static int32 _PopulateAllPackagesEntry(void* cookie); - void _PopulateAllPackagesThread(); + void _PopulateAllPackagesThread(bool fromCacheOnly); void _PopulatePackageIcon( - const PackageInfoRef& package); + const PackageInfoRef& package, + bool fromCacheOnly); private: BLocker fLock;