From 9984ca59f6fb840ef91a3d385bc0f710a5bd9c83 Mon Sep 17 00:00:00 2001 From: Andrew Lindesay Date: Thu, 7 Jan 2021 22:00:25 +1300 Subject: [PATCH] HaikuDepot: Remove Custom List Further removal of the use of custom list class. Relates To #15534 Change-Id: I1d84b562b334e5e52ed4772bad3a6aea7b715562 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3657 Reviewed-by: Adrien Destugues --- src/apps/haikudepot/model/Model.cpp | 73 ++++------- src/apps/haikudepot/model/Model.h | 10 +- src/apps/haikudepot/model/PackageInfo.cpp | 73 +++++++---- src/apps/haikudepot/model/PackageInfo.h | 33 ++--- src/apps/haikudepot/model/PackageManager.cpp | 118 ++++++++++------- src/apps/haikudepot/model/PackageManager.h | 9 +- .../server/ServerPkgDataUpdateProcess.cpp | 4 +- src/apps/haikudepot/ui/PackageInfoView.cpp | 124 ++++++++++-------- src/apps/haikudepot/ui/ScreenshotWindow.cpp | 78 ++++++----- src/apps/haikudepot/ui/ScreenshotWindow.h | 2 + src/apps/haikudepot/util/Collector.h | 37 ++++++ 11 files changed, 328 insertions(+), 233 deletions(-) create mode 100644 src/apps/haikudepot/util/Collector.h diff --git a/src/apps/haikudepot/model/Model.cpp b/src/apps/haikudepot/model/Model.cpp index c45eff3364..6fd1803c07 100644 --- a/src/apps/haikudepot/model/Model.cpp +++ b/src/apps/haikudepot/model/Model.cpp @@ -1,7 +1,7 @@ /* * Copyright 2013-2014, Stephan Aßmus . * Copyright 2014, Axel Dörfler . - * Copyright 2016-2020, Andrew Lindesay . + * Copyright 2016-2021, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ @@ -167,38 +167,6 @@ private: }; -class NotContainedInFilter : public PackageFilter { -public: - NotContainedInFilter(const PackageList* packageList, ...) - { - va_list args; - va_start(args, packageList); - while (true) { - const PackageList* packageList = va_arg(args, const PackageList*); - if (packageList == NULL) - break; - fPackageLists.Add(packageList); - } - va_end(args); - } - - virtual bool AcceptsPackage(const PackageInfoRef& package) const - { - if (package.Get() == NULL) - return false; - - for (int32 i = 0; i < fPackageLists.CountItems(); i++) { - if (fPackageLists.ItemAtFast(i)->Contains(package)) - return false; - } - return true; - } - -private: - List fPackageLists; -}; - - class StateFilter : public PackageFilter { public: StateFilter(PackageState state) @@ -348,10 +316,10 @@ Model::InitPackageIconRepository() } -bool +void Model::AddListener(const ModelListenerRef& listener) { - return fListeners.Add(listener); + fListeners.push_back(listener); } @@ -725,9 +693,10 @@ Model::PopulatePackage(const PackageInfoRef& package, uint32 flags) item.FindDouble("createTimestamp", &createTimestamp); // Add the rating to the PackageInfo - UserRating userRating = UserRating(UserInfo(user), rating, + UserRatingRef userRating(new UserRating( + UserInfo(user), rating, comment, languageCode, versionString, - (uint64) createTimestamp); + (uint64) createTimestamp), true); package->AddUserRating(userRating); HDDEBUG("rating [%s] retrieved from server", code.String()); } @@ -741,14 +710,16 @@ Model::PopulatePackage(const PackageInfoRef& package, uint32 flags) } if ((flags & POPULATE_SCREEN_SHOTS) != 0) { - ScreenshotInfoList screenshotInfos; + std::vector screenshotInfos; { BAutolock locker(&fLock); - screenshotInfos = package->ScreenshotInfos(); + for (int32 i = 0; i < package->CountScreenshotInfos(); i++) + screenshotInfos.push_back(package->ScreenshotInfoAtIndex(i)); package->ClearScreenshots(); } - for (int i = 0; i < screenshotInfos.CountItems(); i++) { - const ScreenshotInfo& info = screenshotInfos.ItemAtFast(i); + std::vector::iterator it; + for (it = screenshotInfos.begin(); it != screenshotInfos.end(); it++) { + const ScreenshotInfoRef& info = *it; _PopulatePackageScreenshot(package, info, 320, false); } } @@ -942,7 +913,7 @@ Model::DumpExportPkgDataPath(BPath& path, void Model::_PopulatePackageScreenshot(const PackageInfoRef& package, - const ScreenshotInfo& info, int32 scaledWidth, bool fromCacheOnly) + const ScreenshotInfoRef& info, int32 scaledWidth, bool fromCacheOnly) { // See if there is a cached screenshot BFile screenshotFile; @@ -957,7 +928,7 @@ Model::_PopulatePackageScreenshot(const PackageInfoRef& package, } bool fileExists = false; - BString screenshotName(info.Code()); + BString screenshotName(info->Code()); screenshotName << "@" << scaledWidth; screenshotName << ".png"; time_t modifiedTime; @@ -989,9 +960,9 @@ Model::_PopulatePackageScreenshot(const PackageInfoRef& package, // Retrieve screenshot from web-app BMallocIO buffer; - int32 scaledHeight = scaledWidth * info.Height() / info.Width(); + int32 scaledHeight = scaledWidth * info->Height() / info->Width(); - status_t status = fWebAppInterface.RetrieveScreenshot(info.Code(), + status_t status = fWebAppInterface.RetrieveScreenshot(info->Code(), scaledWidth, scaledHeight, &buffer); if (status == B_OK) { BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(buffer), true); @@ -1004,7 +975,7 @@ Model::_PopulatePackageScreenshot(const PackageInfoRef& package, } } else { HDERROR("Failed to retrieve screenshot for code '%s' " - "at %" B_PRIi32 "x%" B_PRIi32 ".", info.Code().String(), + "at %" B_PRIi32 "x%" B_PRIi32 ".", info->Code().String(), scaledWidth, scaledHeight); } } @@ -1016,8 +987,9 @@ Model::_PopulatePackageScreenshot(const PackageInfoRef& package, void Model::_NotifyAuthorizationChanged() { - for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) { - const ModelListenerRef& listener = fListeners.ItemAtFast(i); + std::vector::const_iterator it; + for (it = fListeners.begin(); it != fListeners.end(); it++) { + const ModelListenerRef& listener = *it; if (listener.Get() != NULL) listener->AuthorizationChanged(); } @@ -1027,8 +999,9 @@ Model::_NotifyAuthorizationChanged() void Model::_NotifyCategoryListChanged() { - for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) { - const ModelListenerRef& listener = fListeners.ItemAtFast(i); + std::vector::const_iterator it; + for (it = fListeners.begin(); it != fListeners.end(); it++) { + const ModelListenerRef& listener = *it; if (listener.Get() != NULL) listener->CategoryListChanged(); } diff --git a/src/apps/haikudepot/model/Model.h b/src/apps/haikudepot/model/Model.h index 4e16686410..47bdae8c2e 100644 --- a/src/apps/haikudepot/model/Model.h +++ b/src/apps/haikudepot/model/Model.h @@ -1,6 +1,6 @@ /* * Copyright 2013-2014, Stephan Aßmus . - * Copyright 2016-2020, Andrew Lindesay . + * Copyright 2016-2021, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ #ifndef MODEL_H @@ -58,7 +58,6 @@ public: typedef BReference ModelListenerRef; -typedef List ModelListenerList; class Model { @@ -74,7 +73,7 @@ public: BLocker* Lock() { return &fLock; } - bool AddListener(const ModelListenerRef& listener); + void AddListener(const ModelListenerRef& listener); PackageInfoRef PackageForName(const BString& name); bool MatchesFilter( @@ -176,7 +175,7 @@ private: void _PopulatePackageScreenshot( const PackageInfoRef& package, - const ScreenshotInfo& info, + const ScreenshotInfoRef& info, int32 scaledWidth, bool fromCacheOnly); void _NotifyAuthorizationChanged(); @@ -215,7 +214,8 @@ private: fPackageIconRepository; WebAppInterface fWebAppInterface; - ModelListenerList fListeners; + std::vector + fListeners; }; diff --git a/src/apps/haikudepot/model/PackageInfo.cpp b/src/apps/haikudepot/model/PackageInfo.cpp index 8846780f24..acdacc3fb1 100644 --- a/src/apps/haikudepot/model/PackageInfo.cpp +++ b/src/apps/haikudepot/model/PackageInfo.cpp @@ -1,7 +1,7 @@ /* * Copyright 2013-2014, Stephan Aßmus . * Copyright 2013, Rene Gollent . - * Copyright 2016-2020, Andrew Lindesay . + * Copyright 2016-2021, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ @@ -792,22 +792,32 @@ PackageInfo::IsLocalFile() const void PackageInfo::ClearUserRatings() { - if (!fUserRatings.IsEmpty()) { - fUserRatings.Clear(); + if (!fUserRatings.empty()) { + fUserRatings.clear(); _NotifyListeners(PKG_CHANGED_RATINGS); } } -bool -PackageInfo::AddUserRating(const UserRating& rating) +int32 +PackageInfo::CountUserRatings() const { - if (!fUserRatings.Add(rating)) - return false; + return fUserRatings.size(); +} + +UserRatingRef +PackageInfo::UserRatingAtIndex(int32 index) const +{ + return fUserRatings[index]; +} + + +void +PackageInfo::AddUserRating(const UserRatingRef& rating) +{ + fUserRatings.push_back(rating); _NotifyListeners(PKG_CHANGED_RATINGS); - - return true; } @@ -826,11 +836,11 @@ PackageInfo::SetRatingSummary(const RatingSummary& summary) RatingSummary PackageInfo::CalculateRatingSummary() const { - if (fUserRatings.CountItems() == 0) + if (fUserRatings.empty()) return fCachedRatingSummary; RatingSummary summary; - summary.ratingCount = fUserRatings.CountItems(); + summary.ratingCount = fUserRatings.size(); summary.averageRating = 0.0f; int starRatingCount = sizeof(summary.ratingCountByStar) / sizeof(int); for (int i = 0; i < starRatingCount; i++) @@ -843,7 +853,7 @@ PackageInfo::CalculateRatingSummary() const int ratingsSpecified = summary.ratingCount; for (int i = 0; i < summary.ratingCount; i++) { - float rating = fUserRatings.ItemAtFast(i).Rating(); + float rating = fUserRatings[i]->Rating(); if (rating < 0.0f) rating = -1.0f; @@ -897,14 +907,28 @@ PackageInfo::IsProminent() const void PackageInfo::ClearScreenshotInfos() { - fScreenshotInfos.Clear(); + fScreenshotInfos.clear(); } -bool -PackageInfo::AddScreenshotInfo(const ScreenshotInfo& info) +int32 +PackageInfo::CountScreenshotInfos() const { - return fScreenshotInfos.Add(info); + return fScreenshotInfos.size(); +} + + +ScreenshotInfoRef +PackageInfo::ScreenshotInfoAtIndex(int32 index) const +{ + return fScreenshotInfos[index]; +} + + +void +PackageInfo::AddScreenshotInfo(const ScreenshotInfoRef& info) +{ + fScreenshotInfos.push_back(info); } @@ -977,14 +1001,15 @@ PackageInfo::SetDepotName(const BString& depotName) bool PackageInfo::AddListener(const PackageInfoListenerRef& listener) { - return fListeners.Add(listener); + fListeners.push_back(listener); + return true; } void PackageInfo::RemoveListener(const PackageInfoListenerRef& listener) { - fListeners.Remove(listener); + std::remove(fListeners.begin(), fListeners.end(), listener); } @@ -1026,21 +1051,23 @@ PackageInfo::_NotifyListeners(uint32 changes) void PackageInfo::_NotifyListenersImmediate(uint32 changes) { - int count = fListeners.CountItems(); + int count = fListeners.size(); if (count == 0) return; // Clone list to avoid listeners detaching themselves in notifications // to screw up the list while iterating it. - PackageListenerList listeners(fListeners); + std::vector listeners(fListeners); + // Check if it worked: - if (listeners.CountItems() != count) + if (listeners.size() != count) return; PackageInfoEvent event(PackageInfoRef(this), changes); - for (int i = 0; i < count; i++) { - const PackageInfoListenerRef& listener = listeners.ItemAtFast(i); + std::vector::iterator it; + for (it = listeners.begin(); it != listeners.end(); it++) { + const PackageInfoListenerRef listener = *it; if (listener.Get() != NULL) listener->PackageChanged(event); } diff --git a/src/apps/haikudepot/model/PackageInfo.h b/src/apps/haikudepot/model/PackageInfo.h index df59c11964..77945c964d 100644 --- a/src/apps/haikudepot/model/PackageInfo.h +++ b/src/apps/haikudepot/model/PackageInfo.h @@ -1,6 +1,6 @@ /* * Copyright 2013-2014, Stephan Aßmus . - * Copyright 2016-2020, Andrew Lindesay . + * Copyright 2016-2021, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ #ifndef PACKAGE_INFO_H @@ -64,7 +64,7 @@ private: }; -class UserRating { +class UserRating : public BReferenceable { public: UserRating(); UserRating(const UserInfo& userInfo, @@ -102,7 +102,7 @@ private: }; -typedef List UserRatingList; +typedef BReference UserRatingRef; class RatingSummary { @@ -183,7 +183,7 @@ extern bool IsPackageCategoryBefore(const CategoryRef& c1, const CategoryRef& c2); -class ScreenshotInfo { +class ScreenshotInfo : public BReferenceable { public: ScreenshotInfo(); ScreenshotInfo(const BString& code, @@ -211,10 +211,9 @@ private: }; -typedef List ScreenshotInfoList; +typedef BReference ScreenshotInfoRef; -typedef List PackageListenerList; typedef std::set PackageInstallationLocationSet; @@ -309,9 +308,9 @@ public: CategoryRef CategoryAtIndex(int32 index) const; void ClearUserRatings(); - bool AddUserRating(const UserRating& rating); - const UserRatingList& UserRatings() const - { return fUserRatings; } + void AddUserRating(const UserRatingRef& rating); + int32 CountUserRatings() const; + UserRatingRef UserRatingAtIndex(int32 index) const; void SetRatingSummary(const RatingSummary& summary); RatingSummary CalculateRatingSummary() const; @@ -323,9 +322,10 @@ public: bool IsProminent() const; void ClearScreenshotInfos(); - bool AddScreenshotInfo(const ScreenshotInfo& info); - const ScreenshotInfoList& ScreenshotInfos() const - { return fScreenshotInfos; } + void AddScreenshotInfo( + const ScreenshotInfoRef& info); + int32 CountScreenshotInfos() const; + ScreenshotInfoRef ScreenshotInfoAtIndex(int32 index) const; void ClearScreenshots(); bool AddScreenshot(const BitmapRef& screenshot); @@ -366,17 +366,20 @@ private: BString fChangelog; std::vector fCategories; - UserRatingList fUserRatings; + std::vector + fUserRatings; RatingSummary fCachedRatingSummary; int64 fProminence; - ScreenshotInfoList fScreenshotInfos; + std::vector + fScreenshotInfos; std::vector fScreenshots; PackageState fState; PackageInstallationLocationSet fInstallationLocations; float fDownloadProgress; - PackageListenerList fListeners; + std::vector + fListeners; int32 fFlags; bool fSystemDependency; BString fArchitecture; diff --git a/src/apps/haikudepot/model/PackageManager.cpp b/src/apps/haikudepot/model/PackageManager.cpp index b7855286c5..9b2d21e818 100644 --- a/src/apps/haikudepot/model/PackageManager.cpp +++ b/src/apps/haikudepot/model/PackageManager.cpp @@ -331,22 +331,23 @@ private: // #pragma mark - OpenPackageAction -struct DeskbarLink { +class DeskbarLink { +public: DeskbarLink() { } DeskbarLink(const BString& path, const BString& link) : - path(path), - link(link) + fPath(path), + fLink(link) { } DeskbarLink(const DeskbarLink& other) : - path(other.path), - link(other.link) + fPath(other.fPath), + fLink(other.fLink) { } @@ -354,14 +355,24 @@ struct DeskbarLink { { if (this == &other) return *this; - path = other.path; - link = other.link; + fPath = other.Path(); + fLink = other.Link(); return *this; } + const BString Path() const + { + return fPath; + } + + const BString Link() const + { + return fLink; + } + bool operator==(const DeskbarLink& other) { - return path == other.path && link == other.link; + return fPath == other.fPath && fLink == other.fLink; } bool operator!=(const DeskbarLink& other) @@ -369,17 +380,18 @@ struct DeskbarLink { return !(*this == other); } - BString path; - BString link; +private: + BString fPath; + BString fLink; }; -typedef List DeskbarLinkList; +typedef BReference DeskbarLinkRef; class DeskbarLinkFinder : public BPackageContentHandler { public: - DeskbarLinkFinder(DeskbarLinkList& foundLinks) + DeskbarLinkFinder(std::vector& foundLinks) : fDeskbarLinks(foundLinks) { @@ -392,7 +404,7 @@ public: && entry->SymlinkPath() != NULL) { HDINFO("found deskbar entry: %s -> %s", path.String(), entry->SymlinkPath()); - fDeskbarLinks.Add(DeskbarLink(path, entry->SymlinkPath())); + fDeskbarLinks.push_back(DeskbarLink(path, entry->SymlinkPath())); } return B_OK; } @@ -431,7 +443,7 @@ public: } private: - DeskbarLinkList& fDeskbarLinks; + std::vector fDeskbarLinks; }; @@ -444,7 +456,7 @@ public: fDeskbarLink(link), fLabel(B_TRANSLATE("Open %DeskbarLink%")) { - BString target = fDeskbarLink.link; + BString target = fDeskbarLink.Link(); int32 lastPathSeparator = target.FindLast('/'); if (lastPathSeparator > 0 && lastPathSeparator + 1 < target.Length()) target.Remove(0, lastPathSeparator + 1); @@ -461,8 +473,8 @@ public: { status_t status; BPath path; - if (fDeskbarLink.link.FindFirst('/') == 0) { - status = path.SetTo(fDeskbarLink.link); + if (fDeskbarLink.Link().FindFirst('/') == 0) { + status = path.SetTo(fDeskbarLink.Link()); HDINFO("trying to launch (absolute link): %s", path.Path()); } else { int32 location = InstallLocation(); @@ -478,11 +490,11 @@ public: return B_ERROR; } - status = path.Append(fDeskbarLink.path); + status = path.Append(fDeskbarLink.Path()); if (status == B_OK) status = path.GetParent(&path); if (status == B_OK) { - status = path.Append(fDeskbarLink.link, true); + status = path.Append(fDeskbarLink.Link(), true); HDINFO("trying to launch: %s", path.Path()); } } @@ -498,7 +510,7 @@ public: } static bool FindAppToLaunch(const PackageInfoRef& package, - DeskbarLinkList& foundLinks) + std::vector& foundLinks) { if (package.Get() == NULL) return false; @@ -545,7 +557,7 @@ public: return false; } - return foundLinks.CountItems() > 0; + return !foundLinks.empty(); } private: @@ -585,36 +597,50 @@ PackageManager::GetPackageState(const PackageInfo& package) } -PackageActionList -PackageManager::GetPackageActions(PackageInfoRef package, Model* model) +void +PackageManager::GetPackageActions(PackageInfoRef package, Model* model, + Collector& actionList) { - PackageActionList actionList; if (package->IsSystemPackage() || package->IsSystemDependency()) - return actionList; + return; - int32 state = package->State(); - if (state == ACTIVATED || state == INSTALLED) { - actionList.Add(PackageActionRef(new UninstallPackageAction( - package, model), true)); - - // Add OpenPackageActions for each deskbar link found in the - // package - DeskbarLinkList foundLinks; - if (OpenPackageAction::FindAppToLaunch(package, foundLinks) - && foundLinks.CountItems() < 4) { - for (int32 i = 0; i < foundLinks.CountItems(); i++) { - const DeskbarLink& link = foundLinks.ItemAtFast(i); - actionList.Add(PackageActionRef(new OpenPackageAction( - package, model, link), true)); - } - } - } else if (state == NONE || state == UNINSTALLED) { - actionList.Add(PackageActionRef(new InstallPackageAction(package, - model), true)); + switch (package->State()) { + case ACTIVATED: + case INSTALLED: + _GatherPackageActionsForActivatedOrInstalled( + package, model, actionList); + break; + case NONE: + case UNINSTALLED: + actionList.Add(PackageActionRef( + new InstallPackageAction(package, model), true)); + break; + default: + break; } - // TODO: activation status +} - return actionList; + +void +PackageManager::_GatherPackageActionsForActivatedOrInstalled( + PackageInfoRef package, Model* model, + Collector& actionList) +{ + actionList.Add(PackageActionRef(new UninstallPackageAction( + package, model), true)); + + // Add OpenPackageActions for each deskbar link found in the + // package + std::vector foundLinks; + if (OpenPackageAction::FindAppToLaunch(package, foundLinks) + && foundLinks.size() < 4) { + std::vector::const_iterator it; + for (it = foundLinks.begin(); it != foundLinks.end(); it++) { + const DeskbarLink& aLink = *it; + actionList.Add(PackageActionRef(new OpenPackageAction( + package, model, aLink), true)); + } + } } diff --git a/src/apps/haikudepot/model/PackageManager.h b/src/apps/haikudepot/model/PackageManager.h index 5fb63e19bd..699e314db0 100644 --- a/src/apps/haikudepot/model/PackageManager.h +++ b/src/apps/haikudepot/model/PackageManager.h @@ -14,6 +14,7 @@ #include #include +#include "Collector.h" #include "DecisionProvider.h" #include "JobStateListener.h" #include "PackageAction.h" @@ -72,8 +73,9 @@ public: virtual ~PackageManager(); virtual PackageState GetPackageState(const PackageInfo& package); - virtual PackageActionList GetPackageActions(PackageInfoRef package, - Model* model); + virtual void GetPackageActions(PackageInfoRef package, + Model* model, + Collector& actionList); void SetCurrentActionPackage( PackageInfoRef package, @@ -120,6 +122,9 @@ private: InstalledRepository& repository); private: + void _GatherPackageActionsForActivatedOrInstalled( + PackageInfoRef package, Model* model, + Collector& actionList); bool _AddResults( BPackageManager::InstalledRepository& repository, diff --git a/src/apps/haikudepot/server/ServerPkgDataUpdateProcess.cpp b/src/apps/haikudepot/server/ServerPkgDataUpdateProcess.cpp index 9418f8c491..771b8a4ba0 100644 --- a/src/apps/haikudepot/server/ServerPkgDataUpdateProcess.cpp +++ b/src/apps/haikudepot/server/ServerPkgDataUpdateProcess.cpp @@ -143,12 +143,12 @@ PackageFillingPkgListener::ConsumePackage(const PackageInfoRef& package, for (i = 0; i < countPkgScreenshots; i++) { DumpExportPkgScreenshot* screenshot = pkg->PkgScreenshotsItemAt(i); - package->AddScreenshotInfo(ScreenshotInfo( + package->AddScreenshotInfo(ScreenshotInfoRef(new ScreenshotInfo( *(screenshot->Code()), static_cast(screenshot->Width()), static_cast(screenshot->Height()), static_cast(screenshot->Length()) - )); + ), true)); } HDDEBUG("did populate data for [%s] (%s)", pkg->Name()->String(), diff --git a/src/apps/haikudepot/ui/PackageInfoView.cpp b/src/apps/haikudepot/ui/PackageInfoView.cpp index 925d191e74..76f098d17e 100644 --- a/src/apps/haikudepot/ui/PackageInfoView.cpp +++ b/src/apps/haikudepot/ui/PackageInfoView.cpp @@ -525,50 +525,20 @@ public: // TODO: if the given package is either a system package // or a system dependency, show a message indicating that status // so the user knows why no actions are presented - PackageActionList actions = manager.GetPackageActions( + std::vector actions; + VectorCollector actionsCollector(actions); + manager.GetPackageActions( const_cast(&package), - fPackageActionHandler->GetModel()); - - bool clearNeeded = fStatusBar != NULL; - if (!clearNeeded) { - if (actions.CountItems() != fPackageActions.CountItems()) - clearNeeded = true; - else { - for (int32 i = 0; i < actions.CountItems(); i++) { - if (actions.ItemAtFast(i)->Type() - != fPackageActions.ItemAtFast(i)->Type()) { - clearNeeded = true; - break; - } - } - } - } + fPackageActionHandler->GetModel(), actionsCollector); + bool clearNeeded = _IsClearNeededToAdoptActions(actions); fPackageActions = actions; - if (!clearNeeded && fButtons.CountItems() == actions.CountItems()) { - int32 index = 0; - for (int32 i = fPackageActions.CountItems() - 1; i >= 0; i--) { - const PackageActionRef& action = fPackageActions.ItemAtFast(i); - BButton* button = (BButton*)fButtons.ItemAtFast(index++); - button->SetLabel(action->Label()); - } - return; - } - Clear(); - - // Add Buttons in reverse action order - for (int32 i = fPackageActions.CountItems() - 1; i >= 0; i--) { - const PackageActionRef& action = fPackageActions.ItemAtFast(i); - - BMessage* message = new BMessage(MSG_PACKAGE_ACTION); - message->AddInt32("index", i); - - BButton* button = new BButton(action->Label(), message); - fLayout->AddView(button); - button->SetTarget(this); - - fButtons.AddItem(button); + if (clearNeeded) { + Clear(); + _CreateAllNewButtonsForAdoptActions(); + } else { + _UpdateExistingButtonsForAdoptActions(); } } @@ -615,13 +585,56 @@ public: } private: + bool _IsClearNeededToAdoptActions(std::vector actions) + { + if (fStatusBar != NULL) + return true; + if (actions.size() != fPackageActions.size()) + return true; + if (fButtons.CountItems() != actions.size()) + return true; + for (int i = 0; (i < actions.size()); i++) { + if (actions[i]->Type() != fPackageActions[i]->Type()) + return true; + } + return false; + } + + void _UpdateExistingButtonsForAdoptActions() + { + // note that by this point, the actions will have been set to the + // member variable. + int32 index = 0; + for (int32 i = fPackageActions.size() - 1; i >= 0; i--) { + const PackageActionRef& action = fPackageActions[i]; + BButton* button = (BButton*)fButtons.ItemAtFast(index++); + button->SetLabel(action->Label()); + } + } + + void _CreateAllNewButtonsForAdoptActions() + { + for (int32 i = fPackageActions.size() - 1; i >= 0; i--) { + const PackageActionRef& action = fPackageActions[i]; + + BMessage* message = new BMessage(MSG_PACKAGE_ACTION); + message->AddInt32("index", i); + + BButton* button = new BButton(action->Label(), message); + fLayout->AddView(button); + button->SetTarget(this); + + fButtons.AddItem(button); + } + } + void _RunPackageAction(BMessage* message) { int32 index; if (message->FindInt32("index", &index) != B_OK) return; - const PackageActionRef& action = fPackageActions.ItemAt(index); + const PackageActionRef& action = fPackageActions[index]; if (action.Get() == NULL) return; @@ -670,8 +683,10 @@ private: private: BGroupLayout* fLayout; - PackageActionList fPackageActions; - PackageActionHandler* fPackageActionHandler; + std::vector + fPackageActions; + PackageActionHandler* + fPackageActionHandler; BList fButtons; BStringView* fStatusLabel; @@ -889,7 +904,7 @@ private: class RatingItemView : public BGroupView { public: - RatingItemView(const UserRating& rating) + RatingItemView(const UserRatingRef rating) : BGroupView(B_HORIZONTAL, 0.0f) { @@ -900,7 +915,7 @@ public: { BStringView* userNicknameView = new BStringView("user-nickname", - rating.User().NickName()); + rating->User().NickName()); userNicknameView->SetFont(be_bold_font); verticalGroup->AddView(userNicknameView); } @@ -909,23 +924,23 @@ public: new BGroupLayout(B_HORIZONTAL, B_USE_DEFAULT_SPACING); verticalGroup->AddItem(ratingGroup); - if (rating.Rating() >= 0) { + if (rating->Rating() >= 0) { RatingView* ratingView = new RatingView("package rating view"); - ratingView->SetRating(rating.Rating()); + ratingView->SetRating(rating->Rating()); ratingGroup->AddView(ratingView); } { BString createTimestampPresentation = LocaleUtils::TimestampToDateTimeString( - rating.CreateTimestamp()); + rating->CreateTimestamp()); BString ratingContextDescription( B_TRANSLATE("%hd.timestamp% (version %hd.version%)")); ratingContextDescription.ReplaceAll("%hd.timestamp%", createTimestampPresentation); ratingContextDescription.ReplaceAll("%hd.version%", - rating.PackageVersion()); + rating->PackageVersion()); BStringView* ratingContextView = new BStringView("rating-context", ratingContextDescription); @@ -936,12 +951,12 @@ public: ratingGroup->AddItem(BSpaceLayoutItem::CreateGlue()); - if (rating.Comment() > 0) { + if (rating->Comment() > 0) { TextView* textView = new TextView("rating-text"); ParagraphStyle paragraphStyle(textView->ParagraphStyle()); paragraphStyle.SetJustify(true); textView->SetParagraphStyle(paragraphStyle); - textView->SetText(rating.Comment()); + textView->SetText(rating->Comment()); verticalGroup->AddItem(BSpaceLayoutItem::CreateVerticalStrut(8.0f)); verticalGroup->AddView(textView); verticalGroup->AddItem(BSpaceLayoutItem::CreateVerticalStrut(8.0f)); @@ -1078,9 +1093,7 @@ public: // TODO: Re-use rating summary already used for TitleView... fRatingSummaryView->SetToSummary(package.CalculateRatingSummary()); - const UserRatingList& userRatings = package.UserRatings(); - - int count = userRatings.CountItems(); + int count = package.CountUserRatings(); if (count == 0) { BStringView* noRatingsView = new BStringView("no ratings", B_TRANSLATE("No user ratings available.")); @@ -1094,9 +1107,8 @@ public: return; } - // TODO: Sort by age or usefullness rating for (int i = count - 1; i >= 0; i--) { - const UserRating& rating = userRatings.ItemAtFast(i); + UserRatingRef rating = package.UserRatingAtIndex(i); // was previously filtering comments just for the current // user's language, but as there are not so many comments at // the moment, just show all of them for now. diff --git a/src/apps/haikudepot/ui/ScreenshotWindow.cpp b/src/apps/haikudepot/ui/ScreenshotWindow.cpp index ae5fe67713..111a13533a 100644 --- a/src/apps/haikudepot/ui/ScreenshotWindow.cpp +++ b/src/apps/haikudepot/ui/ScreenshotWindow.cpp @@ -1,7 +1,7 @@ /* * Copyright 2014, Stephan Aßmus . * Copyright 2017, Julian Harnath . - * Copyright 2020, Andrew Lindesay . + * Copyright 2020-2021, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ @@ -254,6 +254,8 @@ ScreenshotWindow::_DownloadThreadEntry(void* data) void ScreenshotWindow::_DownloadThread() { + ScreenshotInfoRef info; + if (!Lock()) { HDERROR("failed to lock screenshot window"); return; @@ -261,23 +263,24 @@ ScreenshotWindow::_DownloadThread() fScreenshotView->UnsetBitmap(); - ScreenshotInfoList screenshotInfos; - if (fPackage.Get() != NULL) - screenshotInfos = fPackage->ScreenshotInfos(); + if (fPackage.Get() == NULL) + HDINFO("package not set"); + else { + if (fPackage->CountScreenshotInfos() == 0) + HDINFO("package has no screenshots"); + else { + int32 index = atomic_get(&fCurrentScreenshotIndex); + info = fPackage->ScreenshotInfoAtIndex(index); + } + } Unlock(); - if (screenshotInfos.CountItems() == 0) { - HDINFO("package has no screenshots"); + if (info.Get() == NULL) { + HDINFO("screenshot not set"); return; } - // Obtain the correct code for the screenshot to display - // TODO: Once navigation buttons are added, we could use the - // ScreenshotInfo at the "current" index. - const ScreenshotInfo& info = screenshotInfos.ItemAtFast( - atomic_get(&fCurrentScreenshotIndex)); - BMallocIO buffer; WebAppInterface interface; @@ -288,8 +291,8 @@ ScreenshotWindow::_DownloadThread() kProgressIndicatorDelay, 1); // Retrieve screenshot from web-app - status_t status = interface.RetrieveScreenshot(info.Code(), - info.Width(), info.Height(), &buffer); + status_t status = interface.RetrieveScreenshot(info->Code(), + info->Width(), info->Height(), &buffer); delayedMessenger.SetCount(0); messenger.SendMessage(MSG_DOWNLOAD_STOP); @@ -305,28 +308,35 @@ ScreenshotWindow::_DownloadThread() } +BSize +ScreenshotWindow::_MaxWidthAndHeightOfAllScreenshots() +{ + BSize size(0, 0); + + // Find out dimensions of the largest screenshot of this package + if (fPackage.Get() != NULL) { + int count = fPackage->CountScreenshotInfos(); + for(int32 i = 0; i < count; i++) { + const ScreenshotInfoRef& info = fPackage->ScreenshotInfoAtIndex(i); + if (info.Get() != NULL) { + float w = (float) info->Width(); + float h = (float) info->Height(); + if (w > size.Width()) + size.SetWidth(w); + if (h > size.Height()) + size.SetHeight(h); + } + } + } + + return size; +} + + void ScreenshotWindow::_ResizeToFitAndCenter() { - // Find out dimensions of the largest screenshot of this package - ScreenshotInfoList screenshotInfos; - if (fPackage.Get() != NULL) - screenshotInfos = fPackage->ScreenshotInfos(); - - int32 largestScreenshotWidth = 0; - int32 largestScreenshotHeight = 0; - - const uint32 numScreenshots = fPackage->ScreenshotInfos().CountItems(); - for (uint32 i = 0; i < numScreenshots; i++) { - const ScreenshotInfo& info = screenshotInfos.ItemAtFast(i); - if (info.Width() > largestScreenshotWidth) - largestScreenshotWidth = info.Width(); - if (info.Height() > largestScreenshotHeight) - largestScreenshotHeight = info.Height(); - } - - fScreenshotView->SetExplicitMinSize( - BSize(largestScreenshotWidth, largestScreenshotHeight)); + fScreenshotView->SetExplicitMinSize(_MaxWidthAndHeightOfAllScreenshots()); Layout(false); // TODO: Limit window size to screen size (with a little margin), @@ -343,7 +353,7 @@ ScreenshotWindow::_ResizeToFitAndCenter() void ScreenshotWindow::_UpdateToolBar() { - const int32 numScreenshots = fPackage->ScreenshotInfos().CountItems(); + const int32 numScreenshots = fPackage->CountScreenshotInfos(); const int32 currentIndex = atomic_get(&fCurrentScreenshotIndex); fToolBar->SetActionEnabled(MSG_PREVIOUS_SCREENSHOT, diff --git a/src/apps/haikudepot/ui/ScreenshotWindow.h b/src/apps/haikudepot/ui/ScreenshotWindow.h index e96ca02f04..ee73cdf962 100644 --- a/src/apps/haikudepot/ui/ScreenshotWindow.h +++ b/src/apps/haikudepot/ui/ScreenshotWindow.h @@ -1,5 +1,6 @@ /* * Copyright 2014, Stephan Aßmus . + * Copyright 2021, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ #ifndef SCREENSHOT_WINDOW_H @@ -51,6 +52,7 @@ private: static int32 _DownloadThreadEntry(void* data); void _DownloadThread(); + BSize _MaxWidthAndHeightOfAllScreenshots(); void _ResizeToFitAndCenter(); void _UpdateToolBar(); diff --git a/src/apps/haikudepot/util/Collector.h b/src/apps/haikudepot/util/Collector.h new file mode 100644 index 0000000000..cbc3542098 --- /dev/null +++ b/src/apps/haikudepot/util/Collector.h @@ -0,0 +1,37 @@ +/* + * Copyright 2021, Andrew Lindesay + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef COLLECTOR_H +#define COLLECTOR_H + + +#include + + +template +class Collector { +public: + virtual void Add(T value) = 0; +}; + + +template +class VectorCollector : public Collector { +public: + VectorCollector(std::vector& target) + : + fTarget(target) + { + } + + virtual void Add(T value) { + fTarget.push_back(value); + } + +private: + std::vector& fTarget; +}; + + +#endif // COLLECTOR_H