diff --git a/src/apps/haikudepot/MainWindow.cpp b/src/apps/haikudepot/MainWindow.cpp index 0e564a362c..9ebbfb6933 100644 --- a/src/apps/haikudepot/MainWindow.cpp +++ b/src/apps/haikudepot/MainWindow.cpp @@ -475,7 +475,10 @@ MainWindow::_RefreshPackageList() | BSolver::B_FIND_IN_PROVIDES, packages); if (result != B_OK) { - // TODO: notify user + BString message(B_TRANSLATE("An error occurred while " + "obtaining the package list: %message%")); + message.ReplaceFirst("%message%", strerror(result)); + _NotifyUser("Error", message.String()); return; } @@ -532,7 +535,8 @@ MainWindow::_RefreshPackageList() PublisherInfo(BitmapRef(), publisherName, "", publisherURL), repoPackageInfo.Summary(), repoPackageInfo.Description(), - repoPackageInfo.Flags()), + repoPackageInfo.Flags(), + repoPackageInfo.ArchitectureName()), true); if (modelInfo.Get() == NULL) diff --git a/src/apps/haikudepot/Model.cpp b/src/apps/haikudepot/Model.cpp index e995d1c8e7..80623d594b 100644 --- a/src/apps/haikudepot/Model.cpp +++ b/src/apps/haikudepot/Model.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -588,6 +589,18 @@ int32 Model::_PopulateAllPackagesEntry(void* cookie) { Model* model = static_cast(cookie); + + model->fPreferredLanguage = "en"; + BLocaleRoster* localeRoster = BLocaleRoster::Default(); + if (localeRoster != NULL) { + BMessage preferredLanguages; + if (localeRoster->GetPreferredLanguages(&preferredLanguages) == B_OK) { + BString language; + if (preferredLanguages.FindString("language", 0, &language) == B_OK) + language.CopyInto(model->fPreferredLanguage, 0, 2); + } + } + model->_PopulateAllPackagesThread(true); model->_PopulateAllPackagesThread(false); return 0; @@ -641,7 +654,7 @@ Model::_PopulateAllPackagesThread(bool fromCacheOnly) // list view, so without the user clicking the package. } - if (!fStopPopulatingAllPackages && bulkPackageList.CountItems() > 0) { + if (bulkPackageList.CountItems() > 0) { _PopulatePackageInfos(bulkPackageList, fromCacheOnly, packagesWithIconsList); } @@ -663,11 +676,15 @@ void Model::_PopulatePackageInfos(PackageList& packages, bool fromCacheOnly, PackageList& packagesWithIcons) { + if (fStopPopulatingAllPackages) + return; + if (fromCacheOnly) return; // Retrieve info from web-app WebAppInterface interface; + interface.SetPreferredLanguage(fPreferredLanguage); BMessage info; StringList packageNames; @@ -686,6 +703,8 @@ Model::_PopulatePackageInfos(PackageList& packages, bool fromCacheOnly, && result.FindMessage("pkgs", &pkgs) == B_OK) { int32 index = 0; while (true) { + if (fStopPopulatingAllPackages) + return; BString name; name << index++; BMessage pkgInfo; @@ -753,9 +772,11 @@ Model::_PopulatePackageInfo(const PackageInfoRef& package, bool fromCacheOnly) // Retrieve info from web-app WebAppInterface interface; + interface.SetPreferredLanguage(fPreferredLanguage); BMessage info; - status_t status = interface.RetrievePackageInfo(package->Title(), info); + status_t status = interface.RetrievePackageInfo(package->Title(), + package->Architecture(), info); if (status == B_OK) { // Parse message // info.PrintToStream(); @@ -766,15 +787,46 @@ Model::_PopulatePackageInfo(const PackageInfoRef& package, bool fromCacheOnly) } -void -Model::_PopulatePackageInfo(const PackageInfoRef& package, - const BMessage& data) +static void +append_word_list(BString& words, const char* word) { - const char* categoriesDebug = ""; - const char* ratingDebug = ""; + if (words.Length() > 0) + words << ", "; + words << word; +} + + +void +Model::_PopulatePackageInfo(const PackageInfoRef& package, const BMessage& data) +{ + BAutolock locker(&fLock); + + BString foundInfo; + + BMessage versions; + BMessage version; + if (data.FindMessage("versions", &versions) == B_OK + && versions.FindMessage("0", &version)) { + BString languageCode; + if (version.FindString("naturalLanguageCode", &languageCode) == B_OK) { + if (languageCode == fPreferredLanguage) { + BString summary; + if (version.FindString("summary", &summary) == B_OK) { + package->SetShortDescription(summary); + append_word_list(foundInfo, "summary"); + } + BString description; + if (version.FindString("description", &description) == B_OK) { + package->SetFullDescription(description); + append_word_list(foundInfo, "description"); + } + } + } + } BMessage categories; if (data.FindMessage("pkgCategoryCodes", &categories) == B_OK) { + bool foundCategory = false; int32 index = 0; while (true) { BString name; @@ -810,8 +862,10 @@ Model::_PopulatePackageInfo(const PackageInfoRef& package, // This should then be used instead of hard-coded // categories and translations in the app. - categoriesDebug = "categories"; + foundCategory = true; } + if (foundCategory) + append_word_list(foundInfo, "categories"); } double derivedRating; double derivedRatingSampleSize; @@ -824,14 +878,13 @@ Model::_PopulatePackageInfo(const PackageInfoRef& package, summary.ratingCount = (int)derivedRatingSampleSize; package->SetRatingSummary(summary); - if (strlen(categoriesDebug) > 0) - ratingDebug = ", rating"; - else - ratingDebug = "rating"; + append_word_list(foundInfo, "rating"); } } - printf("Populated package info for %s: %s%s\n", - package->Title().String(), categoriesDebug, ratingDebug); + if (foundInfo.Length() > 0) { + printf("Populated package info for %s: %s\n", + package->Title().String(), foundInfo.String()); + } } @@ -862,6 +915,7 @@ Model::_PopulatePackageIcon(const PackageInfoRef& package, bool fromCacheOnly) if (fromCacheOnly || now - modifiedTime < 60 * 60) { // Cache file is recent enough, just use it and return. BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(iconFile), true); + BAutolock locker(&fLock); package->SetIcon(bitmapRef); return; } @@ -877,7 +931,9 @@ Model::_PopulatePackageIcon(const PackageInfoRef& package, bool fromCacheOnly) status_t status = interface.RetrievePackageIcon(package->Title(), &buffer); if (status == B_OK) { BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(buffer), true); + BAutolock locker(&fLock); package->SetIcon(bitmapRef); + locker.Unlock(); if (iconFile.SetTo(iconCachePath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) == B_OK) { iconFile.Write(buffer.Buffer(), buffer.BufferLength()); @@ -893,9 +949,6 @@ Model::_HasNativeIcon(const BMessage& message) const if (message.FindMessage("pkgIcons", &pkgIcons) != B_OK) return false; - if (!pkgIcons.IsEmpty()) - pkgIcons.PrintToStream(); - int32 index = 0; while (true) { BString name; diff --git a/src/apps/haikudepot/Model.h b/src/apps/haikudepot/Model.h index d9c1b558e2..d4568927fe 100644 --- a/src/apps/haikudepot/Model.h +++ b/src/apps/haikudepot/Model.h @@ -156,6 +156,7 @@ private: thread_id fPopulateAllPackagesThread; volatile bool fStopPopulatingAllPackages; + BString fPreferredLanguage; }; diff --git a/src/apps/haikudepot/PackageInfo.cpp b/src/apps/haikudepot/PackageInfo.cpp index 2aaaf2d878..dceed9e3f1 100644 --- a/src/apps/haikudepot/PackageInfo.cpp +++ b/src/apps/haikudepot/PackageInfo.cpp @@ -569,7 +569,8 @@ PackageInfo::PackageInfo() fState(NONE), fDownloadProgress(0.0), fFlags(0), - fSystemDependency(false) + fSystemDependency(false), + fArchitecture() { } @@ -577,7 +578,7 @@ PackageInfo::PackageInfo() PackageInfo::PackageInfo(const BString& title, const BString& version, const PublisherInfo& publisher, const BString& shortDescription, const BString& fullDescription, - int32 flags) + int32 flags, const char* architecture) : fIcon(), fTitle(title), @@ -593,7 +594,8 @@ PackageInfo::PackageInfo(const BString& title, fState(NONE), fDownloadProgress(0.0), fFlags(flags), - fSystemDependency(false) + fSystemDependency(false), + fArchitecture(architecture) { } @@ -615,7 +617,8 @@ PackageInfo::PackageInfo(const PackageInfo& other) fInstallationLocations(other.fInstallationLocations), fDownloadProgress(other.fDownloadProgress), fFlags(other.fFlags), - fSystemDependency(other.fSystemDependency) + fSystemDependency(other.fSystemDependency), + fArchitecture(other.fArchitecture) { } @@ -639,6 +642,7 @@ PackageInfo::operator=(const PackageInfo& other) fDownloadProgress = other.fDownloadProgress; fFlags = other.fFlags; fSystemDependency = other.fSystemDependency; + fArchitecture = other.fArchitecture; return *this; } @@ -660,7 +664,8 @@ PackageInfo::operator==(const PackageInfo& other) const && fState == other.fState && fFlags == other.fFlags && fDownloadProgress == other.fDownloadProgress - && fSystemDependency == other.fSystemDependency; + && fSystemDependency == other.fSystemDependency + && fArchitecture == other.fArchitecture; } @@ -671,6 +676,26 @@ PackageInfo::operator!=(const PackageInfo& other) const } +void +PackageInfo::SetShortDescription(const BString& description) +{ + if (fShortDescription != description) { + fShortDescription = description; + _NotifyListeners(PKG_CHANGED_SUMMARY); + } +} + + +void +PackageInfo::SetFullDescription(const BString& description) +{ + if (fFullDescription != description) { + fFullDescription = description; + _NotifyListeners(PKG_CHANGED_DESCRIPTION); + } +} + + void PackageInfo::SetIcon(const BitmapRef& icon) { diff --git a/src/apps/haikudepot/PackageInfo.h b/src/apps/haikudepot/PackageInfo.h index dc62aaf2a5..49fb2930a5 100644 --- a/src/apps/haikudepot/PackageInfo.h +++ b/src/apps/haikudepot/PackageInfo.h @@ -224,7 +224,8 @@ public: const PublisherInfo& publisher, const BString& shortDescription, const BString& fullDescription, - int32 packageFlags); + int32 packageFlags, + const char* architecture); PackageInfo(const PackageInfo& other); PackageInfo& operator=(const PackageInfo& other); @@ -235,8 +236,10 @@ public: { return fTitle; } const BString& Version() const { return fVersion; } + void SetShortDescription(const BString& description); const BString& ShortDescription() const { return fShortDescription; } + void SetFullDescription(const BString& description); const BString& FullDescription() const { return fFullDescription; } const PublisherInfo& Publisher() const @@ -257,6 +260,9 @@ public: { return fSystemDependency; } void SetSystemDependency(bool isDependency); + const BString Architecture() const + { return fArchitecture; } + PackageState State() const { return fState; } void SetState(PackageState state); @@ -311,6 +317,7 @@ private: PackageListenerList fListeners; int32 fFlags; bool fSystemDependency; + BString fArchitecture; }; diff --git a/src/apps/haikudepot/PackageInfoListener.h b/src/apps/haikudepot/PackageInfoListener.h index 6b199784be..9c145fe03f 100644 --- a/src/apps/haikudepot/PackageInfoListener.h +++ b/src/apps/haikudepot/PackageInfoListener.h @@ -10,13 +10,14 @@ enum { - PKG_CHANGED_DESCRIPTION = 1 << 0, - PKG_CHANGED_RATINGS = 1 << 1, - PKG_CHANGED_SCREENSHOTS = 1 << 2, - PKG_CHANGED_STATE = 1 << 3, - PKG_CHANGED_ICON = 1 << 4, - PKG_CHANGED_CHANGELOG = 1 << 5, - PKG_CHANGED_CATEGORIES = 1 << 6 + PKG_CHANGED_SUMMARY = 1 << 0, + PKG_CHANGED_DESCRIPTION = 1 << 1, + PKG_CHANGED_RATINGS = 1 << 2, + PKG_CHANGED_SCREENSHOTS = 1 << 3, + PKG_CHANGED_STATE = 1 << 4, + PKG_CHANGED_ICON = 1 << 5, + PKG_CHANGED_CHANGELOG = 1 << 6, + PKG_CHANGED_CATEGORIES = 1 << 7 // ... }; diff --git a/src/apps/haikudepot/PackageListView.cpp b/src/apps/haikudepot/PackageListView.cpp index 725bac23fc..7eea276ad1 100644 --- a/src/apps/haikudepot/PackageListView.cpp +++ b/src/apps/haikudepot/PackageListView.cpp @@ -124,6 +124,7 @@ public: { return fPackage; } void UpdateTitle(); + void UpdateSummary(); void UpdateState(); void UpdateRating(); @@ -472,8 +473,8 @@ PackageRow::PackageRow(const PackageInfoRef& packageRef, // Rating UpdateRating(); - // Description - SetField(new BStringField(package.ShortDescription()), kDescriptionColumn); + // Summary + UpdateSummary(); // Size // TODO: Store package size @@ -518,6 +519,17 @@ PackageRow::UpdateState() } +void +PackageRow::UpdateSummary() +{ + if (fPackage.Get() == NULL) + return; + + SetField(new BStringField(fPackage->ShortDescription()), + kDescriptionColumn); +} + + void PackageRow::UpdateRating() { @@ -676,6 +688,8 @@ PackageListView::MessageReceived(BMessage* message) BAutolock _(fModelLock); PackageRow* row = _FindRow(title); if (row != NULL) { + if ((changes & PKG_CHANGED_SUMMARY) != 0) + row->UpdateSummary(); if ((changes & PKG_CHANGED_RATINGS) != 0) row->UpdateRating(); if ((changes & PKG_CHANGED_STATE) != 0) diff --git a/src/apps/haikudepot/WebAppInterface.cpp b/src/apps/haikudepot/WebAppInterface.cpp index 8cff1ca944..1160f2c304 100644 --- a/src/apps/haikudepot/WebAppInterface.cpp +++ b/src/apps/haikudepot/WebAppInterface.cpp @@ -232,6 +232,8 @@ WebAppInterface::fRequestIndex = 0; WebAppInterface::WebAppInterface() + : + fLanguage("en") { } @@ -250,9 +252,16 @@ WebAppInterface::SetAuthorization(const BString& username, } +void +WebAppInterface::SetPreferredLanguage(const BString& language) +{ + fLanguage = language; +} + + status_t WebAppInterface::RetrievePackageInfo(const BString& packageName, - BMessage& message) + const BString& architecture, BMessage& message) { BString jsonString = JsonBuilder() .AddValue("jsonrpc", "2.0") @@ -261,8 +270,8 @@ WebAppInterface::RetrievePackageInfo(const BString& packageName, .AddArray("params") .AddObject() .AddValue("name", packageName) - .AddValue("architectureCode", "x86_gcc2") - .AddValue("naturalLanguageCode", "en") + .AddValue("architectureCode", architecture) + .AddValue("naturalLanguageCode", fLanguage) .AddValue("versionType", "NONE") .EndObject() .EndArray() @@ -288,7 +297,7 @@ WebAppInterface::RetrieveBulkPackageInfo(const StringList& packageNames, .AddStrings(packageNames) .EndArray() .AddValue("architectureCode", "x86_gcc2") - .AddValue("naturalLanguageCode", "en") + .AddValue("naturalLanguageCode", fLanguage) .AddValue("versionType", "LATEST") .AddArray("filter") .AddItem("PKGCATEGORIES") diff --git a/src/apps/haikudepot/WebAppInterface.h b/src/apps/haikudepot/WebAppInterface.h index 5436b99a72..e829f085d5 100644 --- a/src/apps/haikudepot/WebAppInterface.h +++ b/src/apps/haikudepot/WebAppInterface.h @@ -25,9 +25,12 @@ public: void SetAuthorization(const BString& username, const BString& password); + void SetPreferredLanguage(const BString& language); + void SetArchitecture(const BString& architecture); status_t RetrievePackageInfo( const BString& packageName, + const BString& architecture, BMessage& message); status_t RetrieveBulkPackageInfo( @@ -45,6 +48,8 @@ private: private: BString fUsername; BString fPassword; + BString fLanguage; + BString fArchitecture; static int fRequestIndex; };