HaikuDepot: Update package list when necessary

* Pass the Model lock to the PackageListView.
 * Register a PackageInfoListener with every listed package.
 * Update the rating when it is fetched.
This commit is contained in:
Stephan Aßmus
2013-09-17 14:42:03 +02:00
committed by Rene Gollent
parent ed6f171aa6
commit b748950b74
3 changed files with 133 additions and 12 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ MainWindow::MainWindow(BRect frame)
_BuildMenu(menuBar);
fFilterView = new FilterView(fModel);
fPackageListView = new PackageListView();
fPackageListView = new PackageListView(fModel.Lock());
fPackageInfoView = new PackageInfoView(fModel.Lock(), &fPackageManager);
fSplitView = new BSplitView(B_VERTICAL, 5.0f);
+123 -9
View File
@@ -8,6 +8,7 @@
#include <algorithm>
#include <stdio.h>
#include <Autolock.h>
#include <Catalog.h>
#include <ScrollBar.h>
#include <Window.h>
@@ -80,13 +81,58 @@ private:
class PackageRow : public BRow {
typedef BRow Inherited;
public:
PackageRow(const PackageInfoRef& package);
PackageRow(const PackageInfoRef& package,
PackageListener* listener);
virtual ~PackageRow();
const PackageInfoRef& Package() const
{ return fPackage; }
void UpdateRating();
private:
PackageInfoRef fPackage;
PackageInfoListenerRef fPackageListener;
};
enum {
MSG_UPDATE_PACKAGE = 'updp'
};
class PackageListener : public PackageInfoListener {
public:
PackageListener(PackageListView* view)
:
fView(view)
{
}
virtual ~PackageListener()
{
}
virtual void PackageChanged(const PackageInfoEvent& event)
{
if ((event.Changes() & PKG_CHANGED_RATINGS) == 0)
return;
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);
}
private:
PackageListView* fView;
};
@@ -374,15 +420,17 @@ enum {
};
PackageRow::PackageRow(const PackageInfoRef& packageRef)
PackageRow::PackageRow(const PackageInfoRef& packageRef,
PackageListener* packageListener)
:
Inherited(ceilf(be_plain_font->Size() * 1.8f)),
fPackage(packageRef)
fPackage(packageRef),
fPackageListener(packageListener)
{
if (packageRef.Get() == NULL)
return;
const PackageInfo& package = *packageRef.Get();
PackageInfo& package = *packageRef.Get();
// Package icon and title
// NOTE: The icon BBitmap is referenced by the fPackage member.
@@ -392,8 +440,7 @@ PackageRow::PackageRow(const PackageInfoRef& packageRef)
SetField(new BBitmapStringField(icon, package.Title()), kTitleColumn);
// Rating
RatingSummary summary = package.CalculateRatingSummary();
SetField(new RatingField(summary.averageRating), kRatingColumn);
UpdateRating();
// Description
SetField(new BStringField(package.ShortDescription()), kDescriptionColumn);
@@ -405,6 +452,25 @@ PackageRow::PackageRow(const PackageInfoRef& packageRef)
// Status
// TODO: Fetch info about installed/deactivated/unintalled/...
SetField(new BStringField("n/a"), kStatusColumn);
package.AddListener(fPackageListener);
}
PackageRow::~PackageRow()
{
if (fPackage.Get() != NULL)
fPackage->RemoveListener(fPackageListener);
}
void
PackageRow::UpdateRating()
{
if (fPackage.Get() == NULL)
return;
RatingSummary summary = fPackage->CalculateRatingSummary();
SetField(new RatingField(summary.averageRating), kRatingColumn);
}
@@ -492,9 +558,11 @@ private:
// #pragma mark - PackageListView
PackageListView::PackageListView()
PackageListView::PackageListView(BLocker* modelLock)
:
BColumnListView("package list view", 0, B_FANCY_BORDER, true)
BColumnListView("package list view", 0, B_FANCY_BORDER, true),
fModelLock(modelLock),
fPackageListener(new(std::nothrow) PackageListener(this))
{
AddColumn(new PackageColumn(B_TRANSLATE("Name"), 150, 50, 300,
B_TRUNCATE_MIDDLE), kTitleColumn);
@@ -516,6 +584,8 @@ PackageListView::PackageListView()
PackageListView::~PackageListView()
{
Clear();
delete fPackageListener;
}
@@ -530,6 +600,27 @@ void
PackageListView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_UPDATE_PACKAGE:
{
BString title;
uint32 changes;
if (message->FindString("title", &title) != B_OK
|| message->FindUInt32("changes", &changes) != B_OK) {
break;
}
if ((changes & PKG_CHANGED_RATINGS) == 0)
break;
BAutolock _(fModelLock);
PackageRow* row = _FindRow(title);
if (row != NULL)
row->UpdateRating();
break;
}
default:
BColumnListView::MessageReceived(message);
break;
@@ -561,8 +652,10 @@ PackageListView::AddPackage(const PackageInfoRef& package)
if (packageRow != NULL)
return;
BAutolock _(fModelLock);
// create the row for this package
packageRow = new PackageRow(package);
packageRow = new PackageRow(package, fPackageListener);
// add the row, parent may be NULL (add at top level)
AddRow(packageRow);
@@ -592,3 +685,24 @@ PackageListView::_FindRow(const PackageInfoRef& package, PackageRow* parent)
return NULL;
}
PackageRow*
PackageListView::_FindRow(const BString& packageTitle, PackageRow* parent)
{
for (int32 i = CountRows(parent) - 1; i >= 0; i--) {
PackageRow* row = dynamic_cast<PackageRow*>(RowAt(i, parent));
if (row != NULL && row->Package().Get() != NULL
&& row->Package()->Title() == packageTitle) {
return row;
}
if (CountRows(row) > 0) {
// recurse into child rows
row = _FindRow(packageTitle, row);
if (row != NULL)
return row;
}
}
return NULL;
}
+9 -2
View File
@@ -8,11 +8,13 @@
#include <ColumnListView.h>
#include <ColumnTypes.h>
#include <Locker.h>
#include "PackageInfo.h"
class PackageRow;
class PackageListener;
enum {
MSG_PACKAGE_SELECTED = 'pkgs',
@@ -21,7 +23,7 @@ enum {
class PackageListView : public BColumnListView {
public:
PackageListView();
PackageListView(BLocker* modelLock);
virtual ~PackageListView();
virtual void AttachedToWindow();
@@ -34,10 +36,15 @@ public:
private:
PackageRow* _FindRow(const PackageInfoRef& package,
PackageRow* parent = NULL);
PackageRow* _FindRow(const BString& packageTitle,
PackageRow* parent = NULL);
private:
class ItemCountView;
BLocker* fModelLock;
ItemCountView* fItemCountView;
PackageListener* fPackageListener;
};
#endif // PACKAGE_LIST_VIEW_H