diff --git a/src/apps/haiku-depot/MainWindow.cpp b/src/apps/haiku-depot/MainWindow.cpp index 92eaa9c338..6b332b93aa 100644 --- a/src/apps/haiku-depot/MainWindow.cpp +++ b/src/apps/haiku-depot/MainWindow.cpp @@ -40,7 +40,7 @@ MainWindow::MainWindow(BRect frame) fFilterView = new FilterView(fModel); fPackageListView = new PackageListView(); - fPackageInfoView = new PackageInfoView(&fPackageManager); + fPackageInfoView = new PackageInfoView(fModel.Lock(), &fPackageManager); fSplitView = new BSplitView(B_VERTICAL, 5.0f); @@ -162,7 +162,8 @@ MainWindow::_AdoptModel() void MainWindow::_AdoptPackage(const PackageInfoRef& package) { - fPackageInfoView->SetPackage(*package.Get()); + fPackageInfoView->SetPackage(package); + fModel.PopulatePackage(package); } @@ -176,9 +177,12 @@ MainWindow::_ClearPackage() void MainWindow::_InitDummyModel() { - // TODO: The Model could be filled from another thread by - // sending messages which contain collected package information. - // The Model could be cached on disk. + // TODO: The Model needs to be filled initially by the Package Kit APIs. + // It already caches information locally. Error handlers need to be + // installed to display problems to the user. When a package is selected + // for display, extra information is retrieved like screen-shots, user- + // ratings and so on. This triggers notifications which in turn updates + // the UI. DepotInfo depot(B_TRANSLATE("Default")); @@ -197,16 +201,6 @@ MainWindow::_InitDummyModel() "on Haiku. It combines many great under-the-hood features with " "powerful tools and an efficient and intuitive interface.", "2.1.2 - Initial Haiku release."), true); - wonderbrush->AddUserRating( - UserRating(UserInfo("humdinger"), 4.5f, - "Awesome!", "en", "2.1.2", 0, 0) - ); - wonderbrush->AddUserRating( - UserRating(UserInfo("bonefish"), 5.0f, - "The best!", "en", "2.1.2", 3, 1) - ); - wonderbrush->AddScreenshot( - BitmapRef(new SharedBitmap(603), true)); wonderbrush->AddCategory(fModel.CategoryGraphics()); wonderbrush->AddCategory(fModel.CategoryProductivity()); @@ -228,23 +222,6 @@ MainWindow::_InitDummyModel() "missing from BeIDE, like running a project in the Terminal, " "and has a bundled text editor based upon Pe.", ""), true); - paladin->AddUserRating( - UserRating(UserInfo("stippi"), 3.5f, - "Could be more integrated from the sounds of it.", - "en", "1.2.0", 0, 1) - ); - paladin->AddUserRating( - UserRating(UserInfo("mmadia"), 5.0f, - "It rocks! Give a try", - "en", "1.1.0", 1, 0) - ); - paladin->AddUserRating( - UserRating(UserInfo("bonefish"), 2.0f, - "It just needs to use my jam-rewrite 'ham' and it will be great.", - "en", "1.1.0", 3, 1) - ); - paladin->AddScreenshot( - BitmapRef(new SharedBitmap(605), true)); paladin->AddCategory(fModel.CategoryDevelopment()); depot.AddPackage(paladin); @@ -315,24 +292,6 @@ MainWindow::_InitDummyModel() "filter.\n\n" " * ''Note to filter developers:'' The filter API has changed. You " "will need to recompile your filters."), true); - sequitur->AddUserRating( - UserRating(UserInfo("pete"), 4.5f, - "I can weave a web of sound! And it connects to PatchBay. Check " - "it out, I can wholeheartly recommend this app!! This rating " - "comment is of course only so long, because the new TextView " - "layout needs some testing. Oh, and did I mention it works with " - "custom installed sound fonts? Reading through this comment I find " - "that I did not until now. Hopefully there are enough lines now to " - "please the programmer with the text layouting and scrolling of " - "long ratings!", "en", "2.1.0", 4, 1) - ); - sequitur->AddUserRating( - UserRating(UserInfo("stippi"), 3.5f, - "It seems very capable. Still runs fine on Haiku. The interface " - "is composed of many small, hard to click items. But you can " - "configure a tool for each mouse button, which is great for the " - "work flow.", "en", "2.1.0", 2, 1) - ); sequitur->AddCategory(fModel.CategoryAudio()); depot.AddPackage(sequitur); diff --git a/src/apps/haiku-depot/Model.cpp b/src/apps/haiku-depot/Model.cpp index a6c16f5917..fecc10f5f4 100644 --- a/src/apps/haiku-depot/Model.cpp +++ b/src/apps/haiku-depot/Model.cpp @@ -7,6 +7,7 @@ #include +#include #include @@ -366,3 +367,86 @@ Model::SetSearchTerms(const BString& searchTerms) fSearchTermsFilter.SetTo(filter, true); } + +// #pragma mark - information retrival + + +void +Model::PopulatePackage(const PackageInfoRef& package) +{ + if (fPopulatedPackages.Contains(package)) + return; + + BAutolock _(&fLock); + + // TODO: Replace with actual backend that retrieves package extra + // information and user-contributed package information. + + // TODO: There should probably also be a way to "unpopulate" the + // package information. Maybe a cache of populated packages, so that + // packages loose their extra information after a certain amount of + // time when they have not been accessed/displayed in the UI. Otherwise + // HaikuDepot will consume more and more resources in the packages. + // Especially screen-shots will be a problem eventually. + + // TODO: Simulate a delay in retrieving this info, and do that on + // a separate thread. + + fPopulatedPackages.Add(package); + + if (package->Title() == "WonderBrush") { + + package->AddUserRating( + UserRating(UserInfo("humdinger"), 4.5f, + "Awesome!", "en", "2.1.2", 0, 0) + ); + package->AddUserRating( + UserRating(UserInfo("bonefish"), 5.0f, + "The best!", "en", "2.1.2", 3, 1) + ); + package->AddScreenshot( + BitmapRef(new SharedBitmap(603), true)); + + } else if (package->Title() == "Paladin") { + + package->AddUserRating( + UserRating(UserInfo("stippi"), 3.5f, + "Could be more integrated from the sounds of it.", + "en", "1.2.0", 0, 1) + ); + package->AddUserRating( + UserRating(UserInfo("mmadia"), 5.0f, + "It rocks! Give a try", + "en", "1.1.0", 1, 0) + ); + package->AddUserRating( + UserRating(UserInfo("bonefish"), 2.0f, + "It just needs to use my jam-rewrite 'ham' and it will be great.", + "en", "1.1.0", 3, 1) + ); + package->AddScreenshot( + BitmapRef(new SharedBitmap(605), true)); + + } else if (package->Title() == "Sequitur") { + + package->AddUserRating( + UserRating(UserInfo("pete"), 4.5f, + "I can weave a web of sound! And it connects to PatchBay. Check " + "it out, I can wholeheartly recommend this app!! This rating " + "comment is of course only so long, because the new TextView " + "layout needs some testing. Oh, and did I mention it works with " + "custom installed sound fonts? Reading through this comment I find " + "that I did not until now. Hopefully there are enough lines now to " + "please the programmer with the text layouting and scrolling of " + "long ratings!", "en", "2.1.0", 4, 1) + ); + package->AddUserRating( + UserRating(UserInfo("stippi"), 3.5f, + "It seems very capable. Still runs fine on Haiku. The interface " + "is composed of many small, hard to click items. But you can " + "configure a tool for each mouse button, which is great for the " + "work flow.", "en", "2.1.0", 2, 1) + ); + + } +} diff --git a/src/apps/haiku-depot/Model.h b/src/apps/haiku-depot/Model.h index 390c0a6c39..f6f5087c20 100644 --- a/src/apps/haiku-depot/Model.h +++ b/src/apps/haiku-depot/Model.h @@ -5,6 +5,7 @@ #ifndef MODEL_H #define MODEL_H +#include #include "PackageInfo.h" @@ -24,6 +25,9 @@ class Model { public: Model(); + BLocker* Lock() + { return &fLock; } + // !Returns new PackageInfoList from current parameters PackageList CreatePackageList() const; @@ -63,7 +67,12 @@ public: void SetDepot(const BString& depot); void SetSearchTerms(const BString& searchTerms); + // Retrieve package information + void PopulatePackage(const PackageInfoRef& package); + private: + BLocker fLock; + DepotList fDepots; CategoryRef fCategoryAudio; @@ -84,6 +93,7 @@ private: PackageList fUninstalledPackages; PackageList fDownloadingPackages; PackageList fUpdateablePackages; + PackageList fPopulatedPackages; PackageFilterRef fCategoryFilter; BString fDepotFilter; diff --git a/src/apps/haiku-depot/PackageInfoView.cpp b/src/apps/haiku-depot/PackageInfoView.cpp index 51b92c51e5..d040ee26d7 100644 --- a/src/apps/haiku-depot/PackageInfoView.cpp +++ b/src/apps/haiku-depot/PackageInfoView.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -1122,12 +1123,77 @@ private: }; +// #pragma mark - PackageInfoViewListener + + +enum { + MSG_UPDATE_PACKAGE = 'updp' +}; + + +class PackageInfoView::Listener : public PackageInfoListener { +public: + Listener(PackageInfoView* view) + : + fView(view) + { + } + + virtual ~Listener() + { + } + + virtual void PackageChanged(const PackageInfoEvent& event) + { + BMessenger messenger(fView); + if (!messenger.IsValid()) + return; + + const PackageInfo& package = *event.Package().Get(); + + BMessage message(MSG_UPDATE_PACKAGE); + message.AddString("title", package.Title()); + message.AddUInt32("changes", event.Changes()); + + messenger.SendMessage(&message); + } + + void SetPackage(const PackageInfoRef& package) + { + if (fPackage == package) + return; + + PackageInfoListenerRef listener(this); + + if (fPackage.Get() != NULL) + fPackage->RemoveListener(listener); + + fPackage = package; + + if (fPackage.Get() != NULL) + fPackage->AddListener(listener); + } + + const PackageInfoRef& Package() const + { + return fPackage; + } + +private: + PackageInfoView* fView; + PackageInfoRef fPackage; +}; + + // #pragma mark - PackageInfoView -PackageInfoView::PackageInfoView(PackageManager* packageManager) +PackageInfoView::PackageInfoView(BLocker* modelLock, + PackageManager* packageManager) : - BGroupView("package info view", B_VERTICAL) + BGroupView("package info view", B_VERTICAL), + fModelLock(modelLock), + fPackageListener(new(std::nothrow) Listener(this)) { fTitleView = new TitleView(); fPackageActionView = new PackageActionView(packageManager); @@ -1150,6 +1216,8 @@ PackageInfoView::PackageInfoView(PackageManager* packageManager) PackageInfoView::~PackageInfoView() { + fPackageListener->SetPackage(PackageInfoRef(NULL)); + delete fPackageListener; } @@ -1163,6 +1231,35 @@ void PackageInfoView::MessageReceived(BMessage* message) { switch (message->what) { + case MSG_UPDATE_PACKAGE: + { + if (fPackageListener->Package().Get() == NULL) + break; + + BString title; + uint32 changes; + if (message->FindString("title", &title) != B_OK + || message->FindUInt32("changes", &changes) != B_OK) { + break; + } + + const PackageInfo& package = *fPackageListener->Package().Get(); + if (package.Title() != title) + break; + + BAutolock _(fModelLock); + + if ((changes & PKG_CHANGED_DESCRIPTION) != 0 + || (changes & PKG_CHANGED_SCREENSHOTS) != 0) { + fTitleView->SetPackage(package); + } + + if ((changes & PKG_CHANGED_RATINGS) != 0) { + fPagesView->SetPackage(package); + } + + break; + } default: BGroupView::MessageReceived(message); break; @@ -1171,14 +1268,20 @@ PackageInfoView::MessageReceived(BMessage* message) void -PackageInfoView::SetPackage(const PackageInfo& package) +PackageInfoView::SetPackage(const PackageInfoRef& packageRef) { + BAutolock _(fModelLock); + + const PackageInfo& package = *packageRef.Get(); + fTitleView->SetPackage(package); fPackageActionView->SetPackage(package); fPagesView->SetPackage(package); if (fPagesView->IsHidden(fPagesView)) fPagesView->Show(); + + fPackageListener->SetPackage(packageRef); } @@ -1191,5 +1294,9 @@ PackageInfoView::Clear() if (!fPagesView->IsHidden(fPagesView)) fPagesView->Hide(); + + BAutolock _(fModelLock); + + fPackageListener->SetPackage(PackageInfoRef(NULL)); } diff --git a/src/apps/haiku-depot/PackageInfoView.h b/src/apps/haiku-depot/PackageInfoView.h index ea871dda36..723fa7a266 100644 --- a/src/apps/haiku-depot/PackageInfoView.h +++ b/src/apps/haiku-depot/PackageInfoView.h @@ -8,8 +8,10 @@ #include #include "PackageInfo.h" +#include "PackageInfoListener.h" +class BLocker; class TitleView; class PackageActionView; class PackageManager; @@ -23,19 +25,27 @@ enum { class PackageInfoView : public BGroupView { public: - PackageInfoView(PackageManager* packageManager); + PackageInfoView(BLocker* modelLock, + PackageManager* packageManager); virtual ~PackageInfoView(); virtual void AttachedToWindow(); virtual void MessageReceived(BMessage* message); - void SetPackage(const PackageInfo& package); + void SetPackage(const PackageInfoRef& package); void Clear(); private: + class Listener; + +private: + BLocker* fModelLock; + TitleView* fTitleView; PackageActionView* fPackageActionView; PagesView* fPagesView; + + Listener* fPackageListener; }; #endif // PACKAGE_INFO_VIEW_H