HaikuDepot: Package information can be retrieved asynchronously

This commit is contained in:
Stephan Aßmus 2013-09-16 22:07:43 +02:00 committed by Rene Gollent
parent 62b27e6277
commit 7eec822d5e
5 changed files with 225 additions and 55 deletions

View File

@ -40,7 +40,7 @@ MainWindow::MainWindow(BRect frame)
fFilterView = new FilterView(fModel); fFilterView = new FilterView(fModel);
fPackageListView = new PackageListView(); fPackageListView = new PackageListView();
fPackageInfoView = new PackageInfoView(&fPackageManager); fPackageInfoView = new PackageInfoView(fModel.Lock(), &fPackageManager);
fSplitView = new BSplitView(B_VERTICAL, 5.0f); fSplitView = new BSplitView(B_VERTICAL, 5.0f);
@ -162,7 +162,8 @@ MainWindow::_AdoptModel()
void void
MainWindow::_AdoptPackage(const PackageInfoRef& package) MainWindow::_AdoptPackage(const PackageInfoRef& package)
{ {
fPackageInfoView->SetPackage(*package.Get()); fPackageInfoView->SetPackage(package);
fModel.PopulatePackage(package);
} }
@ -176,9 +177,12 @@ MainWindow::_ClearPackage()
void void
MainWindow::_InitDummyModel() MainWindow::_InitDummyModel()
{ {
// TODO: The Model could be filled from another thread by // TODO: The Model needs to be filled initially by the Package Kit APIs.
// sending messages which contain collected package information. // It already caches information locally. Error handlers need to be
// The Model could be cached on disk. // 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")); DepotInfo depot(B_TRANSLATE("Default"));
@ -197,16 +201,6 @@ MainWindow::_InitDummyModel()
"on Haiku. It combines many great under-the-hood features with " "on Haiku. It combines many great under-the-hood features with "
"powerful tools and an efficient and intuitive interface.", "powerful tools and an efficient and intuitive interface.",
"2.1.2 - Initial Haiku release."), true); "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.CategoryGraphics());
wonderbrush->AddCategory(fModel.CategoryProductivity()); wonderbrush->AddCategory(fModel.CategoryProductivity());
@ -228,23 +222,6 @@ MainWindow::_InitDummyModel()
"missing from BeIDE, like running a project in the Terminal, " "missing from BeIDE, like running a project in the Terminal, "
"and has a bundled text editor based upon Pe.", "and has a bundled text editor based upon Pe.",
""), true); ""), 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()); paladin->AddCategory(fModel.CategoryDevelopment());
depot.AddPackage(paladin); depot.AddPackage(paladin);
@ -315,24 +292,6 @@ MainWindow::_InitDummyModel()
"filter.\n\n" "filter.\n\n"
" * ''Note to filter developers:'' The filter API has changed. You " " * ''Note to filter developers:'' The filter API has changed. You "
"will need to recompile your filters."), true); "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()); sequitur->AddCategory(fModel.CategoryAudio());
depot.AddPackage(sequitur); depot.AddPackage(sequitur);

View File

@ -7,6 +7,7 @@
#include <stdio.h> #include <stdio.h>
#include <Autolock.h>
#include <Catalog.h> #include <Catalog.h>
@ -366,3 +367,86 @@ Model::SetSearchTerms(const BString& searchTerms)
fSearchTermsFilter.SetTo(filter, true); 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)
);
}
}

View File

@ -5,6 +5,7 @@
#ifndef MODEL_H #ifndef MODEL_H
#define MODEL_H #define MODEL_H
#include <Locker.h>
#include "PackageInfo.h" #include "PackageInfo.h"
@ -24,6 +25,9 @@ class Model {
public: public:
Model(); Model();
BLocker* Lock()
{ return &fLock; }
// !Returns new PackageInfoList from current parameters // !Returns new PackageInfoList from current parameters
PackageList CreatePackageList() const; PackageList CreatePackageList() const;
@ -63,7 +67,12 @@ public:
void SetDepot(const BString& depot); void SetDepot(const BString& depot);
void SetSearchTerms(const BString& searchTerms); void SetSearchTerms(const BString& searchTerms);
// Retrieve package information
void PopulatePackage(const PackageInfoRef& package);
private: private:
BLocker fLock;
DepotList fDepots; DepotList fDepots;
CategoryRef fCategoryAudio; CategoryRef fCategoryAudio;
@ -84,6 +93,7 @@ private:
PackageList fUninstalledPackages; PackageList fUninstalledPackages;
PackageList fDownloadingPackages; PackageList fDownloadingPackages;
PackageList fUpdateablePackages; PackageList fUpdateablePackages;
PackageList fPopulatedPackages;
PackageFilterRef fCategoryFilter; PackageFilterRef fCategoryFilter;
BString fDepotFilter; BString fDepotFilter;

View File

@ -8,6 +8,7 @@
#include <algorithm> #include <algorithm>
#include <stdio.h> #include <stdio.h>
#include <Autolock.h>
#include <Bitmap.h> #include <Bitmap.h>
#include <Button.h> #include <Button.h>
#include <CardLayout.h> #include <CardLayout.h>
@ -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 // #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(); fTitleView = new TitleView();
fPackageActionView = new PackageActionView(packageManager); fPackageActionView = new PackageActionView(packageManager);
@ -1150,6 +1216,8 @@ PackageInfoView::PackageInfoView(PackageManager* packageManager)
PackageInfoView::~PackageInfoView() PackageInfoView::~PackageInfoView()
{ {
fPackageListener->SetPackage(PackageInfoRef(NULL));
delete fPackageListener;
} }
@ -1163,6 +1231,35 @@ void
PackageInfoView::MessageReceived(BMessage* message) PackageInfoView::MessageReceived(BMessage* message)
{ {
switch (message->what) { 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: default:
BGroupView::MessageReceived(message); BGroupView::MessageReceived(message);
break; break;
@ -1171,14 +1268,20 @@ PackageInfoView::MessageReceived(BMessage* message)
void void
PackageInfoView::SetPackage(const PackageInfo& package) PackageInfoView::SetPackage(const PackageInfoRef& packageRef)
{ {
BAutolock _(fModelLock);
const PackageInfo& package = *packageRef.Get();
fTitleView->SetPackage(package); fTitleView->SetPackage(package);
fPackageActionView->SetPackage(package); fPackageActionView->SetPackage(package);
fPagesView->SetPackage(package); fPagesView->SetPackage(package);
if (fPagesView->IsHidden(fPagesView)) if (fPagesView->IsHidden(fPagesView))
fPagesView->Show(); fPagesView->Show();
fPackageListener->SetPackage(packageRef);
} }
@ -1191,5 +1294,9 @@ PackageInfoView::Clear()
if (!fPagesView->IsHidden(fPagesView)) if (!fPagesView->IsHidden(fPagesView))
fPagesView->Hide(); fPagesView->Hide();
BAutolock _(fModelLock);
fPackageListener->SetPackage(PackageInfoRef(NULL));
} }

View File

@ -8,8 +8,10 @@
#include <GroupView.h> #include <GroupView.h>
#include "PackageInfo.h" #include "PackageInfo.h"
#include "PackageInfoListener.h"
class BLocker;
class TitleView; class TitleView;
class PackageActionView; class PackageActionView;
class PackageManager; class PackageManager;
@ -23,19 +25,27 @@ enum {
class PackageInfoView : public BGroupView { class PackageInfoView : public BGroupView {
public: public:
PackageInfoView(PackageManager* packageManager); PackageInfoView(BLocker* modelLock,
PackageManager* packageManager);
virtual ~PackageInfoView(); virtual ~PackageInfoView();
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
void SetPackage(const PackageInfo& package); void SetPackage(const PackageInfoRef& package);
void Clear(); void Clear();
private: private:
class Listener;
private:
BLocker* fModelLock;
TitleView* fTitleView; TitleView* fTitleView;
PackageActionView* fPackageActionView; PackageActionView* fPackageActionView;
PagesView* fPagesView; PagesView* fPagesView;
Listener* fPackageListener;
}; };
#endif // PACKAGE_INFO_VIEW_H #endif // PACKAGE_INFO_VIEW_H