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);
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);

View File

@ -7,6 +7,7 @@
#include <stdio.h>
#include <Autolock.h>
#include <Catalog.h>
@ -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)
);
}
}

View File

@ -5,6 +5,7 @@
#ifndef MODEL_H
#define MODEL_H
#include <Locker.h>
#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;

View File

@ -8,6 +8,7 @@
#include <algorithm>
#include <stdio.h>
#include <Autolock.h>
#include <Bitmap.h>
#include <Button.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
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));
}

View File

@ -8,8 +8,10 @@
#include <GroupView.h>
#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