HaikuDepot: Refactor for general performance
This commit is a large "big bang" commit of a composite of changes
that would have been challenging to put in place over a PR train.
The changes yield a significant performance improvement in general
but also lay the foundation for being able to make further smaller
gains over time. The changes should also improve stability of the
application. This commit is a high-risk change and would ideally
be coupled with testing.
The key things which have changed in this commit;
- Code reformatting has been applied at the same time.
- Data models are now largely immutable with builder-style
constructors.
- The code base was previously handling locking of data obtained
from the central model manually in many places which was
prone to mistakes. Now accessing data is, from the clients'
perspective, largely lock-free.
- The removal of locks now removes lock-contention in various
areas of the application including startup which helps with
improving performance.
- Repositories of data such as categories and languages are
now also immutable.
- To simplify data immutability, packages' data is stored in the
central model separately from depots' data.
- Large package data mutations are now done in chunks of packages
rather than package-by-package which means reduced messaging
within the application; especially around the GUI.
- The resolution of data / mutations' notifications is larger
so that changes are not being considered on each property of
a package which simplifies the processing logic in a number of
places.
- Package change-notification is driven out of the central model
rather than from each and every package. There is scope for
further simplification in this space.
- Where logic already knows what data is changed, it is able to
control the change-notification process rather than cause a
large number of object-comparisons to be required.
- The data-loaders from the local package manager and from HDS
have been re-written to work with immutable models.
- The icon repositories have been re-written to make a one-time
notification that icons have changed rather than notify for
every package.
- Data updates reflection in the UI has been changed to work in
chunks of packages rather than package by package which
reduces the quantity of UI window-invalidation / redraws and
also reduces the quantity of re-calculation of scrollbars and
other UI elements.
- Some UI elements have their metrics calculated lazily rather
than up-front which yields a significant performance gain.
Change-Id: Iefaf4a137411e379e4c461ebc8c783fd1646bcf4
Reviewed-on: https://review.haiku-os.org/c/haiku/+/9093
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: Andrew Lindesay <[email protected]>
This commit is contained in:
@@ -8,7 +8,7 @@ resource app_flags B_SINGLE_LAUNCH;
|
|||||||
resource app_version {
|
resource app_version {
|
||||||
major = 0,
|
major = 0,
|
||||||
middle = 0,
|
middle = 0,
|
||||||
minor = 8,
|
minor = 9,
|
||||||
|
|
||||||
variety = B_APPV_ALPHA,
|
variety = B_APPV_ALPHA,
|
||||||
internal = 1,
|
internal = 1,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2018-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef HAIKU_DEPOT_CONSTANTS_H
|
#ifndef HAIKU_DEPOT_CONSTANTS_H
|
||||||
@@ -118,9 +118,19 @@ enum UserUsageConditionsSelectionMode {
|
|||||||
// any prominence ordering value greater than this is not prominent.
|
// any prominence ordering value greater than this is not prominent.
|
||||||
#define PROMINANCE_ORDERING_MAX 1000
|
#define PROMINANCE_ORDERING_MAX 1000
|
||||||
// this is the highest prominence value possible.
|
// this is the highest prominence value possible.
|
||||||
|
#define PROMINANCE_ORDERING_NONE 0
|
||||||
|
|
||||||
#define SINGLE_PACKAGE_DEPOT_NAME "__hd_single_pkg_depot"
|
#define SINGLE_PACKAGE_DEPOT_NAME "__hd_single_pkg_depot"
|
||||||
// used as a fake depot name for the case where the application is looking
|
// used as a fake depot name for the case where the application is looking
|
||||||
// at a single package based on a file.
|
// at a single package based on a file.
|
||||||
|
|
||||||
|
#define SINGLE_PACKAGE_DEPOT_IDENTIFIER "__hd_single_pkg_depot_id_c07fb16620f4"
|
||||||
|
// used as a fake depot name for the case where the application is looking
|
||||||
|
// at a single package based on a file.
|
||||||
|
|
||||||
|
#define LOCAL_DEPOT_IDENTIFIER "__hd_local_depot_id_008922773013"
|
||||||
|
// used as a fake depot identifier that is a placeholder used to convey
|
||||||
|
// packages that are only installed locally and do not exist in a remote
|
||||||
|
// repository.
|
||||||
|
|
||||||
#endif // HAIKU_DEPOT_CONSTANTS_H
|
#endif // HAIKU_DEPOT_CONSTANTS_H
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ local dumpExportReferenceModelTargetFile =
|
|||||||
# source directories
|
# source directories
|
||||||
local sourceDirs =
|
local sourceDirs =
|
||||||
edits_generic
|
edits_generic
|
||||||
|
icon
|
||||||
model
|
model
|
||||||
packagemanagement
|
packagemanagement
|
||||||
packagemodel
|
packagemodel
|
||||||
@@ -124,21 +125,18 @@ local applicationSources =
|
|||||||
FeaturedPackagesView.cpp
|
FeaturedPackagesView.cpp
|
||||||
FilterView.cpp
|
FilterView.cpp
|
||||||
GeneralContentScrollView.cpp
|
GeneralContentScrollView.cpp
|
||||||
IconTarPtr.cpp
|
IdentityAndAccessUtils.cpp
|
||||||
IncrementViewCounterProcess.cpp
|
IncrementViewCounterProcess.cpp
|
||||||
JobStateListener.cpp
|
JobStateListener.cpp
|
||||||
JwtTokenHelper.cpp
|
JwtTokenHelper.cpp
|
||||||
LanguageRepository.cpp
|
|
||||||
LinkView.cpp
|
LinkView.cpp
|
||||||
LinkedBitmapView.cpp
|
LinkedBitmapView.cpp
|
||||||
Logger.cpp
|
Logger.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
MainWindow.cpp
|
MainWindow.cpp
|
||||||
MarkupTextView.cpp
|
MarkupTextView.cpp
|
||||||
MessagePackageListener.cpp
|
|
||||||
Model.cpp
|
Model.cpp
|
||||||
PackageContentsView.cpp
|
PackageContentsView.cpp
|
||||||
PackageIconTarRepository.cpp
|
|
||||||
PackageInfoListener.cpp
|
PackageInfoListener.cpp
|
||||||
PackageInfoView.cpp
|
PackageInfoView.cpp
|
||||||
PackageListView.cpp
|
PackageListView.cpp
|
||||||
@@ -165,6 +163,11 @@ local applicationSources =
|
|||||||
ValidationUtils.cpp
|
ValidationUtils.cpp
|
||||||
WorkStatusView.cpp
|
WorkStatusView.cpp
|
||||||
|
|
||||||
|
# icon
|
||||||
|
IconTarPtr.cpp
|
||||||
|
PackageIconDefaultRepository.cpp
|
||||||
|
PackageIconTarRepository.cpp
|
||||||
|
|
||||||
# packagemanagement
|
# packagemanagement
|
||||||
AbstractPackageProcess.cpp
|
AbstractPackageProcess.cpp
|
||||||
InstallPackageProcess.cpp
|
InstallPackageProcess.cpp
|
||||||
@@ -180,17 +183,17 @@ local applicationSources =
|
|||||||
PackageClassificationInfo.cpp
|
PackageClassificationInfo.cpp
|
||||||
PackageCoreInfo.cpp
|
PackageCoreInfo.cpp
|
||||||
PackageFilter.cpp
|
PackageFilter.cpp
|
||||||
PackageFilterModel.cpp
|
PackageFilterSpecification.cpp
|
||||||
PackageInfo.cpp
|
PackageInfo.cpp
|
||||||
PackageLocalInfo.cpp
|
PackageLocalInfo.cpp
|
||||||
PackageLocalizedText.cpp
|
PackageLocalizedText.cpp
|
||||||
PackagePublisherInfo.cpp
|
PackagePublisherInfo.cpp
|
||||||
PackageScreenshotInfo.cpp
|
PackageScreenshotInfo.cpp
|
||||||
|
PackageUserRatingInfo.cpp
|
||||||
PackageVersion.cpp
|
PackageVersion.cpp
|
||||||
ScreenshotInfo.cpp
|
ScreenshotInfo.cpp
|
||||||
UserInfo.cpp
|
UserInfo.cpp
|
||||||
UserRating.cpp
|
UserRating.cpp
|
||||||
UserRatingInfo.cpp
|
|
||||||
UserRatingSummary.cpp
|
UserRatingSummary.cpp
|
||||||
|
|
||||||
# network + server / local processes
|
# network + server / local processes
|
||||||
@@ -231,7 +234,6 @@ local applicationSources =
|
|||||||
PackageUtils.cpp
|
PackageUtils.cpp
|
||||||
StorageUtils.cpp
|
StorageUtils.cpp
|
||||||
StringUtils.cpp
|
StringUtils.cpp
|
||||||
LoggingUrlProtocolListener.cpp
|
|
||||||
|
|
||||||
# package_daemon
|
# package_daemon
|
||||||
ProblemWindow.cpp
|
ProblemWindow.cpp
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
# =====================================
|
# =====================================
|
||||||
# Copyright 2017-2023, Andrew Lindesay
|
# Copyright 2017-2025, Andrew Lindesay
|
||||||
# Distributed under the terms of the MIT License.
|
# Distributed under the terms of the MIT License.
|
||||||
# =====================================
|
# =====================================
|
||||||
|
|
||||||
@@ -38,21 +38,21 @@ public:
|
|||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
{{#propertyarray}}{{#property.iscppscalartype}}
|
{{#propertyarray}}{{#property.iscppscalartype}}
|
||||||
{{property.cpptype}} {{property.cppname}}();
|
{{property.cpptype}} {{property.cppname}}() const;
|
||||||
void Set{{property.cppname}}({{property.cpptype}} value);
|
void Set{{property.cppname}}({{property.cpptype}} value);
|
||||||
void Set{{property.cppname}}Null();
|
void Set{{property.cppname}}Null();
|
||||||
bool {{property.cppname}}IsNull();
|
bool {{property.cppname}}IsNull() const;
|
||||||
{{/property.iscppscalartype}}{{#property.isarray}}
|
{{/property.iscppscalartype}}{{#property.isarray}}
|
||||||
void AddTo{{property.cppname}}({{property.items.cpptype}}* value);
|
void AddTo{{property.cppname}}({{property.items.cpptype}}* value);
|
||||||
void Set{{property.cppname}}({{property.cpptype}}* value);
|
void Set{{property.cppname}}({{property.cpptype}}* value);
|
||||||
int32 Count{{property.cppname}}();
|
int32 Count{{property.cppname}}() const;
|
||||||
{{property.items.cpptype}}* {{property.cppname}}ItemAt(int32 index);
|
{{property.items.cpptype}}* {{property.cppname}}ItemAt(int32 index) const;
|
||||||
bool {{property.cppname}}IsNull();
|
bool {{property.cppname}}IsNull() const;
|
||||||
{{/property.isarray}}{{#property.iscppnonscalarnoncollectiontype}}
|
{{/property.isarray}}{{#property.iscppnonscalarnoncollectiontype}}
|
||||||
{{property.cpptype}}* {{property.cppname}}();
|
{{property.cpptype}}* {{property.cppname}}() const;
|
||||||
void Set{{property.cppname}}({{property.cpptype}}* value);
|
void Set{{property.cppname}}({{property.cpptype}}* value);
|
||||||
void Set{{property.cppname}}Null();
|
void Set{{property.cppname}}Null();
|
||||||
bool {{property.cppname}}IsNull();
|
bool {{property.cppname}}IsNull() const;
|
||||||
{{/property.iscppnonscalarnoncollectiontype}}
|
{{/property.iscppnonscalarnoncollectiontype}}
|
||||||
{{/propertyarray}}
|
{{/propertyarray}}
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ void
|
|||||||
}
|
}
|
||||||
|
|
||||||
{{#propertyarray}}{{#property.iscppscalartype}}{{property.cpptype}}
|
{{#propertyarray}}{{#property.iscppscalartype}}{{property.cpptype}}
|
||||||
{{cppobjectname}}::{{property.cppname}}()
|
{{cppobjectname}}::{{property.cppname}}() const
|
||||||
{
|
{
|
||||||
return {{property.cppmembername}};
|
return {{property.cppmembername}};
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ void
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
{{cppobjectname}}::{{property.cppname}}IsNull()
|
{{cppobjectname}}::{{property.cppname}}IsNull() const
|
||||||
{
|
{
|
||||||
return 0 == (fHasValueBitmask & k{{property.cppname}}Bitmask);
|
return 0 == (fHasValueBitmask & k{{property.cppname}}Bitmask);
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ void
|
|||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
{{cppobjectname}}::Count{{property.cppname}}()
|
{{cppobjectname}}::Count{{property.cppname}}() const
|
||||||
{
|
{
|
||||||
if ({{property.cppmembername}} == NULL)
|
if ({{property.cppmembername}} == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -169,20 +169,20 @@ int32
|
|||||||
|
|
||||||
|
|
||||||
{{property.items.cpptype}}*
|
{{property.items.cpptype}}*
|
||||||
{{cppobjectname}}::{{property.cppname}}ItemAt(int32 index)
|
{{cppobjectname}}::{{property.cppname}}ItemAt(int32 index) const
|
||||||
{
|
{
|
||||||
return {{property.cppmembername}}->ItemAt(index);
|
return {{property.cppmembername}}->ItemAt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
{{cppobjectname}}::{{property.cppname}}IsNull()
|
{{cppobjectname}}::{{property.cppname}}IsNull() const
|
||||||
{
|
{
|
||||||
return {{property.cppmembername}} == NULL;
|
return {{property.cppmembername}} == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
{{/property.isarray}}{{#property.iscppnonscalarnoncollectiontype}}{{property.cpptype}}*
|
{{/property.isarray}}{{#property.iscppnonscalarnoncollectiontype}}{{property.cpptype}}*
|
||||||
{{cppobjectname}}::{{property.cppname}}()
|
{{cppobjectname}}::{{property.cppname}}() const
|
||||||
{
|
{
|
||||||
return {{property.cppmembername}};
|
return {{property.cppmembername}};
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ void
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
{{cppobjectname}}::{{property.cppname}}IsNull()
|
{{cppobjectname}}::{{property.cppname}}IsNull() const
|
||||||
{
|
{
|
||||||
return {{property.cppmembername}} == NULL;
|
return {{property.cppmembername}} == NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025, Andrew Lindesay <[email protected]>.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include "PackageIconDefaultRepository.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <IconUtils.h>
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const int32 kCacheLimit = 50;
|
||||||
|
|
||||||
|
|
||||||
|
PackageIconDefaultRepository::PackageIconDefaultRepository()
|
||||||
|
:
|
||||||
|
fVectorData(NULL),
|
||||||
|
fVectorDataSize(0),
|
||||||
|
fCache(kCacheLimit)
|
||||||
|
{
|
||||||
|
_InitDefaultVectorIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageIconDefaultRepository::~PackageIconDefaultRepository()
|
||||||
|
{
|
||||||
|
delete fVectorData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageIconDefaultRepository::GetIcon(const BString& pkgName, uint32 size,
|
||||||
|
BitmapHolderRef& bitmapHolderRef)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (fVectorData == NULL)
|
||||||
|
return B_NOT_INITIALIZED;
|
||||||
|
|
||||||
|
bitmapHolderRef.Unset();
|
||||||
|
|
||||||
|
status_t status = B_OK;
|
||||||
|
HashString key(BString() << size);
|
||||||
|
|
||||||
|
if (!fCache.ContainsKey(key)) {
|
||||||
|
BBitmap* bitmap = NULL;
|
||||||
|
|
||||||
|
if (status == B_OK) {
|
||||||
|
bitmap = new BBitmap(BRect(0, 0, size - 1, size - 1), 0, B_RGBA32);
|
||||||
|
status = bitmap->InitCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == B_OK)
|
||||||
|
status = BIconUtils::GetVectorIcon(fVectorData, fVectorDataSize, bitmap);
|
||||||
|
|
||||||
|
if (status == B_OK) {
|
||||||
|
HDINFO("did create default package icon size %" B_PRId32, size);
|
||||||
|
BitmapHolderRef bitmapHolder(new(std::nothrow) BitmapHolder(bitmap), true);
|
||||||
|
fCache.Put(key, bitmapHolder);
|
||||||
|
} else {
|
||||||
|
delete bitmap;
|
||||||
|
bitmap = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == B_OK)
|
||||||
|
bitmapHolderRef.SetTo(fCache.Get(key).Get());
|
||||||
|
else
|
||||||
|
HDERROR("failed to create default package icon size %" B_PRId32, size);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageIconDefaultRepository::_InitDefaultVectorIcon()
|
||||||
|
{
|
||||||
|
if (fVectorData != NULL) {
|
||||||
|
delete fVectorData;
|
||||||
|
fVectorData = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fVectorDataSize = 0;
|
||||||
|
|
||||||
|
BMimeType mimeType("application/x-vnd.haiku-package");
|
||||||
|
status_t status = mimeType.InitCheck();
|
||||||
|
|
||||||
|
if (status != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8* data;
|
||||||
|
size_t dataSize;
|
||||||
|
|
||||||
|
if (mimeType.GetIcon(&data, &dataSize) != B_OK)
|
||||||
|
debugger("the default icon was unable to be acquired");
|
||||||
|
|
||||||
|
fVectorData = new(std::nothrow) uint8[dataSize];
|
||||||
|
|
||||||
|
if (fVectorData == NULL)
|
||||||
|
HDFATAL("unable to allocate memory for the default icon");
|
||||||
|
|
||||||
|
memcpy(fVectorData, data, dataSize);
|
||||||
|
fVectorDataSize = dataSize;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025, Andrew Lindesay <[email protected]>.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef PACKAGE_ICON_DEFAULT_REPOSITORY_H
|
||||||
|
#define PACKAGE_ICON_DEFAULT_REPOSITORY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <HashMap.h>
|
||||||
|
#include <HashString.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "LRUCache.h"
|
||||||
|
#include "PackageIconRepository.h"
|
||||||
|
|
||||||
|
|
||||||
|
class PackageIconDefaultRepository : public PackageIconRepository {
|
||||||
|
public:
|
||||||
|
PackageIconDefaultRepository();
|
||||||
|
virtual ~PackageIconDefaultRepository();
|
||||||
|
|
||||||
|
virtual status_t GetIcon(const BString& pkgName, uint32 size,
|
||||||
|
BitmapHolderRef& bitmapHolderRef);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitDefaultVectorIcon();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8* fVectorData;
|
||||||
|
size_t fVectorDataSize;
|
||||||
|
LRUCache<HashString, BitmapHolderRef>
|
||||||
|
fCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PACKAGE_ICON_DEFAULT_REPOSITORY_H
|
||||||
+5
-4
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_ICON_REPOSITORY_H
|
#ifndef PACKAGE_ICON_REPOSITORY_H
|
||||||
@@ -11,13 +11,14 @@
|
|||||||
#include "HaikuDepotConstants.h"
|
#include "HaikuDepotConstants.h"
|
||||||
|
|
||||||
|
|
||||||
class PackageIconRepository {
|
class PackageIconRepository : public BReferenceable {
|
||||||
public:
|
public:
|
||||||
virtual bool HasAnyIcon(const BString& pkgName) = 0;
|
|
||||||
virtual status_t GetIcon(const BString& pkgName, uint32 size,
|
virtual status_t GetIcon(const BString& pkgName, uint32 size,
|
||||||
BitmapHolderRef& bitmapHolderRef) = 0;
|
BitmapHolderRef& bitmapHolderRef) = 0;
|
||||||
virtual void Clear() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef BReference<PackageIconRepository> PackageIconRepositoryRef;
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_ICON_REPOSITORY_H
|
#endif // PACKAGE_ICON_REPOSITORY_H
|
||||||
+44
-144
@@ -1,11 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "PackageIconTarRepository.h"
|
#include "PackageIconTarRepository.h"
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
#include <Autolock.h>
|
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <IconUtils.h>
|
#include <IconUtils.h>
|
||||||
#include <StopWatch.h>
|
#include <StopWatch.h>
|
||||||
@@ -87,8 +86,7 @@ IconTarPtrEntryListener::Handle(const TarArchiveHeader& header,
|
|||||||
BString packageName;
|
BString packageName;
|
||||||
BString leafName;
|
BString leafName;
|
||||||
fileName.CopyInto(packageName, 5, secondSlashIdx - 5);
|
fileName.CopyInto(packageName, 5, secondSlashIdx - 5);
|
||||||
fileName.CopyInto(leafName, secondSlashIdx + 1,
|
fileName.CopyInto(leafName, secondSlashIdx + 1, fileName.Length() - (secondSlashIdx + 1));
|
||||||
fileName.Length() - (secondSlashIdx + 1));
|
|
||||||
BitmapSize storedSize;
|
BitmapSize storedSize;
|
||||||
|
|
||||||
if (_LeafNameToBitmapSize(leafName, &storedSize) == B_OK)
|
if (_LeafNameToBitmapSize(leafName, &storedSize) == B_OK)
|
||||||
@@ -121,31 +119,21 @@ IconTarPtrEntryListener::_LeafNameToBitmapSize(BString& leafName, BitmapSize* st
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageIconTarRepository::PackageIconTarRepository()
|
PackageIconTarRepository::PackageIconTarRepository(BPath& tarPath)
|
||||||
:
|
:
|
||||||
|
fTarPath(tarPath),
|
||||||
fTarIo(NULL),
|
fTarIo(NULL),
|
||||||
fIconCache(LIMIT_ICON_CACHE),
|
fIconCache(LIMIT_ICON_CACHE),
|
||||||
fDefaultIconVectorData(NULL),
|
fIconDataBuffer(new BMallocIO()),
|
||||||
fDefaultIconVectorDataSize(0),
|
fFallbackRepository(PackageIconDefaultRepository())
|
||||||
fDefaultIconCache(LIMIT_ICON_CACHE),
|
|
||||||
fIconDataBuffer(new BMallocIO())
|
|
||||||
{
|
{
|
||||||
_InitDefaultVectorIcon();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageIconTarRepository::~PackageIconTarRepository()
|
PackageIconTarRepository::~PackageIconTarRepository()
|
||||||
{
|
{
|
||||||
|
_Close();
|
||||||
delete fIconDataBuffer;
|
delete fIconDataBuffer;
|
||||||
delete fDefaultIconVectorData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageIconTarRepository::Clear() {
|
|
||||||
BAutolock locker(&fLock);
|
|
||||||
fIconCache.Clear();
|
|
||||||
fDefaultIconCache.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -155,27 +143,25 @@ PackageIconTarRepository::Clear() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageIconTarRepository::Init(BPath& tarPath)
|
PackageIconTarRepository::Init()
|
||||||
{
|
{
|
||||||
BAutolock locker(&fLock);
|
|
||||||
|
|
||||||
_Close();
|
_Close();
|
||||||
|
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
|
|
||||||
if (tarPath.Path() == NULL) {
|
if (fTarPath.Path() == NULL) {
|
||||||
HDINFO("empty path to tar-ball");
|
HDINFO("empty path to tar-ball");
|
||||||
result = B_BAD_VALUE;
|
result = B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BFile *tarIo = NULL;
|
BFile* tarIo = NULL;
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
HDINFO("will init icon model from tar [%s]", tarPath.Path());
|
HDINFO("will init icon model from tar [%s]", fTarPath.Path());
|
||||||
tarIo = new BFile(tarPath.Path(), O_RDONLY);
|
tarIo = new BFile(fTarPath.Path(), O_RDONLY);
|
||||||
|
|
||||||
if (!tarIo->IsReadable()) {
|
if (!tarIo->IsReadable()) {
|
||||||
HDERROR("unable to read the tar [%s]", tarPath.Path());
|
HDERROR("unable to read the tar [%s]", fTarPath.Path());
|
||||||
result = B_IO_ERROR;
|
result = B_IO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,15 +170,14 @@ PackageIconTarRepository::Init(BPath& tarPath)
|
|||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
BStopWatch watch("PackageIconTarRepository::Init", true);
|
BStopWatch watch("PackageIconTarRepository::Init", true);
|
||||||
HDINFO("will read [%s] and collect the tar pointers", tarPath.Path());
|
HDINFO("will read [%s] and collect the tar pointers", fTarPath.Path());
|
||||||
|
|
||||||
IconTarPtrEntryListener* listener = new IconTarPtrEntryListener(this);
|
IconTarPtrEntryListener* listener = new IconTarPtrEntryListener(this);
|
||||||
ObjectDeleter<IconTarPtrEntryListener> listenerDeleter(listener);
|
ObjectDeleter<IconTarPtrEntryListener> listenerDeleter(listener);
|
||||||
TarArchiveService::ForEachEntry(*tarIo, listener);
|
TarArchiveService::ForEachEntry(*tarIo, listener);
|
||||||
|
|
||||||
double secs = watch.ElapsedTime() / 1000000.0;
|
double secs = watch.ElapsedTime() / 1000000.0;
|
||||||
HDINFO("did collect %" B_PRIi32 " tar pointers (%6.3g secs)",
|
HDINFO("did collect %" B_PRIi32 " tar pointers (%6.3g secs)", fIconTarPtrs.Size(), secs);
|
||||||
fIconTarPtrs.Size(), secs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == B_OK)
|
if (result == B_OK)
|
||||||
@@ -214,14 +199,13 @@ PackageIconTarRepository::_Close()
|
|||||||
delete fTarIo;
|
delete fTarIo;
|
||||||
fTarIo = NULL;
|
fTarIo = NULL;
|
||||||
fIconTarPtrs.Clear();
|
fIconTarPtrs.Clear();
|
||||||
fDefaultIconCache.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This method should be treated private and only called from a situation
|
/*! This method is used to populate data from the parsing of the tar headers.
|
||||||
in which the class's lock is acquired. It is used to populate data from
|
It is called from the listener above.
|
||||||
the parsing of the tar headers. It is called from the listener above.
|
|
||||||
*/
|
*/
|
||||||
|
// TODO; should be friend to the listener
|
||||||
void
|
void
|
||||||
PackageIconTarRepository::AddIconTarPtr(const BString& packageName, BitmapSize storedSize,
|
PackageIconTarRepository::AddIconTarPtr(const BString& packageName, BitmapSize storedSize,
|
||||||
off_t offset)
|
off_t offset)
|
||||||
@@ -231,15 +215,6 @@ PackageIconTarRepository::AddIconTarPtr(const BString& packageName, BitmapSize s
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
PackageIconTarRepository::HasAnyIcon(const BString& pkgName)
|
|
||||||
{
|
|
||||||
BAutolock locker(&fLock);
|
|
||||||
HashString key(pkgName);
|
|
||||||
return fIconTarPtrs.ContainsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageIconTarRepository::GetIcon(const BString& pkgName, uint32 size,
|
PackageIconTarRepository::GetIcon(const BString& pkgName, uint32 size,
|
||||||
BitmapHolderRef& bitmapHolderRef)
|
BitmapHolderRef& bitmapHolderRef)
|
||||||
@@ -250,39 +225,44 @@ PackageIconTarRepository::GetIcon(const BString& pkgName, uint32 size,
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t result = B_OK;
|
||||||
bitmapHolderRef.Unset();
|
bitmapHolderRef.Unset();
|
||||||
|
|
||||||
BAutolock locker(&fLock);
|
if (fTarIo == NULL) {
|
||||||
status_t result = B_OK;
|
// get the default icon in this case.
|
||||||
off_t iconDataTarOffset = -1;
|
HDDEBUG("the tar io was not configured indicating a possible initialization error");
|
||||||
const IconTarPtrRef tarPtrRef = _GetIconTarPtr(pkgName);
|
} else {
|
||||||
BitmapSize storedSize;
|
off_t iconDataTarOffset = -1;
|
||||||
|
const IconTarPtrRef tarPtrRef = _GetIconTarPtr(pkgName);
|
||||||
|
BitmapSize storedSize;
|
||||||
|
|
||||||
if (tarPtrRef.IsSet()) {
|
if (tarPtrRef.IsSet()) {
|
||||||
storedSize = _BestStoredSize(tarPtrRef, size);
|
storedSize = _BestStoredSize(tarPtrRef, size);
|
||||||
iconDataTarOffset = tarPtrRef->Offset(storedSize);
|
iconDataTarOffset = tarPtrRef->Offset(storedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iconDataTarOffset >= 0) {
|
if (iconDataTarOffset >= 0) {
|
||||||
HashString key = _ToIconCacheKey(pkgName, storedSize, size);
|
HashString key = _ToIconCacheKey(pkgName, storedSize, size);
|
||||||
|
|
||||||
if (fIconCache.ContainsKey(key)) {
|
if (fIconCache.ContainsKey(key)) {
|
||||||
bitmapHolderRef.SetTo(fIconCache.Get(key).Get());
|
|
||||||
} else {
|
|
||||||
result = _CreateIconFromTarOffset(iconDataTarOffset, storedSize, size, bitmapHolderRef);
|
|
||||||
if (result == B_OK) {
|
|
||||||
HDTRACE("loaded package icon [%s] of size %" B_PRId32, pkgName.String(), size);
|
|
||||||
fIconCache.Put(key, bitmapHolderRef);
|
|
||||||
bitmapHolderRef.SetTo(fIconCache.Get(key).Get());
|
bitmapHolderRef.SetTo(fIconCache.Get(key).Get());
|
||||||
} else {
|
} else {
|
||||||
HDERROR("failure to read image for package [%s] at offset %"
|
result = _CreateIconFromTarOffset(iconDataTarOffset, storedSize, size,
|
||||||
B_PRIdOFF, pkgName.String(), iconDataTarOffset);
|
bitmapHolderRef);
|
||||||
|
if (result == B_OK) {
|
||||||
|
HDTRACE("loaded package icon [%s] of size %" B_PRId32, pkgName.String(), size);
|
||||||
|
fIconCache.Put(key, bitmapHolderRef);
|
||||||
|
bitmapHolderRef.SetTo(fIconCache.Get(key).Get());
|
||||||
|
} else {
|
||||||
|
HDERROR("failure to read image for package [%s] at offset %" B_PRIdOFF,
|
||||||
|
pkgName.String(), iconDataTarOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bitmapHolderRef.IsSet())
|
if (!bitmapHolderRef.IsSet())
|
||||||
result = _GetDefaultIcon(size, bitmapHolderRef);
|
result = fFallbackRepository.GetIcon(pkgName, size, bitmapHolderRef);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -324,8 +304,6 @@ PackageIconTarRepository::_ToIconCacheKey(const BString& pkgName, BitmapSize sto
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This method must only be invoked with the class locked.
|
|
||||||
*/
|
|
||||||
status_t
|
status_t
|
||||||
PackageIconTarRepository::_CreateIconFromTarOffset(off_t offset, BitmapSize storedSize, uint32 size,
|
PackageIconTarRepository::_CreateIconFromTarOffset(off_t offset, BitmapSize storedSize, uint32 size,
|
||||||
BitmapHolderRef& bitmapHolderRef)
|
BitmapHolderRef& bitmapHolderRef)
|
||||||
@@ -409,7 +387,6 @@ PackageIconTarRepository::_BestStoredSize(const IconTarPtrRef iconTarPtrRef, int
|
|||||||
IconTarPtrRef
|
IconTarPtrRef
|
||||||
PackageIconTarRepository::_GetOrCreateIconTarPtr(const BString& pkgName)
|
PackageIconTarRepository::_GetOrCreateIconTarPtr(const BString& pkgName)
|
||||||
{
|
{
|
||||||
BAutolock locker(&fLock);
|
|
||||||
HashString key(pkgName);
|
HashString key(pkgName);
|
||||||
if (!fIconTarPtrs.ContainsKey(key)) {
|
if (!fIconTarPtrs.ContainsKey(key)) {
|
||||||
IconTarPtrRef value(new IconTarPtr(pkgName));
|
IconTarPtrRef value(new IconTarPtr(pkgName));
|
||||||
@@ -418,80 +395,3 @@ PackageIconTarRepository::_GetOrCreateIconTarPtr(const BString& pkgName)
|
|||||||
}
|
}
|
||||||
return fIconTarPtrs.Get(key);
|
return fIconTarPtrs.Get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
PackageIconTarRepository::_GetDefaultIcon(uint32 size, BitmapHolderRef& bitmapHolderRef)
|
|
||||||
{
|
|
||||||
if (fDefaultIconVectorData == NULL)
|
|
||||||
return B_NOT_INITIALIZED;
|
|
||||||
|
|
||||||
bitmapHolderRef.Unset();
|
|
||||||
|
|
||||||
status_t status = B_OK;
|
|
||||||
HashString key(BString() << size);
|
|
||||||
|
|
||||||
if (!fDefaultIconCache.ContainsKey(key)) {
|
|
||||||
BBitmap* bitmap = NULL;
|
|
||||||
|
|
||||||
if (status == B_OK) {
|
|
||||||
bitmap = new BBitmap(BRect(0, 0, size - 1, size - 1), 0, B_RGBA32);
|
|
||||||
status = bitmap->InitCheck();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == B_OK) {
|
|
||||||
status = BIconUtils::GetVectorIcon(fDefaultIconVectorData, fDefaultIconVectorDataSize,
|
|
||||||
bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == B_OK) {
|
|
||||||
HDINFO("did create default package icon size %" B_PRId32, size);
|
|
||||||
BitmapHolderRef bitmapHolder(new(std::nothrow) BitmapHolder(bitmap), true);
|
|
||||||
fDefaultIconCache.Put(key, bitmapHolder);
|
|
||||||
} else {
|
|
||||||
delete bitmap;
|
|
||||||
bitmap = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == B_OK)
|
|
||||||
bitmapHolderRef.SetTo(fDefaultIconCache.Get(key).Get());
|
|
||||||
else
|
|
||||||
HDERROR("failed to create default package icon size %" B_PRId32, size);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageIconTarRepository::_InitDefaultVectorIcon()
|
|
||||||
{
|
|
||||||
if (fDefaultIconVectorData != NULL) {
|
|
||||||
delete fDefaultIconVectorData;
|
|
||||||
fDefaultIconVectorData = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fDefaultIconVectorDataSize = 0;
|
|
||||||
|
|
||||||
BMimeType mimeType("application/x-vnd.haiku-package");
|
|
||||||
status_t status = mimeType.InitCheck();
|
|
||||||
|
|
||||||
uint8* data;
|
|
||||||
size_t dataSize;
|
|
||||||
|
|
||||||
if (status == B_OK)
|
|
||||||
status = mimeType.GetIcon(&data, &dataSize);
|
|
||||||
|
|
||||||
if (status == B_OK) {
|
|
||||||
fDefaultIconVectorData = new(std::nothrow) uint8[dataSize];
|
|
||||||
|
|
||||||
if (fDefaultIconVectorData == NULL)
|
|
||||||
HDFATAL("unable to allocate memory for the default icon");
|
|
||||||
|
|
||||||
memcpy(fDefaultIconVectorData, data, dataSize);
|
|
||||||
fDefaultIconVectorDataSize = dataSize;
|
|
||||||
} else {
|
|
||||||
fDefaultIconVectorData = NULL;
|
|
||||||
fDefaultIconVectorDataSize = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+8
-16
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_ICON_TAR_REPOSITORY_H
|
#ifndef PACKAGE_ICON_TAR_REPOSITORY_H
|
||||||
@@ -9,12 +9,12 @@
|
|||||||
#include <DataIO.h>
|
#include <DataIO.h>
|
||||||
#include <HashMap.h>
|
#include <HashMap.h>
|
||||||
#include <HashString.h>
|
#include <HashString.h>
|
||||||
#include <Locker.h>
|
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
#include "IconTarPtr.h"
|
#include "IconTarPtr.h"
|
||||||
#include "LRUCache.h"
|
#include "LRUCache.h"
|
||||||
|
#include "PackageIconDefaultRepository.h"
|
||||||
#include "PackageIconRepository.h"
|
#include "PackageIconRepository.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -23,17 +23,15 @@ typedef BReference<IconTarPtr> IconTarPtrRef;
|
|||||||
|
|
||||||
class PackageIconTarRepository : public PackageIconRepository {
|
class PackageIconTarRepository : public PackageIconRepository {
|
||||||
public:
|
public:
|
||||||
PackageIconTarRepository();
|
PackageIconTarRepository(BPath& tarPath);
|
||||||
virtual ~PackageIconTarRepository();
|
virtual ~PackageIconTarRepository();
|
||||||
|
|
||||||
status_t Init(BPath& tarPath);
|
status_t Init();
|
||||||
|
|
||||||
void AddIconTarPtr(const BString& pkgName,
|
void AddIconTarPtr(const BString& pkgName,
|
||||||
BitmapSize size, off_t offset);
|
BitmapSize size, off_t offset);
|
||||||
virtual status_t GetIcon(const BString& pkgName, uint32 size,
|
virtual status_t GetIcon(const BString& pkgName, uint32 size,
|
||||||
BitmapHolderRef& bitmapHolderRef);
|
BitmapHolderRef& bitmapHolderRef);
|
||||||
virtual bool HasAnyIcon(const BString& pkgName);
|
|
||||||
virtual void Clear();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _Close();
|
void _Close();
|
||||||
@@ -48,27 +46,21 @@ private:
|
|||||||
status_t _CreateIconFromTarOffset(off_t offset, BitmapSize bitmapSize,
|
status_t _CreateIconFromTarOffset(off_t offset, BitmapSize bitmapSize,
|
||||||
uint32 size, BitmapHolderRef& bitmapHolderRef);
|
uint32 size, BitmapHolderRef& bitmapHolderRef);
|
||||||
|
|
||||||
status_t _GetDefaultIcon(uint32 size, BitmapHolderRef& bitmapHolderRef);
|
|
||||||
|
|
||||||
static BitmapSize _BestStoredSize(const IconTarPtrRef iconTarPtrRef,
|
static BitmapSize _BestStoredSize(const IconTarPtrRef iconTarPtrRef,
|
||||||
int32 desiredSize);
|
int32 desiredSize);
|
||||||
|
|
||||||
void _InitDefaultVectorIcon();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BLocker fLock;
|
BPath fTarPath;
|
||||||
BPositionIO* fTarIo;
|
BPositionIO* fTarIo;
|
||||||
LRUCache<HashString, BitmapHolderRef>
|
LRUCache<HashString, BitmapHolderRef>
|
||||||
fIconCache;
|
fIconCache;
|
||||||
HashMap<HashString, IconTarPtrRef>
|
HashMap<HashString, IconTarPtrRef>
|
||||||
fIconTarPtrs;
|
fIconTarPtrs;
|
||||||
|
|
||||||
uint8* fDefaultIconVectorData;
|
|
||||||
size_t fDefaultIconVectorDataSize;
|
|
||||||
LRUCache<HashString, BitmapHolderRef>
|
|
||||||
fDefaultIconCache;
|
|
||||||
|
|
||||||
BMallocIO* fIconDataBuffer;
|
BMallocIO* fIconDataBuffer;
|
||||||
|
|
||||||
|
PackageIconDefaultRepository
|
||||||
|
fFallbackRepository;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PACKAGE_ICON_TAR_REPOSITORY_H
|
#endif // PACKAGE_ICON_TAR_REPOSITORY_H
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#include "LanguageRepository.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "HaikuDepotConstants.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "StringUtils.h"
|
|
||||||
|
|
||||||
|
|
||||||
LanguageRepository::LanguageRepository()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LanguageRepository::~LanguageRepository()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LanguageRepository::Clear()
|
|
||||||
{
|
|
||||||
fLanguages.clear();
|
|
||||||
HDINFO("did clear the languages");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
LanguageRepository::IsEmpty() const
|
|
||||||
{
|
|
||||||
return fLanguages.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
LanguageRepository::CountLanguages() const
|
|
||||||
{
|
|
||||||
return fLanguages.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const LanguageRef
|
|
||||||
LanguageRepository::LanguageAtIndex(int32 index) const
|
|
||||||
{
|
|
||||||
return fLanguages[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LanguageRepository::AddLanguage(const LanguageRef& value)
|
|
||||||
{
|
|
||||||
int32 index = IndexOfLanguage(value->Code(), value->CountryCode(), value->ScriptCode());
|
|
||||||
|
|
||||||
if (-1 == index) {
|
|
||||||
std::vector<LanguageRef>::iterator itInsertionPt
|
|
||||||
= std::lower_bound(fLanguages.begin(), fLanguages.end(), value, &IsLanguageBefore);
|
|
||||||
fLanguages.insert(itInsertionPt, value);
|
|
||||||
HDTRACE("did add the language [%s]", value->ID());
|
|
||||||
} else {
|
|
||||||
fLanguages[index] = value;
|
|
||||||
HDTRACE("did replace the language [%s]", value->ID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
LanguageRepository::IndexOfLanguage(const char* code, const char* countryCode,
|
|
||||||
const char* scriptCode) const
|
|
||||||
{
|
|
||||||
size_t size = fLanguages.size();
|
|
||||||
for (uint32 i = 0; i < size; i++) {
|
|
||||||
const char* lCode = fLanguages[i]->Code();
|
|
||||||
const char* lCountryCode = fLanguages[i]->CountryCode();
|
|
||||||
const char* lScriptCode = fLanguages[i]->ScriptCode();
|
|
||||||
|
|
||||||
if (0 == StringUtils::NullSafeCompare(code, lCode)
|
|
||||||
&& 0 == StringUtils::NullSafeCompare(countryCode, lCountryCode)
|
|
||||||
&& 0 == StringUtils::NullSafeCompare(scriptCode, lScriptCode)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef LANGUAGE_REPOSITORY_H
|
|
||||||
#define LANGUAGE_REPOSITORY_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "Language.h"
|
|
||||||
|
|
||||||
|
|
||||||
class LanguageRepository
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LanguageRepository();
|
|
||||||
virtual ~LanguageRepository();
|
|
||||||
|
|
||||||
void Clear();
|
|
||||||
bool IsEmpty() const;
|
|
||||||
int32 CountLanguages() const;
|
|
||||||
const LanguageRef LanguageAtIndex(int32 index) const;
|
|
||||||
void AddLanguage(const LanguageRef& value);
|
|
||||||
|
|
||||||
int32 IndexOfLanguage(const char* code, const char* countryCode,
|
|
||||||
const char* scriptCode) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<LanguageRef>
|
|
||||||
fLanguages;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // LANGUAGE_REPOSITORY_H
|
|
||||||
+415
-299
@@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2014, Axel Dörfler <[email protected]>.
|
* Copyright 2014, Axel Dörfler <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
@@ -35,11 +35,8 @@
|
|||||||
#define B_TRANSLATION_CONTEXT "Model"
|
#define B_TRANSLATION_CONTEXT "Model"
|
||||||
|
|
||||||
|
|
||||||
#define KEY_STORE_IDENTIFIER_PREFIX "hds.password."
|
static const uint32 kChangeMaskAll = UINT32_MAX;
|
||||||
// this prefix is added before the nickname in the keystore
|
// covers all of the possible values.
|
||||||
// so that HDS username/password pairs can be identified.
|
|
||||||
|
|
||||||
static const char* kHaikuDepotKeyring = "HaikuDepot";
|
|
||||||
|
|
||||||
|
|
||||||
ModelListener::~ModelListener()
|
ModelListener::~ModelListener()
|
||||||
@@ -56,58 +53,107 @@ Model::Model()
|
|||||||
fDepots(),
|
fDepots(),
|
||||||
fCategories(),
|
fCategories(),
|
||||||
fPackageListViewMode(PROMINENT),
|
fPackageListViewMode(PROMINENT),
|
||||||
fCanShareAnonymousUsageData(false)
|
fCanShareAnonymousUsageData(false),
|
||||||
|
fWebApp(WebAppInterfaceRef(new WebAppInterface(UserCredentials()), true)),
|
||||||
|
fLanguages(LocaleUtils::WellKnownLanguages())
|
||||||
{
|
{
|
||||||
|
fIconRepository = PackageIconRepositoryRef(new PackageIconDefaultRepository(), true);
|
||||||
|
|
||||||
// setup the language into a default state with a hard-coded language so
|
fFilterSpecification = PackageFilterSpecificationBuilder().BuildRef();
|
||||||
// that there is a language at all.
|
fFilter = PackageFilterFactory::CreateFilter(fFilterSpecification);
|
||||||
fLanguageRepository = new LanguageRepository();
|
|
||||||
fLanguageRepository->AddLanguage(fPreferredLanguage);
|
|
||||||
|
|
||||||
fPackageFilterModel = new PackageFilterModel();
|
fPackageScreenshotRepository
|
||||||
fPackageScreenshotRepository = new PackageScreenshotRepository(
|
= new PackageScreenshotRepository(PackageScreenshotRepositoryListenerRef(this), this);
|
||||||
PackageScreenshotRepositoryListenerRef(this),
|
|
||||||
&fWebAppInterface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Model::~Model()
|
Model::~Model()
|
||||||
{
|
{
|
||||||
delete fPackageFilterModel;
|
|
||||||
delete fPackageScreenshotRepository;
|
delete fPackageScreenshotRepository;
|
||||||
delete fLanguageRepository;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LanguageRepository*
|
const std::vector<LanguageRef>
|
||||||
Model::Languages()
|
Model::Languages() const
|
||||||
{
|
{
|
||||||
return fLanguageRepository;
|
BAutolock locker(&fLock);
|
||||||
|
return fLanguages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageFilterModel*
|
void
|
||||||
Model::PackageFilter()
|
Model::SetLanguagesAndPreferred(const std::vector<LanguageRef>& value, const LanguageRef& preferred)
|
||||||
{
|
{
|
||||||
return fPackageFilterModel;
|
if (value.empty())
|
||||||
|
HDFATAL("unable to set the languages to an empty list");
|
||||||
|
|
||||||
|
if (std::find(value.begin(), value.end(), preferred) == value.end())
|
||||||
|
HDFATAL("the preferred language is not in the list of languages");
|
||||||
|
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
fLanguages = value;
|
||||||
|
std::sort(fLanguages.begin(), fLanguages.end(), IsLanguageRefLess);
|
||||||
|
SetPreferredLanguage(preferred);
|
||||||
|
|
||||||
|
HDINFO("did configure %" B_PRIu32 " languages with default [%s]",
|
||||||
|
static_cast<uint32>(fLanguages.size()), preferred->ID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageIconRepository&
|
void
|
||||||
Model::GetPackageIconRepository()
|
Model::SetFilterSpecification(const PackageFilterSpecificationRef& value)
|
||||||
{
|
{
|
||||||
return fPackageIconRepository;
|
BAutolock locker(&fLock);
|
||||||
|
if (value != fFilterSpecification) {
|
||||||
|
fFilterSpecification = value;
|
||||||
|
fFilter = PackageFilterFactory::CreateFilter(value);
|
||||||
|
_NotifyPackageFilterChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
const PackageFilterSpecificationRef
|
||||||
Model::InitPackageIconRepository()
|
Model::FilterSpecification() const
|
||||||
{
|
{
|
||||||
BPath tarPath;
|
BAutolock locker(&fLock);
|
||||||
status_t result = StorageUtils::IconTarPath(tarPath);
|
return fFilterSpecification;
|
||||||
if (result == B_OK)
|
}
|
||||||
result = fPackageIconRepository.Init(tarPath);
|
|
||||||
return result;
|
|
||||||
|
PackageFilterRef
|
||||||
|
Model::Filter() const
|
||||||
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
return fFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageIconRepositoryRef
|
||||||
|
Model::IconRepository()
|
||||||
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
return fIconRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Model::SetIconRepository(PackageIconRepositoryRef value)
|
||||||
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
fIconRepository = value;
|
||||||
|
_NotifyIconsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Model::_NotifyIconsChanged()
|
||||||
|
{
|
||||||
|
std::vector<ModelListenerRef>::const_iterator it;
|
||||||
|
for (it = fListeners.begin(); it != fListeners.end(); it++) {
|
||||||
|
const ModelListenerRef& listener = *it;
|
||||||
|
if (listener.IsSet())
|
||||||
|
listener->IconsChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -125,101 +171,286 @@ Model::AddListener(const ModelListenerRef& listener)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LanguageRef
|
void
|
||||||
|
Model::AddPackageListener(const PackageInfoListenerRef& packageListener)
|
||||||
|
{
|
||||||
|
fPackageListeners.push_back(packageListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! This method will take the event info data stored in the supplied message
|
||||||
|
and turn it back into an instance of `PackageInfoEvents`. It is done in
|
||||||
|
this way because the lookup of the packages within each `PackageInfoEvent`
|
||||||
|
has to come from the model.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
Model::DearchiveInfoEvents(const BMessage* message, PackageInfoEvents& packageInfoEvents) const
|
||||||
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
int32 i = 0;
|
||||||
|
BMessage eventMessage;
|
||||||
|
BString packageName;
|
||||||
|
uint32 changeMask;
|
||||||
|
|
||||||
|
while (message->FindMessage(kPackageInfoEventsKey, i, &eventMessage) == B_OK) {
|
||||||
|
status_t result = B_OK;
|
||||||
|
|
||||||
|
if (result == B_OK)
|
||||||
|
result = eventMessage.FindString(kPackageInfoPackageNameKey, &packageName);
|
||||||
|
|
||||||
|
if (result == B_OK)
|
||||||
|
result = eventMessage.FindUInt32(kPackageInfoChangesKey, &changeMask);
|
||||||
|
|
||||||
|
if (result == B_OK) {
|
||||||
|
PackageInfoRef package = PackageForName(packageName);
|
||||||
|
|
||||||
|
if (package.IsSet()) {
|
||||||
|
PackageInfoEvent event(package, changeMask);
|
||||||
|
packageInfoEvents.AddEvent(event);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HDFATAL("broken event info found processing events");
|
||||||
|
// should not occur as the data assembly is entirely inside the application
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const LanguageRef
|
||||||
Model::PreferredLanguage() const
|
Model::PreferredLanguage() const
|
||||||
{
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
return fPreferredLanguage;
|
return fPreferredLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::SetPreferredLanguage(LanguageRef value)
|
Model::SetPreferredLanguage(const LanguageRef& value)
|
||||||
{
|
{
|
||||||
if (value.IsSet()) {
|
if (value.IsSet()) {
|
||||||
if (fPreferredLanguage != value)
|
BAutolock locker(&fLock);
|
||||||
fPreferredLanguage = value;
|
fPreferredLanguage = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO; part of a wider change; cope with the package being in more than one
|
|
||||||
// depot
|
|
||||||
PackageInfoRef
|
|
||||||
Model::PackageForName(const BString& name)
|
|
||||||
{
|
|
||||||
std::vector<DepotInfoRef>::iterator it;
|
|
||||||
for (it = fDepots.begin(); it != fDepots.end(); it++) {
|
|
||||||
DepotInfoRef depotInfoRef = *it;
|
|
||||||
PackageInfoRef packageInfoRef = depotInfoRef->PackageByName(name);
|
|
||||||
if (packageInfoRef.Get() != NULL)
|
|
||||||
return packageInfoRef;
|
|
||||||
}
|
|
||||||
return PackageInfoRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::MergeOrAddDepot(const DepotInfoRef& depot)
|
Model::SetDepots(const DepotInfoRef& depot)
|
||||||
{
|
{
|
||||||
BString depotName = depot->Name();
|
BAutolock locker(&fLock);
|
||||||
for(uint32 i = 0; i < fDepots.size(); i++) {
|
std::vector<DepotInfoRef> depots;
|
||||||
if (fDepots[i]->Name() == depotName) {
|
depots.push_back(depot);
|
||||||
DepotInfoRef ersatzDepot(new DepotInfo(*(fDepots[i].Get())), true);
|
SetDepots(depots);
|
||||||
ersatzDepot->SyncPackagesFromDepot(depot);
|
|
||||||
fDepots[i] = ersatzDepot;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fDepots.push_back(depot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
void
|
||||||
Model::HasDepot(const BString& name) const
|
Model::SetDepots(const std::vector<DepotInfoRef>& depots)
|
||||||
{
|
{
|
||||||
return NULL != DepotForName(name).Get();
|
BAutolock locker(&fLock);
|
||||||
|
fDepots.clear();
|
||||||
|
|
||||||
|
std::vector<DepotInfoRef>::const_iterator it;
|
||||||
|
|
||||||
|
for (it = depots.begin(); it != depots.end(); it++) {
|
||||||
|
DepotInfoRef depot = *it;
|
||||||
|
|
||||||
|
if (!depot.IsSet()) {
|
||||||
|
HDFATAL("attempt to add an unset depot");
|
||||||
|
} else {
|
||||||
|
if (depot->Name().IsEmpty())
|
||||||
|
HDFATAL("depot has no name");
|
||||||
|
|
||||||
|
if (depot->Identifier().IsEmpty())
|
||||||
|
HDFATAL("depot has no identifier");
|
||||||
|
|
||||||
|
fDepots[depot->Name()] = depot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector<DepotInfoRef>
|
||||||
|
Model::Depots() const
|
||||||
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
std::vector<DepotInfoRef> result;
|
||||||
|
std::map<BString, DepotInfoRef>::const_iterator it;
|
||||||
|
|
||||||
|
for (it = fDepots.begin(); it != fDepots.end(); it++)
|
||||||
|
result.push_back(it->second);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const DepotInfoRef
|
const DepotInfoRef
|
||||||
Model::DepotForName(const BString& name) const
|
Model::DepotForName(const BString& name) const
|
||||||
{
|
{
|
||||||
if (name.IsEmpty())
|
BAutolock locker(&fLock);
|
||||||
return DepotInfoRef();
|
std::map<BString, DepotInfoRef>::const_iterator it = fDepots.find(name);
|
||||||
|
if (it != fDepots.end())
|
||||||
std::vector<DepotInfoRef>::const_iterator it;
|
return it->second;
|
||||||
for (it = fDepots.begin(); it != fDepots.end(); it++) {
|
|
||||||
DepotInfoRef aDepot = *it;
|
|
||||||
if (aDepot->Name() == name)
|
|
||||||
return aDepot;
|
|
||||||
}
|
|
||||||
return DepotInfoRef();
|
return DepotInfoRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
const DepotInfoRef
|
||||||
Model::CountDepots() const
|
Model::DepotForIdentifier(const BString& identifier) const
|
||||||
{
|
{
|
||||||
return fDepots.size();
|
BAutolock locker(&fLock);
|
||||||
|
std::map<BString, DepotInfoRef>::const_iterator it;
|
||||||
|
|
||||||
|
for (it = fDepots.begin(); it != fDepots.end(); it++) {
|
||||||
|
if (it->second->Identifier() == identifier)
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DepotInfoRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DepotInfoRef
|
const std::vector<PackageInfoRef>
|
||||||
Model::DepotAtIndex(int32 index) const
|
Model::FilteredPackages() const
|
||||||
{
|
{
|
||||||
return fDepots[index];
|
BAutolock locker(&fLock);
|
||||||
|
std::map<BString, PackageInfoRef>::const_iterator it;
|
||||||
|
std::vector<PackageInfoRef> result;
|
||||||
|
|
||||||
|
for (it = fPackages.begin(); it != fPackages.end(); it++) {
|
||||||
|
PackageInfoRef package = it->second;
|
||||||
|
if (fFilter->AcceptsPackage(package))
|
||||||
|
result.push_back(package);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector<PackageInfoRef>
|
||||||
|
Model::Packages() const
|
||||||
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
std::map<BString, PackageInfoRef>::const_iterator it;
|
||||||
|
std::vector<PackageInfoRef> result;
|
||||||
|
|
||||||
|
for (it = fPackages.begin(); it != fPackages.end(); it++)
|
||||||
|
result.push_back(it->second);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
Model::_ChangeDiff(const PackageInfoRef& package)
|
||||||
|
{
|
||||||
|
uint32 changeMask = kChangeMaskAll;
|
||||||
|
const PackageInfoRef existingPackage = PackageForName(package->Name());
|
||||||
|
|
||||||
|
if (existingPackage.IsSet())
|
||||||
|
changeMask = package->ChangeMask(*(existingPackage.Get()));
|
||||||
|
|
||||||
|
return changeMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Model::AddPackage(const PackageInfoRef& package)
|
||||||
|
{
|
||||||
|
if (!package.IsSet())
|
||||||
|
HDFATAL("attempt to add an unset package");
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
uint32 changeMask = _ChangeDiff(package);
|
||||||
|
fPackages[package->Name()] = package;
|
||||||
|
_NotifyPackageChange(PackageInfoEvent(package, changeMask));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Model::AddPackages(const std::vector<PackageInfoRef>& packages)
|
||||||
|
{
|
||||||
|
if (packages.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
PackageInfoEvents events;
|
||||||
|
std::vector<PackageInfoRef>::const_iterator it;
|
||||||
|
|
||||||
|
for (it = packages.begin(); it != packages.end(); it++) {
|
||||||
|
PackageInfoRef package = *it;
|
||||||
|
events.AddEvent(PackageInfoEvent(package, _ChangeDiff(package)));
|
||||||
|
fPackages[package->Name()] = package;
|
||||||
|
}
|
||||||
|
|
||||||
|
_NotifyPackageChanges(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Model::AddPackagesWithChange(const std::vector<PackageInfoRef>& packages, uint32 changeMask)
|
||||||
|
{
|
||||||
|
if (packages.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
PackageInfoEvents events;
|
||||||
|
|
||||||
|
std::vector<PackageInfoRef>::const_iterator it;
|
||||||
|
for (it = packages.begin(); it != packages.end(); it++) {
|
||||||
|
PackageInfoRef package = *it;
|
||||||
|
events.AddEvent(PackageInfoEvent(package, changeMask));
|
||||||
|
fPackages[package->Name()] = package;
|
||||||
|
}
|
||||||
|
|
||||||
|
_NotifyPackageChanges(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackageInfoRef
|
||||||
|
Model::PackageForName(const BString& name) const
|
||||||
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
std::map<BString, PackageInfoRef>::const_iterator it = fPackages.find(name);
|
||||||
|
if (it != fPackages.end())
|
||||||
|
return it->second;
|
||||||
|
return PackageInfoRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Model::HasPackage(const BString& packageName) const
|
||||||
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
if (fPackages.find(packageName) != fPackages.end())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Model::HasAnyProminentPackages()
|
Model::HasAnyProminentPackages()
|
||||||
{
|
{
|
||||||
std::vector<DepotInfoRef>::iterator it;
|
BAutolock locker(&fLock);
|
||||||
for (it = fDepots.begin(); it != fDepots.end(); it++) {
|
std::map<BString, PackageInfoRef>::iterator it;
|
||||||
DepotInfoRef aDepot = *it;
|
|
||||||
if (aDepot->HasAnyProminentPackages())
|
for (it = fPackages.begin(); it != fPackages.end(); it++) {
|
||||||
return true;
|
const PackageInfoRef package = it->second;
|
||||||
|
|
||||||
|
if (package.IsSet()) {
|
||||||
|
const PackageClassificationInfoRef classificationInfo
|
||||||
|
= package->PackageClassificationInfo();
|
||||||
|
|
||||||
|
if (classificationInfo.IsSet()) {
|
||||||
|
if (classificationInfo->IsProminent())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,47 +458,41 @@ Model::HasAnyProminentPackages()
|
|||||||
void
|
void
|
||||||
Model::Clear()
|
Model::Clear()
|
||||||
{
|
{
|
||||||
GetPackageIconRepository().Clear();
|
BAutolock locker(&fLock);
|
||||||
|
fIconRepository = PackageIconRepositoryRef(new PackageIconDefaultRepository(), true);
|
||||||
fDepots.clear();
|
fDepots.clear();
|
||||||
fPopulatedPackageNames.MakeEmpty();
|
fPackages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
package_list_view_mode
|
||||||
Model::SetStateForPackagesByName(BStringList& packageNames, PackageState state)
|
Model::PackageListViewMode() const
|
||||||
{
|
{
|
||||||
for (int32 i = 0; i < packageNames.CountStrings(); i++) {
|
BAutolock locker(&fLock);
|
||||||
BString packageName = packageNames.StringAt(i);
|
return fPackageListViewMode;
|
||||||
PackageInfoRef packageInfo = PackageForName(packageName);
|
|
||||||
|
|
||||||
if (packageInfo.IsSet()) {
|
|
||||||
// TODO; make this immutable
|
|
||||||
|
|
||||||
PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(packageInfo);
|
|
||||||
localInfo->SetState(state);
|
|
||||||
packageInfo->SetLocalInfo(localInfo);
|
|
||||||
|
|
||||||
HDINFO("did update package [%s] with state [%s]", packageName.String(),
|
|
||||||
PackageUtils::StateToString(state));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
HDINFO("was unable to find package [%s] so was not possible to set the state to [%s]",
|
|
||||||
packageName.String(), PackageUtils::StateToString(state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::SetPackageListViewMode(package_list_view_mode mode)
|
Model::SetPackageListViewMode(package_list_view_mode mode)
|
||||||
{
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
fPackageListViewMode = mode;
|
fPackageListViewMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Model::CanShareAnonymousUsageData() const
|
||||||
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
|
return fCanShareAnonymousUsageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::SetCanShareAnonymousUsageData(bool value)
|
Model::SetCanShareAnonymousUsageData(bool value)
|
||||||
{
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
fCanShareAnonymousUsageData = value;
|
fCanShareAnonymousUsageData = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,104 +518,29 @@ Model::CanPopulatePackage(const PackageInfoRef& package)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
WebAppInterfaceRef
|
||||||
model_remove_key_for_user(const BString& nickname)
|
Model::WebApp()
|
||||||
{
|
{
|
||||||
if (nickname.IsEmpty())
|
BAutolock locker(&fLock);
|
||||||
return;
|
return fWebApp;
|
||||||
BKeyStore keyStore;
|
|
||||||
BPasswordKey key;
|
|
||||||
BString passwordIdentifier = BString(KEY_STORE_IDENTIFIER_PREFIX)
|
|
||||||
<< nickname;
|
|
||||||
status_t result = keyStore.GetKey(kHaikuDepotKeyring, B_KEY_TYPE_PASSWORD,
|
|
||||||
passwordIdentifier, key);
|
|
||||||
|
|
||||||
switch (result) {
|
|
||||||
case B_OK:
|
|
||||||
result = keyStore.RemoveKey(kHaikuDepotKeyring, key);
|
|
||||||
if (result != B_OK) {
|
|
||||||
HDERROR("error occurred when removing password for nickname "
|
|
||||||
"[%s] : %s", nickname.String(), strerror(result));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case B_ENTRY_NOT_FOUND:
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
HDERROR("error occurred when finding password for nickname "
|
|
||||||
"[%s] : %s", nickname.String(), strerror(result));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Model::SetNickname(BString nickname)
|
|
||||||
{
|
|
||||||
BString password;
|
|
||||||
BString existingNickname = Nickname();
|
|
||||||
|
|
||||||
// this happens when the user is logging out. Best to remove the password
|
|
||||||
// stored for the existing user since it is no longer required.
|
|
||||||
|
|
||||||
if (!existingNickname.IsEmpty() && nickname.IsEmpty())
|
|
||||||
model_remove_key_for_user(existingNickname);
|
|
||||||
|
|
||||||
if (nickname.Length() > 0) {
|
|
||||||
BPasswordKey key;
|
|
||||||
BKeyStore keyStore;
|
|
||||||
BString passwordIdentifier = BString(KEY_STORE_IDENTIFIER_PREFIX)
|
|
||||||
<< nickname;
|
|
||||||
if (keyStore.GetKey(kHaikuDepotKeyring, B_KEY_TYPE_PASSWORD,
|
|
||||||
passwordIdentifier, key) == B_OK) {
|
|
||||||
password = key.Password();
|
|
||||||
}
|
|
||||||
if (password.IsEmpty())
|
|
||||||
nickname = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
SetCredentials(nickname, password, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const BString&
|
const BString&
|
||||||
Model::Nickname()
|
Model::Nickname()
|
||||||
{
|
{
|
||||||
return fWebAppInterface.Nickname();
|
BAutolock locker(&fLock);
|
||||||
|
return fWebApp->Nickname();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::SetCredentials(const BString& nickname, const BString& passwordClear,
|
Model::SetCredentials(const UserCredentials& credentials)
|
||||||
bool storePassword)
|
|
||||||
{
|
{
|
||||||
BString existingNickname = Nickname();
|
|
||||||
|
|
||||||
if (storePassword) {
|
|
||||||
// no point continuing to store the password for the previous user.
|
|
||||||
|
|
||||||
if (!existingNickname.IsEmpty())
|
|
||||||
model_remove_key_for_user(existingNickname);
|
|
||||||
|
|
||||||
// adding a key that is already there does not seem to override the
|
|
||||||
// existing key so the old key needs to be removed first.
|
|
||||||
|
|
||||||
if (!nickname.IsEmpty())
|
|
||||||
model_remove_key_for_user(nickname);
|
|
||||||
|
|
||||||
if (!nickname.IsEmpty() && !passwordClear.IsEmpty()) {
|
|
||||||
BString keyIdentifier = BString(KEY_STORE_IDENTIFIER_PREFIX)
|
|
||||||
<< nickname;
|
|
||||||
BPasswordKey key(passwordClear, B_KEY_PURPOSE_WEB, keyIdentifier);
|
|
||||||
BKeyStore keyStore;
|
|
||||||
keyStore.AddKeyring(kHaikuDepotKeyring);
|
|
||||||
keyStore.AddKey(kHaikuDepotKeyring, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BAutolock locker(&fLock);
|
BAutolock locker(&fLock);
|
||||||
fWebAppInterface.SetCredentials(UserCredentials(nickname, passwordClear));
|
const BString existingNickname = Nickname();
|
||||||
|
fWebApp = WebAppInterfaceRef(new WebAppInterface(credentials));
|
||||||
if (nickname != existingNickname)
|
if (credentials.Nickname() != existingNickname)
|
||||||
_NotifyAuthorizationChanged();
|
_NotifyAuthorizationChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,6 +548,22 @@ Model::SetCredentials(const BString& nickname, const BString& passwordClear,
|
|||||||
// #pragma mark - listener notification methods
|
// #pragma mark - listener notification methods
|
||||||
|
|
||||||
|
|
||||||
|
/*! Assumes that the class is locked.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Model::_NotifyPackageFilterChanged()
|
||||||
|
{
|
||||||
|
std::vector<ModelListenerRef>::const_iterator it;
|
||||||
|
for (it = fListeners.begin(); it != fListeners.end(); it++) {
|
||||||
|
const ModelListenerRef& listener = *it;
|
||||||
|
if (listener.IsSet())
|
||||||
|
listener->PackageFilterChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Assumes that the class is locked.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
Model::_NotifyAuthorizationChanged()
|
Model::_NotifyAuthorizationChanged()
|
||||||
{
|
{
|
||||||
@@ -423,8 +589,35 @@ Model::_NotifyCategoryListChanged()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::_MaybeLogJsonRpcError(const BMessage &responsePayload,
|
Model::_NotifyPackageChange(const PackageInfoEvent& event)
|
||||||
const char *sourceDescription) const
|
{
|
||||||
|
std::vector<PackageInfoListenerRef>::const_iterator it;
|
||||||
|
for (it = fPackageListeners.begin(); it != fPackageListeners.end(); it++) {
|
||||||
|
const PackageInfoListenerRef& listener = *it;
|
||||||
|
if (listener.IsSet())
|
||||||
|
listener->PackagesChanged(PackageInfoEvents(event));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: future work to optimize how this is conveyed to the listener in one go.
|
||||||
|
void
|
||||||
|
Model::_NotifyPackageChanges(const PackageInfoEvents& events)
|
||||||
|
{
|
||||||
|
if (events.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<PackageInfoListenerRef>::const_iterator it;
|
||||||
|
for (it = fPackageListeners.begin(); it != fPackageListeners.end(); it++) {
|
||||||
|
const PackageInfoListenerRef& listener = *it;
|
||||||
|
if (listener.IsSet())
|
||||||
|
listener->PackagesChanged(events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Model::_MaybeLogJsonRpcError(const BMessage& responsePayload, const char* sourceDescription) const
|
||||||
{
|
{
|
||||||
BMessage error;
|
BMessage error;
|
||||||
BString errorMessage;
|
BString errorMessage;
|
||||||
@@ -433,143 +626,66 @@ Model::_MaybeLogJsonRpcError(const BMessage &responsePayload,
|
|||||||
if (responsePayload.FindMessage("error", &error) == B_OK
|
if (responsePayload.FindMessage("error", &error) == B_OK
|
||||||
&& error.FindString("message", &errorMessage) == B_OK
|
&& error.FindString("message", &errorMessage) == B_OK
|
||||||
&& error.FindDouble("code", &errorCode) == B_OK) {
|
&& error.FindDouble("code", &errorCode) == B_OK) {
|
||||||
HDERROR("[%s] --> error : [%s] (%f)", sourceDescription,
|
HDERROR("[%s] --> error : [%s] (%f)", sourceDescription, errorMessage.String(), errorCode);
|
||||||
errorMessage.String(), errorCode);
|
} else {
|
||||||
} else
|
|
||||||
HDERROR("[%s] --> an undefined error has occurred", sourceDescription);
|
HDERROR("[%s] --> an undefined error has occurred", sourceDescription);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Rating Stabilities
|
// #pragma mark - Rating Stabilities
|
||||||
|
|
||||||
|
|
||||||
int32
|
const std::vector<RatingStabilityRef>
|
||||||
Model::CountRatingStabilities() const
|
Model::RatingStabilities() const
|
||||||
{
|
{
|
||||||
return fRatingStabilities.size();
|
BAutolock locker(&fLock);
|
||||||
}
|
return fRatingStabilities;
|
||||||
|
|
||||||
|
|
||||||
RatingStabilityRef
|
|
||||||
Model::RatingStabilityByCode(BString& code) const
|
|
||||||
{
|
|
||||||
std::vector<RatingStabilityRef>::const_iterator it;
|
|
||||||
for (it = fRatingStabilities.begin(); it != fRatingStabilities.end();
|
|
||||||
it++) {
|
|
||||||
RatingStabilityRef aRatingStability = *it;
|
|
||||||
if (aRatingStability->Code() == code)
|
|
||||||
return aRatingStability;
|
|
||||||
}
|
|
||||||
return RatingStabilityRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RatingStabilityRef
|
|
||||||
Model::RatingStabilityAtIndex(int32 index) const
|
|
||||||
{
|
|
||||||
return fRatingStabilities[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::AddRatingStabilities(std::vector<RatingStabilityRef>& values)
|
Model::SetRatingStabilities(const std::vector<RatingStabilityRef> value)
|
||||||
{
|
{
|
||||||
std::vector<RatingStabilityRef>::const_iterator it;
|
BAutolock locker(&fLock);
|
||||||
for (it = values.begin(); it != values.end(); it++)
|
fRatingStabilities = value;
|
||||||
_AddRatingStability(*it);
|
std::sort(fRatingStabilities.begin(), fRatingStabilities.end(), IsRatingStabilityRefLess);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Model::_AddRatingStability(const RatingStabilityRef& value)
|
|
||||||
{
|
|
||||||
std::vector<RatingStabilityRef>::const_iterator itInsertionPtConst
|
|
||||||
= std::lower_bound(
|
|
||||||
fRatingStabilities.begin(),
|
|
||||||
fRatingStabilities.end(),
|
|
||||||
value,
|
|
||||||
&IsRatingStabilityBefore);
|
|
||||||
std::vector<RatingStabilityRef>::iterator itInsertionPt =
|
|
||||||
fRatingStabilities.begin()
|
|
||||||
+ (itInsertionPtConst - fRatingStabilities.begin());
|
|
||||||
|
|
||||||
if (itInsertionPt != fRatingStabilities.end()
|
|
||||||
&& (*itInsertionPt)->Code() == value->Code()) {
|
|
||||||
itInsertionPt = fRatingStabilities.erase(itInsertionPt);
|
|
||||||
// replace the one with the same code.
|
|
||||||
}
|
|
||||||
|
|
||||||
fRatingStabilities.insert(itInsertionPt, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Categories
|
// #pragma mark - Categories
|
||||||
|
|
||||||
|
|
||||||
int32
|
bool
|
||||||
Model::CountCategories() const
|
Model::HasCategories()
|
||||||
{
|
{
|
||||||
return fCategories.size();
|
BAutolock locker(&fLock);
|
||||||
|
return !fCategories.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CategoryRef
|
const std::vector<CategoryRef>
|
||||||
Model::CategoryByCode(BString& code) const
|
Model::Categories() const
|
||||||
{
|
{
|
||||||
std::vector<CategoryRef>::const_iterator it;
|
BAutolock locker(&fLock);
|
||||||
for (it = fCategories.begin(); it != fCategories.end(); it++) {
|
return fCategories;
|
||||||
CategoryRef aCategory = *it;
|
|
||||||
if (aCategory->Code() == code)
|
|
||||||
return aCategory;
|
|
||||||
}
|
|
||||||
return CategoryRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CategoryRef
|
|
||||||
Model::CategoryAtIndex(int32 index) const
|
|
||||||
{
|
|
||||||
return fCategories[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::AddCategories(std::vector<CategoryRef>& values)
|
Model::SetCategories(const std::vector<CategoryRef> value)
|
||||||
{
|
{
|
||||||
std::vector<CategoryRef>::iterator it;
|
BAutolock locker(&fLock);
|
||||||
for (it = values.begin(); it != values.end(); it++)
|
fCategories = value;
|
||||||
_AddCategory(*it);
|
std::sort(fCategories.begin(), fCategories.end(), IsPackageCategoryRefLess);
|
||||||
_NotifyCategoryListChanged();
|
_NotifyCategoryListChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! This will insert the category in order.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
Model::_AddCategory(const CategoryRef& category)
|
|
||||||
{
|
|
||||||
std::vector<CategoryRef>::const_iterator itInsertionPtConst
|
|
||||||
= std::lower_bound(
|
|
||||||
fCategories.begin(),
|
|
||||||
fCategories.end(),
|
|
||||||
category,
|
|
||||||
&IsPackageCategoryBefore);
|
|
||||||
std::vector<CategoryRef>::iterator itInsertionPt =
|
|
||||||
fCategories.begin() + (itInsertionPtConst - fCategories.begin());
|
|
||||||
|
|
||||||
if (itInsertionPt != fCategories.end()
|
|
||||||
&& (*itInsertionPt)->Code() == category->Code()) {
|
|
||||||
itInsertionPt = fCategories.erase(itInsertionPt);
|
|
||||||
// replace the one with the same code.
|
|
||||||
}
|
|
||||||
|
|
||||||
fCategories.insert(itInsertionPt, category);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::ScreenshotCached(const ScreenshotCoordinate& coord)
|
Model::ScreenshotCached(const ScreenshotCoordinate& coord)
|
||||||
{
|
{
|
||||||
|
BAutolock locker(&fLock);
|
||||||
std::vector<ModelListenerRef>::const_iterator it;
|
std::vector<ModelListenerRef>::const_iterator it;
|
||||||
for (it = fListeners.begin(); it != fListeners.end(); it++) {
|
for (it = fListeners.begin(); it != fListeners.end(); it++) {
|
||||||
const ModelListenerRef& listener = *it;
|
const ModelListenerRef& listener = *it;
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef MODEL_H
|
#ifndef MODEL_H
|
||||||
#define MODEL_H
|
#define MODEL_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
|
|
||||||
#include "AbstractProcess.h"
|
#include "AbstractProcess.h"
|
||||||
#include "DepotInfo.h"
|
#include "DepotInfo.h"
|
||||||
#include "LanguageRepository.h"
|
#include "PackageFilter.h"
|
||||||
#include "PackageFilterModel.h"
|
#include "PackageFilterSpecification.h"
|
||||||
#include "PackageIconTarRepository.h"
|
#include "PackageIconDefaultRepository.h"
|
||||||
#include "PackageInfo.h"
|
#include "PackageInfo.h"
|
||||||
|
#include "PackageInfoListener.h"
|
||||||
#include "PackageScreenshotRepository.h"
|
#include "PackageScreenshotRepository.h"
|
||||||
#include "RatingStability.h"
|
#include "RatingStability.h"
|
||||||
#include "ScreenshotCoordinate.h"
|
#include "ScreenshotCoordinate.h"
|
||||||
@@ -40,6 +42,8 @@ public:
|
|||||||
virtual void AuthorizationChanged() = 0;
|
virtual void AuthorizationChanged() = 0;
|
||||||
virtual void CategoryListChanged() = 0;
|
virtual void CategoryListChanged() = 0;
|
||||||
virtual void ScreenshotCached(const ScreenshotCoordinate& coordinate) = 0;
|
virtual void ScreenshotCached(const ScreenshotCoordinate& coordinate) = 0;
|
||||||
|
virtual void IconsChanged() = 0;
|
||||||
|
virtual void PackageFilterChanged() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -59,77 +63,82 @@ public:
|
|||||||
Model();
|
Model();
|
||||||
virtual ~Model();
|
virtual ~Model();
|
||||||
|
|
||||||
PackageFilterModel* PackageFilter();
|
void Clear();
|
||||||
PackageIconRepository&
|
|
||||||
GetPackageIconRepository();
|
void AddListener(const ModelListenerRef& listener);
|
||||||
status_t InitPackageIconRepository();
|
void AddPackageListener(const PackageInfoListenerRef& packageListener);
|
||||||
|
|
||||||
|
status_t DearchiveInfoEvents(const BMessage* message,
|
||||||
|
PackageInfoEvents& packageInfoEvents) const;
|
||||||
|
|
||||||
PackageScreenshotRepository*
|
PackageScreenshotRepository*
|
||||||
GetPackageScreenshotRepository();
|
GetPackageScreenshotRepository();
|
||||||
|
|
||||||
BLocker* Lock()
|
void SetFilterSpecification(const PackageFilterSpecificationRef& value);
|
||||||
{ return &fLock; }
|
const PackageFilterSpecificationRef
|
||||||
|
FilterSpecification() const;
|
||||||
|
PackageFilterRef Filter() const;
|
||||||
|
|
||||||
void AddListener(const ModelListenerRef& listener);
|
PackageIconRepositoryRef
|
||||||
|
IconRepository();
|
||||||
|
void SetIconRepository(PackageIconRepositoryRef value);
|
||||||
|
|
||||||
LanguageRef PreferredLanguage() const;
|
const std::vector<PackageInfoRef>
|
||||||
void SetPreferredLanguage(LanguageRef value);
|
Packages() const;
|
||||||
LanguageRepository* Languages();
|
const std::vector<PackageInfoRef>
|
||||||
|
FilteredPackages() const;
|
||||||
PackageInfoRef PackageForName(const BString& name);
|
void AddPackage(const PackageInfoRef& package);
|
||||||
|
void AddPackages(const std::vector<PackageInfoRef>& packages);
|
||||||
void MergeOrAddDepot(const DepotInfoRef& depot);
|
void AddPackagesWithChange(const std::vector<PackageInfoRef>& packages,
|
||||||
bool HasDepot(const BString& name) const;
|
uint32 changesMask);
|
||||||
int32 CountDepots() const;
|
const PackageInfoRef
|
||||||
DepotInfoRef DepotAtIndex(int32 index) const;
|
PackageForName(const BString& name) const;
|
||||||
const DepotInfoRef DepotForName(const BString& name) const;
|
bool HasPackage(const BString& packageName) const;
|
||||||
bool HasAnyProminentPackages();
|
bool HasAnyProminentPackages();
|
||||||
|
|
||||||
void Clear();
|
const LanguageRef PreferredLanguage() const;
|
||||||
|
void SetPreferredLanguage(const LanguageRef& value);
|
||||||
|
const std::vector<LanguageRef>
|
||||||
|
Languages() const;
|
||||||
|
void SetLanguagesAndPreferred(const std::vector<LanguageRef>& value,
|
||||||
|
const LanguageRef& preferred);
|
||||||
|
|
||||||
int32 CountCategories() const;
|
void SetDepots(const DepotInfoRef& depot);
|
||||||
CategoryRef CategoryByCode(BString& code) const;
|
void SetDepots(const std::vector<DepotInfoRef>& depots);
|
||||||
CategoryRef CategoryAtIndex(int32 index) const;
|
const std::vector<DepotInfoRef>
|
||||||
void AddCategories(
|
Depots() const;
|
||||||
std::vector<CategoryRef>& values);
|
const DepotInfoRef DepotForName(const BString& name) const;
|
||||||
|
const DepotInfoRef DepotForIdentifier(const BString& identifier) const;
|
||||||
|
|
||||||
int32 CountRatingStabilities() const;
|
const std::vector<CategoryRef>
|
||||||
RatingStabilityRef RatingStabilityByCode(BString& code) const;
|
Categories() const;
|
||||||
RatingStabilityRef RatingStabilityAtIndex(int32 index) const;
|
void SetCategories(const std::vector<CategoryRef> value);
|
||||||
void AddRatingStabilities(
|
bool HasCategories();
|
||||||
std::vector<RatingStabilityRef>& values);
|
|
||||||
|
|
||||||
void SetStateForPackagesByName(
|
|
||||||
BStringList& packageNames,
|
|
||||||
PackageState state);
|
|
||||||
|
|
||||||
|
const std::vector<RatingStabilityRef>
|
||||||
|
RatingStabilities() const;
|
||||||
|
void SetRatingStabilities(const std::vector<RatingStabilityRef> value);
|
||||||
|
|
||||||
void SetPackageListViewMode(
|
void SetPackageListViewMode(
|
||||||
package_list_view_mode mode);
|
package_list_view_mode mode);
|
||||||
package_list_view_mode
|
package_list_view_mode
|
||||||
PackageListViewMode() const
|
PackageListViewMode() const;
|
||||||
{ return fPackageListViewMode; }
|
|
||||||
|
|
||||||
void SetCanShareAnonymousUsageData(bool value);
|
void SetCanShareAnonymousUsageData(bool value);
|
||||||
bool CanShareAnonymousUsageData() const
|
bool CanShareAnonymousUsageData() const;
|
||||||
{ return fCanShareAnonymousUsageData; }
|
|
||||||
|
|
||||||
bool CanPopulatePackage(
|
bool CanPopulatePackage(const PackageInfoRef& package);
|
||||||
const PackageInfoRef& package);
|
|
||||||
|
|
||||||
void SetNickname(BString nickname);
|
void SetCredentials(const UserCredentials& credentials);
|
||||||
const BString& Nickname();
|
const BString& Nickname();
|
||||||
void SetCredentials(const BString& nickname,
|
WebAppInterfaceRef WebApp();
|
||||||
const BString& passwordClear,
|
|
||||||
bool storePassword);
|
|
||||||
|
|
||||||
WebAppInterface* GetWebAppInterface()
|
|
||||||
{ return &fWebAppInterface; }
|
|
||||||
|
|
||||||
// PackageScreenshotRepositoryListener
|
// PackageScreenshotRepositoryListener
|
||||||
virtual void ScreenshotCached(const ScreenshotCoordinate& coord);
|
virtual void ScreenshotCached(const ScreenshotCoordinate& coord);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _AddCategory(const CategoryRef& category);
|
uint32 _ChangeDiff(const PackageInfoRef& package);
|
||||||
|
|
||||||
void _AddRatingStability(
|
void _AddRatingStability(
|
||||||
const RatingStabilityRef& value);
|
const RatingStabilityRef& value);
|
||||||
@@ -138,41 +147,52 @@ private:
|
|||||||
const BMessage &responsePayload,
|
const BMessage &responsePayload,
|
||||||
const char *sourceDescription) const;
|
const char *sourceDescription) const;
|
||||||
|
|
||||||
|
void _NotifyPackageFilterChanged();
|
||||||
|
void _NotifyIconsChanged();
|
||||||
void _NotifyAuthorizationChanged();
|
void _NotifyAuthorizationChanged();
|
||||||
void _NotifyCategoryListChanged();
|
void _NotifyCategoryListChanged();
|
||||||
|
void _NotifyPackageChange(const PackageInfoEvent& event);
|
||||||
|
void _NotifyPackageChanges(const PackageInfoEvents& events);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BLocker fLock;
|
mutable BLocker fLock;
|
||||||
|
|
||||||
LanguageRef fPreferredLanguage;
|
LanguageRef fPreferredLanguage;
|
||||||
|
|
||||||
std::vector<DepotInfoRef>
|
std::map<BString, DepotInfoRef>
|
||||||
fDepots;
|
fDepots;
|
||||||
|
std::map<BString, PackageInfoRef>
|
||||||
|
fPackages;
|
||||||
|
|
||||||
std::vector<CategoryRef>
|
std::vector<CategoryRef>
|
||||||
fCategories;
|
fCategories;
|
||||||
std::vector<RatingStabilityRef>
|
std::vector<RatingStabilityRef>
|
||||||
fRatingStabilities;
|
fRatingStabilities;
|
||||||
|
|
||||||
BStringList fPopulatedPackageNames;
|
|
||||||
|
|
||||||
package_list_view_mode
|
package_list_view_mode
|
||||||
fPackageListViewMode;
|
fPackageListViewMode;
|
||||||
|
|
||||||
bool fCanShareAnonymousUsageData;
|
bool fCanShareAnonymousUsageData;
|
||||||
|
|
||||||
WebAppInterface fWebAppInterface;
|
WebAppInterfaceRef fWebApp;
|
||||||
|
|
||||||
PackageFilterModel* fPackageFilterModel;
|
PackageFilterSpecificationRef
|
||||||
|
fFilterSpecification;
|
||||||
|
PackageFilterRef fFilter;
|
||||||
|
|
||||||
LanguageRepository* fLanguageRepository;
|
std::vector<LanguageRef>
|
||||||
PackageIconTarRepository
|
fLanguages;
|
||||||
fPackageIconRepository;
|
PackageIconRepositoryRef
|
||||||
|
fIconRepository;
|
||||||
PackageScreenshotRepository*
|
PackageScreenshotRepository*
|
||||||
fPackageScreenshotRepository;
|
fPackageScreenshotRepository;
|
||||||
|
|
||||||
std::vector<ModelListenerRef>
|
std::vector<ModelListenerRef>
|
||||||
fListeners;
|
fListeners;
|
||||||
|
|
||||||
|
std::vector<PackageInfoListenerRef>
|
||||||
|
fPackageListeners;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_INFO_H
|
#endif // MODEL_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2025, Stephan Aßmus <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "PackageInfoListener.h"
|
#include "PackageInfoListener.h"
|
||||||
@@ -9,6 +9,11 @@
|
|||||||
#include "PackageInfo.h"
|
#include "PackageInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char* kPackageInfoChangesKey = "change";
|
||||||
|
const char* kPackageInfoPackageNameKey = "packageName";
|
||||||
|
const char* kPackageInfoEventsKey = "events";
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - PackageInfoEvent
|
// #pragma mark - PackageInfoEvent
|
||||||
|
|
||||||
|
|
||||||
@@ -20,8 +25,7 @@ PackageInfoEvent::PackageInfoEvent()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageInfoEvent::PackageInfoEvent(const PackageInfoRef& package,
|
PackageInfoEvent::PackageInfoEvent(const PackageInfoRef& package, uint32 changes)
|
||||||
uint32 changes)
|
|
||||||
:
|
:
|
||||||
fPackage(package),
|
fPackage(package),
|
||||||
fChanges(changes)
|
fChanges(changes)
|
||||||
@@ -47,9 +51,7 @@ PackageInfoEvent::operator==(const PackageInfoEvent& other)
|
|||||||
{
|
{
|
||||||
if (this == &other)
|
if (this == &other)
|
||||||
return true;
|
return true;
|
||||||
|
return fPackage == other.fPackage && fChanges == other.fChanges;
|
||||||
return fPackage == other.fPackage
|
|
||||||
&& fChanges == other.fChanges;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -72,6 +74,85 @@ PackageInfoEvent::operator=(const PackageInfoEvent& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageInfoEvent::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t result = B_OK;
|
||||||
|
if (result == B_OK)
|
||||||
|
result = into->AddUInt32(kPackageInfoChangesKey, fChanges);
|
||||||
|
if (result == B_OK)
|
||||||
|
result = into->AddString(kPackageInfoPackageNameKey, fPackage->Name());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageInfoEvents
|
||||||
|
|
||||||
|
|
||||||
|
PackageInfoEvents::PackageInfoEvents()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageInfoEvents::PackageInfoEvents(const PackageInfoEvent& event)
|
||||||
|
{
|
||||||
|
fEvents.push_back(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageInfoEvents::PackageInfoEvents(const PackageInfoEvents& other)
|
||||||
|
{
|
||||||
|
for (int32 i = other.CountEvents() - 1; i >= 0; i--)
|
||||||
|
fEvents.push_back(other.EventAtIndex(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageInfoEvents::AddEvent(const PackageInfoEvent event)
|
||||||
|
{
|
||||||
|
fEvents.push_back(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageInfoEvents::IsEmpty() const
|
||||||
|
{
|
||||||
|
return fEvents.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PackageInfoEvents::CountEvents() const
|
||||||
|
{
|
||||||
|
return fEvents.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackageInfoEvent&
|
||||||
|
PackageInfoEvents::EventAtIndex(int32 index) const
|
||||||
|
{
|
||||||
|
return fEvents[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageInfoEvents::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t result = B_OK;
|
||||||
|
BString indexString;
|
||||||
|
std::vector<PackageInfoEvent>::const_iterator it;
|
||||||
|
|
||||||
|
for (it = fEvents.begin(); it != fEvents.end(); it++) {
|
||||||
|
BMessage eventMessage;
|
||||||
|
result = (*it).Archive(&eventMessage);
|
||||||
|
if (result == B_OK)
|
||||||
|
result = into->AddMessage(kPackageInfoEventsKey, &eventMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - PackageInfoListener
|
// #pragma mark - PackageInfoListener
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2022, Andrew Lindesay <[email protected]>.
|
* Copyright 2022-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_INFO_LISTENER_H
|
#ifndef PACKAGE_INFO_LISTENER_H
|
||||||
#define PACKAGE_INFO_LISTENER_H
|
#define PACKAGE_INFO_LISTENER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Archivable.h>
|
||||||
|
#include <String.h>
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern const char* kPackageInfoChangesKey;
|
||||||
|
extern const char* kPackageInfoPackageNameKey;
|
||||||
|
extern const char* kPackageInfoEventsKey;
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PKG_CHANGED_LOCALIZED_TEXT = 1 << 0,
|
PKG_CHANGED_LOCALIZED_TEXT = 1 << 0,
|
||||||
// ^ Covers title, summary, description and changelog.
|
// ^ Covers title, summary, description and changelog.
|
||||||
@@ -17,13 +26,10 @@ enum {
|
|||||||
PKG_CHANGED_SCREENSHOTS = 1 << 2,
|
PKG_CHANGED_SCREENSHOTS = 1 << 2,
|
||||||
PKG_CHANGED_LOCAL_INFO = 1 << 3,
|
PKG_CHANGED_LOCAL_INFO = 1 << 3,
|
||||||
// ^ Covers state, download and size.
|
// ^ Covers state, download and size.
|
||||||
PKG_CHANGED_ICON = 1 << 4,
|
PKG_CHANGED_CLASSIFICATION = 1 << 4,
|
||||||
// ^ Handled slightly differently.
|
|
||||||
PKG_CHANGED_CLASSIFICATION = 1 << 5,
|
|
||||||
// ^ This covers categories, prominence and is native desktop
|
// ^ This covers categories, prominence and is native desktop
|
||||||
PKG_CHANGED_CORE_INFO = 1 << 6
|
PKG_CHANGED_CORE_INFO = 1 << 5
|
||||||
// ^ covers the version change timestamp
|
// ^ covers the version change timestamp
|
||||||
// ...
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -31,11 +37,10 @@ class PackageInfo;
|
|||||||
typedef BReference<PackageInfo> PackageInfoRef;
|
typedef BReference<PackageInfo> PackageInfoRef;
|
||||||
|
|
||||||
|
|
||||||
class PackageInfoEvent {
|
class PackageInfoEvent : public BArchivable {
|
||||||
public:
|
public:
|
||||||
PackageInfoEvent();
|
PackageInfoEvent();
|
||||||
PackageInfoEvent(const PackageInfoRef& package,
|
PackageInfoEvent(const PackageInfoRef& package, uint32 changes);
|
||||||
uint32 changes);
|
|
||||||
PackageInfoEvent(const PackageInfoEvent& other);
|
PackageInfoEvent(const PackageInfoEvent& other);
|
||||||
virtual ~PackageInfoEvent();
|
virtual ~PackageInfoEvent();
|
||||||
|
|
||||||
@@ -43,25 +48,47 @@ public:
|
|||||||
bool operator!=(const PackageInfoEvent& other);
|
bool operator!=(const PackageInfoEvent& other);
|
||||||
PackageInfoEvent& operator=(const PackageInfoEvent& other);
|
PackageInfoEvent& operator=(const PackageInfoEvent& other);
|
||||||
|
|
||||||
inline const PackageInfoRef& Package() const
|
inline const PackageInfoRef&
|
||||||
|
Package() const
|
||||||
{ return fPackage; }
|
{ return fPackage; }
|
||||||
|
|
||||||
inline uint32 Changes() const
|
inline uint32 Changes() const
|
||||||
{ return fChanges; }
|
{ return fChanges; }
|
||||||
|
|
||||||
|
status_t Archive(BMessage* into, bool deep = true) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PackageInfoRef fPackage;
|
PackageInfoRef fPackage;
|
||||||
uint32 fChanges;
|
uint32 fChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PackageInfoEvents : public BArchivable {
|
||||||
|
public:
|
||||||
|
PackageInfoEvents();
|
||||||
|
PackageInfoEvents(const PackageInfoEvent& event);
|
||||||
|
PackageInfoEvents(const PackageInfoEvents& other);
|
||||||
|
|
||||||
|
bool IsEmpty() const;
|
||||||
|
void AddEvent(const PackageInfoEvent event);
|
||||||
|
int32 CountEvents() const;
|
||||||
|
const PackageInfoEvent&
|
||||||
|
EventAtIndex(int32 index) const;
|
||||||
|
|
||||||
|
status_t Archive(BMessage* into, bool deep = true) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<PackageInfoEvent>
|
||||||
|
fEvents;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class PackageInfoListener : public BReferenceable {
|
class PackageInfoListener : public BReferenceable {
|
||||||
public:
|
public:
|
||||||
PackageInfoListener();
|
PackageInfoListener();
|
||||||
virtual ~PackageInfoListener();
|
virtual ~PackageInfoListener();
|
||||||
|
|
||||||
virtual void PackageChanged(
|
virtual void PackagesChanged(const PackageInfoEvents& events) = 0;
|
||||||
const PackageInfoEvent& event) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "PackageScreenshotRepository.h"
|
#include "PackageScreenshotRepository.h"
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "FileIO.h"
|
#include "FileIO.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "Model.h"
|
||||||
#include "StorageUtils.h"
|
#include "StorageUtils.h"
|
||||||
#include "WebAppInterface.h"
|
#include "WebAppInterface.h"
|
||||||
|
|
||||||
@@ -19,11 +20,10 @@ static const uint32 kMaxRetainedCachedScreenshots = 25;
|
|||||||
|
|
||||||
|
|
||||||
PackageScreenshotRepository::PackageScreenshotRepository(
|
PackageScreenshotRepository::PackageScreenshotRepository(
|
||||||
PackageScreenshotRepositoryListenerRef listener,
|
PackageScreenshotRepositoryListenerRef listener, Model* model)
|
||||||
WebAppInterface* webAppInterface)
|
|
||||||
:
|
:
|
||||||
fListener(listener),
|
fListener(listener),
|
||||||
fWebAppInterface(webAppInterface)
|
fModel(model)
|
||||||
{
|
{
|
||||||
_Init();
|
_Init();
|
||||||
}
|
}
|
||||||
@@ -162,8 +162,7 @@ PackageScreenshotRepository::_Init()
|
|||||||
{
|
{
|
||||||
fBaseDirectory.Unset();
|
fBaseDirectory.Unset();
|
||||||
|
|
||||||
status_t result = StorageUtils::LocalWorkingDirectoryPath(
|
status_t result = StorageUtils::LocalWorkingDirectoryPath("screenshot_cache", fBaseDirectory);
|
||||||
"screenshot_cache", fBaseDirectory);
|
|
||||||
|
|
||||||
if (B_OK != result)
|
if (B_OK != result)
|
||||||
HDERROR("unable to setup the cache directory");
|
HDERROR("unable to setup the cache directory");
|
||||||
@@ -202,8 +201,8 @@ PackageScreenshotRepository::_DownloadToLocalFile(const ScreenshotCoordinate& co
|
|||||||
}
|
}
|
||||||
|
|
||||||
BFileIO outputDataStream(file, true); // takes ownership
|
BFileIO outputDataStream(file, true); // takes ownership
|
||||||
status_t result = fWebAppInterface->RetrieveScreenshot(
|
status_t result = _WebApp()->RetrieveScreenshot(coord.Code(), coord.Width(), coord.Height(),
|
||||||
coord.Code(), coord.Width(), coord.Height(), &outputDataStream);
|
&outputDataStream);
|
||||||
|
|
||||||
if (result == B_OK)
|
if (result == B_OK)
|
||||||
result = outputDataStream.Flush();
|
result = outputDataStream.Flush();
|
||||||
@@ -225,7 +224,8 @@ PackageScreenshotRepository::_DeriveCachePath(const ScreenshotCoordinate& coord)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageScreenshotRepository::_CreateCachedData(const ScreenshotCoordinate& coord, BPositionIO** data)
|
PackageScreenshotRepository::_CreateCachedData(const ScreenshotCoordinate& coord,
|
||||||
|
BPositionIO** data)
|
||||||
{
|
{
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
BPath path = _DeriveCachePath(coord);
|
BPath path = _DeriveCachePath(coord);
|
||||||
@@ -243,3 +243,10 @@ PackageScreenshotRepository::_CreateCachedData(const ScreenshotCoordinate& coord
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WebAppInterfaceRef
|
||||||
|
PackageScreenshotRepository::_WebApp()
|
||||||
|
{
|
||||||
|
return fModel->WebApp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef SCREENSHOT_REPOSITORY_H
|
#ifndef SCREENSHOT_REPOSITORY_H
|
||||||
@@ -12,9 +12,10 @@
|
|||||||
|
|
||||||
#include "BitmapHolder.h"
|
#include "BitmapHolder.h"
|
||||||
#include "ScreenshotCoordinate.h"
|
#include "ScreenshotCoordinate.h"
|
||||||
|
#include "WebAppInterface.h"
|
||||||
|
|
||||||
|
|
||||||
class WebAppInterface;
|
class Model;
|
||||||
|
|
||||||
|
|
||||||
class PackageScreenshotRepositoryListener : public BReferenceable {
|
class PackageScreenshotRepositoryListener : public BReferenceable {
|
||||||
@@ -36,7 +37,7 @@ public:
|
|||||||
|
|
||||||
PackageScreenshotRepository(
|
PackageScreenshotRepository(
|
||||||
PackageScreenshotRepositoryListenerRef listener,
|
PackageScreenshotRepositoryListenerRef listener,
|
||||||
WebAppInterface* webAppInterface);
|
Model* model);
|
||||||
~PackageScreenshotRepository();
|
~PackageScreenshotRepository();
|
||||||
|
|
||||||
status_t LoadScreenshot(const ScreenshotCoordinate& coord,
|
status_t LoadScreenshot(const ScreenshotCoordinate& coord,
|
||||||
@@ -48,6 +49,8 @@ public:
|
|||||||
status_t CacheScreenshot(const ScreenshotCoordinate& coord);
|
status_t CacheScreenshot(const ScreenshotCoordinate& coord);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WebAppInterfaceRef _WebApp();
|
||||||
|
|
||||||
status_t _Init();
|
status_t _Init();
|
||||||
|
|
||||||
status_t _CleanCache();
|
status_t _CleanCache();
|
||||||
@@ -61,7 +64,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
PackageScreenshotRepositoryListenerRef
|
PackageScreenshotRepositoryListenerRef
|
||||||
fListener;
|
fListener;
|
||||||
WebAppInterface* fWebAppInterface;
|
Model* fModel;
|
||||||
BPath fBaseDirectory;
|
BPath fBaseDirectory;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Andrew Lindesay <[email protected]>.
|
* Copyright 2020-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -12,12 +12,12 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
|
|
||||||
bool IsRatingStabilityBefore(const RatingStabilityRef& rs1,
|
bool
|
||||||
const RatingStabilityRef& rs2)
|
IsRatingStabilityRefLess(const RatingStabilityRef& rs1, const RatingStabilityRef& rs2)
|
||||||
{
|
{
|
||||||
if (!rs1.IsSet() || !rs2.IsSet())
|
if (!rs1.IsSet() || !rs2.IsSet())
|
||||||
HDFATAL("unexpected NULL reference in a referencable");
|
debugger("illegal state in rating stability less");
|
||||||
return rs1->Compare(*rs2) < 0;
|
return *(rs1.Get()) < *(rs2.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -30,8 +30,7 @@ RatingStability::RatingStability()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RatingStability::RatingStability(const BString& code,
|
RatingStability::RatingStability(const BString& code, const BString& name, int64 ordering)
|
||||||
const BString& name, int64 ordering)
|
|
||||||
:
|
:
|
||||||
fCode(code),
|
fCode(code),
|
||||||
fName(name),
|
fName(name),
|
||||||
@@ -49,21 +48,17 @@ RatingStability::RatingStability(const RatingStability& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RatingStability&
|
bool
|
||||||
RatingStability::operator=(const RatingStability& other)
|
RatingStability::operator<(const RatingStability& other) const
|
||||||
{
|
{
|
||||||
fCode = other.fCode;
|
return Compare(other) < 0;
|
||||||
fName = other.fName;
|
|
||||||
fOrdering = other.fOrdering;
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RatingStability::operator==(const RatingStability& other) const
|
RatingStability::operator==(const RatingStability& other) const
|
||||||
{
|
{
|
||||||
return fCode == other.fCode && fName == other.fName
|
return fCode == other.fCode && fName == other.fName && fOrdering == other.fOrdering;
|
||||||
&& fOrdering == other.fOrdering;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Andrew Lindesay <[email protected]>.
|
* Copyright 2020-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef RATING_STABILITY_H
|
#ifndef RATING_STABILITY_H
|
||||||
@@ -20,12 +20,9 @@ public:
|
|||||||
RatingStability(
|
RatingStability(
|
||||||
const RatingStability& other);
|
const RatingStability& other);
|
||||||
|
|
||||||
RatingStability&
|
bool operator<(const RatingStability& other) const;
|
||||||
operator=(const RatingStability& other);
|
bool operator==(const RatingStability& other) const;
|
||||||
bool operator==(const RatingStability& other)
|
bool operator!=(const RatingStability& other) const;
|
||||||
const;
|
|
||||||
bool operator!=(const RatingStability& other)
|
|
||||||
const;
|
|
||||||
|
|
||||||
const BString& Code() const
|
const BString& Code() const
|
||||||
{ return fCode; }
|
{ return fCode; }
|
||||||
@@ -46,7 +43,7 @@ private:
|
|||||||
typedef BReference<RatingStability> RatingStabilityRef;
|
typedef BReference<RatingStability> RatingStabilityRef;
|
||||||
|
|
||||||
|
|
||||||
extern bool IsRatingStabilityBefore(const RatingStabilityRef& rs1,
|
extern bool IsRatingStabilityRefLess(const RatingStabilityRef& rs1,
|
||||||
const RatingStabilityRef& rs2);
|
const RatingStabilityRef& rs2);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ UserCredentials::UserCredentials(BMessage* from)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UserCredentials::UserCredentials(const BString& nickname,
|
UserCredentials::UserCredentials(const BString& nickname, const BString& passwordClear)
|
||||||
const BString& passwordClear)
|
|
||||||
:
|
:
|
||||||
fNickname(nickname),
|
fNickname(nickname),
|
||||||
fPasswordClear(passwordClear),
|
fPasswordClear(passwordClear),
|
||||||
@@ -140,4 +139,4 @@ UserCredentials::Archive(BMessage* into, bool deep) const
|
|||||||
if (result == B_OK)
|
if (result == B_OK)
|
||||||
result = into->AddBool(KEY_IS_SUCCESSFUL, fIsSuccessful);
|
result = into->AddBool(KEY_IS_SUCCESSFUL, fIsSuccessful);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,11 @@
|
|||||||
|
|
||||||
class UserCredentials : public BArchivable {
|
class UserCredentials : public BArchivable {
|
||||||
public:
|
public:
|
||||||
|
UserCredentials();
|
||||||
UserCredentials(BMessage* from);
|
UserCredentials(BMessage* from);
|
||||||
UserCredentials(const BString& nickname,
|
UserCredentials(const BString& nickname,
|
||||||
const BString& passwordClear);
|
const BString& passwordClear);
|
||||||
UserCredentials(const UserCredentials& other);
|
UserCredentials(const UserCredentials& other);
|
||||||
UserCredentials();
|
|
||||||
virtual ~UserCredentials();
|
virtual ~UserCredentials();
|
||||||
|
|
||||||
UserCredentials& operator=(const UserCredentials& other);
|
UserCredentials& operator=(const UserCredentials& other);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2013, Rene Gollent, <[email protected]>
|
* Copyright 2013, Rene Gollent, <[email protected]>
|
||||||
* Copyright 2020-2024, Andrew Lindesay <[email protected]>
|
* Copyright 2020-2025, Andrew Lindesay <[email protected]>
|
||||||
*
|
*
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include "AbstractPackageProcess.h"
|
#include "AbstractPackageProcess.h"
|
||||||
|
|
||||||
|
#include <Autolock.h>
|
||||||
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
#include "PackageKitUtils.h"
|
#include "PackageKitUtils.h"
|
||||||
@@ -18,78 +20,93 @@
|
|||||||
|
|
||||||
using namespace BPackageKit;
|
using namespace BPackageKit;
|
||||||
|
|
||||||
// #pragma mark - PackageAction
|
|
||||||
|
|
||||||
|
AbstractPackageProcess::AbstractPackageProcess(const BString& packageName, Model* model)
|
||||||
AbstractPackageProcess::AbstractPackageProcess(
|
|
||||||
PackageInfoRef package, Model* model)
|
|
||||||
:
|
:
|
||||||
fPackage(package),
|
fPackageName(packageName),
|
||||||
fModel(model)
|
fModel(model)
|
||||||
{
|
{
|
||||||
if (package.IsSet())
|
|
||||||
fInstallLocation = PackageKitUtils::DeriveInstallLocation(package.Get());
|
|
||||||
else
|
|
||||||
fInstallLocation = B_PACKAGE_INSTALLATION_LOCATION_SYSTEM;
|
|
||||||
|
|
||||||
// TODO: ideally if the package is installed at multiple locations,
|
|
||||||
// the user should be able to pick which one to remove.
|
|
||||||
// TODO: allow configuring the installation location
|
|
||||||
fPackageManager = new(std::nothrow) PackageManager(
|
|
||||||
(BPackageInstallationLocation)fInstallLocation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AbstractPackageProcess::~AbstractPackageProcess()
|
AbstractPackageProcess::~AbstractPackageProcess()
|
||||||
{
|
{
|
||||||
delete fPackageManager;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
AbstractPackageProcess::InstallLocation() const
|
||||||
|
{
|
||||||
|
PackageInfoRef package = FindPackageByName(fPackageName);
|
||||||
|
if (package.IsSet())
|
||||||
|
return PackageKitUtils::DeriveInstallLocation(package.Get());
|
||||||
|
return B_PACKAGE_INSTALLATION_LOCATION_SYSTEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageInfoRef
|
PackageInfoRef
|
||||||
AbstractPackageProcess::FindPackageByName(const BString& name)
|
AbstractPackageProcess::FindPackageByName(const BString& packageName) const
|
||||||
{
|
{
|
||||||
return fModel->PackageForName(name);
|
return fModel->PackageForName(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO; will refactor once the models go immutable.
|
|
||||||
void
|
void
|
||||||
AbstractPackageProcess::SetPackageState(PackageInfoRef& package, PackageState state)
|
AbstractPackageProcess::SetPackageState(const BString& packageName, PackageState state)
|
||||||
{
|
{
|
||||||
|
PackageInfoRef package = fModel->PackageForName(packageName);
|
||||||
|
|
||||||
if (package.IsSet()) {
|
if (package.IsSet()) {
|
||||||
PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(package);
|
PackageLocalInfoRef localInfo
|
||||||
localInfo->SetState(state);
|
= PackageLocalInfoBuilder(package->LocalInfo()).WithState(state).BuildRef();
|
||||||
package->SetLocalInfo(localInfo);
|
|
||||||
|
PackageInfoRef updatedPackage
|
||||||
|
= PackageInfoBuilder(package).WithLocalInfo(localInfo).BuildRef();
|
||||||
|
|
||||||
|
fModel->AddPackage(updatedPackage);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
HDERROR("setting state, but the package is not set");
|
HDERROR("setting state, but the package [%s] is not present", packageName.String());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO; will refactor once the models go immutable.
|
|
||||||
void
|
void
|
||||||
AbstractPackageProcess::SetPackageDownloadProgress(PackageInfoRef& package, float value)
|
AbstractPackageProcess::SetPackageDownloadProgress(const BString& packageName, float value)
|
||||||
{
|
{
|
||||||
|
PackageInfoRef package = fModel->PackageForName(packageName);
|
||||||
|
|
||||||
if (package.IsSet()) {
|
if (package.IsSet()) {
|
||||||
PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(package);
|
PackageLocalInfoRef localInfo
|
||||||
localInfo->SetDownloadProgress(value);
|
= PackageLocalInfoBuilder(package->LocalInfo()).WithDownloadProgress(value).BuildRef();
|
||||||
package->SetLocalInfo(localInfo);
|
|
||||||
|
PackageInfoRef updatedPackage
|
||||||
|
= PackageInfoBuilder(package).WithLocalInfo(localInfo).BuildRef();
|
||||||
|
|
||||||
|
fModel->AddPackage(updatedPackage);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
HDERROR("setting progress, but the package is not set");
|
HDERROR("setting progress, but the package [%s] is not present", packageName.String());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO; will refactor once the models go immutable.
|
|
||||||
void
|
void
|
||||||
AbstractPackageProcess::ClearPackageInstallationLocations(PackageInfoRef& package)
|
AbstractPackageProcess::ClearPackageInstallationLocations(const BString& packageName)
|
||||||
{
|
{
|
||||||
|
PackageInfoRef package = fModel->PackageForName(packageName);
|
||||||
|
|
||||||
if (package.IsSet()) {
|
if (package.IsSet()) {
|
||||||
PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(package);
|
PackageLocalInfoRef localInfo
|
||||||
localInfo->ClearInstallationLocations();
|
= PackageLocalInfoBuilder(package->LocalInfo()).ClearInstallationLocations().BuildRef();
|
||||||
package->SetLocalInfo(localInfo);
|
|
||||||
|
PackageInfoRef updatedPackage
|
||||||
|
= PackageInfoBuilder(package).WithLocalInfo(localInfo).BuildRef();
|
||||||
|
|
||||||
|
fModel->AddPackage(updatedPackage);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
HDERROR("clearing installation locations, but the package is not set");
|
HDERROR("clearing installation locations, but the package [%s] is not present",
|
||||||
|
packageName.String());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2022, Andrew Lindesay <[email protected]>
|
* Copyright 2022-2025, Andrew Lindesay <[email protected]>
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef ABSTRACT_PACKAGE_PROCESS_H
|
#ifndef ABSTRACT_PACKAGE_PROCESS_H
|
||||||
@@ -18,27 +18,23 @@ class Model;
|
|||||||
|
|
||||||
class AbstractPackageProcess : public BReferenceable, public AbstractProcess {
|
class AbstractPackageProcess : public BReferenceable, public AbstractProcess {
|
||||||
public:
|
public:
|
||||||
AbstractPackageProcess(PackageInfoRef package,
|
AbstractPackageProcess(const BString& packageName, Model* model);
|
||||||
Model* model);
|
|
||||||
virtual ~AbstractPackageProcess();
|
virtual ~AbstractPackageProcess();
|
||||||
|
|
||||||
int32 InstallLocation() const
|
|
||||||
{ return fInstallLocation; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PackageInfoRef FindPackageByName(const BString& name);
|
int32 InstallLocation() const;
|
||||||
|
PackageInfoRef FindPackageByName(const BString& packageName) const;
|
||||||
|
|
||||||
void SetPackageState(PackageInfoRef& package, PackageState state);
|
void SetPackageState(const BString& packageName, PackageState state);
|
||||||
void SetPackageDownloadProgress(PackageInfoRef& package, float value);
|
void SetPackageDownloadProgress(const BString& packageName, float value);
|
||||||
void ClearPackageInstallationLocations(PackageInfoRef& package);
|
void ClearPackageInstallationLocations(const BString& packageName);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PackageManager* fPackageManager;
|
BString fPackageName;
|
||||||
PackageInfoRef fPackage;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model* fModel;
|
Model* fModel;
|
||||||
int32 fInstallLocation;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2024, Haiku, Inc. All Rights Reserved.
|
* Copyright 2013-2025, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -18,16 +18,17 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
#include <Catalog.h>
|
#include <Catalog.h>
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
|
|
||||||
#include <package/manager/Exceptions.h>
|
|
||||||
#include <package/hpkg/NoErrorOutput.h>
|
#include <package/hpkg/NoErrorOutput.h>
|
||||||
#include <package/hpkg/PackageContentHandler.h>
|
#include <package/hpkg/PackageContentHandler.h>
|
||||||
#include <package/hpkg/PackageEntry.h>
|
#include <package/hpkg/PackageEntry.h>
|
||||||
#include <package/hpkg/PackageEntryAttribute.h>
|
#include <package/hpkg/PackageEntryAttribute.h>
|
||||||
#include <package/hpkg/PackageReader.h>
|
#include <package/hpkg/PackageReader.h>
|
||||||
|
#include <package/manager/Exceptions.h>
|
||||||
#include <package/solver/SolverPackage.h>
|
#include <package/solver/SolverPackage.h>
|
||||||
|
|
||||||
#include "AppUtils.h"
|
#include "AppUtils.h"
|
||||||
@@ -57,6 +58,13 @@ using BPackageKit::BHPKG::BPackageReader;
|
|||||||
|
|
||||||
class DownloadProgress {
|
class DownloadProgress {
|
||||||
public:
|
public:
|
||||||
|
DownloadProgress()
|
||||||
|
:
|
||||||
|
fPackageName(),
|
||||||
|
fProgress(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
DownloadProgress(BString packageName, float progress)
|
DownloadProgress(BString packageName, float progress)
|
||||||
:
|
:
|
||||||
fPackageName(packageName),
|
fPackageName(packageName),
|
||||||
@@ -84,14 +92,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
InstallPackageProcess::InstallPackageProcess(
|
InstallPackageProcess::InstallPackageProcess(const BString& packageName, Model* model)
|
||||||
PackageInfoRef package, Model* model)
|
|
||||||
:
|
:
|
||||||
AbstractPackageProcess(package, model),
|
AbstractPackageProcess(packageName, model),
|
||||||
fLastDownloadUpdate(0)
|
fLastDownloadUpdate(0)
|
||||||
{
|
{
|
||||||
fDescription = B_TRANSLATE("Installing \"%PackageName%\"");
|
fDescription = B_TRANSLATE("Installing \"%PackageName%\"");
|
||||||
fDescription.ReplaceAll("%PackageName%", package->Name());
|
fDescription.ReplaceAll("%PackageName%", packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -120,14 +127,20 @@ InstallPackageProcess::Progress()
|
|||||||
if (ProcessState() == PROCESS_RUNNING && !fDownloadProgresses.empty()) {
|
if (ProcessState() == PROCESS_RUNNING && !fDownloadProgresses.empty()) {
|
||||||
AutoLocker<BLocker> locker(&fLock);
|
AutoLocker<BLocker> locker(&fLock);
|
||||||
float sum = 0.0;
|
float sum = 0.0;
|
||||||
std::vector<DownloadProgress>::const_iterator it;
|
int32 count = 0;
|
||||||
for (it = fDownloadProgresses.begin();
|
|
||||||
it != fDownloadProgresses.end(); it++) {
|
std::map<BString, DownloadProgress>::const_iterator it;
|
||||||
DownloadProgress downloadProgress = *it;
|
|
||||||
sum += downloadProgress.Progress();
|
for (it = fDownloadProgresses.begin(); it != fDownloadProgresses.end(); it++) {
|
||||||
|
DownloadProgress downloadProgress = it->second;
|
||||||
|
|
||||||
|
if (!downloadProgress.PackageName().IsEmpty()) {
|
||||||
|
sum += downloadProgress.Progress();
|
||||||
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (sum > 0.0)
|
if (sum > 0.0)
|
||||||
return sum / (float) fDownloadProgresses.size();
|
return sum / static_cast<float>(count);
|
||||||
}
|
}
|
||||||
return kProgressIndeterminate;
|
return kProgressIndeterminate;
|
||||||
}
|
}
|
||||||
@@ -136,57 +149,61 @@ InstallPackageProcess::Progress()
|
|||||||
status_t
|
status_t
|
||||||
InstallPackageProcess::RunInternal()
|
InstallPackageProcess::RunInternal()
|
||||||
{
|
{
|
||||||
PackageInfoRef ref(fPackage);
|
// TODO: allow configuring the installation location
|
||||||
SetPackageState(ref, PENDING);
|
|
||||||
|
|
||||||
fPackageManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES
|
PackageManager* packageManager = new(std::nothrow)
|
||||||
| BPackageManager::B_ADD_REMOTE_REPOSITORIES
|
PackageManager(static_cast<BPackageInstallationLocation>(InstallLocation()));
|
||||||
| BPackageManager::B_REFRESH_REPOSITORIES);
|
ObjectDeleter<PackageManager> solverDeleter(packageManager);
|
||||||
|
|
||||||
PackageState state = PackageUtils::State(ref);
|
SetPackageState(fPackageName, PENDING);
|
||||||
|
|
||||||
fPackageManager->SetCurrentActionPackage(ref, true);
|
packageManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES
|
||||||
fPackageManager->AddProgressListener(this);
|
| BPackageManager::B_ADD_REMOTE_REPOSITORIES | BPackageManager::B_REFRESH_REPOSITORIES);
|
||||||
|
|
||||||
BString packageName = ref->Name();
|
|
||||||
PackageLocalInfoRef localInfo = ref->LocalInfo();
|
PackageInfoRef package = FindPackageByName(fPackageName);
|
||||||
|
PackageState state = PackageUtils::State(package);
|
||||||
|
|
||||||
|
packageManager->SetCurrentActionPackage(package, true);
|
||||||
|
packageManager->AddProgressListener(this);
|
||||||
|
|
||||||
|
BString packageName = fPackageName;
|
||||||
|
PackageLocalInfoRef localInfo = package->LocalInfo();
|
||||||
|
|
||||||
if (localInfo.IsSet() && localInfo->IsLocalFile())
|
if (localInfo.IsSet() && localInfo->IsLocalFile())
|
||||||
packageName = localInfo->LocalFilePath();
|
packageName = localInfo->LocalFilePath();
|
||||||
|
|
||||||
const char* packageNameString = packageName.String();
|
const char* packageNameString = packageName.String();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fPackageManager->Install(&packageNameString, 1);
|
packageManager->Install(&packageNameString, 1);
|
||||||
} catch (BFatalErrorException& ex) {
|
} catch (BFatalErrorException& ex) {
|
||||||
BString errorString;
|
BString errorString;
|
||||||
errorString.SetToFormat(
|
errorString.SetToFormat("Fatal error occurred while installing package %s: %s (%s)\n",
|
||||||
"Fatal error occurred while installing package %s: "
|
packageNameString, ex.Message().String(), ex.Details().String());
|
||||||
"%s (%s)\n", packageNameString, ex.Message().String(),
|
AppUtils::NotifySimpleError(B_TRANSLATE("Fatal error"), errorString, B_STOP_ALERT);
|
||||||
ex.Details().String());
|
|
||||||
AppUtils::NotifySimpleError(B_TRANSLATE("Fatal error"), errorString,
|
|
||||||
B_STOP_ALERT);
|
|
||||||
_SetDownloadedPackagesState(NONE);
|
_SetDownloadedPackagesState(NONE);
|
||||||
SetPackageState(ref, state);
|
SetPackageState(fPackageName, state);
|
||||||
return ex.Error();
|
return ex.Error();
|
||||||
} catch (BAbortedByUserException& ex) {
|
} catch (BAbortedByUserException& ex) {
|
||||||
HDINFO("Installation of package %s is aborted by user: %s",
|
HDINFO("Installation of package %s is aborted by user: %s", packageNameString,
|
||||||
packageNameString, ex.Message().String());
|
ex.Message().String());
|
||||||
_SetDownloadedPackagesState(NONE);
|
_SetDownloadedPackagesState(NONE);
|
||||||
SetPackageState(ref, state);
|
SetPackageState(fPackageName, state);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} catch (BNothingToDoException& ex) {
|
} catch (BNothingToDoException& ex) {
|
||||||
HDINFO("Nothing to do while installing package %s: %s",
|
HDINFO("Nothing to do while installing package %s: %s", packageNameString,
|
||||||
packageNameString, ex.Message().String());
|
ex.Message().String());
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} catch (BException& ex) {
|
} catch (BException& ex) {
|
||||||
HDERROR("Exception occurred while installing package %s: %s",
|
HDERROR("Exception occurred while installing package %s: %s", packageNameString,
|
||||||
packageNameString, ex.Message().String());
|
ex.Message().String());
|
||||||
_SetDownloadedPackagesState(NONE);
|
_SetDownloadedPackagesState(NONE);
|
||||||
SetPackageState(ref, state);
|
SetPackageState(fPackageName, state);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
fPackageManager->RemoveProgressListener(this);
|
packageManager->RemoveProgressListener(this);
|
||||||
|
|
||||||
_SetDownloadedPackagesState(ACTIVATED);
|
_SetDownloadedPackagesState(ACTIVATED);
|
||||||
|
|
||||||
@@ -198,26 +215,20 @@ InstallPackageProcess::RunInternal()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
InstallPackageProcess::DownloadProgressChanged(
|
InstallPackageProcess::DownloadProgressChanged(const char* packageName, float progress)
|
||||||
const char* packageName, float progress)
|
|
||||||
{
|
{
|
||||||
bigtime_t now = system_time();
|
if (!_ShouldProcessProgress() && progress != 1.0)
|
||||||
if (now - fLastDownloadUpdate < 250000 && progress != 1.0)
|
|
||||||
return;
|
return;
|
||||||
fLastDownloadUpdate = now;
|
|
||||||
BString simplePackageName;
|
BString simplePackageName;
|
||||||
|
|
||||||
if (_DeriveSimplePackageName(packageName, simplePackageName) != B_OK) {
|
if (_DeriveSimplePackageName(packageName, simplePackageName) != B_OK) {
|
||||||
HDERROR("malformed canonical package name [%s]", packageName);
|
HDERROR("malformed canonical package name [%s]", packageName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PackageInfoRef ref(FindPackageByName(simplePackageName));
|
|
||||||
if (ref.IsSet()) {
|
SetPackageDownloadProgress(simplePackageName, progress);
|
||||||
SetPackageDownloadProgress(ref, progress);
|
_SetDownloadProgress(simplePackageName, progress);
|
||||||
_SetDownloadProgress(simplePackageName, progress);
|
|
||||||
} else {
|
|
||||||
HDERROR("unable to find the package info for simple package name [%s]",
|
|
||||||
simplePackageName.String());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -230,29 +241,21 @@ InstallPackageProcess::DownloadProgressComplete(const char* packageName)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_SetDownloadProgress(simplePackageName, 1.0);
|
_SetDownloadProgress(simplePackageName, 1.0);
|
||||||
PackageInfoRef ref(FindPackageByName(simplePackageName));
|
SetPackageDownloadProgress(simplePackageName, 1.0);
|
||||||
if (!ref.IsSet()) {
|
fDownloadedPackageNames.insert(simplePackageName);
|
||||||
HDERROR("unable to find the package info for simple package name [%s]",
|
|
||||||
simplePackageName.String());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SetPackageDownloadProgress(ref, 1.0);
|
|
||||||
fDownloadedPackages.insert(ref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
InstallPackageProcess::ConfirmedChanges(
|
InstallPackageProcess::ConfirmedChanges(BPackageManager::InstalledRepository& repository)
|
||||||
BPackageManager::InstalledRepository& repository)
|
|
||||||
{
|
{
|
||||||
BPackageManager::InstalledRepository::PackageList& activationList =
|
BPackageManager::InstalledRepository::PackageList& activationList
|
||||||
repository.PackagesToActivate();
|
= repository.PackagesToActivate();
|
||||||
|
|
||||||
BSolverPackage* package = NULL;
|
BSolverPackage* package = NULL;
|
||||||
for (int32 i = 0; (package = activationList.ItemAt(i)); i++) {
|
for (int32 i = 0; (package = activationList.ItemAt(i)); i++) {
|
||||||
PackageInfoRef ref(FindPackageByName(package->Info().Name()));
|
BString packageName = package->Info().Name();
|
||||||
if (ref.IsSet())
|
SetPackageState(packageName, PENDING);
|
||||||
SetPackageState(ref, PENDING);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,22 +263,14 @@ InstallPackageProcess::ConfirmedChanges(
|
|||||||
void
|
void
|
||||||
InstallPackageProcess::_SetDownloadedPackagesState(PackageState state)
|
InstallPackageProcess::_SetDownloadedPackagesState(PackageState state)
|
||||||
{
|
{
|
||||||
for (PackageInfoSet::iterator it = fDownloadedPackages.begin();
|
std::set<BString>::const_iterator it;
|
||||||
it != fDownloadedPackages.end(); ++it) {
|
for (it = fDownloadedPackageNames.begin(); it != fDownloadedPackageNames.end(); ++it) {
|
||||||
PackageInfoRef ref = (*it);
|
BString packageName = *it;
|
||||||
SetPackageState(ref, state);
|
SetPackageState(packageName, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
_IsDownloadProgressBefore(const DownloadProgress& dp1,
|
|
||||||
const DownloadProgress& dp2)
|
|
||||||
{
|
|
||||||
return dp1.PackageName().Compare(dp2.PackageName()) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! This method will extract the plain package name from the canonical
|
/*! This method will extract the plain package name from the canonical
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -293,22 +288,9 @@ InstallPackageProcess::_DeriveSimplePackageName(const BString& canonicalForm,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
InstallPackageProcess::_SetDownloadProgress(const BString& simplePackageName,
|
InstallPackageProcess::_SetDownloadProgress(const BString& simplePackageName, float progress)
|
||||||
float progress)
|
|
||||||
{
|
{
|
||||||
AutoLocker<BLocker> locker(&fLock);
|
|
||||||
DownloadProgress downloadProgress(simplePackageName, progress);
|
DownloadProgress downloadProgress(simplePackageName, progress);
|
||||||
std::vector<DownloadProgress>::iterator itInsertionPt
|
fDownloadProgresses[simplePackageName] = downloadProgress;
|
||||||
= std::lower_bound(
|
|
||||||
fDownloadProgresses.begin(), fDownloadProgresses.end(),
|
|
||||||
downloadProgress, &_IsDownloadProgressBefore);
|
|
||||||
|
|
||||||
if (itInsertionPt != fDownloadProgresses.end()) {
|
|
||||||
if ((*itInsertionPt).PackageName() == simplePackageName) {
|
|
||||||
itInsertionPt = fDownloadProgresses.erase(itInsertionPt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fDownloadProgresses.insert(itInsertionPt, downloadProgress);
|
|
||||||
_NotifyChanged();
|
_NotifyChanged();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Copyright 2011, Ingo Weinhold, <[email protected]>
|
* Copyright 2011, Ingo Weinhold, <[email protected]>
|
||||||
* Copyright 2013, Rene Gollent, <[email protected]>
|
* Copyright 2013, Rene Gollent, <[email protected]>
|
||||||
* Copyright 2017, Julian Harnath <[email protected]>.
|
* Copyright 2017, Julian Harnath <[email protected]>.
|
||||||
* Copyright 2021, Andrew Lindesay <[email protected]>.
|
* Copyright 2021-2025, Andrew Lindesay <[email protected]>.
|
||||||
*
|
*
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -30,7 +30,7 @@ class InstallPackageProcess
|
|||||||
private PackageProgressListener {
|
private PackageProgressListener {
|
||||||
public:
|
public:
|
||||||
InstallPackageProcess(
|
InstallPackageProcess(
|
||||||
PackageInfoRef package, Model* model);
|
const BString& packageName, Model* model);
|
||||||
virtual ~InstallPackageProcess();
|
virtual ~InstallPackageProcess();
|
||||||
|
|
||||||
virtual const char* Name() const;
|
virtual const char* Name() const;
|
||||||
@@ -63,11 +63,11 @@ private:
|
|||||||
float progress);
|
float progress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<DownloadProgress>
|
std::map<BString, DownloadProgress>
|
||||||
fDownloadProgresses;
|
fDownloadProgresses;
|
||||||
BString fDescription;
|
BString fDescription;
|
||||||
bigtime_t fLastDownloadUpdate;
|
bigtime_t fLastDownloadUpdate;
|
||||||
PackageInfoSet fDownloadedPackages;
|
std::set<BString> fDownloadedPackageNames;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INSTALL_PACKAGE_PROCESS_H
|
#endif // INSTALL_PACKAGE_PROCESS_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2022, Haiku, Inc. All Rights Reserved.
|
* Copyright 2013-2025, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -64,8 +64,7 @@ public:
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t HandleEntryAttribute(BPackageEntry* entry,
|
virtual status_t HandleEntryAttribute(BPackageEntry* entry, BPackageEntryAttribute* attribute)
|
||||||
BPackageEntryAttribute* attribute)
|
|
||||||
{
|
{
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -75,8 +74,7 @@ public:
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual status_t HandlePackageAttribute(
|
virtual status_t HandlePackageAttribute(const BPackageInfoAttributeValue& value)
|
||||||
const BPackageInfoAttributeValue& value)
|
|
||||||
{
|
{
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -105,10 +103,10 @@ private:
|
|||||||
// #pragma mark - OpenPackageProcess
|
// #pragma mark - OpenPackageProcess
|
||||||
|
|
||||||
|
|
||||||
OpenPackageProcess::OpenPackageProcess(PackageInfoRef package, Model* model,
|
OpenPackageProcess::OpenPackageProcess(const BString& packageName, Model* model,
|
||||||
const DeskbarLink& link)
|
const DeskbarLink& link)
|
||||||
:
|
:
|
||||||
AbstractPackageProcess(package, model),
|
AbstractPackageProcess(packageName, model),
|
||||||
fDeskbarLink(link)
|
fDeskbarLink(link)
|
||||||
{
|
{
|
||||||
fDescription = _DeriveDescription();
|
fDescription = _DeriveDescription();
|
||||||
@@ -192,7 +190,7 @@ OpenPackageProcess::_DeriveDescription()
|
|||||||
|
|
||||||
/*static*/ bool
|
/*static*/ bool
|
||||||
OpenPackageProcess::FindAppToLaunch(const PackageInfoRef& package,
|
OpenPackageProcess::FindAppToLaunch(const PackageInfoRef& package,
|
||||||
std::vector<DeskbarLink>& foundLinks)
|
std::vector<DeskbarLink>& foundLinks)
|
||||||
{
|
{
|
||||||
if (!package.IsSet())
|
if (!package.IsSet())
|
||||||
return false;
|
return false;
|
||||||
@@ -208,8 +206,7 @@ OpenPackageProcess::FindAppToLaunch(const PackageInfoRef& package,
|
|||||||
|
|
||||||
status_t status = reader.Init(packagePath.Path());
|
status_t status = reader.Init(packagePath.Path());
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
HDINFO("OpenPackageAction::FindAppToLaunch(): "
|
HDINFO("OpenPackageAction::FindAppToLaunch(): failed to init BPackageReader(%s): %s",
|
||||||
"failed to init BPackageReader(%s): %s",
|
|
||||||
packagePath.Path(), strerror(status));
|
packagePath.Path(), strerror(status));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -218,8 +215,7 @@ OpenPackageProcess::FindAppToLaunch(const PackageInfoRef& package,
|
|||||||
DeskbarLinkFinder contentHandler(foundLinks);
|
DeskbarLinkFinder contentHandler(foundLinks);
|
||||||
status = reader.ParseContent(&contentHandler);
|
status = reader.ParseContent(&contentHandler);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
HDINFO("OpenPackageAction::FindAppToLaunch(): "
|
HDINFO("OpenPackageAction::FindAppToLaunch(): failed parse package contents (%s): %s",
|
||||||
"failed parse package contents (%s): %s",
|
|
||||||
packagePath.Path(), strerror(status));
|
packagePath.Path(), strerror(status));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Copyright 2011, Ingo Weinhold, <[email protected]>
|
* Copyright 2011, Ingo Weinhold, <[email protected]>
|
||||||
* Copyright 2013, Rene Gollent, <[email protected]>
|
* Copyright 2013, Rene Gollent, <[email protected]>
|
||||||
* Copyright 2017, Julian Harnath <[email protected]>
|
* Copyright 2017, Julian Harnath <[email protected]>
|
||||||
* Copyright 2021, Andrew Lindesay <[email protected]>
|
* Copyright 2021-2025, Andrew Lindesay <[email protected]>
|
||||||
*
|
*
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -24,7 +24,7 @@ class OpenPackageProcess
|
|||||||
private PackageProgressListener {
|
private PackageProgressListener {
|
||||||
public:
|
public:
|
||||||
OpenPackageProcess(
|
OpenPackageProcess(
|
||||||
PackageInfoRef package, Model* model,
|
const BString& packageName, Model* model,
|
||||||
const DeskbarLink& link);
|
const DeskbarLink& link);
|
||||||
virtual ~OpenPackageProcess();
|
virtual ~OpenPackageProcess();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2021, Haiku, Inc. All Rights Reserved.
|
* Copyright 2013-2025, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <package/manager/Exceptions.h>
|
#include <package/manager/Exceptions.h>
|
||||||
#include <package/solver/SolverPackage.h>
|
#include <package/solver/SolverPackage.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <Catalog.h>
|
#include <Catalog.h>
|
||||||
|
|
||||||
#include "Alert.h"
|
#include "Alert.h"
|
||||||
@@ -38,13 +39,12 @@ using namespace BPackageKit::BManager::BPrivate;
|
|||||||
using BPackageKit::BSolverPackage;
|
using BPackageKit::BSolverPackage;
|
||||||
|
|
||||||
|
|
||||||
UninstallPackageProcess::UninstallPackageProcess(PackageInfoRef package,
|
UninstallPackageProcess::UninstallPackageProcess(const BString& packageName, Model* model)
|
||||||
Model* model)
|
|
||||||
:
|
:
|
||||||
AbstractPackageProcess(package, model)
|
AbstractPackageProcess(packageName, model)
|
||||||
{
|
{
|
||||||
fDescription = B_TRANSLATE("Uninstalling \"%PackageName%\"");
|
fDescription = B_TRANSLATE("Uninstalling \"%PackageName%\"");
|
||||||
fDescription.ReplaceAll("%PackageName%", fPackage->Name());
|
fDescription.ReplaceAll("%PackageName%", packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,67 +70,68 @@ UninstallPackageProcess::Description() const
|
|||||||
status_t
|
status_t
|
||||||
UninstallPackageProcess::RunInternal()
|
UninstallPackageProcess::RunInternal()
|
||||||
{
|
{
|
||||||
fPackageManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES);
|
// TODO: ideally if the package is installed at multiple locations,
|
||||||
|
// the user should be able to pick which one to remove.
|
||||||
|
|
||||||
PackageInfoRef ref(fPackage);
|
PackageManager* packageManager = new(std::nothrow)
|
||||||
PackageState state = PackageUtils::State(fPackage);
|
PackageManager(static_cast<BPackageInstallationLocation>(InstallLocation()));
|
||||||
const char* packageName = ref->Name().String();
|
ObjectDeleter<PackageManager> solverDeleter(packageManager);
|
||||||
|
|
||||||
fPackageManager->SetCurrentActionPackage(ref, false);
|
packageManager->Init(BPackageManager::B_ADD_INSTALLED_REPOSITORIES);
|
||||||
fPackageManager->AddProgressListener(this);
|
|
||||||
|
PackageInfoRef package = FindPackageByName(fPackageName);
|
||||||
|
PackageState state = PackageUtils::State(package);
|
||||||
|
|
||||||
|
packageManager->SetCurrentActionPackage(package, false);
|
||||||
|
packageManager->AddProgressListener(this);
|
||||||
|
|
||||||
|
const char* packageNameString = package->Name().String();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fPackageManager->Uninstall(&packageName, 1);
|
packageManager->Uninstall(&packageNameString, 1);
|
||||||
} catch (BFatalErrorException& ex) {
|
} catch (BFatalErrorException& ex) {
|
||||||
BString errorString;
|
BString errorString;
|
||||||
errorString.SetToFormat(
|
errorString.SetToFormat("Fatal error occurred while uninstalling package %s: %s (%s)\n",
|
||||||
"Fatal error occurred while uninstalling package %s: "
|
fPackageName.String(), ex.Message().String(), ex.Details().String());
|
||||||
"%s (%s)\n", packageName, ex.Message().String(),
|
AppUtils::NotifySimpleError(B_TRANSLATE("Fatal error"), errorString, B_STOP_ALERT);
|
||||||
ex.Details().String());
|
SetPackageState(fPackageName, state);
|
||||||
AppUtils::NotifySimpleError(B_TRANSLATE("Fatal error"), errorString,
|
|
||||||
B_STOP_ALERT);
|
|
||||||
SetPackageState(ref, state);
|
|
||||||
return ex.Error();
|
return ex.Error();
|
||||||
} catch (BAbortedByUserException& ex) {
|
} catch (BAbortedByUserException& ex) {
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} catch (BNothingToDoException& ex) {
|
} catch (BNothingToDoException& ex) {
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} catch (BException& ex) {
|
} catch (BException& ex) {
|
||||||
HDERROR("Exception occurred while uninstalling package %s: %s",
|
HDERROR("Exception occurred while uninstalling package %s: %s", fPackageName.String(),
|
||||||
packageName, ex.Message().String());
|
ex.Message().String());
|
||||||
SetPackageState(ref, state);
|
SetPackageState(fPackageName, state);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
fPackageManager->RemoveProgressListener(this);
|
packageManager->RemoveProgressListener(this);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
UninstallPackageProcess::StartApplyingChanges(
|
UninstallPackageProcess::StartApplyingChanges(BPackageManager::InstalledRepository& repository)
|
||||||
BPackageManager::InstalledRepository& repository)
|
|
||||||
{
|
{
|
||||||
BPackageManager::InstalledRepository::PackageList& packages
|
BPackageManager::InstalledRepository::PackageList& packages = repository.PackagesToDeactivate();
|
||||||
= repository.PackagesToDeactivate();
|
|
||||||
for (int32 i = 0; i < packages.CountItems(); i++) {
|
for (int32 i = 0; i < packages.CountItems(); i++) {
|
||||||
PackageInfoRef ref(FindPackageByName(packages.ItemAt(i)
|
BString packageName = packages.ItemAt(i)->Name();
|
||||||
->Name()));
|
fRemovedPackageNames.insert(packageName);
|
||||||
if (ref.IsSet())
|
|
||||||
fRemovedPackages.push_back(ref);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
UninstallPackageProcess::ApplyingChangesDone(
|
UninstallPackageProcess::ApplyingChangesDone(BPackageManager::InstalledRepository& repository)
|
||||||
BPackageManager::InstalledRepository& repository)
|
|
||||||
{
|
{
|
||||||
std::vector<PackageInfoRef>::iterator it;
|
std::set<BString>::const_iterator it;
|
||||||
for (it = fRemovedPackages.begin(); it != fRemovedPackages.end(); it++) {
|
for (it = fRemovedPackageNames.begin(); it != fRemovedPackageNames.end(); it++) {
|
||||||
PackageInfoRef packageInfoRef = *it;
|
BString packageName = *it;
|
||||||
SetPackageState(packageInfoRef, NONE);
|
SetPackageState(packageName, NONE);
|
||||||
ClearPackageInstallationLocations(packageInfoRef);
|
ClearPackageInstallationLocations(packageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Copyright 2011, Ingo Weinhold, <[email protected]>
|
* Copyright 2011, Ingo Weinhold, <[email protected]>
|
||||||
* Copyright 2013, Rene Gollent, <[email protected]>
|
* Copyright 2013, Rene Gollent, <[email protected]>
|
||||||
* Copyright 2017, Julian Harnath <[email protected]>
|
* Copyright 2017, Julian Harnath <[email protected]>
|
||||||
* Copyright 2021, Andrew Lindesay <[email protected]>
|
* Copyright 2021-2025, Andrew Lindesay <[email protected]>
|
||||||
*
|
*
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -23,7 +23,7 @@ class UninstallPackageProcess
|
|||||||
private PackageProgressListener {
|
private PackageProgressListener {
|
||||||
public:
|
public:
|
||||||
UninstallPackageProcess(
|
UninstallPackageProcess(
|
||||||
PackageInfoRef package, Model* model);
|
const BString& packageName, Model* model);
|
||||||
virtual ~UninstallPackageProcess();
|
virtual ~UninstallPackageProcess();
|
||||||
|
|
||||||
virtual const char* Name() const;
|
virtual const char* Name() const;
|
||||||
@@ -41,8 +41,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BString fDescription;
|
BString fDescription;
|
||||||
std::vector<PackageInfoRef>
|
std::set<BString> fRemovedPackageNames;
|
||||||
fRemovedPackages;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INSTALL_PACKAGE_PROCESS_H
|
#endif // INSTALL_PACKAGE_PROCESS_H
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2013, Rene Gollent <[email protected]>.
|
* Copyright 2013, Rene Gollent <[email protected]>.
|
||||||
* Copyright 2016-2023, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -14,27 +14,6 @@
|
|||||||
#include "PackageUtils.h"
|
#include "PackageUtils.h"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Sorting Functions
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
_IsPackageBeforeByName(const PackageInfoRef& p1, const BString& packageName)
|
|
||||||
{
|
|
||||||
return p1->Name().Compare(packageName) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! This function is used in order to provide an ordering on the packages
|
|
||||||
that are stored on a Depot.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static bool
|
|
||||||
_IsPackageBefore(const PackageInfoRef& p1, const PackageInfoRef& p2)
|
|
||||||
{
|
|
||||||
return _IsPackageBeforeByName(p1, p2->Name());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Class implementation
|
// #pragma mark - Class implementation
|
||||||
|
|
||||||
|
|
||||||
@@ -61,31 +40,16 @@ DepotInfo::DepotInfo(const DepotInfo& other)
|
|||||||
:
|
:
|
||||||
fName(other.fName),
|
fName(other.fName),
|
||||||
fIdentifier(other.fIdentifier),
|
fIdentifier(other.fIdentifier),
|
||||||
fPackages(other.fPackages),
|
|
||||||
fWebAppRepositoryCode(other.fWebAppRepositoryCode),
|
fWebAppRepositoryCode(other.fWebAppRepositoryCode),
|
||||||
fWebAppRepositorySourceCode(other.fWebAppRepositorySourceCode)
|
fWebAppRepositorySourceCode(other.fWebAppRepositorySourceCode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DepotInfo&
|
|
||||||
DepotInfo::operator=(const DepotInfo& other)
|
|
||||||
{
|
|
||||||
fName = other.fName;
|
|
||||||
fIdentifier = other.fIdentifier;
|
|
||||||
fPackages = other.fPackages;
|
|
||||||
fWebAppRepositoryCode = other.fWebAppRepositoryCode;
|
|
||||||
fWebAppRepositorySourceCode = other.fWebAppRepositorySourceCode;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DepotInfo::operator==(const DepotInfo& other) const
|
DepotInfo::operator==(const DepotInfo& other) const
|
||||||
{
|
{
|
||||||
return fName == other.fName
|
return fName == other.fName && fIdentifier == fIdentifier;
|
||||||
&& fIdentifier == fIdentifier
|
|
||||||
&& fPackages == other.fPackages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -96,127 +60,31 @@ DepotInfo::operator!=(const DepotInfo& other) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
const BString&
|
||||||
DepotInfo::CountPackages() const
|
DepotInfo::Name() const
|
||||||
{
|
{
|
||||||
return fPackages.size();
|
return fName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageInfoRef
|
const BString&
|
||||||
DepotInfo::PackageAtIndex(int32 index)
|
DepotInfo::Identifier() const
|
||||||
{
|
{
|
||||||
return fPackages[index];
|
return fIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This method will insert the package into the list of packages
|
const BString&
|
||||||
in order so that the list of packages remains in order.
|
DepotInfo::WebAppRepositoryCode() const
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
DepotInfo::AddPackage(PackageInfoRef& package)
|
|
||||||
{
|
{
|
||||||
std::vector<PackageInfoRef>::iterator itInsertionPt
|
return fWebAppRepositoryCode;
|
||||||
= std::lower_bound(
|
|
||||||
fPackages.begin(),
|
|
||||||
fPackages.end(),
|
|
||||||
package,
|
|
||||||
&_IsPackageBefore);
|
|
||||||
if (fPackages.end() != itInsertionPt && (*itInsertionPt)->Name() == package->Name())
|
|
||||||
*itInsertionPt = package;
|
|
||||||
else
|
|
||||||
fPackages.insert(itInsertionPt, package);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
const BString&
|
||||||
DepotInfo::HasPackage(const BString& packageName)
|
DepotInfo::WebAppRepositorySourceCode() const
|
||||||
{
|
{
|
||||||
std::vector<PackageInfoRef>::const_iterator it
|
return fWebAppRepositorySourceCode;
|
||||||
= std::lower_bound(
|
|
||||||
fPackages.begin(),
|
|
||||||
fPackages.end(),
|
|
||||||
packageName,
|
|
||||||
&_IsPackageBeforeByName);
|
|
||||||
if (it != fPackages.end()) {
|
|
||||||
PackageInfoRef candidate = *it;
|
|
||||||
return (candidate.Get() != NULL
|
|
||||||
&& candidate.Get()->Name() == packageName);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PackageInfoRef
|
|
||||||
DepotInfo::PackageByName(const BString& packageName)
|
|
||||||
{
|
|
||||||
std::vector<PackageInfoRef>::const_iterator it
|
|
||||||
= std::lower_bound(
|
|
||||||
fPackages.begin(),
|
|
||||||
fPackages.end(),
|
|
||||||
packageName,
|
|
||||||
&_IsPackageBeforeByName);
|
|
||||||
|
|
||||||
if (it != fPackages.end()) {
|
|
||||||
PackageInfoRef candidate = *it;
|
|
||||||
if (candidate.Get() != NULL && candidate.Get()->Name() == packageName)
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
return PackageInfoRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
DepotInfo::SyncPackagesFromDepot(const DepotInfoRef& other)
|
|
||||||
{
|
|
||||||
for (int32 i = other->CountPackages() - 1; i >= 0; i--) {
|
|
||||||
PackageInfoRef otherPackage = other->PackageAtIndex(i);
|
|
||||||
PackageInfoRef myPackage = PackageByName(otherPackage->Name());
|
|
||||||
|
|
||||||
if (myPackage.IsSet()) {
|
|
||||||
PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(myPackage);
|
|
||||||
PackageLocalInfoRef otherLocalInfo = otherPackage->LocalInfo();
|
|
||||||
|
|
||||||
if (otherLocalInfo.IsSet()) {
|
|
||||||
localInfo->SetState(otherLocalInfo->State());
|
|
||||||
localInfo->SetLocalFilePath(otherLocalInfo->LocalFilePath());
|
|
||||||
localInfo->SetSystemDependency(otherLocalInfo->IsSystemDependency());
|
|
||||||
}
|
|
||||||
|
|
||||||
myPackage->SetLocalInfo(localInfo);
|
|
||||||
} else {
|
|
||||||
HDINFO("%s: new package: '%s'", fName.String(),
|
|
||||||
otherPackage->Name().String());
|
|
||||||
AddPackage(otherPackage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32 i = CountPackages() - 1; i >= 0; i--) {
|
|
||||||
PackageInfoRef myPackage = PackageAtIndex(i);
|
|
||||||
if (!other->HasPackage(myPackage->Name())) {
|
|
||||||
HDINFO("%s: removing package: '%s'", fName.String(),
|
|
||||||
myPackage->Name().String());
|
|
||||||
fPackages.erase(fPackages.begin() + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
DepotInfo::HasAnyProminentPackages() const
|
|
||||||
{
|
|
||||||
std::vector<PackageInfoRef>::const_iterator it;
|
|
||||||
for (it = fPackages.begin(); it != fPackages.end(); it++) {
|
|
||||||
const PackageInfoRef& package = *it;
|
|
||||||
const PackageClassificationInfoRef& classification = package->PackageClassificationInfo();
|
|
||||||
|
|
||||||
if (classification.IsSet()) {
|
|
||||||
if (classification->IsProminent())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -239,3 +107,110 @@ DepotInfo::SetWebAppRepositorySourceCode(const BString& code)
|
|||||||
{
|
{
|
||||||
fWebAppRepositorySourceCode = code;
|
fWebAppRepositorySourceCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - DepotInfoBuilder
|
||||||
|
|
||||||
|
|
||||||
|
DepotInfoBuilder::DepotInfoBuilder()
|
||||||
|
:
|
||||||
|
fName(),
|
||||||
|
fIdentifier(),
|
||||||
|
fWebAppRepositoryCode(),
|
||||||
|
fWebAppRepositorySourceCode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DepotInfoBuilder::DepotInfoBuilder(const DepotInfoRef& value)
|
||||||
|
:
|
||||||
|
fName(),
|
||||||
|
fIdentifier(),
|
||||||
|
fWebAppRepositoryCode(),
|
||||||
|
fWebAppRepositorySourceCode()
|
||||||
|
{
|
||||||
|
fSource = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DepotInfoBuilder::~DepotInfoBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DepotInfoBuilder::_InitFromSource()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet()) {
|
||||||
|
_Init(fSource.Get());
|
||||||
|
fSource.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DepotInfoBuilder::_Init(const DepotInfo* value)
|
||||||
|
{
|
||||||
|
fName = value->Name();
|
||||||
|
fIdentifier = value->Identifier();
|
||||||
|
fWebAppRepositoryCode = value->WebAppRepositoryCode();
|
||||||
|
fWebAppRepositorySourceCode = value->WebAppRepositorySourceCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DepotInfoRef
|
||||||
|
DepotInfoBuilder::BuildRef() const
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
return fSource;
|
||||||
|
|
||||||
|
DepotInfo* depotInfo = new DepotInfo(fName);
|
||||||
|
depotInfo->SetIdentifier(fIdentifier);
|
||||||
|
depotInfo->SetWebAppRepositoryCode(fWebAppRepositoryCode);
|
||||||
|
depotInfo->SetWebAppRepositorySourceCode(fWebAppRepositorySourceCode);
|
||||||
|
return DepotInfoRef(depotInfo, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DepotInfoBuilder&
|
||||||
|
DepotInfoBuilder::WithName(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Name() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fName = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DepotInfoBuilder&
|
||||||
|
DepotInfoBuilder::WithIdentifier(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Identifier() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fIdentifier = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DepotInfoBuilder&
|
||||||
|
DepotInfoBuilder::WithWebAppRepositoryCode(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->WebAppRepositoryCode() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fWebAppRepositoryCode = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DepotInfoBuilder&
|
||||||
|
DepotInfoBuilder::WithWebAppRepositorySourceCode(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->WebAppRepositorySourceCode() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fWebAppRepositorySourceCode = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2023, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef DEPOT_INFO_H
|
#ifndef DEPOT_INFO_H
|
||||||
@@ -14,48 +14,36 @@
|
|||||||
#include "PackageInfo.h"
|
#include "PackageInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
class DepotInfoBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
/*! Instances of this class should not be created directly; instead use the
|
||||||
|
DepotInfoBuilder class as a builder-constructor.
|
||||||
|
*/
|
||||||
class DepotInfo : public BReferenceable {
|
class DepotInfo : public BReferenceable {
|
||||||
|
friend class DepotInfoBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DepotInfo();
|
DepotInfo();
|
||||||
DepotInfo(const BString& name);
|
DepotInfo(const BString& name);
|
||||||
DepotInfo(const DepotInfo& other);
|
DepotInfo(const DepotInfo& other);
|
||||||
|
|
||||||
DepotInfo& operator=(const DepotInfo& other);
|
|
||||||
bool operator==(const DepotInfo& other) const;
|
bool operator==(const DepotInfo& other) const;
|
||||||
bool operator!=(const DepotInfo& other) const;
|
bool operator!=(const DepotInfo& other) const;
|
||||||
|
|
||||||
const BString& Name() const
|
const BString& Name() const;
|
||||||
{ return fName; }
|
const BString& Identifier() const;
|
||||||
|
const BString& WebAppRepositoryCode() const;
|
||||||
|
const BString& WebAppRepositorySourceCode() const;
|
||||||
|
|
||||||
|
private:
|
||||||
void SetIdentifier(const BString& value);
|
void SetIdentifier(const BString& value);
|
||||||
const BString& Identifier() const
|
|
||||||
{ return fIdentifier; }
|
|
||||||
|
|
||||||
int32 CountPackages() const;
|
|
||||||
PackageInfoRef PackageAtIndex(int32 index);
|
|
||||||
void AddPackage(PackageInfoRef& package);
|
|
||||||
PackageInfoRef PackageByName(const BString& packageName);
|
|
||||||
bool HasPackage(const BString& packageName);
|
|
||||||
|
|
||||||
void SyncPackagesFromDepot(
|
|
||||||
const BReference<DepotInfo>& other);
|
|
||||||
|
|
||||||
bool HasAnyProminentPackages() const;
|
|
||||||
|
|
||||||
void SetWebAppRepositoryCode(const BString& code);
|
void SetWebAppRepositoryCode(const BString& code);
|
||||||
const BString& WebAppRepositoryCode() const
|
void SetWebAppRepositorySourceCode(const BString& code);
|
||||||
{ return fWebAppRepositoryCode; }
|
|
||||||
|
|
||||||
void SetWebAppRepositorySourceCode(
|
|
||||||
const BString& code);
|
|
||||||
const BString& WebAppRepositorySourceCode() const
|
|
||||||
{ return fWebAppRepositorySourceCode; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BString fName;
|
BString fName;
|
||||||
BString fIdentifier;
|
BString fIdentifier;
|
||||||
std::vector<PackageInfoRef>
|
|
||||||
fPackages;
|
|
||||||
BString fWebAppRepositoryCode;
|
BString fWebAppRepositoryCode;
|
||||||
BString fWebAppRepositorySourceCode;
|
BString fWebAppRepositorySourceCode;
|
||||||
};
|
};
|
||||||
@@ -64,4 +52,31 @@ private:
|
|||||||
typedef BReference<DepotInfo> DepotInfoRef;
|
typedef BReference<DepotInfo> DepotInfoRef;
|
||||||
|
|
||||||
|
|
||||||
|
class DepotInfoBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DepotInfoBuilder();
|
||||||
|
DepotInfoBuilder(const DepotInfoRef& value);
|
||||||
|
virtual ~DepotInfoBuilder();
|
||||||
|
|
||||||
|
DepotInfoRef BuildRef() const;
|
||||||
|
|
||||||
|
DepotInfoBuilder& WithName(const BString& value);
|
||||||
|
DepotInfoBuilder& WithIdentifier(const BString& value);
|
||||||
|
DepotInfoBuilder& WithWebAppRepositoryCode(const BString& value);
|
||||||
|
DepotInfoBuilder& WithWebAppRepositorySourceCode(const BString& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitFromSource();
|
||||||
|
void _Init(const DepotInfo* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DepotInfoRef fSource;
|
||||||
|
BString fName;
|
||||||
|
BString fIdentifier;
|
||||||
|
BString fWebAppRepositoryCode;
|
||||||
|
BString fWebAppRepositorySourceCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // DEPOT_INFO_H
|
#endif // DEPOT_INFO_H
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2013, Rene Gollent <[email protected]>.
|
* Copyright 2013, Rene Gollent <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -13,11 +13,10 @@
|
|||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
|
||||||
|
|
||||||
/*! serverName is the name of the language on the server.
|
/*! @param serverName is the name of the language on the server.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Language::Language(const char* language, const BString& serverName,
|
Language::Language(const char* language, const BString& serverName, bool isPopular)
|
||||||
bool isPopular)
|
|
||||||
:
|
:
|
||||||
BLanguage(language),
|
BLanguage(language),
|
||||||
fServerName(serverName),
|
fServerName(serverName),
|
||||||
@@ -35,6 +34,27 @@ Language::Language(const Language& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Language::operator==(const Language& other) const
|
||||||
|
{
|
||||||
|
return Compare(other) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Language::operator!=(const Language& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Language::operator<(const Language& other) const
|
||||||
|
{
|
||||||
|
return Compare(other) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Language::GetName(BString& name, const BLanguage* displayLanguage) const
|
Language::GetName(BString& name, const BLanguage* displayLanguage) const
|
||||||
{
|
{
|
||||||
@@ -60,9 +80,9 @@ Language::Compare(const Language& other) const
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IsLanguageBefore(const LanguageRef& l1, const LanguageRef& l2)
|
IsLanguageRefLess(const LanguageRef& l1, const LanguageRef& l2)
|
||||||
{
|
{
|
||||||
if (!l1.IsSet() || !l2.IsSet())
|
if (!l1.IsSet() || !l2.IsSet())
|
||||||
HDFATAL("unexpected NULL reference in a referencable");
|
debugger("illegal state in language less");
|
||||||
return l1.Get()->Compare(*(l2.Get())) < 0;
|
return *(l1.Get()) < *(l2.Get());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2023, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef LANGUAGE_H
|
#ifndef LANGUAGE_H
|
||||||
@@ -14,6 +14,10 @@
|
|||||||
/*! This class represents a language that is supported by the Haiku
|
/*! This class represents a language that is supported by the Haiku
|
||||||
Depot Server system. This may differ from the set of languages
|
Depot Server system. This may differ from the set of languages
|
||||||
that are supported in the platform itself.
|
that are supported in the platform itself.
|
||||||
|
|
||||||
|
No builder is provided for this class because it sub-classes from
|
||||||
|
a Haiku type. Instead always create new instances with the constructor
|
||||||
|
and do not use any mutating functions offered by the superclass.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Language : public BReferenceable, public BLanguage {
|
class Language : public BReferenceable, public BLanguage {
|
||||||
@@ -23,6 +27,10 @@ public:
|
|||||||
bool isPopular);
|
bool isPopular);
|
||||||
Language(const Language& other);
|
Language(const Language& other);
|
||||||
|
|
||||||
|
bool operator<(const Language& other) const;
|
||||||
|
bool operator==(const Language& other) const;
|
||||||
|
bool operator!=(const Language& other) const;
|
||||||
|
|
||||||
status_t GetName(BString& name,
|
status_t GetName(BString& name,
|
||||||
const BLanguage* displayLanguage = NULL
|
const BLanguage* displayLanguage = NULL
|
||||||
) const;
|
) const;
|
||||||
@@ -40,7 +48,7 @@ private:
|
|||||||
typedef BReference<Language> LanguageRef;
|
typedef BReference<Language> LanguageRef;
|
||||||
|
|
||||||
|
|
||||||
extern bool IsLanguageBefore(const LanguageRef& l1, const LanguageRef& l2);
|
extern bool IsLanguageRefLess(const LanguageRef& l1, const LanguageRef& l2);
|
||||||
|
|
||||||
|
|
||||||
#endif // LANGUAGE_H
|
#endif // LANGUAGE_H
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2013, Rene Gollent <[email protected]>.
|
* Copyright 2013, Rene Gollent <[email protected]>.
|
||||||
* Copyright 2016-2023, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -41,12 +41,10 @@ PackageCategory::PackageCategory(const PackageCategory& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageCategory&
|
bool
|
||||||
PackageCategory::operator=(const PackageCategory& other)
|
PackageCategory::operator<(const PackageCategory& other) const
|
||||||
{
|
{
|
||||||
fCode = other.fCode;
|
return Compare(other) < 0;
|
||||||
fName = other.fName;
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -68,18 +66,17 @@ int
|
|||||||
PackageCategory::Compare(const PackageCategory& other) const
|
PackageCategory::Compare(const PackageCategory& other) const
|
||||||
{
|
{
|
||||||
BCollator* collator = LocaleUtils::GetSharedCollator();
|
BCollator* collator = LocaleUtils::GetSharedCollator();
|
||||||
int32 result = collator->Compare(Name().String(),
|
int32 result = collator->Compare(Name().String(), other.Name().String());
|
||||||
other.Name().String());
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
result = Code().Compare(other.Code());
|
result = Code().Compare(other.Code());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool IsPackageCategoryBefore(const CategoryRef& c1,
|
bool
|
||||||
const CategoryRef& c2)
|
IsPackageCategoryRefLess(const CategoryRef& c1, const CategoryRef& c2)
|
||||||
{
|
{
|
||||||
if (!c1.IsSet() || !c2.IsSet())
|
if (!c1.IsSet() || !c2.IsSet())
|
||||||
HDFATAL("unexpected NULL reference in a referencable");
|
HDFATAL("illegal state in package category less");
|
||||||
return c1->Compare(*c2) < 0;
|
return *(c1.Get()) < *(c2.Get());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2023, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_CATEGORY_H
|
#ifndef PACKAGE_CATEGORY_H
|
||||||
@@ -11,6 +11,13 @@
|
|||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*! This class represents a category into which a package may be assigned. The
|
||||||
|
`code` corresponds to a code on the server.
|
||||||
|
|
||||||
|
No builder is provided for this class; always create new instances using
|
||||||
|
the constructor.
|
||||||
|
*/
|
||||||
|
|
||||||
class PackageCategory : public BReferenceable {
|
class PackageCategory : public BReferenceable {
|
||||||
public:
|
public:
|
||||||
PackageCategory();
|
PackageCategory();
|
||||||
@@ -18,7 +25,7 @@ public:
|
|||||||
const BString& name);
|
const BString& name);
|
||||||
PackageCategory(const PackageCategory& other);
|
PackageCategory(const PackageCategory& other);
|
||||||
|
|
||||||
PackageCategory& operator=(const PackageCategory& other);
|
bool operator<(const PackageCategory& other) const;
|
||||||
bool operator==(const PackageCategory& other) const;
|
bool operator==(const PackageCategory& other) const;
|
||||||
bool operator!=(const PackageCategory& other) const;
|
bool operator!=(const PackageCategory& other) const;
|
||||||
|
|
||||||
@@ -38,7 +45,7 @@ private:
|
|||||||
typedef BReference<PackageCategory> CategoryRef;
|
typedef BReference<PackageCategory> CategoryRef;
|
||||||
|
|
||||||
|
|
||||||
extern bool IsPackageCategoryBefore(const CategoryRef& c1, const CategoryRef& c2);
|
extern bool IsPackageCategoryRefLess(const CategoryRef& c1, const CategoryRef& c2);
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_CATEGORY_H
|
#endif // PACKAGE_CATEGORY_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
PackageClassificationInfo::PackageClassificationInfo()
|
PackageClassificationInfo::PackageClassificationInfo()
|
||||||
:
|
:
|
||||||
fCategories(),
|
fCategories(),
|
||||||
fProminence(-1L),
|
fProminence(PROMINANCE_ORDERING_NONE),
|
||||||
fIsNativeDesktop(false)
|
fIsNativeDesktop(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,20 @@ PackageClassificationInfo::PackageClassificationInfo(const PackageClassification
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
PackageClassificationInfo::Prominence() const
|
||||||
|
{
|
||||||
|
return fProminence;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageClassificationInfo::HasProminence() const
|
||||||
|
{
|
||||||
|
return fProminence != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
PackageClassificationInfo::CountCategories() const
|
PackageClassificationInfo::CountCategories() const
|
||||||
{
|
{
|
||||||
@@ -36,26 +50,18 @@ PackageClassificationInfo::CountCategories() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CategoryRef
|
const CategoryRef
|
||||||
PackageClassificationInfo::CategoryAtIndex(int32 index) const
|
PackageClassificationInfo::CategoryAtIndex(int32 index) const
|
||||||
{
|
{
|
||||||
return fCategories[index];
|
return fCategories[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageClassificationInfo::ClearCategories()
|
|
||||||
{
|
|
||||||
if (!fCategories.empty())
|
|
||||||
fCategories.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PackageClassificationInfo::AddCategory(const CategoryRef& category)
|
PackageClassificationInfo::AddCategory(const CategoryRef& category)
|
||||||
{
|
{
|
||||||
std::vector<CategoryRef>::const_iterator itInsertionPt = std::lower_bound(fCategories.begin(),
|
std::vector<CategoryRef>::const_iterator itInsertionPt = std::lower_bound(fCategories.begin(),
|
||||||
fCategories.end(), category, &IsPackageCategoryBefore);
|
fCategories.end(), category, &IsPackageCategoryRefLess);
|
||||||
|
|
||||||
if (itInsertionPt == fCategories.end()) {
|
if (itInsertionPt == fCategories.end()) {
|
||||||
fCategories.push_back(category);
|
fCategories.push_back(category);
|
||||||
@@ -131,3 +137,104 @@ PackageClassificationInfo::operator!=(const PackageClassificationInfo& other) co
|
|||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageClassificationInfoBuilder
|
||||||
|
|
||||||
|
|
||||||
|
PackageClassificationInfoBuilder::PackageClassificationInfoBuilder()
|
||||||
|
:
|
||||||
|
fCategories(),
|
||||||
|
fProminence(-1L),
|
||||||
|
fIsNativeDesktop(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageClassificationInfoBuilder::PackageClassificationInfoBuilder(
|
||||||
|
const PackageClassificationInfoRef& value)
|
||||||
|
:
|
||||||
|
fCategories(),
|
||||||
|
fProminence(PROMINANCE_ORDERING_NONE),
|
||||||
|
fIsNativeDesktop(false)
|
||||||
|
{
|
||||||
|
fSource = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageClassificationInfoBuilder::~PackageClassificationInfoBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageClassificationInfoBuilder::_InitFromSource()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet()) {
|
||||||
|
_Init(fSource.Get());
|
||||||
|
fSource.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageClassificationInfoBuilder::_Init(const PackageClassificationInfo* value)
|
||||||
|
{
|
||||||
|
for (int32 i = value->CountCategories() - 1; i >= 0; i--)
|
||||||
|
fCategories.push_back(value->CategoryAtIndex(i));
|
||||||
|
fProminence = value->Prominence();
|
||||||
|
fIsNativeDesktop = value->IsNativeDesktop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageClassificationInfoRef
|
||||||
|
PackageClassificationInfoBuilder::BuildRef() const
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
return fSource;
|
||||||
|
|
||||||
|
PackageClassificationInfo* classificationInfo = new PackageClassificationInfo();
|
||||||
|
|
||||||
|
classificationInfo->SetProminence(fProminence);
|
||||||
|
classificationInfo->SetIsNativeDesktop(fIsNativeDesktop);
|
||||||
|
|
||||||
|
std::vector<CategoryRef>::const_iterator it;
|
||||||
|
|
||||||
|
for (it = fCategories.begin(); it != fCategories.end(); it++)
|
||||||
|
classificationInfo->AddCategory(*it);
|
||||||
|
|
||||||
|
return PackageClassificationInfoRef(classificationInfo, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageClassificationInfoBuilder&
|
||||||
|
PackageClassificationInfoBuilder::WithProminence(uint32 prominence)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Prominence() != prominence) {
|
||||||
|
_InitFromSource();
|
||||||
|
fProminence = prominence;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageClassificationInfoBuilder&
|
||||||
|
PackageClassificationInfoBuilder::WithIsNativeDesktop(bool value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->IsNativeDesktop() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fIsNativeDesktop = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageClassificationInfoBuilder&
|
||||||
|
PackageClassificationInfoBuilder::AddCategory(const CategoryRef& category)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->HasCategoryByCode(category->Code())) {
|
||||||
|
_InitFromSource();
|
||||||
|
fCategories.push_back(category);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_CLASSIFICATION_INFO_H
|
#ifndef PACKAGE_CLASSIFICATION_INFO_H
|
||||||
@@ -13,8 +13,16 @@
|
|||||||
#include "PackageCategory.h"
|
#include "PackageCategory.h"
|
||||||
|
|
||||||
|
|
||||||
|
class PackageClassificationInfoBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
/*! Instances of this class should not be created directly; instead use the
|
||||||
|
PackageClassificationInfoBuilder class as a builder-constructor.
|
||||||
|
*/
|
||||||
class PackageClassificationInfo : public BReferenceable
|
class PackageClassificationInfo : public BReferenceable
|
||||||
{
|
{
|
||||||
|
friend class PackageClassificationInfoBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PackageClassificationInfo();
|
PackageClassificationInfo();
|
||||||
PackageClassificationInfo(const PackageClassificationInfo& other);
|
PackageClassificationInfo(const PackageClassificationInfo& other);
|
||||||
@@ -22,20 +30,20 @@ public:
|
|||||||
bool operator==(const PackageClassificationInfo& other) const;
|
bool operator==(const PackageClassificationInfo& other) const;
|
||||||
bool operator!=(const PackageClassificationInfo& other) const;
|
bool operator!=(const PackageClassificationInfo& other) const;
|
||||||
|
|
||||||
void SetProminence(uint32 prominence);
|
uint32 Prominence() const;
|
||||||
uint32 Prominence() const
|
bool HasProminence() const;
|
||||||
{ return fProminence; }
|
|
||||||
bool HasProminence() const
|
|
||||||
{ return fProminence != 0; }
|
|
||||||
bool IsProminent() const;
|
bool IsProminent() const;
|
||||||
|
|
||||||
void ClearCategories();
|
|
||||||
bool AddCategory(const CategoryRef& category);
|
|
||||||
int32 CountCategories() const;
|
int32 CountCategories() const;
|
||||||
CategoryRef CategoryAtIndex(int32 index) const;
|
const CategoryRef CategoryAtIndex(int32 index) const;
|
||||||
bool HasCategoryByCode(const BString& code) const;
|
bool HasCategoryByCode(const BString& code) const;
|
||||||
|
|
||||||
bool IsNativeDesktop() const;
|
bool IsNativeDesktop() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetProminence(uint32 prominence);
|
||||||
|
void ClearCategories();
|
||||||
|
bool AddCategory(const CategoryRef& category);
|
||||||
void SetIsNativeDesktop(bool value);
|
void SetIsNativeDesktop(bool value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -49,4 +57,37 @@ private:
|
|||||||
typedef BReference<PackageClassificationInfo> PackageClassificationInfoRef;
|
typedef BReference<PackageClassificationInfo> PackageClassificationInfoRef;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageClassificationInfoBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PackageClassificationInfoBuilder();
|
||||||
|
PackageClassificationInfoBuilder(
|
||||||
|
const PackageClassificationInfoRef& value);
|
||||||
|
virtual ~PackageClassificationInfoBuilder();
|
||||||
|
|
||||||
|
PackageClassificationInfoRef
|
||||||
|
BuildRef() const;
|
||||||
|
|
||||||
|
PackageClassificationInfoBuilder&
|
||||||
|
WithProminence(uint32 prominence);
|
||||||
|
PackageClassificationInfoBuilder&
|
||||||
|
WithIsNativeDesktop(bool value);
|
||||||
|
|
||||||
|
PackageClassificationInfoBuilder&
|
||||||
|
AddCategory(const CategoryRef& category);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitFromSource();
|
||||||
|
void _Init(const PackageClassificationInfo* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageClassificationInfoRef
|
||||||
|
fSource;
|
||||||
|
std::vector<CategoryRef>
|
||||||
|
fCategories;
|
||||||
|
uint32 fProminence;
|
||||||
|
bool fIsNativeDesktop;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_CLASSIFICATION_INFO_H
|
#endif // PACKAGE_CLASSIFICATION_INFO_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -34,18 +34,6 @@ PackageCoreInfo::~PackageCoreInfo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageCoreInfo&
|
|
||||||
PackageCoreInfo::operator=(const PackageCoreInfo& other)
|
|
||||||
{
|
|
||||||
fVersion = other.fVersion;
|
|
||||||
fPublisher = other.fPublisher;
|
|
||||||
fArchitecture = other.fArchitecture;
|
|
||||||
fDepotName = other.fDepotName;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PackageCoreInfo::operator==(const PackageCoreInfo& other) const
|
PackageCoreInfo::operator==(const PackageCoreInfo& other) const
|
||||||
{
|
{
|
||||||
@@ -63,6 +51,34 @@ PackageCoreInfo::operator!=(const PackageCoreInfo& other) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackageVersionRef&
|
||||||
|
PackageCoreInfo::Version() const
|
||||||
|
{
|
||||||
|
return fVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackagePublisherInfoRef&
|
||||||
|
PackageCoreInfo::Publisher() const
|
||||||
|
{
|
||||||
|
return fPublisher;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BString
|
||||||
|
PackageCoreInfo::Architecture() const
|
||||||
|
{
|
||||||
|
return fArchitecture;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BString&
|
||||||
|
PackageCoreInfo::DepotName() const
|
||||||
|
{
|
||||||
|
return fDepotName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PackageCoreInfo::SetVersion(PackageVersionRef value)
|
PackageCoreInfo::SetVersion(PackageVersionRef value)
|
||||||
{
|
{
|
||||||
@@ -89,3 +105,112 @@ PackageCoreInfo::SetDepotName(const BString& value)
|
|||||||
{
|
{
|
||||||
fDepotName = value;
|
fDepotName = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageCoreInfoBuilder
|
||||||
|
|
||||||
|
|
||||||
|
PackageCoreInfoBuilder::PackageCoreInfoBuilder()
|
||||||
|
:
|
||||||
|
fVersion(),
|
||||||
|
fPublisher(),
|
||||||
|
fArchitecture(),
|
||||||
|
fDepotName()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageCoreInfoBuilder::PackageCoreInfoBuilder(const PackageCoreInfoRef& other)
|
||||||
|
:
|
||||||
|
fVersion(),
|
||||||
|
fPublisher(),
|
||||||
|
fArchitecture(),
|
||||||
|
fDepotName()
|
||||||
|
{
|
||||||
|
fSource = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageCoreInfoBuilder::~PackageCoreInfoBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageCoreInfoBuilder::_InitFromSource()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet()) {
|
||||||
|
_Init(fSource.Get());
|
||||||
|
fSource.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageCoreInfoBuilder::_Init(const PackageCoreInfo* other)
|
||||||
|
{
|
||||||
|
fVersion = other->Version();
|
||||||
|
fPublisher = other->Publisher();
|
||||||
|
fArchitecture = other->Architecture();
|
||||||
|
fDepotName = other->DepotName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageCoreInfoRef
|
||||||
|
PackageCoreInfoBuilder::BuildRef()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
return fSource;
|
||||||
|
|
||||||
|
PackageCoreInfo* coreInfo = new PackageCoreInfo();
|
||||||
|
coreInfo->SetVersion(fVersion);
|
||||||
|
coreInfo->SetPublisher(fPublisher);
|
||||||
|
coreInfo->SetArchitecture(fArchitecture);
|
||||||
|
coreInfo->SetDepotName(fDepotName);
|
||||||
|
|
||||||
|
return PackageCoreInfoRef(coreInfo, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageCoreInfoBuilder&
|
||||||
|
PackageCoreInfoBuilder::WithVersion(PackageVersionRef value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Version() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fVersion = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageCoreInfoBuilder&
|
||||||
|
PackageCoreInfoBuilder::WithPublisher(PackagePublisherInfoRef value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Publisher() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fPublisher = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageCoreInfoBuilder&
|
||||||
|
PackageCoreInfoBuilder::WithArchitecture(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Architecture() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fArchitecture = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageCoreInfoBuilder&
|
||||||
|
PackageCoreInfoBuilder::WithDepotName(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->DepotName() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fDepotName = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_CORE_INFO_H
|
#ifndef PACKAGE_CORE_INFO_H
|
||||||
@@ -15,38 +15,79 @@
|
|||||||
using BPackageKit::BPackageVersion;
|
using BPackageKit::BPackageVersion;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageCoreInfoBuilder;
|
||||||
|
|
||||||
|
|
||||||
/*! This class models the core data for the package.
|
/*! This class models the core data for the package.
|
||||||
|
|
||||||
|
Instances of this class should not be created directly; instead use the
|
||||||
|
PackageCoreInfoBuilder class as a builder-constructor.
|
||||||
*/
|
*/
|
||||||
class PackageCoreInfo : public BReferenceable
|
class PackageCoreInfo : public BReferenceable
|
||||||
{
|
{
|
||||||
|
friend class PackageCoreInfoBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PackageCoreInfo();
|
PackageCoreInfo();
|
||||||
PackageCoreInfo(const PackageCoreInfo& other);
|
PackageCoreInfo(const PackageCoreInfo& other);
|
||||||
virtual ~PackageCoreInfo();
|
virtual ~PackageCoreInfo();
|
||||||
|
|
||||||
PackageCoreInfo& operator=(const PackageCoreInfo& other);
|
|
||||||
bool operator==(const PackageCoreInfo& other) const;
|
bool operator==(const PackageCoreInfo& other) const;
|
||||||
bool operator!=(const PackageCoreInfo& other) const;
|
bool operator!=(const PackageCoreInfo& other) const;
|
||||||
|
|
||||||
const PackageVersionRef&
|
const PackageVersionRef&
|
||||||
Version() const
|
Version() const;
|
||||||
{ return fVersion; }
|
|
||||||
void SetVersion(PackageVersionRef value);
|
|
||||||
|
|
||||||
const PackagePublisherInfoRef&
|
const PackagePublisherInfoRef&
|
||||||
Publisher() const
|
Publisher() const;
|
||||||
{ return fPublisher; }
|
const BString Architecture() const;
|
||||||
void SetPublisher(PackagePublisherInfoRef value);
|
const BString& DepotName() const;
|
||||||
|
|
||||||
const BString Architecture() const
|
|
||||||
{ return fArchitecture; }
|
|
||||||
void SetArchitecture(const BString& value);
|
|
||||||
|
|
||||||
void SetDepotName(const BString& value);
|
|
||||||
const BString& DepotName() const
|
|
||||||
{ return fDepotName; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SetVersion(PackageVersionRef value);
|
||||||
|
void SetPublisher(PackagePublisherInfoRef value);
|
||||||
|
void SetArchitecture(const BString& value);
|
||||||
|
void SetDepotName(const BString& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageVersionRef
|
||||||
|
fVersion;
|
||||||
|
PackagePublisherInfoRef
|
||||||
|
fPublisher;
|
||||||
|
BString fArchitecture;
|
||||||
|
BString fDepotName;
|
||||||
|
// The name and not the identifier are used here because the
|
||||||
|
// identifier is not readily available in all API situations.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef BReference<PackageCoreInfo> PackageCoreInfoRef;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageCoreInfoBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PackageCoreInfoBuilder();
|
||||||
|
PackageCoreInfoBuilder(const PackageCoreInfoRef& other);
|
||||||
|
virtual ~PackageCoreInfoBuilder();
|
||||||
|
|
||||||
|
PackageCoreInfoRef BuildRef();
|
||||||
|
|
||||||
|
PackageCoreInfoBuilder&
|
||||||
|
WithVersion(PackageVersionRef value);
|
||||||
|
PackageCoreInfoBuilder&
|
||||||
|
WithPublisher(PackagePublisherInfoRef value);
|
||||||
|
PackageCoreInfoBuilder&
|
||||||
|
WithArchitecture(const BString& value);
|
||||||
|
PackageCoreInfoBuilder&
|
||||||
|
WithDepotName(const BString& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitFromSource();
|
||||||
|
void _Init(const PackageCoreInfo* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageCoreInfoRef
|
||||||
|
fSource;
|
||||||
PackageVersionRef
|
PackageVersionRef
|
||||||
fVersion;
|
fVersion;
|
||||||
PackagePublisherInfoRef
|
PackagePublisherInfoRef
|
||||||
@@ -56,7 +97,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef BReference<PackageCoreInfo> PackageCoreInfoRef;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_CORE_INFO_H
|
#endif // PACKAGE_CORE_INFO_H
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2014, Axel Dörfler <[email protected]>.
|
* Copyright 2014, Axel Dörfler <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Note that this file included code earlier from `Model.cpp` and
|
* Note that this file included code earlier from `Model.cpp` and
|
||||||
* copyrights have been latterly been carried across in 2024.
|
* copyrights have been latterly been carried across in 2024.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "PackageFilter.h"
|
#include "PackageFilter.h"
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "PackageFilterSpecification.h"
|
||||||
#include "PackageUtils.h"
|
#include "PackageUtils.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -52,6 +53,20 @@ AndFilter::AcceptsPackage(const PackageInfoRef& package) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FalseFilter : public PackageFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FalseFilter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool AcceptsPackage(const PackageInfoRef& package) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class StateFilter : public PackageFilter
|
class StateFilter : public PackageFilter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -138,16 +153,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DevelopmentFilter : public PackageFilter
|
class DevelopmentFilter : public PackageFilter {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual bool AcceptsPackage(const PackageInfoRef& package) const
|
virtual bool AcceptsPackage(const PackageInfoRef& package) const
|
||||||
{
|
{
|
||||||
if (!package.IsSet())
|
if (!package.IsSet())
|
||||||
return false;
|
return false;
|
||||||
const BString& packageName = package->Name();
|
const BString& packageName = package->Name();
|
||||||
return packageName.EndsWith("_devel")
|
return packageName.EndsWith("_devel") || packageName.EndsWith("_debuginfo");
|
||||||
|| packageName.EndsWith("_debuginfo");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -179,8 +192,7 @@ public:
|
|||||||
// Every search term must be found in one of the package texts
|
// Every search term must be found in one of the package texts
|
||||||
for (int32 i = fSearchTerms.CountStrings() - 1; i >= 0; i--) {
|
for (int32 i = fSearchTerms.CountStrings() - 1; i >= 0; i--) {
|
||||||
const BString& term = fSearchTerms.StringAt(i);
|
const BString& term = fSearchTerms.StringAt(i);
|
||||||
if (package->Name().FindFirst(term) < 0
|
if (package->Name().FindFirst(term) < 0 && !_AcceptsPackageFromPublisher(package, term)
|
||||||
&& !_AcceptsPackageFromPublisher(package, term)
|
|
||||||
&& !_AcceptsPackageFromLocalizedText(package, term)) {
|
&& !_AcceptsPackageFromLocalizedText(package, term)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -199,15 +211,15 @@ public:
|
|||||||
searchTerms.Append(" ");
|
searchTerms.Append(" ");
|
||||||
searchTerms.Append(term);
|
searchTerms.Append(term);
|
||||||
}
|
}
|
||||||
return searchTerms;
|
return searchTerms;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _TextContains(BString text, const BString& string) const
|
bool _TextContains(BString text, const BString& string) const
|
||||||
{
|
{
|
||||||
int32 index = text.IFindFirst(string);
|
int32 index = text.IFindFirst(string);
|
||||||
return index >= 0;
|
return index >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _AcceptsPackageFromPublisher(const PackageInfoRef& package,
|
bool _AcceptsPackageFromPublisher(const PackageInfoRef& package,
|
||||||
const BString& searchTerm) const
|
const BString& searchTerm) const
|
||||||
@@ -228,12 +240,12 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return _TextContains(localizedText->Title(), searchTerm)
|
return _TextContains(localizedText->Title(), searchTerm)
|
||||||
|| _TextContains(localizedText->Summary(), searchTerm)
|
|| _TextContains(localizedText->Summary(), searchTerm)
|
||||||
|| _TextContains(localizedText->Description(), searchTerm);
|
|| _TextContains(localizedText->Description(), searchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BStringList fSearchTerms;
|
BStringList fSearchTerms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -280,3 +292,43 @@ PackageFilterFactory::CreateDevelopmentFilter()
|
|||||||
{
|
{
|
||||||
return PackageFilterRef(new DevelopmentFilter(), true);
|
return PackageFilterRef(new DevelopmentFilter(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ PackageFilterRef
|
||||||
|
PackageFilterFactory::CreateFalseFilter()
|
||||||
|
{
|
||||||
|
return PackageFilterRef(new FalseFilter(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ PackageFilterRef
|
||||||
|
PackageFilterFactory::CreateFilter(const PackageFilterSpecificationRef specification)
|
||||||
|
{
|
||||||
|
if (!specification.IsSet())
|
||||||
|
return CreateFalseFilter();
|
||||||
|
|
||||||
|
AndFilter* andFilter = new AndFilter();
|
||||||
|
|
||||||
|
if (!specification->SearchTerms().IsEmpty())
|
||||||
|
andFilter->AddFilter(CreateSearchTermsFilter(specification->SearchTerms()));
|
||||||
|
|
||||||
|
if (!specification->DepotName().IsEmpty())
|
||||||
|
andFilter->AddFilter(CreateDepotFilter(specification->DepotName()));
|
||||||
|
|
||||||
|
if (!specification->Category().IsEmpty())
|
||||||
|
andFilter->AddFilter(CreateCategoryFilter(specification->Category()));
|
||||||
|
|
||||||
|
if (!specification->ShowAvailablePackages())
|
||||||
|
andFilter->AddFilter(PackageFilterRef(new NotFilter(CreateStateFilter(NONE)), true));
|
||||||
|
|
||||||
|
if (!specification->ShowInstalledPackages())
|
||||||
|
andFilter->AddFilter(PackageFilterRef(new NotFilter(CreateStateFilter(ACTIVATED)), true));
|
||||||
|
|
||||||
|
if (!specification->ShowSourcePackages())
|
||||||
|
andFilter->AddFilter(PackageFilterRef(new NotFilter(CreateSourceFilter()), true));
|
||||||
|
|
||||||
|
if (!specification->ShowDevelopPackages())
|
||||||
|
andFilter->AddFilter(PackageFilterRef(new NotFilter(CreateDevelopmentFilter()), true));
|
||||||
|
|
||||||
|
return PackageFilterRef(andFilter, true);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2023, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Note that this file included code earlier from `Model.cpp` and
|
* Note that this file included code earlier from `Model.cpp` and
|
||||||
@@ -14,9 +14,13 @@
|
|||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "PackageFilterSpecification.h"
|
||||||
#include "PackageInfo.h"
|
#include "PackageInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*! See the class PackageFilterFactory for static factory methods that will
|
||||||
|
create concrete instances of this abstract superclass.
|
||||||
|
*/
|
||||||
class PackageFilter : public BReferenceable
|
class PackageFilter : public BReferenceable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -61,6 +65,8 @@ public:
|
|||||||
static PackageFilterRef CreateStateFilter(PackageState state);
|
static PackageFilterRef CreateStateFilter(PackageState state);
|
||||||
static PackageFilterRef CreateSourceFilter();
|
static PackageFilterRef CreateSourceFilter();
|
||||||
static PackageFilterRef CreateDevelopmentFilter();
|
static PackageFilterRef CreateDevelopmentFilter();
|
||||||
|
static PackageFilterRef CreateFalseFilter();
|
||||||
|
static PackageFilterRef CreateFilter(const PackageFilterSpecificationRef specification);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,180 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#include "PackageFilterModel.h"
|
|
||||||
|
|
||||||
|
|
||||||
PackageFilterModel::PackageFilterModel()
|
|
||||||
:
|
|
||||||
fSearchTerms(""),
|
|
||||||
fDepotName(""),
|
|
||||||
fCategory(""),
|
|
||||||
fShowAvailablePackages(true),
|
|
||||||
fShowInstalledPackages(true),
|
|
||||||
fShowSourcePackages(false),
|
|
||||||
fShowDevelopPackages(false)
|
|
||||||
{
|
|
||||||
fFilter = _CreateFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PackageFilterModel::~PackageFilterModel()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BString
|
|
||||||
PackageFilterModel::SearchTerms() const
|
|
||||||
{
|
|
||||||
return fSearchTerms;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BString
|
|
||||||
PackageFilterModel::DepotName() const
|
|
||||||
{
|
|
||||||
return fDepotName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BString
|
|
||||||
PackageFilterModel::Category() const
|
|
||||||
{
|
|
||||||
return fCategory;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
PackageFilterModel::ShowAvailablePackages() const
|
|
||||||
{
|
|
||||||
return fShowAvailablePackages;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
PackageFilterModel::ShowInstalledPackages() const
|
|
||||||
{
|
|
||||||
return fShowInstalledPackages;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
PackageFilterModel::ShowSourcePackages() const
|
|
||||||
{
|
|
||||||
return fShowSourcePackages;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
PackageFilterModel::ShowDevelopPackages() const
|
|
||||||
{
|
|
||||||
return fShowDevelopPackages;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageFilterModel::SetSearchTerms(BString value)
|
|
||||||
{
|
|
||||||
if (fSearchTerms != value) {
|
|
||||||
fSearchTerms = value;
|
|
||||||
fFilter = _CreateFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageFilterModel::SetDepotName(BString value)
|
|
||||||
{
|
|
||||||
if (fDepotName != value) {
|
|
||||||
fDepotName = value;
|
|
||||||
fFilter = _CreateFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageFilterModel::SetCategory(BString value)
|
|
||||||
{
|
|
||||||
if (fCategory != value) {
|
|
||||||
fCategory = value;
|
|
||||||
fFilter = _CreateFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageFilterModel::SetShowAvailablePackages(bool value)
|
|
||||||
{
|
|
||||||
if (fShowAvailablePackages != value) {
|
|
||||||
fShowAvailablePackages = value;
|
|
||||||
fFilter = _CreateFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageFilterModel::SetShowInstalledPackages(bool value)
|
|
||||||
{
|
|
||||||
if (fShowInstalledPackages != value) {
|
|
||||||
fShowInstalledPackages = value;
|
|
||||||
fFilter = _CreateFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageFilterModel::SetShowSourcePackages(bool value)
|
|
||||||
{
|
|
||||||
if (fShowSourcePackages != value) {
|
|
||||||
fShowSourcePackages = value;
|
|
||||||
fFilter = _CreateFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageFilterModel::SetShowDevelopPackages(bool value)
|
|
||||||
{
|
|
||||||
if (fShowDevelopPackages != value) {
|
|
||||||
fShowDevelopPackages = value;
|
|
||||||
fFilter = _CreateFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PackageFilterRef
|
|
||||||
PackageFilterModel::Filter()
|
|
||||||
{
|
|
||||||
return fFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PackageFilterRef
|
|
||||||
PackageFilterModel::_CreateFilter() const
|
|
||||||
{
|
|
||||||
AndFilter* andFilter = new AndFilter();
|
|
||||||
if (!fSearchTerms.IsEmpty())
|
|
||||||
andFilter->AddFilter(PackageFilterFactory::CreateSearchTermsFilter(fSearchTerms));
|
|
||||||
if (!fDepotName.IsEmpty())
|
|
||||||
andFilter->AddFilter(PackageFilterFactory::CreateDepotFilter(fDepotName));
|
|
||||||
if (!fCategory.IsEmpty())
|
|
||||||
andFilter->AddFilter(PackageFilterFactory::CreateCategoryFilter(fCategory));
|
|
||||||
if (!fShowAvailablePackages) {
|
|
||||||
andFilter->AddFilter(
|
|
||||||
PackageFilterRef(new NotFilter(PackageFilterFactory::CreateStateFilter(NONE)), true));
|
|
||||||
}
|
|
||||||
if (!fShowInstalledPackages) {
|
|
||||||
andFilter->AddFilter(PackageFilterRef(
|
|
||||||
new NotFilter(PackageFilterFactory::CreateStateFilter(ACTIVATED)), true));
|
|
||||||
}
|
|
||||||
if (!fShowSourcePackages) {
|
|
||||||
andFilter->AddFilter(
|
|
||||||
PackageFilterRef(new NotFilter(PackageFilterFactory::CreateSourceFilter()), true));
|
|
||||||
}
|
|
||||||
if (!fShowDevelopPackages) {
|
|
||||||
andFilter->AddFilter(
|
|
||||||
PackageFilterRef(new NotFilter(PackageFilterFactory::CreateDevelopmentFilter()), true));
|
|
||||||
}
|
|
||||||
return PackageFilterRef(andFilter, true);
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef PACKAGE_FILTER_MODEL_H
|
|
||||||
#define PACKAGE_FILTER_MODEL_H
|
|
||||||
|
|
||||||
#include <String.h>
|
|
||||||
|
|
||||||
#include "PackageFilter.h"
|
|
||||||
|
|
||||||
|
|
||||||
class PackageFilterModel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PackageFilterModel();
|
|
||||||
virtual ~PackageFilterModel();
|
|
||||||
|
|
||||||
BString SearchTerms() const;
|
|
||||||
BString DepotName() const;
|
|
||||||
BString Category() const;
|
|
||||||
bool ShowAvailablePackages() const;
|
|
||||||
bool ShowInstalledPackages() const;
|
|
||||||
bool ShowSourcePackages() const;
|
|
||||||
bool ShowDevelopPackages() const;
|
|
||||||
|
|
||||||
void SetSearchTerms(BString value);
|
|
||||||
void SetDepotName(BString value);
|
|
||||||
void SetCategory(BString value);
|
|
||||||
void SetShowAvailablePackages(bool value);
|
|
||||||
void SetShowInstalledPackages(bool value);
|
|
||||||
void SetShowSourcePackages(bool value);
|
|
||||||
void SetShowDevelopPackages(bool value);
|
|
||||||
|
|
||||||
PackageFilterRef Filter();
|
|
||||||
|
|
||||||
private:
|
|
||||||
PackageFilterRef _CreateFilter() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
BString fSearchTerms;
|
|
||||||
BString fDepotName;
|
|
||||||
BString fCategory;
|
|
||||||
bool fShowAvailablePackages;
|
|
||||||
bool fShowInstalledPackages;
|
|
||||||
bool fShowSourcePackages;
|
|
||||||
bool fShowDevelopPackages;
|
|
||||||
|
|
||||||
PackageFilterRef fFilter;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_FILTER_MODEL_H
|
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025, Andrew Lindesay <[email protected]>.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include "PackageFilterSpecification.h"
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecification::PackageFilterSpecification()
|
||||||
|
:
|
||||||
|
fSearchTerms(""),
|
||||||
|
fDepotName(""),
|
||||||
|
fCategory(""),
|
||||||
|
fShowAvailablePackages(true),
|
||||||
|
fShowInstalledPackages(true),
|
||||||
|
fShowSourcePackages(false),
|
||||||
|
fShowDevelopPackages(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecification::~PackageFilterSpecification()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageFilterSpecification::operator==(const PackageFilterSpecification& other) const
|
||||||
|
{
|
||||||
|
return fSearchTerms == other.SearchTerms() && fDepotName == other.DepotName()
|
||||||
|
&& fCategory == other.Category() && fShowAvailablePackages == other.ShowAvailablePackages()
|
||||||
|
&& fShowInstalledPackages == other.ShowInstalledPackages()
|
||||||
|
&& fShowDevelopPackages == other.ShowDevelopPackages();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageFilterSpecification::operator!=(const PackageFilterSpecification& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
PackageFilterSpecification::SearchTerms() const
|
||||||
|
{
|
||||||
|
return fSearchTerms;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
PackageFilterSpecification::DepotName() const
|
||||||
|
{
|
||||||
|
return fDepotName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
PackageFilterSpecification::Category() const
|
||||||
|
{
|
||||||
|
return fCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageFilterSpecification::ShowAvailablePackages() const
|
||||||
|
{
|
||||||
|
return fShowAvailablePackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageFilterSpecification::ShowInstalledPackages() const
|
||||||
|
{
|
||||||
|
return fShowInstalledPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageFilterSpecification::ShowSourcePackages() const
|
||||||
|
{
|
||||||
|
return fShowSourcePackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageFilterSpecification::ShowDevelopPackages() const
|
||||||
|
{
|
||||||
|
return fShowDevelopPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFilterSpecification::SetSearchTerms(BString value)
|
||||||
|
{
|
||||||
|
fSearchTerms = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFilterSpecification::SetDepotName(BString value)
|
||||||
|
{
|
||||||
|
fDepotName = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFilterSpecification::SetCategory(BString value)
|
||||||
|
{
|
||||||
|
fCategory = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFilterSpecification::SetShowAvailablePackages(bool value)
|
||||||
|
{
|
||||||
|
fShowAvailablePackages = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFilterSpecification::SetShowInstalledPackages(bool value)
|
||||||
|
{
|
||||||
|
fShowInstalledPackages = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFilterSpecification::SetShowSourcePackages(bool value)
|
||||||
|
{
|
||||||
|
fShowSourcePackages = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFilterSpecification::SetShowDevelopPackages(bool value)
|
||||||
|
{
|
||||||
|
fShowDevelopPackages = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageClassificationInfoBuilder
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder::PackageFilterSpecificationBuilder()
|
||||||
|
:
|
||||||
|
fSearchTerms(""),
|
||||||
|
fDepotName(""),
|
||||||
|
fCategory(""),
|
||||||
|
fShowAvailablePackages(true),
|
||||||
|
fShowInstalledPackages(true),
|
||||||
|
fShowSourcePackages(false),
|
||||||
|
fShowDevelopPackages(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder::PackageFilterSpecificationBuilder(
|
||||||
|
const PackageFilterSpecificationRef& value)
|
||||||
|
:
|
||||||
|
fSource(value),
|
||||||
|
fSearchTerms(""),
|
||||||
|
fDepotName(""),
|
||||||
|
fCategory(""),
|
||||||
|
fShowAvailablePackages(true),
|
||||||
|
fShowInstalledPackages(true),
|
||||||
|
fShowSourcePackages(false),
|
||||||
|
fShowDevelopPackages(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder::~PackageFilterSpecificationBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFilterSpecificationBuilder::_InitFromSource()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet()) {
|
||||||
|
_Init(fSource);
|
||||||
|
fSource.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFilterSpecificationBuilder::_Init(const PackageFilterSpecification* value)
|
||||||
|
{
|
||||||
|
fSearchTerms = value->SearchTerms();
|
||||||
|
fDepotName = value->DepotName();
|
||||||
|
fCategory = value->Category();
|
||||||
|
fShowAvailablePackages = value->ShowAvailablePackages();
|
||||||
|
fShowInstalledPackages = value->ShowInstalledPackages();
|
||||||
|
fShowSourcePackages = value->ShowSourcePackages();
|
||||||
|
fShowDevelopPackages = value->ShowDevelopPackages();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationRef
|
||||||
|
PackageFilterSpecificationBuilder::BuildRef()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
return fSource;
|
||||||
|
|
||||||
|
PackageFilterSpecification* info = new PackageFilterSpecification();
|
||||||
|
info->SetSearchTerms(fSearchTerms);
|
||||||
|
info->SetDepotName(fDepotName);
|
||||||
|
info->SetCategory(fCategory);
|
||||||
|
info->SetShowAvailablePackages(fShowAvailablePackages);
|
||||||
|
info->SetShowInstalledPackages(fShowInstalledPackages);
|
||||||
|
info->SetShowSourcePackages(fShowSourcePackages);
|
||||||
|
info->SetShowDevelopPackages(fShowDevelopPackages);
|
||||||
|
return PackageFilterSpecificationRef(info, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
PackageFilterSpecificationBuilder::WithSearchTerms(BString value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->SearchTerms() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fSearchTerms = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
PackageFilterSpecificationBuilder::WithDepotName(BString value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->DepotName() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fDepotName = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
PackageFilterSpecificationBuilder::WithCategory(BString value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Category() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fCategory = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
PackageFilterSpecificationBuilder::WithShowAvailablePackages(bool value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->ShowAvailablePackages() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fShowAvailablePackages = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
PackageFilterSpecificationBuilder::WithShowInstalledPackages(bool value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->ShowInstalledPackages() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fShowInstalledPackages = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
PackageFilterSpecificationBuilder::WithShowSourcePackages(bool value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->ShowSourcePackages() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fShowSourcePackages = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
PackageFilterSpecificationBuilder::WithShowDevelopPackages(bool value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->ShowDevelopPackages() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fShowDevelopPackages = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025, Andrew Lindesay <[email protected]>.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef PACKAGE_FILTER_SPECIFICATION_H
|
||||||
|
#define PACKAGE_FILTER_SPECIFICATION_H
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*! Instances of this class should not be created directly; instead use the
|
||||||
|
PackageFilterSpecificationBuilder class as a builder-constructor.
|
||||||
|
*/
|
||||||
|
class PackageFilterSpecification : public BReferenceable
|
||||||
|
{
|
||||||
|
friend class PackageFilterSpecificationBuilder;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PackageFilterSpecification();
|
||||||
|
virtual ~PackageFilterSpecification();
|
||||||
|
|
||||||
|
bool operator==(const PackageFilterSpecification& other) const;
|
||||||
|
bool operator!=(const PackageFilterSpecification& other) const;
|
||||||
|
|
||||||
|
BString SearchTerms() const;
|
||||||
|
BString DepotName() const;
|
||||||
|
BString Category() const;
|
||||||
|
bool ShowAvailablePackages() const;
|
||||||
|
bool ShowInstalledPackages() const;
|
||||||
|
bool ShowSourcePackages() const;
|
||||||
|
bool ShowDevelopPackages() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetSearchTerms(BString value);
|
||||||
|
void SetDepotName(BString value);
|
||||||
|
void SetCategory(BString value);
|
||||||
|
void SetShowAvailablePackages(bool value);
|
||||||
|
void SetShowInstalledPackages(bool value);
|
||||||
|
void SetShowSourcePackages(bool value);
|
||||||
|
void SetShowDevelopPackages(bool value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BString fSearchTerms;
|
||||||
|
BString fDepotName;
|
||||||
|
BString fCategory;
|
||||||
|
bool fShowAvailablePackages;
|
||||||
|
bool fShowInstalledPackages;
|
||||||
|
bool fShowSourcePackages;
|
||||||
|
bool fShowDevelopPackages;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef BReference<PackageFilterSpecification> PackageFilterSpecificationRef;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageFilterSpecificationBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PackageFilterSpecificationBuilder();
|
||||||
|
PackageFilterSpecificationBuilder(
|
||||||
|
const PackageFilterSpecificationRef& other);
|
||||||
|
virtual ~PackageFilterSpecificationBuilder();
|
||||||
|
|
||||||
|
PackageFilterSpecificationRef
|
||||||
|
BuildRef();
|
||||||
|
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
WithSearchTerms(BString value);
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
WithDepotName(BString value);
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
WithCategory(BString value);
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
WithShowAvailablePackages(bool value);
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
WithShowInstalledPackages(bool value);
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
WithShowSourcePackages(bool value);
|
||||||
|
PackageFilterSpecificationBuilder
|
||||||
|
WithShowDevelopPackages(bool value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitFromSource();
|
||||||
|
void _Init(const PackageFilterSpecification* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageFilterSpecificationRef
|
||||||
|
fSource;
|
||||||
|
BString fSearchTerms;
|
||||||
|
BString fDepotName;
|
||||||
|
BString fCategory;
|
||||||
|
bool fShowAvailablePackages;
|
||||||
|
bool fShowInstalledPackages;
|
||||||
|
bool fShowSourcePackages;
|
||||||
|
bool fShowDevelopPackages;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PACKAGE_FILTER_SPECIFICATION_H
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2013, Rene Gollent <[email protected]>.
|
* Copyright 2013, Rene Gollent <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "HaikuDepotConstants.h"
|
#include "HaikuDepotConstants.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "PackageInfoListener.h"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - PackageInfo
|
// #pragma mark - PackageInfo
|
||||||
@@ -29,66 +30,11 @@ PackageInfo::PackageInfo()
|
|||||||
fClassificationInfo(),
|
fClassificationInfo(),
|
||||||
fScreenshotInfo(),
|
fScreenshotInfo(),
|
||||||
fUserRatingInfo(),
|
fUserRatingInfo(),
|
||||||
fLocalInfo(),
|
fLocalInfo()
|
||||||
|
|
||||||
fListeners(),
|
|
||||||
fIsCollatingChanges(false),
|
|
||||||
fCollatedChanges(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageInfo::PackageInfo(const BPackageInfo& info)
|
|
||||||
:
|
|
||||||
fName(info.Name()),
|
|
||||||
|
|
||||||
fClassificationInfo(),
|
|
||||||
fScreenshotInfo(),
|
|
||||||
fUserRatingInfo(),
|
|
||||||
|
|
||||||
fListeners(),
|
|
||||||
fIsCollatingChanges(false),
|
|
||||||
fCollatedChanges(0)
|
|
||||||
{
|
|
||||||
|
|
||||||
// TODO; factor this material out.
|
|
||||||
|
|
||||||
BString publisherURL;
|
|
||||||
if (info.URLList().CountStrings() > 0)
|
|
||||||
publisherURL = info.URLList().StringAt(0);
|
|
||||||
|
|
||||||
BString publisherName = info.Vendor();
|
|
||||||
const BStringList& copyrightList = info.CopyrightList();
|
|
||||||
if (!copyrightList.IsEmpty()) {
|
|
||||||
publisherName = "";
|
|
||||||
|
|
||||||
for (int32 i = 0; i < copyrightList.CountStrings(); i++) {
|
|
||||||
if (!publisherName.IsEmpty())
|
|
||||||
publisherName << ", ";
|
|
||||||
publisherName << copyrightList.StringAt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!publisherName.IsEmpty())
|
|
||||||
publisherName.Prepend("© ");
|
|
||||||
|
|
||||||
fCoreInfo = PackageCoreInfoRef(new PackageCoreInfo(), true);
|
|
||||||
fCoreInfo->SetArchitecture(info.ArchitectureName());
|
|
||||||
fCoreInfo->SetVersion(new PackageVersion(info.Version()));
|
|
||||||
fCoreInfo->SetPublisher(
|
|
||||||
PackagePublisherInfoRef(new PackagePublisherInfo(publisherName, publisherURL), true));
|
|
||||||
|
|
||||||
fLocalizedText = PackageLocalizedTextRef(new PackageLocalizedText(), true);
|
|
||||||
fLocalizedText->SetTitle(info.Name());
|
|
||||||
fLocalizedText->SetSummary(info.Summary());
|
|
||||||
fLocalizedText->SetDescription(info.Description());
|
|
||||||
|
|
||||||
// TODO: Retrieve local file size
|
|
||||||
fLocalInfo = PackageLocalInfoRef(new PackageLocalInfo(), true);
|
|
||||||
fLocalInfo->SetFlags(info.Flags());
|
|
||||||
fLocalInfo->SetFileName(info.FileName());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PackageInfo::PackageInfo(const PackageInfo& other)
|
PackageInfo::PackageInfo(const PackageInfo& other)
|
||||||
:
|
:
|
||||||
fName(other.fName),
|
fName(other.fName),
|
||||||
@@ -98,30 +44,11 @@ PackageInfo::PackageInfo(const PackageInfo& other)
|
|||||||
fClassificationInfo(other.fClassificationInfo),
|
fClassificationInfo(other.fClassificationInfo),
|
||||||
fScreenshotInfo(other.fScreenshotInfo),
|
fScreenshotInfo(other.fScreenshotInfo),
|
||||||
fUserRatingInfo(other.fUserRatingInfo),
|
fUserRatingInfo(other.fUserRatingInfo),
|
||||||
fLocalInfo(other.fLocalInfo),
|
fLocalInfo(other.fLocalInfo)
|
||||||
|
|
||||||
fListeners(),
|
|
||||||
fIsCollatingChanges(false),
|
|
||||||
fCollatedChanges(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageInfo&
|
|
||||||
PackageInfo::operator=(const PackageInfo& other)
|
|
||||||
{
|
|
||||||
fName = other.fName;
|
|
||||||
fCoreInfo = other.fCoreInfo;
|
|
||||||
fLocalizedText = other.fLocalizedText;
|
|
||||||
fClassificationInfo = other.fClassificationInfo;
|
|
||||||
fScreenshotInfo = other.fScreenshotInfo;
|
|
||||||
fUserRatingInfo = other.fUserRatingInfo;
|
|
||||||
fLocalInfo = other.fLocalInfo;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PackageInfo::operator==(const PackageInfo& other) const
|
PackageInfo::operator==(const PackageInfo& other) const
|
||||||
{
|
{
|
||||||
@@ -142,8 +69,43 @@ PackageInfo::operator!=(const PackageInfo& other) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BString&
|
||||||
|
PackageInfo::Name() const
|
||||||
|
{
|
||||||
|
return fName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackageCoreInfoRef
|
||||||
|
PackageInfo::CoreInfo() const
|
||||||
|
{
|
||||||
|
return fCoreInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackageClassificationInfoRef
|
||||||
|
PackageInfo::PackageClassificationInfo() const
|
||||||
|
{
|
||||||
|
return fClassificationInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackageScreenshotInfoRef
|
||||||
|
PackageInfo::ScreenshotInfo() const
|
||||||
|
{
|
||||||
|
return fScreenshotInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageInfo::SetName(const BString& value)
|
||||||
|
{
|
||||||
|
fName = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
PackageInfo::DiffMask(const PackageInfo& other) const
|
PackageInfo::ChangeMask(const PackageInfo& other) const
|
||||||
{
|
{
|
||||||
uint32 result = 0;
|
uint32 result = 0;
|
||||||
|
|
||||||
@@ -167,14 +129,11 @@ PackageInfo::DiffMask(const PackageInfo& other) const
|
|||||||
void
|
void
|
||||||
PackageInfo::SetCoreInfo(PackageCoreInfoRef value)
|
PackageInfo::SetCoreInfo(PackageCoreInfoRef value)
|
||||||
{
|
{
|
||||||
if (value != fCoreInfo) {
|
fCoreInfo = value;
|
||||||
fCoreInfo = value;
|
|
||||||
_NotifyListeners(PKG_CHANGED_CORE_INFO);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageLocalizedTextRef
|
const PackageLocalizedTextRef
|
||||||
PackageInfo::LocalizedText() const
|
PackageInfo::LocalizedText() const
|
||||||
{
|
{
|
||||||
return fLocalizedText;
|
return fLocalizedText;
|
||||||
@@ -184,16 +143,11 @@ PackageInfo::LocalizedText() const
|
|||||||
void
|
void
|
||||||
PackageInfo::SetLocalizedText(PackageLocalizedTextRef value)
|
PackageInfo::SetLocalizedText(PackageLocalizedTextRef value)
|
||||||
{
|
{
|
||||||
if (fLocalizedText != value) {
|
fLocalizedText = value;
|
||||||
fLocalizedText = value;
|
|
||||||
_NotifyListeners(PKG_CHANGED_LOCALIZED_TEXT);
|
|
||||||
// TODO; separate out these later - they are bundled for now to keep the existing
|
|
||||||
// logic working.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UserRatingInfoRef
|
const PackageUserRatingInfoRef
|
||||||
PackageInfo::UserRatingInfo() const
|
PackageInfo::UserRatingInfo() const
|
||||||
{
|
{
|
||||||
return fUserRatingInfo;
|
return fUserRatingInfo;
|
||||||
@@ -201,16 +155,13 @@ PackageInfo::UserRatingInfo() const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PackageInfo::SetUserRatingInfo(UserRatingInfoRef value)
|
PackageInfo::SetUserRatingInfo(PackageUserRatingInfoRef& value)
|
||||||
{
|
{
|
||||||
if (fUserRatingInfo != value) {
|
fUserRatingInfo = value;
|
||||||
fUserRatingInfo = value;
|
|
||||||
_NotifyListeners(PKG_CHANGED_RATINGS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageLocalInfoRef
|
const PackageLocalInfoRef
|
||||||
PackageInfo::LocalInfo() const
|
PackageInfo::LocalInfo() const
|
||||||
{
|
{
|
||||||
return fLocalInfo;
|
return fLocalInfo;
|
||||||
@@ -220,99 +171,137 @@ PackageInfo::LocalInfo() const
|
|||||||
void
|
void
|
||||||
PackageInfo::SetLocalInfo(PackageLocalInfoRef& localInfo)
|
PackageInfo::SetLocalInfo(PackageLocalInfoRef& localInfo)
|
||||||
{
|
{
|
||||||
if (fLocalInfo != localInfo) {
|
fLocalInfo = localInfo;
|
||||||
fLocalInfo = localInfo;
|
|
||||||
_NotifyListeners(PKG_CHANGED_LOCAL_INFO);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PackageInfo::SetPackageClassificationInfo(PackageClassificationInfoRef value)
|
PackageInfo::SetPackageClassificationInfo(PackageClassificationInfoRef value)
|
||||||
{
|
{
|
||||||
if (value != fClassificationInfo) {
|
fClassificationInfo = value;
|
||||||
fClassificationInfo = value;
|
|
||||||
_NotifyListeners(PKG_CHANGED_CLASSIFICATION);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PackageInfo::SetScreenshotInfo(PackageScreenshotInfoRef value)
|
PackageInfo::SetScreenshotInfo(PackageScreenshotInfoRef value)
|
||||||
{
|
{
|
||||||
if (value != fScreenshotInfo) {
|
fScreenshotInfo = value;
|
||||||
fScreenshotInfo = value;
|
|
||||||
_NotifyListeners(PKG_CHANGED_SCREENSHOTS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
// #pragma mark - PackageLocalInfoBuilder
|
||||||
PackageInfo::AddListener(const PackageInfoListenerRef& listener)
|
|
||||||
|
|
||||||
|
PackageInfoBuilder::PackageInfoBuilder(const BString& name)
|
||||||
|
:
|
||||||
|
fName(name),
|
||||||
|
fCoreInfo(),
|
||||||
|
fLocalizedText(),
|
||||||
|
fClassificationInfo(),
|
||||||
|
fScreenshotInfo(),
|
||||||
|
fUserRatingInfo(),
|
||||||
|
fLocalInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageInfoBuilder::PackageInfoBuilder(const PackageInfoRef& value)
|
||||||
|
:
|
||||||
|
fName(),
|
||||||
|
fCoreInfo(),
|
||||||
|
fLocalizedText(),
|
||||||
|
fClassificationInfo(),
|
||||||
|
fScreenshotInfo(),
|
||||||
|
fUserRatingInfo(),
|
||||||
|
fLocalInfo()
|
||||||
|
{
|
||||||
|
if (value.IsSet())
|
||||||
|
_Init(value.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageInfoBuilder::PackageInfoBuilder(const PackageInfo& value)
|
||||||
|
{
|
||||||
|
_Init(&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageInfoBuilder::~PackageInfoBuilder()
|
||||||
{
|
{
|
||||||
fListeners.push_back(listener);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PackageInfo::RemoveListener(const PackageInfoListenerRef& listener)
|
PackageInfoBuilder::_Init(const PackageInfo* value)
|
||||||
{
|
{
|
||||||
fListeners.erase(std::remove(fListeners.begin(), fListeners.end(),
|
fName = value->Name();
|
||||||
listener), fListeners.end());
|
fCoreInfo = value->CoreInfo();
|
||||||
|
fLocalizedText = value->LocalizedText();
|
||||||
|
fClassificationInfo = value->PackageClassificationInfo();
|
||||||
|
fScreenshotInfo = value->ScreenshotInfo();
|
||||||
|
fUserRatingInfo = value->UserRatingInfo();
|
||||||
|
fLocalInfo = value->LocalInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
PackageInfoRef
|
||||||
PackageInfo::NotifyChangedIcon()
|
PackageInfoBuilder::BuildRef()
|
||||||
{
|
{
|
||||||
_NotifyListeners(PKG_CHANGED_ICON);
|
PackageInfo* info = new PackageInfo();
|
||||||
|
info->SetName(fName);
|
||||||
|
info->SetCoreInfo(fCoreInfo);
|
||||||
|
info->SetLocalizedText(fLocalizedText);
|
||||||
|
info->SetPackageClassificationInfo(fClassificationInfo);
|
||||||
|
info->SetScreenshotInfo(fScreenshotInfo);
|
||||||
|
info->SetUserRatingInfo(fUserRatingInfo);
|
||||||
|
info->SetLocalInfo(fLocalInfo);
|
||||||
|
return PackageInfoRef(info, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
PackageInfoBuilder&
|
||||||
PackageInfo::StartCollatingChanges()
|
PackageInfoBuilder::WithCoreInfo(PackageCoreInfoRef value)
|
||||||
{
|
{
|
||||||
fIsCollatingChanges = true;
|
fCoreInfo = value;
|
||||||
fCollatedChanges = 0;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
PackageInfoBuilder&
|
||||||
PackageInfo::EndCollatingChanges()
|
PackageInfoBuilder::WithLocalizedText(PackageLocalizedTextRef value)
|
||||||
{
|
{
|
||||||
if (fIsCollatingChanges && fCollatedChanges != 0)
|
fLocalizedText = value;
|
||||||
_NotifyListenersImmediate(fCollatedChanges);
|
return *this;
|
||||||
fIsCollatingChanges = false;
|
|
||||||
fCollatedChanges = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
PackageInfoBuilder&
|
||||||
PackageInfo::_NotifyListeners(uint32 changes)
|
PackageInfoBuilder::WithPackageClassificationInfo(PackageClassificationInfoRef value)
|
||||||
{
|
{
|
||||||
if (fIsCollatingChanges)
|
fClassificationInfo = value;
|
||||||
fCollatedChanges |= changes;
|
return *this;
|
||||||
else
|
|
||||||
_NotifyListenersImmediate(changes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
PackageInfoBuilder&
|
||||||
PackageInfo::_NotifyListenersImmediate(uint32 changes)
|
PackageInfoBuilder::WithUserRatingInfo(PackageUserRatingInfoRef value)
|
||||||
{
|
{
|
||||||
if (fListeners.empty())
|
fUserRatingInfo = value;
|
||||||
return;
|
return *this;
|
||||||
|
}
|
||||||
// Clone list to avoid listeners detaching themselves in notifications
|
|
||||||
// to screw up the list while iterating it.
|
|
||||||
std::vector<PackageInfoListenerRef> listeners(fListeners);
|
PackageInfoBuilder&
|
||||||
PackageInfoEvent event(PackageInfoRef(this), changes);
|
PackageInfoBuilder::WithLocalInfo(PackageLocalInfoRef value)
|
||||||
|
{
|
||||||
std::vector<PackageInfoListenerRef>::iterator it;
|
fLocalInfo = value;
|
||||||
for (it = listeners.begin(); it != listeners.end(); it++) {
|
return *this;
|
||||||
const PackageInfoListenerRef listener = *it;
|
}
|
||||||
if (listener.IsSet())
|
|
||||||
listener->PackageChanged(event);
|
|
||||||
}
|
PackageInfoBuilder&
|
||||||
|
PackageInfoBuilder::WithScreenshotInfo(PackageScreenshotInfoRef value)
|
||||||
|
{
|
||||||
|
fScreenshotInfo = value;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_INFO_H
|
#ifndef PACKAGE_INFO_H
|
||||||
@@ -8,76 +8,63 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
#include <package/PackageInfo.h>
|
|
||||||
|
|
||||||
#include "Language.h"
|
#include "Language.h"
|
||||||
#include "List.h"
|
#include "List.h"
|
||||||
#include "PackageClassificationInfo.h"
|
#include "PackageClassificationInfo.h"
|
||||||
#include "PackageCoreInfo.h"
|
#include "PackageCoreInfo.h"
|
||||||
#include "PackageInfoListener.h"
|
|
||||||
#include "PackageLocalInfo.h"
|
#include "PackageLocalInfo.h"
|
||||||
#include "PackageLocalizedText.h"
|
#include "PackageLocalizedText.h"
|
||||||
#include "PackagePublisherInfo.h"
|
#include "PackagePublisherInfo.h"
|
||||||
#include "PackageScreenshotInfo.h"
|
#include "PackageScreenshotInfo.h"
|
||||||
|
#include "PackageUserRatingInfo.h"
|
||||||
#include "ScreenshotInfo.h"
|
#include "ScreenshotInfo.h"
|
||||||
#include "UserRatingInfo.h"
|
|
||||||
|
|
||||||
|
|
||||||
using BPackageKit::BPackageInfo;
|
using BPackageKit::BPackageInfo;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageInfoBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
/*! Instances of this class should not be created directly; instead use the
|
||||||
|
PackageInfoBuilder class as a builder-constructor.
|
||||||
|
*/
|
||||||
class PackageInfo : public BReferenceable {
|
class PackageInfo : public BReferenceable {
|
||||||
|
friend class PackageInfoBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PackageInfo();
|
PackageInfo();
|
||||||
PackageInfo(const BPackageInfo& info);
|
|
||||||
PackageInfo(const PackageInfo& other);
|
PackageInfo(const PackageInfo& other);
|
||||||
|
|
||||||
PackageInfo& operator=(const PackageInfo& other);
|
|
||||||
bool operator==(const PackageInfo& other) const;
|
bool operator==(const PackageInfo& other) const;
|
||||||
bool operator!=(const PackageInfo& other) const;
|
bool operator!=(const PackageInfo& other) const;
|
||||||
|
|
||||||
uint32 DiffMask(const PackageInfo& other) const;
|
uint32 ChangeMask(const PackageInfo& other) const;
|
||||||
|
|
||||||
const BString& Name() const
|
const BString& Name() const;
|
||||||
{ return fName; }
|
const PackageCoreInfoRef
|
||||||
|
CoreInfo() const;
|
||||||
PackageCoreInfoRef CoreInfo() const
|
const PackageLocalizedTextRef
|
||||||
{ return fCoreInfo; }
|
|
||||||
void SetCoreInfo(PackageCoreInfoRef value);
|
|
||||||
|
|
||||||
PackageLocalizedTextRef
|
|
||||||
LocalizedText() const;
|
LocalizedText() const;
|
||||||
void SetLocalizedText(PackageLocalizedTextRef value);
|
const PackageClassificationInfoRef
|
||||||
|
PackageClassificationInfo() const;
|
||||||
void SetPackageClassificationInfo(
|
const PackageUserRatingInfoRef
|
||||||
PackageClassificationInfoRef value);
|
UserRatingInfo() const;
|
||||||
PackageClassificationInfoRef
|
const PackageLocalInfoRef
|
||||||
PackageClassificationInfo() const
|
LocalInfo() const;
|
||||||
{ return fClassificationInfo; }
|
const PackageScreenshotInfoRef
|
||||||
|
ScreenshotInfo() const;
|
||||||
UserRatingInfoRef UserRatingInfo() const;
|
|
||||||
void SetUserRatingInfo(UserRatingInfoRef userRatingInfo);
|
|
||||||
|
|
||||||
PackageLocalInfoRef LocalInfo() const;
|
|
||||||
void SetLocalInfo(PackageLocalInfoRef& localInfo);
|
|
||||||
|
|
||||||
PackageScreenshotInfoRef
|
|
||||||
ScreenshotInfo() const
|
|
||||||
{ return fScreenshotInfo; }
|
|
||||||
void SetScreenshotInfo(PackageScreenshotInfoRef value);
|
|
||||||
|
|
||||||
bool AddListener(
|
|
||||||
const PackageInfoListenerRef& listener);
|
|
||||||
void RemoveListener(
|
|
||||||
const PackageInfoListenerRef& listener);
|
|
||||||
|
|
||||||
void StartCollatingChanges();
|
|
||||||
void EndCollatingChanges();
|
|
||||||
void NotifyChangedIcon();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _NotifyListeners(uint32 changes);
|
|
||||||
void _NotifyListenersImmediate(uint32 changes);
|
void SetName(const BString& value);
|
||||||
|
void SetCoreInfo(PackageCoreInfoRef value);
|
||||||
|
void SetLocalizedText(PackageLocalizedTextRef value);
|
||||||
|
void SetPackageClassificationInfo(PackageClassificationInfoRef value);
|
||||||
|
void SetUserRatingInfo(PackageUserRatingInfoRef& userRatingInfo);
|
||||||
|
void SetLocalInfo(PackageLocalInfoRef& localInfo);
|
||||||
|
void SetScreenshotInfo(PackageScreenshotInfoRef value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BString fName;
|
BString fName;
|
||||||
@@ -89,19 +76,55 @@ private:
|
|||||||
fClassificationInfo;
|
fClassificationInfo;
|
||||||
PackageScreenshotInfoRef
|
PackageScreenshotInfoRef
|
||||||
fScreenshotInfo;
|
fScreenshotInfo;
|
||||||
UserRatingInfoRef fUserRatingInfo;
|
PackageUserRatingInfoRef
|
||||||
|
fUserRatingInfo;
|
||||||
PackageLocalInfoRef fLocalInfo;
|
PackageLocalInfoRef fLocalInfo;
|
||||||
|
|
||||||
std::vector<PackageInfoListenerRef>
|
|
||||||
fListeners;
|
|
||||||
bool fIsCollatingChanges;
|
|
||||||
uint32 fCollatedChanges;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef BReference<PackageInfo> PackageInfoRef;
|
typedef BReference<PackageInfo> PackageInfoRef;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageInfoBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PackageInfoBuilder(const BString& name);
|
||||||
|
PackageInfoBuilder(const PackageInfoRef& value);
|
||||||
|
PackageInfoBuilder(const PackageInfo& value);
|
||||||
|
virtual ~PackageInfoBuilder();
|
||||||
|
|
||||||
|
PackageInfoRef BuildRef();
|
||||||
|
|
||||||
|
PackageInfoBuilder&
|
||||||
|
WithCoreInfo(PackageCoreInfoRef value);
|
||||||
|
PackageInfoBuilder&
|
||||||
|
WithLocalizedText(PackageLocalizedTextRef value);
|
||||||
|
PackageInfoBuilder&
|
||||||
|
WithPackageClassificationInfo(PackageClassificationInfoRef value);
|
||||||
|
PackageInfoBuilder&
|
||||||
|
WithUserRatingInfo(PackageUserRatingInfoRef userRatingInfo);
|
||||||
|
PackageInfoBuilder&
|
||||||
|
WithLocalInfo(PackageLocalInfoRef localInfo);
|
||||||
|
PackageInfoBuilder&
|
||||||
|
WithScreenshotInfo(PackageScreenshotInfoRef value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _Init(const PackageInfo* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BString fName;
|
||||||
|
|
||||||
|
PackageCoreInfoRef fCoreInfo;
|
||||||
|
PackageLocalizedTextRef
|
||||||
|
fLocalizedText;
|
||||||
|
PackageClassificationInfoRef
|
||||||
|
fClassificationInfo;
|
||||||
|
PackageScreenshotInfoRef
|
||||||
|
fScreenshotInfo;
|
||||||
|
PackageUserRatingInfoRef
|
||||||
|
fUserRatingInfo;
|
||||||
|
PackageLocalInfoRef fLocalInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_INFO_H
|
#endif // PACKAGE_INFO_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -49,23 +49,6 @@ PackageLocalInfo::~PackageLocalInfo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageLocalInfo&
|
|
||||||
PackageLocalInfo::operator=(const PackageLocalInfo& other)
|
|
||||||
{
|
|
||||||
fState = other.fState;
|
|
||||||
fInstallationLocations = other.fInstallationLocations;
|
|
||||||
fDownloadProgress = other.fDownloadProgress;
|
|
||||||
fFlags = other.fFlags;
|
|
||||||
fSystemDependency = other.fSystemDependency;
|
|
||||||
fLocalFilePath = other.fLocalFilePath;
|
|
||||||
fFileName = other.fFileName;
|
|
||||||
fSize = other.fSize;
|
|
||||||
fViewed = other.fViewed;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PackageLocalInfo::operator==(const PackageLocalInfo& other) const
|
PackageLocalInfo::operator==(const PackageLocalInfo& other) const
|
||||||
{
|
{
|
||||||
@@ -88,6 +71,69 @@ PackageLocalInfo::operator!=(const PackageLocalInfo& other) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageLocalInfo::Viewed() const
|
||||||
|
{
|
||||||
|
return fViewed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BString&
|
||||||
|
PackageLocalInfo::LocalFilePath() const
|
||||||
|
{
|
||||||
|
return fLocalFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BString&
|
||||||
|
PackageLocalInfo::FileName() const
|
||||||
|
{
|
||||||
|
return fFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
off_t
|
||||||
|
PackageLocalInfo::Size() const
|
||||||
|
{
|
||||||
|
return fSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PackageLocalInfo::Flags() const
|
||||||
|
{
|
||||||
|
return fFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageLocalInfo::IsSystemDependency() const
|
||||||
|
{
|
||||||
|
return fSystemDependency;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageState
|
||||||
|
PackageLocalInfo::State() const
|
||||||
|
{
|
||||||
|
return fState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackageInstallationLocationSet&
|
||||||
|
PackageLocalInfo::InstallationLocations() const
|
||||||
|
{
|
||||||
|
return fInstallationLocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
PackageLocalInfo::DownloadProgress() const
|
||||||
|
{
|
||||||
|
return fDownloadProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PackageLocalInfo::IsSystemPackage() const
|
PackageLocalInfo::IsSystemPackage() const
|
||||||
{
|
{
|
||||||
@@ -122,10 +168,17 @@ PackageLocalInfo::AddInstallationLocation(int32 location)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
bool
|
||||||
PackageLocalInfo::ClearInstallationLocations()
|
PackageLocalInfo::HasInstallationLocation(int32 location) const
|
||||||
{
|
{
|
||||||
fInstallationLocations.clear();
|
return fInstallationLocations.find(location) != fInstallationLocations.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PackageLocalInfo::CountInstallationLocations() const
|
||||||
|
{
|
||||||
|
return static_cast<int32>(fInstallationLocations.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -177,3 +230,211 @@ PackageLocalInfo::SetFileName(const BString& value)
|
|||||||
{
|
{
|
||||||
fFileName = value;
|
fFileName = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageLocalInfoBuilder
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder::PackageLocalInfoBuilder()
|
||||||
|
:
|
||||||
|
fViewed(false),
|
||||||
|
fLocalFilePath(),
|
||||||
|
fFileName(),
|
||||||
|
fSize(0),
|
||||||
|
fFlags(0),
|
||||||
|
fSystemDependency(false),
|
||||||
|
fState(NONE),
|
||||||
|
fInstallationLocations(),
|
||||||
|
fDownloadProgress(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder::PackageLocalInfoBuilder(const PackageLocalInfoRef& value)
|
||||||
|
:
|
||||||
|
fViewed(false),
|
||||||
|
fLocalFilePath(),
|
||||||
|
fFileName(),
|
||||||
|
fSize(0),
|
||||||
|
fFlags(0),
|
||||||
|
fSystemDependency(false),
|
||||||
|
fState(NONE),
|
||||||
|
fInstallationLocations(),
|
||||||
|
fDownloadProgress(0.0)
|
||||||
|
{
|
||||||
|
fSource = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder::~PackageLocalInfoBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageLocalInfoBuilder::_InitFromSource()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet()) {
|
||||||
|
_Init(fSource);
|
||||||
|
fSource.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageLocalInfoBuilder::_Init(const PackageLocalInfo* value)
|
||||||
|
{
|
||||||
|
fViewed = value->Viewed();
|
||||||
|
fLocalFilePath = value->LocalFilePath();
|
||||||
|
fFileName = value->FileName();
|
||||||
|
fSize = value->Size();
|
||||||
|
fFlags = value->Flags();
|
||||||
|
fSystemDependency = value->IsSystemDependency();
|
||||||
|
fState = value->State();
|
||||||
|
fDownloadProgress = value->DownloadProgress();
|
||||||
|
|
||||||
|
PackageInstallationLocationSet valueLocations = value->InstallationLocations();
|
||||||
|
PackageInstallationLocationSet::const_iterator it;
|
||||||
|
|
||||||
|
for (it = valueLocations.begin(); it != valueLocations.end(); it++)
|
||||||
|
fInstallationLocations.insert(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoRef
|
||||||
|
PackageLocalInfoBuilder::BuildRef()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
return fSource;
|
||||||
|
|
||||||
|
PackageLocalInfo* localInfo = new PackageLocalInfo();
|
||||||
|
|
||||||
|
if (fViewed)
|
||||||
|
localInfo->SetViewed();
|
||||||
|
|
||||||
|
localInfo->SetLocalFilePath(fLocalFilePath);
|
||||||
|
localInfo->SetFileName(fFileName);
|
||||||
|
localInfo->SetSize(fSize);
|
||||||
|
localInfo->SetFlags(fFlags);
|
||||||
|
localInfo->SetSystemDependency(fSystemDependency);
|
||||||
|
localInfo->SetState(fState);
|
||||||
|
if (fState == DOWNLOADING)
|
||||||
|
localInfo->SetDownloadProgress(fDownloadProgress);
|
||||||
|
|
||||||
|
PackageInstallationLocationSet::const_iterator it;
|
||||||
|
|
||||||
|
for (it = fInstallationLocations.begin(); it != fInstallationLocations.end(); it++)
|
||||||
|
localInfo->AddInstallationLocation(*it);
|
||||||
|
|
||||||
|
return PackageLocalInfoRef(localInfo, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::WithViewed()
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Viewed()) {
|
||||||
|
_InitFromSource();
|
||||||
|
fViewed = true;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::WithLocalFilePath(const char* path)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->LocalFilePath() != path) {
|
||||||
|
_InitFromSource();
|
||||||
|
fLocalFilePath.SetTo(path);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::WithFileName(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->FileName() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fFileName.SetTo(value);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::WithSize(off_t size)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Size() != size) {
|
||||||
|
_InitFromSource();
|
||||||
|
fSize = size;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::WithFlags(int32 value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Flags() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fFlags = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::WithSystemDependency(bool value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->IsSystemDependency() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fSystemDependency = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::WithState(PackageState value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->State() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fState = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::WithDownloadProgress(float value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->DownloadProgress() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fDownloadProgress = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::AddInstallationLocation(int32 value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || !fSource->HasInstallationLocation(value)) {
|
||||||
|
_InitFromSource();
|
||||||
|
fInstallationLocations.insert(value);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
PackageLocalInfoBuilder::ClearInstallationLocations()
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->CountInstallationLocations() != 0) {
|
||||||
|
_InitFromSource();
|
||||||
|
fInstallationLocations.clear();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_LOCAL_INFO_H
|
#ifndef PACKAGE_LOCAL_INFO_H
|
||||||
@@ -27,58 +27,49 @@ enum PackageState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PackageLocalInfoBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
/*! Instances of this class should not be created directly; instead use the
|
||||||
|
PackageLocalInfoBuilder class as a builder-constructor.
|
||||||
|
*/
|
||||||
class PackageLocalInfo : public BReferenceable
|
class PackageLocalInfo : public BReferenceable
|
||||||
{
|
{
|
||||||
|
friend class PackageLocalInfoBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PackageLocalInfo();
|
PackageLocalInfo();
|
||||||
PackageLocalInfo(const PackageLocalInfo& other);
|
PackageLocalInfo(const PackageLocalInfo& other);
|
||||||
virtual ~PackageLocalInfo();
|
virtual ~PackageLocalInfo();
|
||||||
|
|
||||||
PackageLocalInfo& operator=(const PackageLocalInfo& other);
|
|
||||||
bool operator==(const PackageLocalInfo& other) const;
|
bool operator==(const PackageLocalInfo& other) const;
|
||||||
bool operator!=(const PackageLocalInfo& other) const;
|
bool operator!=(const PackageLocalInfo& other) const;
|
||||||
|
|
||||||
bool IsLocalFile() const;
|
bool IsLocalFile() const;
|
||||||
|
bool Viewed() const;
|
||||||
void SetViewed();
|
const BString& LocalFilePath() const;
|
||||||
bool Viewed() const
|
const BString& FileName() const;
|
||||||
{ return fViewed; }
|
off_t Size() const;
|
||||||
|
int32 Flags() const;
|
||||||
void SetLocalFilePath(const char* path);
|
|
||||||
const BString& LocalFilePath() const
|
|
||||||
{ return fLocalFilePath; }
|
|
||||||
|
|
||||||
void SetFileName(const BString& value);
|
|
||||||
const BString& FileName() const
|
|
||||||
{ return fFileName; }
|
|
||||||
|
|
||||||
void SetSize(off_t size);
|
|
||||||
off_t Size() const
|
|
||||||
{ return fSize; }
|
|
||||||
|
|
||||||
void SetFlags(int32 value);
|
|
||||||
int32 Flags() const
|
|
||||||
{ return fFlags; }
|
|
||||||
|
|
||||||
bool IsSystemPackage() const;
|
bool IsSystemPackage() const;
|
||||||
|
bool IsSystemDependency() const;
|
||||||
void SetSystemDependency(bool isDependency);
|
PackageState State() const;
|
||||||
bool IsSystemDependency() const
|
bool HasInstallationLocation(int32 location) const;
|
||||||
{ return fSystemDependency; }
|
int32 CountInstallationLocations() const;
|
||||||
|
|
||||||
void SetState(PackageState state);
|
|
||||||
PackageState State() const
|
|
||||||
{ return fState; }
|
|
||||||
|
|
||||||
void AddInstallationLocation(int32 location);
|
|
||||||
const PackageInstallationLocationSet&
|
const PackageInstallationLocationSet&
|
||||||
InstallationLocations() const
|
InstallationLocations() const;
|
||||||
{ return fInstallationLocations; }
|
float DownloadProgress() const;
|
||||||
void ClearInstallationLocations();
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetViewed();
|
||||||
|
void SetLocalFilePath(const char* path);
|
||||||
|
void SetFileName(const BString& value);
|
||||||
|
void SetSize(off_t size);
|
||||||
|
void SetFlags(int32 value);
|
||||||
|
void SetSystemDependency(bool isDependency);
|
||||||
|
void SetState(PackageState state);
|
||||||
|
void AddInstallationLocation(int32 location);
|
||||||
void SetDownloadProgress(float progress);
|
void SetDownloadProgress(float progress);
|
||||||
float DownloadProgress() const
|
|
||||||
{ return fDownloadProgress; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool fViewed;
|
bool fViewed;
|
||||||
@@ -97,4 +88,56 @@ private:
|
|||||||
typedef BReference<PackageLocalInfo> PackageLocalInfoRef;
|
typedef BReference<PackageLocalInfo> PackageLocalInfoRef;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageLocalInfoBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PackageLocalInfoBuilder();
|
||||||
|
PackageLocalInfoBuilder(const PackageLocalInfoRef& value);
|
||||||
|
virtual ~PackageLocalInfoBuilder();
|
||||||
|
|
||||||
|
PackageLocalInfoRef BuildRef();
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
WithViewed();
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
WithLocalFilePath(const char* path);
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
WithFileName(const BString& value);
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
WithSize(off_t size);
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
WithFlags(int32 value);
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
WithSystemDependency(bool isDependency);
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
WithState(PackageState state);
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
WithDownloadProgress(float progress);
|
||||||
|
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
AddInstallationLocation(int32 location);
|
||||||
|
PackageLocalInfoBuilder&
|
||||||
|
ClearInstallationLocations();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitFromSource();
|
||||||
|
void _Init(const PackageLocalInfo* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageLocalInfoRef fSource;
|
||||||
|
bool fViewed;
|
||||||
|
BString fLocalFilePath;
|
||||||
|
BString fFileName;
|
||||||
|
off_t fSize;
|
||||||
|
int32 fFlags;
|
||||||
|
bool fSystemDependency;
|
||||||
|
// When true, this value indicates that the package is a dependency of the
|
||||||
|
// system and so cannot be uninstalled.
|
||||||
|
PackageState fState;
|
||||||
|
PackageInstallationLocationSet
|
||||||
|
fInstallationLocations;
|
||||||
|
float fDownloadProgress;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_LOCAL_INFO_H
|
#endif // PACKAGE_LOCAL_INFO_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -117,3 +117,127 @@ PackageLocalizedText::operator!=(const PackageLocalizedText& other) const
|
|||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageLocalInfoBuilder
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalizedTextBuilder::PackageLocalizedTextBuilder()
|
||||||
|
:
|
||||||
|
fTitle(),
|
||||||
|
fSummary(),
|
||||||
|
fDescription(),
|
||||||
|
fHasChangelog(false),
|
||||||
|
fChangelog()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalizedTextBuilder::PackageLocalizedTextBuilder(const PackageLocalizedTextRef& value)
|
||||||
|
:
|
||||||
|
fTitle(),
|
||||||
|
fSummary(),
|
||||||
|
fDescription(),
|
||||||
|
fHasChangelog(false),
|
||||||
|
fChangelog()
|
||||||
|
{
|
||||||
|
fSource = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalizedTextBuilder::~PackageLocalizedTextBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageLocalizedTextBuilder::_InitFromSource()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet()) {
|
||||||
|
_Init(fSource);
|
||||||
|
fSource.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageLocalizedTextBuilder::_Init(const PackageLocalizedText* value)
|
||||||
|
{
|
||||||
|
fTitle = value->Title();
|
||||||
|
fSummary = value->Summary();
|
||||||
|
fDescription = value->Description();
|
||||||
|
fHasChangelog = value->HasChangelog();
|
||||||
|
fChangelog = value->Changelog();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalizedTextRef
|
||||||
|
PackageLocalizedTextBuilder::BuildRef()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
return fSource;
|
||||||
|
|
||||||
|
PackageLocalizedText* localizedText = new PackageLocalizedText();
|
||||||
|
localizedText->SetTitle(fTitle);
|
||||||
|
localizedText->SetSummary(fSummary);
|
||||||
|
localizedText->SetDescription(fDescription);
|
||||||
|
localizedText->SetHasChangelog(fHasChangelog);
|
||||||
|
localizedText->SetChangelog(fChangelog);
|
||||||
|
|
||||||
|
return PackageLocalizedTextRef(localizedText, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
PackageLocalizedTextBuilder::WithTitle(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Title() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fTitle = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
PackageLocalizedTextBuilder::WithSummary(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Summary() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fSummary = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
PackageLocalizedTextBuilder::WithDescription(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Description() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fDescription = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
PackageLocalizedTextBuilder::WithHasChangelog(bool value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->HasChangelog() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fHasChangelog = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
PackageLocalizedTextBuilder::WithChangelog(const BString& value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Changelog() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fChangelog = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_LOCALIZED_TEXT_H
|
#ifndef PACKAGE_LOCALIZED_TEXT_H
|
||||||
@@ -10,30 +10,37 @@
|
|||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
|
class PackageLocalizedTextBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
/*! Instances of this class should not be created directly; instead use the
|
||||||
|
PackageLocalizedTextBuilder class as a builder-constructor.
|
||||||
|
*/
|
||||||
class PackageLocalizedText : public BReferenceable
|
class PackageLocalizedText : public BReferenceable
|
||||||
{
|
{
|
||||||
|
friend class PackageLocalizedTextBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PackageLocalizedText();
|
PackageLocalizedText();
|
||||||
PackageLocalizedText(const PackageLocalizedText& other);
|
PackageLocalizedText(const PackageLocalizedText& other);
|
||||||
|
|
||||||
const BString& Title() const;
|
|
||||||
void SetTitle(const BString& value);
|
|
||||||
|
|
||||||
const BString& Summary() const;
|
|
||||||
void SetSummary(const BString& value);
|
|
||||||
|
|
||||||
const BString& Description() const;
|
|
||||||
void SetDescription(const BString& value);
|
|
||||||
|
|
||||||
const bool HasChangelog() const;
|
|
||||||
void SetHasChangelog(bool value);
|
|
||||||
|
|
||||||
void SetChangelog(const BString& value);
|
|
||||||
const BString& Changelog() const;
|
|
||||||
|
|
||||||
bool operator==(const PackageLocalizedText& other) const;
|
bool operator==(const PackageLocalizedText& other) const;
|
||||||
bool operator!=(const PackageLocalizedText& other) const;
|
bool operator!=(const PackageLocalizedText& other) const;
|
||||||
|
|
||||||
|
const BString& Title() const;
|
||||||
|
const BString& Summary() const;
|
||||||
|
const BString& Description() const;
|
||||||
|
const bool HasChangelog() const;
|
||||||
|
const BString& Changelog() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void SetTitle(const BString& value);
|
||||||
|
void SetSummary(const BString& value);
|
||||||
|
void SetDescription(const BString& value);
|
||||||
|
void SetHasChangelog(bool value);
|
||||||
|
void SetChangelog(const BString& value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BString fTitle;
|
BString fTitle;
|
||||||
BString fSummary;
|
BString fSummary;
|
||||||
@@ -47,4 +54,40 @@ private:
|
|||||||
typedef BReference<PackageLocalizedText> PackageLocalizedTextRef;
|
typedef BReference<PackageLocalizedText> PackageLocalizedTextRef;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageLocalizedTextBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PackageLocalizedTextBuilder();
|
||||||
|
PackageLocalizedTextBuilder(const PackageLocalizedTextRef& value);
|
||||||
|
virtual ~PackageLocalizedTextBuilder();
|
||||||
|
|
||||||
|
PackageLocalizedTextRef
|
||||||
|
BuildRef();
|
||||||
|
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
WithTitle(const BString& value);
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
WithSummary(const BString& value);
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
WithDescription(const BString& value);
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
WithHasChangelog(bool value);
|
||||||
|
PackageLocalizedTextBuilder&
|
||||||
|
WithChangelog(const BString& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitFromSource();
|
||||||
|
void _Init(const PackageLocalizedText* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageLocalizedTextRef
|
||||||
|
fSource;
|
||||||
|
BString fTitle;
|
||||||
|
BString fSummary;
|
||||||
|
BString fDescription;
|
||||||
|
bool fHasChangelog;
|
||||||
|
BString fChangelog;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_LOCALIZED_TEXT_H
|
#endif // PACKAGE_LOCALIZED_TEXT_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_PUBLISHER_INFO_H
|
#ifndef PACKAGE_PUBLISHER_INFO_H
|
||||||
@@ -33,6 +33,8 @@ private:
|
|||||||
BString fWebsite;
|
BString fWebsite;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef BReference<PackagePublisherInfo> PackagePublisherInfoRef;
|
typedef BReference<PackagePublisherInfo> PackagePublisherInfoRef;
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_PUBLISHER_INFO_H
|
#endif // PACKAGE_PUBLISHER_INFO_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -19,14 +19,6 @@ PackageScreenshotInfo::PackageScreenshotInfo(const PackageScreenshotInfo& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageScreenshotInfo&
|
|
||||||
PackageScreenshotInfo::operator=(const PackageScreenshotInfo& other)
|
|
||||||
{
|
|
||||||
fScreenshotInfos = other.fScreenshotInfos;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PackageScreenshotInfo::operator==(const PackageScreenshotInfo& other) const
|
PackageScreenshotInfo::operator==(const PackageScreenshotInfo& other) const
|
||||||
{
|
{
|
||||||
@@ -41,13 +33,6 @@ PackageScreenshotInfo::operator!=(const PackageScreenshotInfo& other) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PackageScreenshotInfo::Clear()
|
|
||||||
{
|
|
||||||
fScreenshotInfos.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
PackageScreenshotInfo::Count() const
|
PackageScreenshotInfo::Count() const
|
||||||
{
|
{
|
||||||
@@ -55,7 +40,7 @@ PackageScreenshotInfo::Count() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ScreenshotInfoRef
|
const ScreenshotInfoRef
|
||||||
PackageScreenshotInfo::ScreenshotAtIndex(int32 index) const
|
PackageScreenshotInfo::ScreenshotAtIndex(int32 index) const
|
||||||
{
|
{
|
||||||
return fScreenshotInfos[index];
|
return fScreenshotInfos[index];
|
||||||
@@ -66,4 +51,73 @@ void
|
|||||||
PackageScreenshotInfo::AddScreenshot(const ScreenshotInfoRef& info)
|
PackageScreenshotInfo::AddScreenshot(const ScreenshotInfoRef& info)
|
||||||
{
|
{
|
||||||
fScreenshotInfos.push_back(info);
|
fScreenshotInfos.push_back(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageScreenshotInfoBuilder
|
||||||
|
|
||||||
|
|
||||||
|
PackageScreenshotInfoBuilder::PackageScreenshotInfoBuilder()
|
||||||
|
:
|
||||||
|
fSource(),
|
||||||
|
fScreenshotInfos()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageScreenshotInfoBuilder::PackageScreenshotInfoBuilder(const PackageScreenshotInfoRef& other)
|
||||||
|
:
|
||||||
|
fScreenshotInfos()
|
||||||
|
{
|
||||||
|
fSource = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageScreenshotInfoBuilder::~PackageScreenshotInfoBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageScreenshotInfoBuilder::_InitFromSource()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet()) {
|
||||||
|
_Init(fSource.Get());
|
||||||
|
fSource.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageScreenshotInfoBuilder::_Init(const PackageScreenshotInfo* value)
|
||||||
|
{
|
||||||
|
int32 count = value->Count();
|
||||||
|
for (int32 i = 0; i < count; i++)
|
||||||
|
fScreenshotInfos.push_back(value->ScreenshotAtIndex(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageScreenshotInfoRef
|
||||||
|
PackageScreenshotInfoBuilder::BuildRef()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
return fSource;
|
||||||
|
|
||||||
|
PackageScreenshotInfo* screenshotInfo = new PackageScreenshotInfo();
|
||||||
|
|
||||||
|
std::vector<ScreenshotInfoRef>::const_iterator it;
|
||||||
|
for (it = fScreenshotInfos.begin(); it != fScreenshotInfos.end(); it++)
|
||||||
|
screenshotInfo->AddScreenshot(*it);
|
||||||
|
|
||||||
|
return PackageScreenshotInfoRef(screenshotInfo, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageScreenshotInfoBuilder&
|
||||||
|
PackageScreenshotInfoBuilder::AddScreenshot(const ScreenshotInfoRef& value)
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
_InitFromSource();
|
||||||
|
fScreenshotInfos.push_back(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_SCREENSHOT_INFO_H
|
#ifndef PACKAGE_SCREENSHOT_INFO_H
|
||||||
@@ -14,21 +14,28 @@
|
|||||||
#include "ScreenshotInfo.h"
|
#include "ScreenshotInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
class PackageScreenshotInfoBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
/*! Instances of this class should not be created directly; instead use the
|
||||||
|
PackageScreenshotInfoBuilder class as a builder-constructor.
|
||||||
|
*/
|
||||||
class PackageScreenshotInfo : public BReferenceable
|
class PackageScreenshotInfo : public BReferenceable
|
||||||
{
|
{
|
||||||
|
friend class PackageScreenshotInfoBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PackageScreenshotInfo();
|
PackageScreenshotInfo();
|
||||||
PackageScreenshotInfo(const PackageScreenshotInfo& other);
|
PackageScreenshotInfo(const PackageScreenshotInfo& other);
|
||||||
|
|
||||||
PackageScreenshotInfo&
|
|
||||||
operator=(const PackageScreenshotInfo& other);
|
|
||||||
bool operator==(const PackageScreenshotInfo& other) const;
|
bool operator==(const PackageScreenshotInfo& other) const;
|
||||||
bool operator!=(const PackageScreenshotInfo& other) const;
|
bool operator!=(const PackageScreenshotInfo& other) const;
|
||||||
|
|
||||||
void Clear();
|
|
||||||
void AddScreenshot(const ScreenshotInfoRef& info);
|
|
||||||
int32 Count() const;
|
int32 Count() const;
|
||||||
ScreenshotInfoRef ScreenshotAtIndex(int32 index) const;
|
const ScreenshotInfoRef ScreenshotAtIndex(int32 index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AddScreenshot(const ScreenshotInfoRef& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ScreenshotInfoRef>
|
std::vector<ScreenshotInfoRef>
|
||||||
@@ -39,4 +46,29 @@ private:
|
|||||||
typedef BReference<PackageScreenshotInfo> PackageScreenshotInfoRef;
|
typedef BReference<PackageScreenshotInfo> PackageScreenshotInfoRef;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageScreenshotInfoBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PackageScreenshotInfoBuilder();
|
||||||
|
PackageScreenshotInfoBuilder(const PackageScreenshotInfoRef& other);
|
||||||
|
virtual ~PackageScreenshotInfoBuilder();
|
||||||
|
|
||||||
|
PackageScreenshotInfoRef
|
||||||
|
BuildRef();
|
||||||
|
|
||||||
|
PackageScreenshotInfoBuilder&
|
||||||
|
AddScreenshot(const ScreenshotInfoRef& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitFromSource();
|
||||||
|
void _Init(const PackageScreenshotInfo* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageScreenshotInfoRef
|
||||||
|
fSource;
|
||||||
|
std::vector<ScreenshotInfoRef>
|
||||||
|
fScreenshotInfos;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_SCREENSHOT_INFO_H
|
#endif // PACKAGE_SCREENSHOT_INFO_H
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "PackageUserRatingInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
PackageUserRatingInfo::PackageUserRatingInfo()
|
||||||
|
:
|
||||||
|
fUserRatings(),
|
||||||
|
fSummary(),
|
||||||
|
fUserRatingsPopulated(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageUserRatingInfo::PackageUserRatingInfo(const PackageUserRatingInfo& other)
|
||||||
|
:
|
||||||
|
fSummary(other.Summary()),
|
||||||
|
fUserRatingsPopulated(other.UserRatingsPopulated())
|
||||||
|
{
|
||||||
|
for (int32 i = CountUserRatings() - 1; i >= 0; i--)
|
||||||
|
AddUserRating(other.UserRatingAtIndex(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const UserRatingSummaryRef
|
||||||
|
PackageUserRatingInfo::Summary() const
|
||||||
|
{
|
||||||
|
return fSummary;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageUserRatingInfo::SetSummary(UserRatingSummaryRef value)
|
||||||
|
{
|
||||||
|
fSummary = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageUserRatingInfo::SetUserRatingsPopulated()
|
||||||
|
{
|
||||||
|
fUserRatingsPopulated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageUserRatingInfo::UserRatingsPopulated() const
|
||||||
|
{
|
||||||
|
return fUserRatingsPopulated;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PackageUserRatingInfo::CountUserRatings() const
|
||||||
|
{
|
||||||
|
return fUserRatings.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const UserRatingRef
|
||||||
|
PackageUserRatingInfo::UserRatingAtIndex(int32 index) const
|
||||||
|
{
|
||||||
|
return fUserRatings[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageUserRatingInfo::AddUserRating(const UserRatingRef& rating)
|
||||||
|
{
|
||||||
|
fUserRatings.push_back(rating);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageUserRatingInfo::operator==(const PackageUserRatingInfo& other) const
|
||||||
|
{
|
||||||
|
if (Summary() != other.Summary())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (UserRatingsPopulated() != other.UserRatingsPopulated())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (CountUserRatings() != other.CountUserRatings())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int32 i = CountUserRatings() - 1; i >= 0; i--) {
|
||||||
|
if (other.UserRatingAtIndex(i) != UserRatingAtIndex(i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageUserRatingInfo::operator!=(const PackageUserRatingInfo& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageUserRatingInfoBuilder
|
||||||
|
|
||||||
|
|
||||||
|
PackageUserRatingInfoBuilder::PackageUserRatingInfoBuilder()
|
||||||
|
:
|
||||||
|
fSource(),
|
||||||
|
fUserRatings(),
|
||||||
|
fSummary(),
|
||||||
|
fUserRatingsPopulated(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageUserRatingInfoBuilder::PackageUserRatingInfoBuilder(const PackageUserRatingInfoRef& other)
|
||||||
|
:
|
||||||
|
fSource(other),
|
||||||
|
fUserRatings(),
|
||||||
|
fSummary(),
|
||||||
|
fUserRatingsPopulated(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageUserRatingInfoBuilder::~PackageUserRatingInfoBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageUserRatingInfoRef
|
||||||
|
PackageUserRatingInfoBuilder::BuildRef()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
return fSource;
|
||||||
|
|
||||||
|
PackageUserRatingInfo* userRatingInfo = new PackageUserRatingInfo();
|
||||||
|
|
||||||
|
userRatingInfo->SetSummary(fSummary);
|
||||||
|
|
||||||
|
if (fUserRatingsPopulated)
|
||||||
|
userRatingInfo->SetUserRatingsPopulated();
|
||||||
|
|
||||||
|
std::vector<UserRatingRef>::const_iterator it;
|
||||||
|
for (it = fUserRatings.begin(); it != fUserRatings.end(); it++)
|
||||||
|
userRatingInfo->AddUserRating(*it);
|
||||||
|
|
||||||
|
return PackageUserRatingInfoRef(userRatingInfo, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageUserRatingInfoBuilder&
|
||||||
|
PackageUserRatingInfoBuilder::AddUserRating(const UserRatingRef& rating)
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
_InitFromSource();
|
||||||
|
fUserRatings.push_back(rating);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageUserRatingInfoBuilder&
|
||||||
|
PackageUserRatingInfoBuilder::WithSummary(UserRatingSummaryRef value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->Summary() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fSummary = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageUserRatingInfoBuilder&
|
||||||
|
PackageUserRatingInfoBuilder::WithUserRatingsPopulated()
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || !fSource->UserRatingsPopulated()) {
|
||||||
|
_InitFromSource();
|
||||||
|
fUserRatingsPopulated = true;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageUserRatingInfoBuilder::_InitFromSource()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet()) {
|
||||||
|
_Init(fSource.Get());
|
||||||
|
fSource.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageUserRatingInfoBuilder::_Init(const PackageUserRatingInfo* value)
|
||||||
|
{
|
||||||
|
fSummary = value->Summary();
|
||||||
|
fUserRatingsPopulated = value->UserRatingsPopulated();
|
||||||
|
|
||||||
|
int32 count = value->CountUserRatings();
|
||||||
|
for (int32 i = 0; i < count; i++)
|
||||||
|
fUserRatings.push_back(value->UserRatingAtIndex(i));
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef PACKAGE_USER_RATING_INFO_H
|
||||||
|
#define PACKAGE_USER_RATING_INFO_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include "UserRating.h"
|
||||||
|
#include "UserRatingSummary.h"
|
||||||
|
|
||||||
|
|
||||||
|
class PackageUserRatingInfoBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
/*! This class carries the collection of user ratings related to a package but
|
||||||
|
also provides an instance of `UserRatingSummaryRef` which is a summary of
|
||||||
|
the user ratings.
|
||||||
|
|
||||||
|
Instances of this class should not be created directly; instead use the
|
||||||
|
PackageUserRatingInfoBuilder class as a builder-constructor.
|
||||||
|
*/
|
||||||
|
class PackageUserRatingInfo : public BReferenceable
|
||||||
|
{
|
||||||
|
friend class PackageUserRatingInfoBuilder;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PackageUserRatingInfo();
|
||||||
|
PackageUserRatingInfo(const PackageUserRatingInfo& other);
|
||||||
|
|
||||||
|
bool operator==(const PackageUserRatingInfo& other) const;
|
||||||
|
bool operator!=(const PackageUserRatingInfo& other) const;
|
||||||
|
|
||||||
|
const UserRatingSummaryRef
|
||||||
|
Summary() const;
|
||||||
|
int32 CountUserRatings() const;
|
||||||
|
const UserRatingRef UserRatingAtIndex(int32 index) const;
|
||||||
|
bool UserRatingsPopulated() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetSummary(UserRatingSummaryRef value);
|
||||||
|
void AddUserRating(const UserRatingRef& rating);
|
||||||
|
void SetUserRatingsPopulated();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<UserRatingRef>
|
||||||
|
fUserRatings;
|
||||||
|
UserRatingSummaryRef
|
||||||
|
fSummary;
|
||||||
|
bool fUserRatingsPopulated;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef BReference<PackageUserRatingInfo> PackageUserRatingInfoRef;
|
||||||
|
|
||||||
|
|
||||||
|
class PackageUserRatingInfoBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PackageUserRatingInfoBuilder();
|
||||||
|
PackageUserRatingInfoBuilder(const PackageUserRatingInfoRef& other);
|
||||||
|
virtual ~PackageUserRatingInfoBuilder();
|
||||||
|
|
||||||
|
PackageUserRatingInfoRef
|
||||||
|
BuildRef();
|
||||||
|
|
||||||
|
PackageUserRatingInfoBuilder&
|
||||||
|
AddUserRating(const UserRatingRef& rating);
|
||||||
|
PackageUserRatingInfoBuilder&
|
||||||
|
WithSummary(UserRatingSummaryRef value);
|
||||||
|
PackageUserRatingInfoBuilder&
|
||||||
|
WithUserRatingsPopulated();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitFromSource();
|
||||||
|
void _Init(const PackageUserRatingInfo* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageUserRatingInfoRef
|
||||||
|
fSource;
|
||||||
|
std::vector<UserRatingRef>
|
||||||
|
fUserRatings;
|
||||||
|
UserRatingSummaryRef
|
||||||
|
fSummary;
|
||||||
|
bool fUserRatingsPopulated;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PACKAGE_USER_RATING_INFO_H
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -15,6 +15,14 @@ PackageVersion::PackageVersion()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageVersion::PackageVersion(uint64 createTimestamp)
|
||||||
|
:
|
||||||
|
BPackageVersion(),
|
||||||
|
fCreateTimestamp(createTimestamp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageVersion::PackageVersion(const PackageVersion& other)
|
PackageVersion::PackageVersion(const PackageVersion& other)
|
||||||
:
|
:
|
||||||
BPackageVersion(other),
|
BPackageVersion(other),
|
||||||
@@ -23,6 +31,14 @@ PackageVersion::PackageVersion(const PackageVersion& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageVersion::PackageVersion(const PackageVersion& other, uint64 createTimestamp)
|
||||||
|
:
|
||||||
|
BPackageVersion(other),
|
||||||
|
fCreateTimestamp(createTimestamp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageVersion::PackageVersion(const BPackageVersion& other)
|
PackageVersion::PackageVersion(const BPackageVersion& other)
|
||||||
:
|
:
|
||||||
BPackageVersion(other),
|
BPackageVersion(other),
|
||||||
@@ -36,22 +52,10 @@ PackageVersion::~PackageVersion()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
uint64
|
||||||
PackageVersion::SetCreateTimestamp(uint64 value)
|
PackageVersion::CreateTimestamp() const
|
||||||
{
|
{
|
||||||
fCreateTimestamp = value;
|
return fCreateTimestamp;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PackageVersion&
|
|
||||||
PackageVersion::operator=(const PackageVersion& other)
|
|
||||||
{
|
|
||||||
if (this != &other) {
|
|
||||||
// can't use BPackageVersion operator= possibly because it is inlined?
|
|
||||||
SetTo(other.Major(), other.Minor(), other.Micro(), other.PreRelease(), other.Revision());
|
|
||||||
fCreateTimestamp = other.fCreateTimestamp;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2024-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKAGE_VERSION_H
|
#ifndef PACKAGE_VERSION_H
|
||||||
@@ -18,17 +18,16 @@ class PackageVersion : public BPackageVersion, public BReferenceable
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PackageVersion();
|
PackageVersion();
|
||||||
|
PackageVersion(uint64 createTimestamp);
|
||||||
PackageVersion(const PackageVersion& other);
|
PackageVersion(const PackageVersion& other);
|
||||||
|
PackageVersion(const PackageVersion& other, uint64 createTimestamp);
|
||||||
PackageVersion(const BPackageVersion& other);
|
PackageVersion(const BPackageVersion& other);
|
||||||
virtual ~PackageVersion();
|
virtual ~PackageVersion();
|
||||||
|
|
||||||
PackageVersion& operator=(const PackageVersion& other);
|
|
||||||
bool operator==(const PackageVersion& other) const;
|
bool operator==(const PackageVersion& other) const;
|
||||||
bool operator!=(const PackageVersion& other) const;
|
bool operator!=(const PackageVersion& other) const;
|
||||||
|
|
||||||
uint64 CreateTimestamp() const
|
uint64 CreateTimestamp() const;
|
||||||
{ return fCreateTimestamp; }
|
|
||||||
void SetCreateTimestamp(uint64 value);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64 fCreateTimestamp;
|
uint64 fCreateTimestamp;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2013, Rene Gollent <[email protected]>.
|
* Copyright 2013, Rene Gollent <[email protected]>.
|
||||||
* Copyright 2016-2023, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -30,14 +30,6 @@ UserInfo::UserInfo(const UserInfo& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UserInfo&
|
|
||||||
UserInfo::operator=(const UserInfo& other)
|
|
||||||
{
|
|
||||||
fNickName = other.fNickName;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
UserInfo::operator==(const UserInfo& other) const
|
UserInfo::operator==(const UserInfo& other) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2023, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef USER_INFO_H
|
#ifndef USER_INFO_H
|
||||||
@@ -16,7 +16,6 @@ public:
|
|||||||
UserInfo(const BString& nickName);
|
UserInfo(const BString& nickName);
|
||||||
UserInfo(const UserInfo& other);
|
UserInfo(const UserInfo& other);
|
||||||
|
|
||||||
UserInfo& operator=(const UserInfo& other);
|
|
||||||
bool operator==(const UserInfo& other) const;
|
bool operator==(const UserInfo& other) const;
|
||||||
bool operator!=(const UserInfo& other) const;
|
bool operator!=(const UserInfo& other) const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2013, Rene Gollent <[email protected]>.
|
* Copyright 2013, Rene Gollent <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -47,19 +47,6 @@ UserRating::UserRating(const UserRating& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UserRating&
|
|
||||||
UserRating::operator=(const UserRating& other)
|
|
||||||
{
|
|
||||||
fUserInfo = other.fUserInfo;
|
|
||||||
fRating = other.fRating;
|
|
||||||
fComment = other.fComment;
|
|
||||||
fLanguageId = other.fLanguageId;
|
|
||||||
fPackageVersion = other.fPackageVersion;
|
|
||||||
fCreateTimestamp = other.fCreateTimestamp;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
UserRating::operator==(const UserRating& other) const
|
UserRating::operator==(const UserRating& other) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef USER_RATING_H
|
#ifndef USER_RATING_H
|
||||||
@@ -23,7 +23,6 @@ public:
|
|||||||
uint64 createTimestamp);
|
uint64 createTimestamp);
|
||||||
UserRating(const UserRating& other);
|
UserRating(const UserRating& other);
|
||||||
|
|
||||||
UserRating& operator=(const UserRating& other);
|
|
||||||
bool operator==(const UserRating& other) const;
|
bool operator==(const UserRating& other) const;
|
||||||
bool operator!=(const UserRating& other) const;
|
bool operator!=(const UserRating& other) const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "UserRatingInfo.h"
|
|
||||||
|
|
||||||
|
|
||||||
UserRatingInfo::UserRatingInfo()
|
|
||||||
:
|
|
||||||
fUserRatings(),
|
|
||||||
fSummary(),
|
|
||||||
fUserRatingsPopulated(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
UserRatingInfo::UserRatingInfo(const UserRatingInfo& other)
|
|
||||||
:
|
|
||||||
fSummary(other.Summary()),
|
|
||||||
fUserRatingsPopulated(other.UserRatingsPopulated())
|
|
||||||
{
|
|
||||||
for (int32 i = CountUserRatings() - 1; i >= 0; i--)
|
|
||||||
AddUserRating(other.UserRatingAtIndex(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
UserRatingInfo::Clear()
|
|
||||||
{
|
|
||||||
fSummary.Unset();
|
|
||||||
ClearUserRatings();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
UserRatingInfo::SetSummary(UserRatingSummaryRef value)
|
|
||||||
{
|
|
||||||
fSummary = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
UserRatingInfo::SetUserRatingsPopulated()
|
|
||||||
{
|
|
||||||
fUserRatingsPopulated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
UserRatingInfo::UserRatingsPopulated() const
|
|
||||||
{
|
|
||||||
return fUserRatingsPopulated;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
UserRatingInfo::ClearUserRatings()
|
|
||||||
{
|
|
||||||
fUserRatings.clear();
|
|
||||||
fUserRatingsPopulated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
UserRatingInfo::CountUserRatings() const
|
|
||||||
{
|
|
||||||
return fUserRatings.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
UserRatingRef
|
|
||||||
UserRatingInfo::UserRatingAtIndex(int32 index) const
|
|
||||||
{
|
|
||||||
return fUserRatings[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
UserRatingInfo::AddUserRating(const UserRatingRef& rating)
|
|
||||||
{
|
|
||||||
fUserRatings.push_back(rating);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
UserRatingInfo&
|
|
||||||
UserRatingInfo::operator=(const UserRatingInfo& other)
|
|
||||||
{
|
|
||||||
fSummary = other.Summary();
|
|
||||||
|
|
||||||
fUserRatings.clear();
|
|
||||||
|
|
||||||
fUserRatingsPopulated = other.UserRatingsPopulated();
|
|
||||||
|
|
||||||
for (int32 i = CountUserRatings() - 1; i >= 0; i--)
|
|
||||||
AddUserRating(other.UserRatingAtIndex(i));
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
UserRatingInfo::operator==(const UserRatingInfo& other) const
|
|
||||||
{
|
|
||||||
if (Summary() != other.Summary())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (UserRatingsPopulated() != other.UserRatingsPopulated())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (CountUserRatings() != other.CountUserRatings())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (int32 i = CountUserRatings() - 1; i >= 0; i--) {
|
|
||||||
if (other.UserRatingAtIndex(i) != UserRatingAtIndex(i))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
UserRatingInfo::operator!=(const UserRatingInfo& other) const
|
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024, Andrew Lindesay <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef USER_RATING_INFO_H
|
|
||||||
#define USER_RATING_INFO_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <Referenceable.h>
|
|
||||||
|
|
||||||
#include "UserRating.h"
|
|
||||||
#include "UserRatingSummary.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*! This class carries the collection of user ratings related to a package but also provides
|
|
||||||
an instance of `UserRatingSummaryRef` which is a summary of the user ratings.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class UserRatingInfo : public BReferenceable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
UserRatingInfo();
|
|
||||||
UserRatingInfo(const UserRatingInfo& other);
|
|
||||||
|
|
||||||
void Clear();
|
|
||||||
|
|
||||||
const UserRatingSummaryRef
|
|
||||||
Summary() const
|
|
||||||
{ return fSummary; }
|
|
||||||
void SetSummary(UserRatingSummaryRef value);
|
|
||||||
|
|
||||||
void ClearUserRatings();
|
|
||||||
void AddUserRating(const UserRatingRef& rating);
|
|
||||||
int32 CountUserRatings() const;
|
|
||||||
UserRatingRef UserRatingAtIndex(int32 index) const;
|
|
||||||
|
|
||||||
void SetUserRatingsPopulated();
|
|
||||||
bool UserRatingsPopulated() const;
|
|
||||||
|
|
||||||
UserRatingInfo& operator=(const UserRatingInfo& other);
|
|
||||||
bool operator==(const UserRatingInfo& other) const;
|
|
||||||
bool operator!=(const UserRatingInfo& other) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<UserRatingRef>
|
|
||||||
fUserRatings;
|
|
||||||
UserRatingSummaryRef
|
|
||||||
fSummary;
|
|
||||||
bool fUserRatingsPopulated;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef BReference<UserRatingInfo> UserRatingInfoRef;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // USER_RATING_SUMMARY_H
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2013, Rene Gollent <[email protected]>.
|
* Copyright 2013, Rene Gollent <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ UserRatingSummary::UserRatingSummary()
|
|||||||
fRatingCount(0),
|
fRatingCount(0),
|
||||||
fRatingCountNoStar(0)
|
fRatingCountNoStar(0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i <= 5; i++)
|
||||||
fRatingCountByStar[i] = 0;
|
fRatingCountByStar[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,15 +34,17 @@ UserRatingSummary::UserRatingSummary(const UserRatingSummary& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
float
|
||||||
UserRatingSummary::Clear()
|
UserRatingSummary::AverageRating() const
|
||||||
{
|
{
|
||||||
fAverageRating = RATING_MISSING;
|
return fAverageRating;
|
||||||
fRatingCount = 0;
|
}
|
||||||
fRatingCountNoStar = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++)
|
|
||||||
fRatingCountByStar[i] = 0;
|
int
|
||||||
|
UserRatingSummary::RatingCount() const
|
||||||
|
{
|
||||||
|
return fRatingCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -93,20 +95,6 @@ UserRatingSummary::SetRatingByStar(int star, int ratingCount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UserRatingSummary&
|
|
||||||
UserRatingSummary::operator=(const UserRatingSummary& other)
|
|
||||||
{
|
|
||||||
fAverageRating = other.AverageRating();
|
|
||||||
fRatingCount = other.RatingCount();
|
|
||||||
fRatingCountNoStar = other.RatingCountByStar(-1);
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++)
|
|
||||||
fRatingCountByStar[i] = other.RatingCountByStar(i);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
UserRatingSummary::operator==(const UserRatingSummary& other) const
|
UserRatingSummary::operator==(const UserRatingSummary& other) const
|
||||||
{
|
{
|
||||||
@@ -129,3 +117,117 @@ UserRatingSummary::operator!=(const UserRatingSummary& other) const
|
|||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - UserRatingSummaryBuilder
|
||||||
|
|
||||||
|
|
||||||
|
UserRatingSummaryBuilder::UserRatingSummaryBuilder()
|
||||||
|
:
|
||||||
|
fAverageRating(RATING_MISSING),
|
||||||
|
fRatingCount(0),
|
||||||
|
fRatingCountNoStar(0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
fRatingCountByStar[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UserRatingSummaryBuilder::UserRatingSummaryBuilder(const UserRatingSummaryRef& other)
|
||||||
|
:
|
||||||
|
fSource(),
|
||||||
|
fAverageRating(RATING_MISSING),
|
||||||
|
fRatingCount(0),
|
||||||
|
fRatingCountNoStar(0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
fRatingCountByStar[i] = other->RatingCountByStar(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UserRatingSummaryBuilder::~UserRatingSummaryBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UserRatingSummaryRef
|
||||||
|
UserRatingSummaryBuilder::BuildRef()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet())
|
||||||
|
return fSource;
|
||||||
|
|
||||||
|
UserRatingSummary* userRatingSummary = new UserRatingSummary();
|
||||||
|
userRatingSummary->SetAverageRating(fAverageRating);
|
||||||
|
userRatingSummary->SetRatingCount(fRatingCount);
|
||||||
|
userRatingSummary->SetRatingByStar(RATING_MISSING_STAR, fRatingCountNoStar);
|
||||||
|
|
||||||
|
for (int star = 0; star <= 5; star++)
|
||||||
|
userRatingSummary->SetRatingByStar(star, fRatingCountByStar[star]);
|
||||||
|
|
||||||
|
return UserRatingSummaryRef(userRatingSummary, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UserRatingSummaryBuilder&
|
||||||
|
UserRatingSummaryBuilder::WithAverageRating(float value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->AverageRating() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fAverageRating = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UserRatingSummaryBuilder&
|
||||||
|
UserRatingSummaryBuilder::WithRatingCount(int value)
|
||||||
|
{
|
||||||
|
if (!fSource.IsSet() || fSource->RatingCount() != value) {
|
||||||
|
_InitFromSource();
|
||||||
|
fRatingCount = value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UserRatingSummaryBuilder&
|
||||||
|
UserRatingSummaryBuilder::AddRatingByStar(int star, int ratingCount)
|
||||||
|
{
|
||||||
|
if (star < RATING_MISSING_STAR || star > 5) {
|
||||||
|
HDERROR("bad star %" B_PRId32 " in builder", star);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fSource.IsSet() || fSource->RatingCountByStar(star) != ratingCount) {
|
||||||
|
_InitFromSource();
|
||||||
|
|
||||||
|
if (star == RATING_MISSING_STAR)
|
||||||
|
fRatingCountNoStar = ratingCount;
|
||||||
|
else
|
||||||
|
fRatingCountByStar[star] = ratingCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
UserRatingSummaryBuilder::_InitFromSource()
|
||||||
|
{
|
||||||
|
if (fSource.IsSet()) {
|
||||||
|
_Init(fSource.Get());
|
||||||
|
fSource.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
UserRatingSummaryBuilder::_Init(const UserRatingSummary* value)
|
||||||
|
{
|
||||||
|
fAverageRating = value->AverageRating();
|
||||||
|
fRatingCount = value->RatingCount();
|
||||||
|
fRatingCountNoStar = value->RatingCountByStar(RATING_MISSING_STAR);
|
||||||
|
|
||||||
|
for (int i = 0; i <= 5; i++)
|
||||||
|
fRatingCountByStar[i] = value->RatingCountByStar(i);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
* Copyright 2013-2014, Stephan Aßmus <[email protected]>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2016-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef USER_RATING_SUMMARY_H
|
#ifndef USER_RATING_SUMMARY_H
|
||||||
@@ -15,39 +15,70 @@
|
|||||||
include users' ratings for every single version of a package but only the last
|
include users' ratings for every single version of a package but only the last
|
||||||
one. Other rules also apply. For this reason, the calculation is performed on
|
one. Other rules also apply. For this reason, the calculation is performed on
|
||||||
the server-side and presented here.
|
the server-side and presented here.
|
||||||
*/
|
|
||||||
|
|
||||||
|
Instances of this class should not be created directly; instead use the
|
||||||
|
UserRatingSummaryBuilder class as a builder-constructor.
|
||||||
|
*/
|
||||||
class UserRatingSummary : public BReferenceable
|
class UserRatingSummary : public BReferenceable
|
||||||
{
|
{
|
||||||
|
friend class UserRatingSummaryBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UserRatingSummary();
|
UserRatingSummary();
|
||||||
UserRatingSummary(const UserRatingSummary& other);
|
UserRatingSummary(const UserRatingSummary& other);
|
||||||
|
|
||||||
void Clear();
|
bool operator==(const UserRatingSummary& other) const;
|
||||||
|
bool operator!=(const UserRatingSummary& other) const;
|
||||||
|
|
||||||
float AverageRating() const
|
float AverageRating() const;
|
||||||
{ return fAverageRating; }
|
int RatingCount() const;
|
||||||
int RatingCount() const
|
|
||||||
{ return fRatingCount; }
|
|
||||||
int RatingCountByStar(int star) const;
|
int RatingCountByStar(int star) const;
|
||||||
|
|
||||||
|
private:
|
||||||
void SetAverageRating(float value);
|
void SetAverageRating(float value);
|
||||||
void SetRatingCount(int value);
|
void SetRatingCount(int value);
|
||||||
void SetRatingByStar(int star, int ratingCount);
|
void SetRatingByStar(int star, int ratingCount);
|
||||||
|
|
||||||
UserRatingSummary& operator=(const UserRatingSummary& other);
|
|
||||||
bool operator==(const UserRatingSummary& other) const;
|
|
||||||
bool operator!=(const UserRatingSummary& other) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float fAverageRating;
|
float fAverageRating;
|
||||||
int fRatingCount;
|
int fRatingCount;
|
||||||
|
|
||||||
int fRatingCountNoStar;
|
int fRatingCountNoStar;
|
||||||
int fRatingCountByStar[6];
|
int fRatingCountByStar[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef BReference<UserRatingSummary> UserRatingSummaryRef;
|
typedef BReference<UserRatingSummary> UserRatingSummaryRef;
|
||||||
|
|
||||||
|
|
||||||
|
class UserRatingSummaryBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UserRatingSummaryBuilder();
|
||||||
|
UserRatingSummaryBuilder(const UserRatingSummaryRef& other);
|
||||||
|
virtual ~UserRatingSummaryBuilder();
|
||||||
|
|
||||||
|
UserRatingSummaryRef
|
||||||
|
BuildRef();
|
||||||
|
|
||||||
|
UserRatingSummaryBuilder&
|
||||||
|
WithAverageRating(float value);
|
||||||
|
UserRatingSummaryBuilder&
|
||||||
|
WithRatingCount(int value);
|
||||||
|
UserRatingSummaryBuilder&
|
||||||
|
AddRatingByStar(int star, int ratingCount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitFromSource();
|
||||||
|
void _Init(const UserRatingSummary* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
UserRatingSummaryRef
|
||||||
|
fSource;
|
||||||
|
float fAverageRating;
|
||||||
|
int fRatingCount;
|
||||||
|
int fRatingCountNoStar;
|
||||||
|
int fRatingCountByStar[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // USER_RATING_SUMMARY_H
|
#endif // USER_RATING_SUMMARY_H
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2022, Andrew Lindesay <[email protected]>.
|
* Copyright 2018-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "AbstractProcess.h"
|
#include "AbstractProcess.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
@@ -18,6 +18,9 @@
|
|||||||
#include "ProcessListener.h"
|
#include "ProcessListener.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const bigtime_t kProcessUpdateMinimumDelay = 250000;
|
||||||
|
|
||||||
|
|
||||||
AbstractProcess::AbstractProcess()
|
AbstractProcess::AbstractProcess()
|
||||||
:
|
:
|
||||||
fLock(),
|
fLock(),
|
||||||
@@ -25,7 +28,8 @@ AbstractProcess::AbstractProcess()
|
|||||||
fWasStopped(false),
|
fWasStopped(false),
|
||||||
fProcessState(PROCESS_INITIAL),
|
fProcessState(PROCESS_INITIAL),
|
||||||
fErrorStatus(B_OK),
|
fErrorStatus(B_OK),
|
||||||
fDurationSeconds(0.0)
|
fDurationSeconds(0.0),
|
||||||
|
fLastProgressUpdate(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +76,7 @@ AbstractProcess::Run()
|
|||||||
|
|
||||||
BStopWatch stopWatch("process", true);
|
BStopWatch stopWatch("process", true);
|
||||||
status_t runResult = RunInternal();
|
status_t runResult = RunInternal();
|
||||||
fDurationSeconds = ((double) stopWatch.ElapsedTime() / 1000000.0);
|
fDurationSeconds = static_cast<double>(stopWatch.ElapsedTime()) / 1000000.0;
|
||||||
|
|
||||||
if (runResult != B_OK)
|
if (runResult != B_OK)
|
||||||
HDERROR("[%s] an error has arisen; %s", Name(), strerror(runResult));
|
HDERROR("[%s] an error has arisen; %s", Name(), strerror(runResult));
|
||||||
@@ -109,11 +113,11 @@ AbstractProcess::ErrorStatus()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This method will stop the process. The actual process may carry on to
|
/*! This method will stop the process. The actual process may carry on to
|
||||||
perform some tidy-ups on its thread so this does not stop the thread or
|
perform some tidy-ups on its thread so this does not stop the thread or
|
||||||
change the state of the process; just indicates to the running thread that
|
change the state of the process; just indicates to the running thread that
|
||||||
it should stop. If it has not yet been started then it will be put into
|
it should stop. If it has not yet been started then it will be put into
|
||||||
finished state.
|
finished state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
@@ -196,6 +200,22 @@ AbstractProcess::LogReport()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! This method should be called before processing any progress. It will prevent
|
||||||
|
progress updates from coming through too frequently.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
AbstractProcess::_ShouldProcessProgress()
|
||||||
|
{
|
||||||
|
bigtime_t now = system_time();
|
||||||
|
|
||||||
|
if (now - fLastProgressUpdate < kProcessUpdateMinimumDelay)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fLastProgressUpdate = now;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ char
|
/*static*/ char
|
||||||
AbstractProcess::_ProcessStateIdentifier(process_state value)
|
AbstractProcess::_ProcessStateIdentifier(process_state value)
|
||||||
{
|
{
|
||||||
@@ -209,4 +229,4 @@ AbstractProcess::_ProcessStateIdentifier(process_state value)
|
|||||||
default:
|
default:
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2022, Andrew Lindesay <[email protected]>.
|
* Copyright 2018-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef ABSTRACT_PROCESS_H
|
#ifndef ABSTRACT_PROCESS_H
|
||||||
@@ -50,6 +50,8 @@ protected:
|
|||||||
|
|
||||||
static char _ProcessStateIdentifier(process_state value);
|
static char _ProcessStateIdentifier(process_state value);
|
||||||
|
|
||||||
|
bool _ShouldProcessProgress();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BLocker fLock;
|
BLocker fLock;
|
||||||
|
|
||||||
@@ -59,6 +61,7 @@ private:
|
|||||||
process_state fProcessState;
|
process_state fProcessState;
|
||||||
status_t fErrorStatus;
|
status_t fErrorStatus;
|
||||||
double fDurationSeconds;
|
double fDurationSeconds;
|
||||||
|
bigtime_t fLastProgressUpdate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ABSTRACT_PROCESS_H
|
#endif // ABSTRACT_PROCESS_H
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2018-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "ProcessCoordinatorFactory.h"
|
#include "ProcessCoordinatorFactory.h"
|
||||||
|
|
||||||
#include <Autolock.h>
|
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
#include <Autolock.h>
|
||||||
|
|
||||||
#include <package/Context.h>
|
#include <package/Context.h>
|
||||||
#include <package/PackageRoster.h>
|
#include <package/PackageRoster.h>
|
||||||
@@ -42,13 +42,11 @@ using namespace BPackageKit;
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ ProcessCoordinator*
|
/*static*/ ProcessCoordinator*
|
||||||
ProcessCoordinatorFactory::CreateIncrementViewCounter(
|
ProcessCoordinatorFactory::CreateIncrementViewCounter(Model* model, const PackageInfoRef package)
|
||||||
Model* model, const PackageInfoRef package)
|
|
||||||
{
|
{
|
||||||
ProcessCoordinator* processCoordinator = new ProcessCoordinator(
|
ProcessCoordinator* processCoordinator = new ProcessCoordinator("IncrementViewCounter");
|
||||||
"IncrementViewCounter");
|
AbstractProcessNode* node
|
||||||
AbstractProcessNode* node = new ThreadedProcessNode(
|
= new ThreadedProcessNode(new IncrementViewCounterProcess(model, package));
|
||||||
new IncrementViewCounterProcess(model, package));
|
|
||||||
processCoordinator->AddNode(node);
|
processCoordinator->AddNode(node);
|
||||||
return processCoordinator;
|
return processCoordinator;
|
||||||
}
|
}
|
||||||
@@ -56,56 +54,46 @@ ProcessCoordinatorFactory::CreateIncrementViewCounter(
|
|||||||
|
|
||||||
/*static*/ ProcessCoordinator*
|
/*static*/ ProcessCoordinator*
|
||||||
ProcessCoordinatorFactory::CreateUserDetailVerifierCoordinator(
|
ProcessCoordinatorFactory::CreateUserDetailVerifierCoordinator(
|
||||||
UserDetailVerifierListener* userDetailVerifierListener,
|
UserDetailVerifierListener* userDetailVerifierListener, Model* model)
|
||||||
Model* model)
|
|
||||||
{
|
{
|
||||||
ProcessCoordinator* processCoordinator = new ProcessCoordinator(
|
ProcessCoordinator* processCoordinator = new ProcessCoordinator("UserDetailVerifier");
|
||||||
"UserDetailVerifier");
|
AbstractProcessNode* userDetailVerifier
|
||||||
AbstractProcessNode* userDetailVerifier = new ThreadedProcessNode(
|
= new ThreadedProcessNode(new UserDetailVerifierProcess(model, userDetailVerifierListener));
|
||||||
new UserDetailVerifierProcess(model, userDetailVerifierListener));
|
|
||||||
processCoordinator->AddNode(userDetailVerifier);
|
processCoordinator->AddNode(userDetailVerifier);
|
||||||
return processCoordinator;
|
return processCoordinator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* static */ ProcessCoordinator*
|
/* static */ ProcessCoordinator*
|
||||||
ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
|
ProcessCoordinatorFactory::CreateBulkLoadCoordinator(Model* model, bool forceLocalUpdate)
|
||||||
PackageInfoListenerRef packageInfoListener,
|
|
||||||
Model* model, bool forceLocalUpdate)
|
|
||||||
{
|
{
|
||||||
bool areWorkingFilesAvailable = StorageUtils::AreWorkingFilesAvailable();
|
bool areWorkingFilesAvailable = StorageUtils::AreWorkingFilesAvailable();
|
||||||
uint32 serverProcessOptions = _CalculateServerProcessOptions();
|
uint32 serverProcessOptions = _CalculateServerProcessOptions();
|
||||||
BAutolock locker(model->Lock());
|
ProcessCoordinator* processCoordinator
|
||||||
ProcessCoordinator* processCoordinator = new ProcessCoordinator(
|
= new ProcessCoordinator("BulkLoad", new BMessage(MSG_BULK_LOAD_DONE));
|
||||||
"BulkLoad", new BMessage(MSG_BULK_LOAD_DONE));
|
|
||||||
|
|
||||||
AbstractProcessNode *localRepositoryUpdate =
|
AbstractProcessNode* localRepositoryUpdate
|
||||||
new ThreadedProcessNode(new LocalRepositoryUpdateProcess(model,
|
= new ThreadedProcessNode(new LocalRepositoryUpdateProcess(model, forceLocalUpdate));
|
||||||
forceLocalUpdate));
|
|
||||||
processCoordinator->AddNode(localRepositoryUpdate);
|
processCoordinator->AddNode(localRepositoryUpdate);
|
||||||
|
|
||||||
AbstractProcessNode *localPkgDataLoad =
|
AbstractProcessNode* localPkgDataLoad
|
||||||
new ThreadedProcessNode(new LocalPkgDataLoadProcess(
|
= new ThreadedProcessNode(new LocalPkgDataLoadProcess(model, forceLocalUpdate));
|
||||||
packageInfoListener, model, forceLocalUpdate));
|
|
||||||
localPkgDataLoad->AddPredecessor(localRepositoryUpdate);
|
localPkgDataLoad->AddPredecessor(localRepositoryUpdate);
|
||||||
processCoordinator->AddNode(localPkgDataLoad);
|
processCoordinator->AddNode(localPkgDataLoad);
|
||||||
|
|
||||||
if (areWorkingFilesAvailable) {
|
if (areWorkingFilesAvailable) {
|
||||||
AbstractProcessNode *serverIconExportUpdate =
|
AbstractProcessNode* serverIconExportUpdate = new ThreadedProcessNode(
|
||||||
new ThreadedProcessNode(new ServerIconExportUpdateProcess(model,
|
new ServerIconExportUpdateProcess(model, serverProcessOptions));
|
||||||
serverProcessOptions));
|
|
||||||
serverIconExportUpdate->AddPredecessor(localPkgDataLoad);
|
serverIconExportUpdate->AddPredecessor(localPkgDataLoad);
|
||||||
processCoordinator->AddNode(serverIconExportUpdate);
|
processCoordinator->AddNode(serverIconExportUpdate);
|
||||||
|
|
||||||
AbstractProcessNode *serverRepositoryDataUpdate =
|
AbstractProcessNode* serverRepositoryDataUpdate = new ThreadedProcessNode(
|
||||||
new ThreadedProcessNode(new ServerRepositoryDataUpdateProcess(model,
|
new ServerRepositoryDataUpdateProcess(model, serverProcessOptions));
|
||||||
serverProcessOptions));
|
|
||||||
serverRepositoryDataUpdate->AddPredecessor(localPkgDataLoad);
|
serverRepositoryDataUpdate->AddPredecessor(localPkgDataLoad);
|
||||||
processCoordinator->AddNode(serverRepositoryDataUpdate);
|
processCoordinator->AddNode(serverRepositoryDataUpdate);
|
||||||
|
|
||||||
AbstractProcessNode *serverReferenceDataUpdate =
|
AbstractProcessNode* serverReferenceDataUpdate = new ThreadedProcessNode(
|
||||||
new ThreadedProcessNode(new ServerReferenceDataUpdateProcess(model,
|
new ServerReferenceDataUpdateProcess(model, serverProcessOptions));
|
||||||
serverProcessOptions));
|
|
||||||
processCoordinator->AddNode(serverReferenceDataUpdate);
|
processCoordinator->AddNode(serverReferenceDataUpdate);
|
||||||
|
|
||||||
// This one has to run after the server data is taken up because it
|
// This one has to run after the server data is taken up because it
|
||||||
@@ -113,8 +101,8 @@ ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
|
|||||||
// sourced from the server. It has all of the
|
// sourced from the server. It has all of the
|
||||||
// `ServerPkgDataUpdateProcess` nodes configured as its predecessors.
|
// `ServerPkgDataUpdateProcess` nodes configured as its predecessors.
|
||||||
|
|
||||||
AbstractProcessNode* populatePkgSizes =
|
AbstractProcessNode* populatePkgSizes
|
||||||
new ThreadedProcessNode(new PopulatePkgSizesProcess(model));
|
= new ThreadedProcessNode(new PopulatePkgSizesProcess(model));
|
||||||
|
|
||||||
// create a process for each of the repositories that are configured on
|
// create a process for each of the repositories that are configured on
|
||||||
// the local system. Later, only those that have a web-app repository
|
// the local system. Later, only those that have a web-app repository
|
||||||
@@ -127,20 +115,19 @@ ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
|
|||||||
status_t repoNamesResult = roster.GetRepositoryNames(repoNames);
|
status_t repoNamesResult = roster.GetRepositoryNames(repoNames);
|
||||||
|
|
||||||
if (repoNamesResult == B_OK) {
|
if (repoNamesResult == B_OK) {
|
||||||
AutoLocker<BLocker> locker(model->Lock());
|
|
||||||
|
|
||||||
for (int32 i = 0; i < repoNames.CountStrings(); i++) {
|
for (int32 i = 0; i < repoNames.CountStrings(); i++) {
|
||||||
AbstractProcessNode* processNode = new ThreadedProcessNode(
|
AbstractProcessNode* processNode
|
||||||
new ServerPkgDataUpdateProcess(
|
= new ThreadedProcessNode(new ServerPkgDataUpdateProcess(repoNames.StringAt(i),
|
||||||
repoNames.StringAt(i), model, serverProcessOptions));
|
model, serverProcessOptions));
|
||||||
processNode->AddPredecessor(serverRepositoryDataUpdate);
|
processNode->AddPredecessor(serverRepositoryDataUpdate);
|
||||||
processNode->AddPredecessor(serverReferenceDataUpdate);
|
processNode->AddPredecessor(serverReferenceDataUpdate);
|
||||||
processCoordinator->AddNode(processNode);
|
processCoordinator->AddNode(processNode);
|
||||||
|
|
||||||
populatePkgSizes->AddPredecessor(processNode);
|
populatePkgSizes->AddPredecessor(processNode);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
HDERROR("a problem has arisen getting the repository names.");
|
HDERROR("a problem has arisen getting the repository names.");
|
||||||
|
}
|
||||||
|
|
||||||
processCoordinator->AddNode(populatePkgSizes);
|
processCoordinator->AddNode(populatePkgSizes);
|
||||||
}
|
}
|
||||||
@@ -150,8 +137,7 @@ ProcessCoordinatorFactory::CreateBulkLoadCoordinator(
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ ProcessCoordinator*
|
/*static*/ ProcessCoordinator*
|
||||||
ProcessCoordinatorFactory::CreatePackageActionCoordinator(
|
ProcessCoordinatorFactory::CreatePackageActionCoordinator(Model* model, BMessage* message)
|
||||||
Model* model, BMessage* message)
|
|
||||||
{
|
{
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case MSG_PKG_INSTALL:
|
case MSG_PKG_INSTALL:
|
||||||
@@ -176,89 +162,80 @@ ProcessCoordinatorFactory::CacheScreenshotCoordinator(Model* model,
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ ProcessCoordinator*
|
/*static*/ ProcessCoordinator*
|
||||||
ProcessCoordinatorFactory::PopulatePkgChangelogCoordinator(Model* model, PackageInfoRef package)
|
ProcessCoordinatorFactory::PopulatePkgChangelogCoordinator(Model* model, const BString& packageName)
|
||||||
{
|
{
|
||||||
return _CreateSingleProcessCoordinator("PopulatePkgChangelog",
|
return _CreateSingleProcessCoordinator("PopulatePkgChangelog",
|
||||||
new PopulatePkgChangelogFromServerProcess(package, model));
|
new PopulatePkgChangelogFromServerProcess(packageName, model));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ ProcessCoordinator*
|
/*static*/ ProcessCoordinator*
|
||||||
ProcessCoordinatorFactory::PopulatePkgUserRatingsCoordinator(Model* model, PackageInfoRef package)
|
ProcessCoordinatorFactory::PopulatePkgUserRatingsCoordinator(Model* model,
|
||||||
|
const BString& packageName)
|
||||||
{
|
{
|
||||||
return _CreateSingleProcessCoordinator("PopulatePkgUserRatings",
|
return _CreateSingleProcessCoordinator("PopulatePkgUserRatings",
|
||||||
new PopulatePkgUserRatingsFromServerProcess(package, model));
|
new PopulatePkgUserRatingsFromServerProcess(packageName, model));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ PackageInfoRef
|
/*static*/ BString
|
||||||
ProcessCoordinatorFactory::_ExtractPackageFromMessage(
|
ProcessCoordinatorFactory::_ExtractPackageNameFromMessage(BMessage* message)
|
||||||
Model* model, BMessage* message)
|
|
||||||
{
|
{
|
||||||
BString pkgName;
|
BString pkgName;
|
||||||
if (message->FindString(KEY_PACKAGE_NAME, &pkgName) != B_OK)
|
if (message->FindString(KEY_PACKAGE_NAME, &pkgName) != B_OK)
|
||||||
HDFATAL("malformed message missing key [%s]", KEY_PACKAGE_NAME);
|
HDFATAL("malformed message missing key [%s]", KEY_PACKAGE_NAME);
|
||||||
return model->PackageForName(pkgName);
|
return pkgName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ ProcessCoordinator*
|
/*static*/ ProcessCoordinator*
|
||||||
ProcessCoordinatorFactory::_CreateInstallPackageActionCoordinator(
|
ProcessCoordinatorFactory::_CreateInstallPackageActionCoordinator(Model* model, BMessage* message)
|
||||||
Model* model, BMessage* message)
|
|
||||||
{
|
{
|
||||||
ProcessCoordinator* processCoordinator = new ProcessCoordinator(
|
ProcessCoordinator* processCoordinator
|
||||||
"InstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
|
= new ProcessCoordinator("InstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
|
||||||
PackageInfoRef package = _ExtractPackageFromMessage(model, message);
|
|
||||||
if (package.IsSet()) {
|
AbstractProcessNode* processNode = new ThreadedProcessNode(
|
||||||
AbstractProcessNode *processNode =
|
new InstallPackageProcess(_ExtractPackageNameFromMessage(message), model), 10);
|
||||||
new ThreadedProcessNode(
|
|
||||||
new InstallPackageProcess(package, model), 10);
|
processCoordinator->AddNode(processNode);
|
||||||
processCoordinator->AddNode(processNode);
|
|
||||||
} else {
|
|
||||||
HDERROR("unable to find the package");
|
|
||||||
}
|
|
||||||
return processCoordinator;
|
return processCoordinator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ ProcessCoordinator*
|
/*static*/ ProcessCoordinator*
|
||||||
ProcessCoordinatorFactory::_CreateUninstallPackageActionCoordinator(
|
ProcessCoordinatorFactory::_CreateUninstallPackageActionCoordinator(Model* model, BMessage* message)
|
||||||
Model* model, BMessage* message)
|
|
||||||
{
|
{
|
||||||
ProcessCoordinator* processCoordinator = new ProcessCoordinator(
|
ProcessCoordinator* processCoordinator
|
||||||
"UninstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
|
= new ProcessCoordinator("UninstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
|
||||||
PackageInfoRef package = _ExtractPackageFromMessage(model, message);
|
|
||||||
if (package.IsSet()) {
|
AbstractProcessNode* processNode = new ThreadedProcessNode(
|
||||||
AbstractProcessNode *processNode =
|
new UninstallPackageProcess(_ExtractPackageNameFromMessage(message), model), 10);
|
||||||
new ThreadedProcessNode(
|
|
||||||
new UninstallPackageProcess(package, model), 10);
|
processCoordinator->AddNode(processNode);
|
||||||
processCoordinator->AddNode(processNode);
|
|
||||||
} else {
|
|
||||||
HDERROR("unable to find the package");
|
|
||||||
}
|
|
||||||
return processCoordinator;
|
return processCoordinator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ ProcessCoordinator*
|
/*static*/ ProcessCoordinator*
|
||||||
ProcessCoordinatorFactory::_CreateOpenPackageActionCoordinator(
|
ProcessCoordinatorFactory::_CreateOpenPackageActionCoordinator(Model* model, BMessage* message)
|
||||||
Model* model, BMessage* message)
|
|
||||||
{
|
{
|
||||||
ProcessCoordinator* processCoordinator = new ProcessCoordinator(
|
ProcessCoordinator* processCoordinator
|
||||||
"OpenPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
|
= new ProcessCoordinator("OpenPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
|
||||||
PackageInfoRef package = _ExtractPackageFromMessage(model, message);
|
|
||||||
if (package.IsSet()) {
|
BMessage deskbarLinkMessage;
|
||||||
BMessage deskbarLinkMessage;
|
|
||||||
if (message->FindMessage(KEY_DESKBAR_LINK, &deskbarLinkMessage) != B_OK)
|
if (message->FindMessage(KEY_DESKBAR_LINK, &deskbarLinkMessage) != B_OK)
|
||||||
HDFATAL("malformed message missing key [%s]", KEY_DESKBAR_LINK);
|
HDFATAL("malformed message missing key [%s]", KEY_DESKBAR_LINK);
|
||||||
DeskbarLink deskbarLink(&deskbarLinkMessage);
|
|
||||||
AbstractProcessNode *processNode =
|
DeskbarLink deskbarLink(&deskbarLinkMessage);
|
||||||
new ThreadedProcessNode(new OpenPackageProcess(
|
|
||||||
package, model, deskbarLink));
|
AbstractProcessNode* processNode = new ThreadedProcessNode(
|
||||||
processCoordinator->AddNode(processNode);
|
new OpenPackageProcess(_ExtractPackageNameFromMessage(message), model, deskbarLink));
|
||||||
} else {
|
|
||||||
HDERROR("unable to find the package");
|
processCoordinator->AddNode(processNode);
|
||||||
}
|
|
||||||
return processCoordinator;
|
return processCoordinator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,8 +246,7 @@ ProcessCoordinatorFactory::_CalculateServerProcessOptions()
|
|||||||
uint32 processOptions = 0;
|
uint32 processOptions = 0;
|
||||||
|
|
||||||
if (ServerSettings::IsClientTooOld()) {
|
if (ServerSettings::IsClientTooOld()) {
|
||||||
HDINFO("bulk load proceeding without network communications "
|
HDINFO("bulk load proceeding without network communications because the client is too old");
|
||||||
"because the client is too old");
|
|
||||||
processOptions |= SERVER_PROCESS_NO_NETWORKING;
|
processOptions |= SERVER_PROCESS_NO_NETWORKING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024, Andrew Lindesay <[email protected]>.
|
* Copyright 2018-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef PROCESS_COORDINATOR_FACTORY_H
|
#ifndef PROCESS_COORDINATOR_FACTORY_H
|
||||||
@@ -26,13 +26,10 @@ public:
|
|||||||
static ProcessCoordinator* CreateIncrementViewCounter(Model* model,
|
static ProcessCoordinator* CreateIncrementViewCounter(Model* model,
|
||||||
const PackageInfoRef package);
|
const PackageInfoRef package);
|
||||||
|
|
||||||
static ProcessCoordinator* CreateBulkLoadCoordinator(
|
static ProcessCoordinator* CreateBulkLoadCoordinator(Model* model, bool forceLocalUpdate);
|
||||||
PackageInfoListenerRef packageInfoListener,
|
|
||||||
Model* model, bool forceLocalUpdate);
|
|
||||||
|
|
||||||
static ProcessCoordinator* CreateUserDetailVerifierCoordinator(
|
static ProcessCoordinator* CreateUserDetailVerifierCoordinator(
|
||||||
UserDetailVerifierListener*
|
UserDetailVerifierListener* userDetailVerifierListener,
|
||||||
userDetailVerifierListener,
|
|
||||||
Model* model);
|
Model* model);
|
||||||
|
|
||||||
static ProcessCoordinator* CreatePackageActionCoordinator(
|
static ProcessCoordinator* CreatePackageActionCoordinator(
|
||||||
@@ -42,16 +39,15 @@ public:
|
|||||||
Model* model, ScreenshotCoordinate& screenshotCoordinate);
|
Model* model, ScreenshotCoordinate& screenshotCoordinate);
|
||||||
|
|
||||||
static ProcessCoordinator* PopulatePkgChangelogCoordinator(Model* model,
|
static ProcessCoordinator* PopulatePkgChangelogCoordinator(Model* model,
|
||||||
PackageInfoRef package);
|
const BString& packageName);
|
||||||
|
|
||||||
static ProcessCoordinator* PopulatePkgUserRatingsCoordinator(Model* model,
|
static ProcessCoordinator* PopulatePkgUserRatingsCoordinator(Model* model,
|
||||||
PackageInfoRef package);
|
const BString& packageName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uint32 _CalculateServerProcessOptions();
|
static uint32 _CalculateServerProcessOptions();
|
||||||
|
|
||||||
static PackageInfoRef _ExtractPackageFromMessage(
|
static BString _ExtractPackageNameFromMessage(BMessage* message);
|
||||||
Model* model, BMessage* message);
|
|
||||||
|
|
||||||
static ProcessCoordinator* _CreateInstallPackageActionCoordinator(
|
static ProcessCoordinator* _CreateInstallPackageActionCoordinator(
|
||||||
Model* model, BMessage* message);
|
Model* model, BMessage* message);
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2023, Andrew Lindesay <[email protected]>.
|
* Copyright 2017-2025, Andrew Lindesay <[email protected]>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "AbstractServerProcess.h"
|
#include "AbstractServerProcess.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <BufferedDataIO.h>
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
#include <BufferedDataIO.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <FileIO.h>
|
#include <FileIO.h>
|
||||||
#include <HttpTime.h>
|
#include <HttpTime.h>
|
||||||
@@ -26,7 +27,6 @@
|
|||||||
#include "ServerSettings.h"
|
#include "ServerSettings.h"
|
||||||
#include "StandardMetaDataJsonEventListener.h"
|
#include "StandardMetaDataJsonEventListener.h"
|
||||||
#include "StorageUtils.h"
|
#include "StorageUtils.h"
|
||||||
#include "LoggingUrlProtocolListener.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace BPrivate::Network;
|
using namespace BPrivate::Network;
|
||||||
@@ -40,14 +40,173 @@ using namespace BPrivate::Network;
|
|||||||
#define TIMEOUT_MICROSECONDS 3e+7
|
#define TIMEOUT_MICROSECONDS 3e+7
|
||||||
|
|
||||||
|
|
||||||
const size_t kFileBufferSize = 10 * 1024;
|
static const size_t kFileBufferSize = 10 * 1024;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Interface ReadProgressDataIO
|
||||||
|
|
||||||
|
|
||||||
|
class ReadProgressDataIO : public BDataIO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReadProgressDataIO(AbstractServerProcess* serverProcess,
|
||||||
|
BDataIO* delegate, size_t bytesTotal);
|
||||||
|
virtual ~ReadProgressDataIO();
|
||||||
|
|
||||||
|
virtual ssize_t Read(void* buffer, size_t size);
|
||||||
|
virtual ssize_t Write(const void* buffer, size_t size);
|
||||||
|
|
||||||
|
virtual status_t Flush();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AbstractServerProcess*
|
||||||
|
fServerProcess;
|
||||||
|
BDataIO* fDelegate;
|
||||||
|
size_t fBytesRead;
|
||||||
|
size_t fBytesTotal;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Interface LoggingUrlProtocolListener
|
||||||
|
|
||||||
|
|
||||||
|
class LoggingUrlProtocolListener : public BUrlProtocolListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LoggingUrlProtocolListener(AbstractServerProcess* serverProcess,
|
||||||
|
BString traceLoggingIdentifier, bool traceLogging);
|
||||||
|
virtual ~LoggingUrlProtocolListener();
|
||||||
|
|
||||||
|
size_t ContentLength();
|
||||||
|
|
||||||
|
virtual void DownloadProgress(BUrlRequest* caller,
|
||||||
|
off_t bytesReceived, off_t bytesTotal);
|
||||||
|
virtual void BytesWritten(BUrlRequest* caller,
|
||||||
|
size_t bytesWritten);
|
||||||
|
virtual void DebugMessage(BUrlRequest* caller,
|
||||||
|
BUrlProtocolDebugMessage type,
|
||||||
|
const char* text);
|
||||||
|
|
||||||
|
private:
|
||||||
|
AbstractServerProcess*
|
||||||
|
fServerProcess;
|
||||||
|
bool fTraceLogging;
|
||||||
|
BString fTraceLoggingIdentifier;
|
||||||
|
size_t fContentLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Implementation for ReadProgressDataIO
|
||||||
|
|
||||||
|
|
||||||
|
ReadProgressDataIO::ReadProgressDataIO(AbstractServerProcess* serverProcess, BDataIO* delegate,
|
||||||
|
size_t bytesTotal)
|
||||||
|
:
|
||||||
|
fServerProcess(serverProcess),
|
||||||
|
fDelegate(delegate),
|
||||||
|
fBytesRead(0),
|
||||||
|
fBytesTotal(bytesTotal)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReadProgressDataIO::~ReadProgressDataIO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
ReadProgressDataIO::Read(void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
ssize_t actualRead = fDelegate->Read(buffer, size);
|
||||||
|
|
||||||
|
if (actualRead > 0) {
|
||||||
|
fBytesRead += actualRead;
|
||||||
|
|
||||||
|
if (fBytesTotal > 0.0f) {
|
||||||
|
float progress = static_cast<float>(fBytesRead) / static_cast<float>(fBytesTotal);
|
||||||
|
fServerProcess->SetDataProcessingProgress(progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return actualRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
ReadProgressDataIO::Write(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ReadProgressDataIO::Flush()
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Implementation for LoggingUrlProtocolListener
|
||||||
|
|
||||||
|
|
||||||
|
LoggingUrlProtocolListener::LoggingUrlProtocolListener(AbstractServerProcess* serverProcess,
|
||||||
|
BString traceLoggingIdentifier, bool traceLogging)
|
||||||
|
:
|
||||||
|
fServerProcess(serverProcess),
|
||||||
|
fTraceLogging(traceLogging),
|
||||||
|
fTraceLoggingIdentifier(traceLoggingIdentifier),
|
||||||
|
fContentLength(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LoggingUrlProtocolListener::~LoggingUrlProtocolListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LoggingUrlProtocolListener::BytesWritten(BUrlRequest* caller, size_t bytesWritten)
|
||||||
|
{
|
||||||
|
fContentLength += bytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LoggingUrlProtocolListener::DownloadProgress(BUrlRequest* caller, off_t bytesReceived,
|
||||||
|
off_t bytesTotal)
|
||||||
|
{
|
||||||
|
float progress = static_cast<float>(bytesReceived) / static_cast<float>(bytesTotal);
|
||||||
|
fServerProcess->SetDownloadProgress(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LoggingUrlProtocolListener::DebugMessage(BUrlRequest* caller, BUrlProtocolDebugMessage type,
|
||||||
|
const char* text)
|
||||||
|
{
|
||||||
|
HDTRACE("url->file <%s>; %s", fTraceLoggingIdentifier.String(), text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
LoggingUrlProtocolListener::ContentLength()
|
||||||
|
{
|
||||||
|
return fContentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - AbstractServerProcess
|
||||||
|
|
||||||
|
|
||||||
AbstractServerProcess::AbstractServerProcess(uint32 options)
|
AbstractServerProcess::AbstractServerProcess(uint32 options)
|
||||||
:
|
:
|
||||||
AbstractProcess(),
|
AbstractProcess(),
|
||||||
fOptions(options),
|
fOptions(options),
|
||||||
fRequest(NULL)
|
fRequest(NULL),
|
||||||
|
fDownloadProgress(kProgressIndeterminate),
|
||||||
|
fDataProcessingProgress(kProgressIndeterminate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +216,44 @@ AbstractServerProcess::~AbstractServerProcess()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
AbstractServerProcess::Progress()
|
||||||
|
{
|
||||||
|
if (fDataProcessingProgress >= 0.0f)
|
||||||
|
return 0.5f + (0.5f * fminf(fDataProcessingProgress, 1.0));
|
||||||
|
if (fDownloadProgress >= 0.0f)
|
||||||
|
return 0.5f * fminf(fDownloadProgress, 1.0);
|
||||||
|
return kProgressIndeterminate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AbstractServerProcess::SetDownloadProgress(float value)
|
||||||
|
{
|
||||||
|
if (fDownloadProgress == 1.0 || (!_ShouldProcessProgress() && value != 1.0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fDataProcessingProgress < 0.0f)
|
||||||
|
fDownloadProgress = value;
|
||||||
|
else
|
||||||
|
fDownloadProgress = 1.0;
|
||||||
|
|
||||||
|
_NotifyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AbstractServerProcess::SetDataProcessingProgress(float value)
|
||||||
|
{
|
||||||
|
if (fDataProcessingProgress == 1.0 || (!_ShouldProcessProgress() && value != 1.0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
fDownloadProgress = 1.0;
|
||||||
|
fDataProcessingProgress = value;
|
||||||
|
_NotifyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AbstractServerProcess::HasOption(uint32 flag)
|
AbstractServerProcess::HasOption(uint32 flag)
|
||||||
{
|
{
|
||||||
@@ -67,8 +264,7 @@ AbstractServerProcess::HasOption(uint32 flag)
|
|||||||
bool
|
bool
|
||||||
AbstractServerProcess::ShouldAttemptNetworkDownload(bool hasDataAlready)
|
AbstractServerProcess::ShouldAttemptNetworkDownload(bool hasDataAlready)
|
||||||
{
|
{
|
||||||
return
|
return !HasOption(SERVER_PROCESS_NO_NETWORKING)
|
||||||
!HasOption(SERVER_PROCESS_NO_NETWORKING)
|
|
||||||
&& !(HasOption(SERVER_PROCESS_PREFER_CACHE) && hasDataAlready);
|
&& !(HasOption(SERVER_PROCESS_PREFER_CACHE) && hasDataAlready);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,16 +272,15 @@ AbstractServerProcess::ShouldAttemptNetworkDownload(bool hasDataAlready)
|
|||||||
status_t
|
status_t
|
||||||
AbstractServerProcess::StopInternal()
|
AbstractServerProcess::StopInternal()
|
||||||
{
|
{
|
||||||
if (fRequest != NULL) {
|
if (fRequest != NULL)
|
||||||
return fRequest->Stop();
|
return fRequest->Stop();
|
||||||
}
|
|
||||||
|
|
||||||
return AbstractProcess::StopInternal();
|
return AbstractProcess::StopInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue) const
|
AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue)
|
||||||
{
|
{
|
||||||
BPath metaDataPath;
|
BPath metaDataPath;
|
||||||
BString jsonPath;
|
BString jsonPath;
|
||||||
@@ -102,15 +297,15 @@ AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue) const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue,
|
AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue, const BPath& metaDataPath,
|
||||||
const BPath& metaDataPath, const BString& jsonPath) const
|
const BString& jsonPath)
|
||||||
{
|
{
|
||||||
headerValue.SetTo("");
|
headerValue.SetTo("");
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
|
||||||
if (-1 == stat(metaDataPath.Path(), &s)) {
|
if (-1 == stat(metaDataPath.Path(), &s)) {
|
||||||
if (ENOENT != errno)
|
if (ENOENT != errno)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
@@ -121,11 +316,11 @@ AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue,
|
|||||||
StandardMetaData metaData;
|
StandardMetaData metaData;
|
||||||
status_t result = PopulateMetaData(metaData, metaDataPath, jsonPath);
|
status_t result = PopulateMetaData(metaData, metaDataPath, jsonPath);
|
||||||
|
|
||||||
if (result == B_OK)
|
if (result == B_OK) {
|
||||||
SetIfModifiedSinceHeaderValueFromMetaData(headerValue, metaData);
|
SetIfModifiedSinceHeaderValueFromMetaData(headerValue, metaData);
|
||||||
else {
|
} else {
|
||||||
HDERROR("unable to parse the meta-data date and time from [%s]"
|
HDERROR("unable to parse the meta-data date and time from [%s] - cannot set the "
|
||||||
" - cannot set the 'If-Modified-Since' header",
|
"'If-Modified-Since' header",
|
||||||
metaDataPath.Path());
|
metaDataPath.Path());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,23 +329,19 @@ AbstractServerProcess::IfModifiedSinceHeaderValue(BString& headerValue,
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
AbstractServerProcess::SetIfModifiedSinceHeaderValueFromMetaData(
|
AbstractServerProcess::SetIfModifiedSinceHeaderValueFromMetaData(BString& headerValue,
|
||||||
BString& headerValue,
|
|
||||||
const StandardMetaData& metaData)
|
const StandardMetaData& metaData)
|
||||||
{
|
{
|
||||||
// An example of this output would be; 'Fri, 24 Oct 2014 19:32:27 +0000'
|
// An example of this output would be; 'Fri, 24 Oct 2014 19:32:27 +0000'
|
||||||
BDateTime modifiedDateTime = metaData
|
BDateTime modifiedDateTime = metaData.GetDataModifiedTimestampAsDateTime();
|
||||||
.GetDataModifiedTimestampAsDateTime();
|
|
||||||
BHttpTime modifiedHttpTime(modifiedDateTime);
|
BHttpTime modifiedHttpTime(modifiedDateTime);
|
||||||
headerValue.SetTo(modifiedHttpTime
|
headerValue.SetTo(modifiedHttpTime.ToString(B_HTTP_TIME_FORMAT_COOKIE));
|
||||||
.ToString(B_HTTP_TIME_FORMAT_COOKIE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AbstractServerProcess::PopulateMetaData(
|
AbstractServerProcess::PopulateMetaData(StandardMetaData& metaData, const BPath& path,
|
||||||
StandardMetaData& metaData, const BPath& path,
|
const BString& jsonPath)
|
||||||
const BString& jsonPath) const
|
|
||||||
{
|
{
|
||||||
StandardMetaDataJsonEventListener listener(jsonPath, metaData);
|
StandardMetaDataJsonEventListener listener(jsonPath, metaData);
|
||||||
status_t result = ParseJsonFromFileWithListener(&listener, path);
|
status_t result = ParseJsonFromFileWithListener(&listener, path);
|
||||||
@@ -164,8 +355,7 @@ AbstractServerProcess::PopulateMetaData(
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
if (!metaData.IsPopulated()) {
|
if (!metaData.IsPopulated()) {
|
||||||
HDERROR("the meta data was read from [%s], but no values "
|
HDERROR("the meta data was read from [%s], but no values were extracted", path.Path());
|
||||||
"were extracted", path.Path());
|
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +364,7 @@ AbstractServerProcess::PopulateMetaData(
|
|||||||
|
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
AbstractServerProcess::_LooksLikeGzip(const char *pathStr)
|
AbstractServerProcess::_LooksLikeGzip(const char* pathStr)
|
||||||
{
|
{
|
||||||
int l = strlen(pathStr);
|
int l = strlen(pathStr);
|
||||||
return l > 4 && 0 == strncmp(&pathStr[l - 3], ".gz", 3);
|
return l > 4 && 0 == strncmp(&pathStr[l - 3], ".gz", 3);
|
||||||
@@ -187,36 +377,53 @@ AbstractServerProcess::_LooksLikeGzip(const char *pathStr)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AbstractServerProcess::ParseJsonFromFileWithListener(
|
AbstractServerProcess::ParseJsonFromFileWithListener(BJsonEventListener* listener,
|
||||||
BJsonEventListener *listener,
|
const BPath& path)
|
||||||
const BPath& path) const
|
|
||||||
{
|
{
|
||||||
const char* pathStr = path.Path();
|
const char* pathStr = path.Path();
|
||||||
|
|
||||||
|
bool fileExists = false;
|
||||||
|
off_t fileSize = 0;
|
||||||
|
status_t existsResult = StorageUtils::ExistsObject(path, &fileExists, NULL, &fileSize);
|
||||||
|
|
||||||
|
if (existsResult != B_OK) {
|
||||||
|
HDERROR("[%s] unable to get the length of the data file [%s]", Name(), pathStr);
|
||||||
|
return existsResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileExists) {
|
||||||
|
HDERROR("[%s] missing data file [%s]", Name(), pathStr);
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileSize == 0) {
|
||||||
|
HDERROR("[%s] empty data file [%s]", Name(), pathStr);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
FILE* file = fopen(pathStr, "rb");
|
FILE* file = fopen(pathStr, "rb");
|
||||||
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
HDERROR("[%s] unable to find the meta data file at [%s]", Name(),
|
HDERROR("[%s] unable to find the data file at [%s]", Name(), pathStr);
|
||||||
path.Path());
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
BFileIO rawInput(file, true); // takes ownership
|
BFileIO rawInput(file, true); // takes ownership
|
||||||
|
ReadProgressDataIO readProgress(this, &rawInput, fileSize);
|
||||||
BDataIO* bufferedRawInput = new BBufferedDataIO(rawInput, kFileBufferSize, false, true);
|
BDataIO* bufferedRawInput = new BBufferedDataIO(readProgress, kFileBufferSize, false, true);
|
||||||
ObjectDeleter<BDataIO> bufferedRawInputDeleter(bufferedRawInput);
|
ObjectDeleter<BDataIO> bufferedRawInputDeleter(bufferedRawInput);
|
||||||
|
|
||||||
// if the file extension ends with '.gz' then the data will be
|
// if the file extension ends with '.gz' then the data will be
|
||||||
// compressed and the algorithm needs to decompress the data as
|
// compressed and the algorithm needs to decompress the data as
|
||||||
// it is parsed.
|
// it is parsed.
|
||||||
|
|
||||||
if (_LooksLikeGzip(pathStr)) {
|
if (_LooksLikeGzip(pathStr)) {
|
||||||
BDataIO* gzDecompressedInput = NULL;
|
BDataIO* gzDecompressedInput = NULL;
|
||||||
BZlibDecompressionParameters* zlibDecompressionParameters
|
BZlibDecompressionParameters* zlibDecompressionParameters
|
||||||
= new BZlibDecompressionParameters();
|
= new BZlibDecompressionParameters();
|
||||||
|
|
||||||
status_t result = BZlibCompressionAlgorithm()
|
status_t result = BZlibCompressionAlgorithm().CreateDecompressingInputStream(
|
||||||
.CreateDecompressingInputStream(bufferedRawInput,
|
bufferedRawInput, zlibDecompressionParameters, gzDecompressedInput);
|
||||||
zlibDecompressionParameters, gzDecompressedInput);
|
|
||||||
|
|
||||||
if (B_OK != result)
|
if (B_OK != result)
|
||||||
return result;
|
return result;
|
||||||
@@ -231,49 +438,47 @@ AbstractServerProcess::ParseJsonFromFileWithListener(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! In order to reduce the chance of failure half way through downloading a
|
/*! In order to reduce the chance of failure half way through downloading a
|
||||||
large file, this method will download the file to a temporary file and
|
large file, this method will download the file to a temporary file and
|
||||||
then it can rename the file to the final target file.
|
then it can rename the file to the final target file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AbstractServerProcess::DownloadToLocalFileAtomically(
|
AbstractServerProcess::DownloadToLocalFileAtomically(const BPath& targetFilePath, const BUrl& url)
|
||||||
const BPath& targetFilePath,
|
|
||||||
const BUrl& url)
|
|
||||||
{
|
{
|
||||||
BPath temporaryFilePath(tmpnam(NULL), NULL, true);
|
BPath temporaryFilePath(tmpnam(NULL), NULL, true);
|
||||||
status_t result = DownloadToLocalFile(
|
status_t result = DownloadToLocalFile(temporaryFilePath, url, 0, 0);
|
||||||
temporaryFilePath, url, 0, 0);
|
|
||||||
|
|
||||||
// if the data is coming in as .gz, but is not stored as .gz then
|
// if the data is coming in as .gz, but is not stored as .gz then
|
||||||
// the data should be decompressed in the temporary file location
|
// the data should be decompressed in the temporary file location
|
||||||
// before being shifted into place.
|
// before being shifted into place.
|
||||||
|
|
||||||
if (result == B_OK
|
if (result == B_OK && _LooksLikeGzip(url.Path()) && !_LooksLikeGzip(targetFilePath.Path()))
|
||||||
&& _LooksLikeGzip(url.Path())
|
|
||||||
&& !_LooksLikeGzip(targetFilePath.Path()))
|
|
||||||
result = _DeGzipInSitu(temporaryFilePath);
|
result = _DeGzipInSitu(temporaryFilePath);
|
||||||
|
|
||||||
// not copying if the data has not changed because the data will be
|
// not copying if the data has not changed because the data will be
|
||||||
// zero length. This is if the result is APP_ERR_NOT_MODIFIED.
|
// zero length. This is if the result is APP_ERR_NOT_MODIFIED.
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
// if the file is zero length then assume that something has
|
// if the file is zero length then assume that something has
|
||||||
// gone wrong.
|
// gone wrong.
|
||||||
off_t size;
|
off_t size;
|
||||||
bool hasFile;
|
bool hasFile;
|
||||||
|
|
||||||
result = StorageUtils::ExistsObject(temporaryFilePath, &hasFile, NULL,
|
result = StorageUtils::ExistsObject(temporaryFilePath, &hasFile, NULL, &size);
|
||||||
&size);
|
|
||||||
|
|
||||||
if (result == B_OK && hasFile && size > 0) {
|
if (result == B_OK && hasFile && size > 0) {
|
||||||
if (rename(temporaryFilePath.Path(), targetFilePath.Path()) != 0) {
|
if (rename(temporaryFilePath.Path(), targetFilePath.Path()) != 0) {
|
||||||
HDINFO("[%s] did rename [%s] --> [%s]",
|
HDINFO("[%s] did rename [%s] --> [%s]", Name(), temporaryFilePath.Path(),
|
||||||
Name(), temporaryFilePath.Path(), targetFilePath.Path());
|
targetFilePath.Path());
|
||||||
result = B_IO_ERROR;
|
result = B_IO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsSuccess(result))
|
||||||
|
SetDownloadProgress(1.0);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,13 +497,11 @@ AbstractServerProcess::_DeGzipInSitu(const BPath& path)
|
|||||||
BZlibDecompressionParameters* zlibDecompressionParameters
|
BZlibDecompressionParameters* zlibDecompressionParameters
|
||||||
= new BZlibDecompressionParameters();
|
= new BZlibDecompressionParameters();
|
||||||
|
|
||||||
result = BZlibCompressionAlgorithm()
|
result = BZlibCompressionAlgorithm().CreateDecompressingInputStream(&file,
|
||||||
.CreateDecompressingInputStream(&file,
|
zlibDecompressionParameters, gzDecompressedInput);
|
||||||
zlibDecompressionParameters, gzDecompressedInput);
|
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
ObjectDeleter<BDataIO> gzDecompressedInputDeleter(
|
ObjectDeleter<BDataIO> gzDecompressedInputDeleter(gzDecompressedInput);
|
||||||
gzDecompressedInput);
|
|
||||||
result = DataIOUtils::CopyAll(&tmpFile, gzDecompressedInput);
|
result = DataIOUtils::CopyAll(&tmpFile, gzDecompressedInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,8 +511,7 @@ AbstractServerProcess::_DeGzipInSitu(const BPath& path)
|
|||||||
HDERROR("unable to move the uncompressed data into place");
|
HDERROR("unable to move the uncompressed data into place");
|
||||||
result = B_ERROR;
|
result = B_ERROR;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
HDERROR("it was not possible to decompress the data");
|
HDERROR("it was not possible to decompress the data");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,15 +520,14 @@ AbstractServerProcess::_DeGzipInSitu(const BPath& path)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath,
|
AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath, const BUrl& url,
|
||||||
const BUrl& url, uint32 redirects, uint32 failures)
|
uint32 redirects, uint32 failures)
|
||||||
{
|
{
|
||||||
if (WasStopped())
|
if (WasStopped())
|
||||||
return B_CANCELED;
|
return B_CANCELED;
|
||||||
|
|
||||||
if (redirects > MAX_REDIRECTS) {
|
if (redirects > MAX_REDIRECTS) {
|
||||||
HDINFO("[%s] exceeded %d redirects --> failure", Name(),
|
HDINFO("[%s] exceeded %d redirects --> failure", Name(), MAX_REDIRECTS);
|
||||||
MAX_REDIRECTS);
|
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +539,7 @@ AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath,
|
|||||||
HDINFO("[%s] will stream '%s' to [%s]", Name(), url.UrlString().String(),
|
HDINFO("[%s] will stream '%s' to [%s]", Name(), url.UrlString().String(),
|
||||||
targetFilePath.Path());
|
targetFilePath.Path());
|
||||||
|
|
||||||
LoggingUrlProtocolListener listener(Name(), Logger::IsTraceEnabled());
|
LoggingUrlProtocolListener listener(this, Name(), Logger::IsTraceEnabled());
|
||||||
BFile targetFile(targetFilePath.Path(), O_WRONLY | O_CREAT);
|
BFile targetFile(targetFilePath.Path(), O_WRONLY | O_CREAT);
|
||||||
status_t err = targetFile.InitCheck();
|
status_t err = targetFile.InitCheck();
|
||||||
if (err != B_OK)
|
if (err != B_OK)
|
||||||
@@ -348,26 +549,23 @@ AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath,
|
|||||||
ServerSettings::AugmentHeaders(headers);
|
ServerSettings::AugmentHeaders(headers);
|
||||||
|
|
||||||
BString ifModifiedSinceHeader;
|
BString ifModifiedSinceHeader;
|
||||||
status_t ifModifiedSinceHeaderStatus = IfModifiedSinceHeaderValue(
|
status_t ifModifiedSinceHeaderStatus = IfModifiedSinceHeaderValue(ifModifiedSinceHeader);
|
||||||
ifModifiedSinceHeader);
|
|
||||||
|
|
||||||
if (ifModifiedSinceHeaderStatus == B_OK &&
|
if (ifModifiedSinceHeaderStatus == B_OK && ifModifiedSinceHeader.Length() > 0)
|
||||||
ifModifiedSinceHeader.Length() > 0) {
|
|
||||||
headers.AddHeader("If-Modified-Since", ifModifiedSinceHeader);
|
headers.AddHeader("If-Modified-Since", ifModifiedSinceHeader);
|
||||||
}
|
|
||||||
|
|
||||||
thread_id thread;
|
thread_id thread;
|
||||||
|
|
||||||
BUrlRequest* request = BUrlProtocolRoster::MakeRequest(url, &targetFile,
|
BUrlRequest* request = BUrlProtocolRoster::MakeRequest(url, &targetFile, &listener);
|
||||||
&listener);
|
|
||||||
if (request == NULL)
|
if (request == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
fRequest = dynamic_cast<BHttpRequest *>(request);
|
fRequest = dynamic_cast<BHttpRequest*>(request);
|
||||||
if (fRequest == NULL) {
|
if (fRequest == NULL) {
|
||||||
delete request;
|
delete request;
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
fRequest->SetHeaders(headers);
|
fRequest->SetHeaders(headers);
|
||||||
fRequest->SetMaxRedirections(0);
|
fRequest->SetMaxRedirections(0);
|
||||||
fRequest->SetTimeout(TIMEOUT_MICROSECONDS);
|
fRequest->SetTimeout(TIMEOUT_MICROSECONDS);
|
||||||
@@ -376,11 +574,10 @@ AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath,
|
|||||||
|
|
||||||
wait_for_thread(thread, NULL);
|
wait_for_thread(thread, NULL);
|
||||||
|
|
||||||
const BHttpResult& result = dynamic_cast<const BHttpResult&>(
|
const BHttpResult& result = dynamic_cast<const BHttpResult&>(fRequest->Result());
|
||||||
fRequest->Result());
|
|
||||||
int32 statusCode = result.StatusCode();
|
int32 statusCode = result.StatusCode();
|
||||||
const BHttpHeaders responseHeaders = result.Headers();
|
const BHttpHeaders responseHeaders = result.Headers();
|
||||||
const char *locationC = responseHeaders["Location"];
|
const char* locationC = responseHeaders["Location"];
|
||||||
BString location;
|
BString location;
|
||||||
|
|
||||||
if (locationC != NULL)
|
if (locationC != NULL)
|
||||||
@@ -415,8 +612,7 @@ AbstractServerProcess::DownloadToLocalFile(const BPath& targetFilePath,
|
|||||||
return DownloadToLocalFile(targetFilePath, url, redirects, failures + 1);
|
return DownloadToLocalFile(targetFilePath, url, redirects, failures + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
HDERROR("[%s] unexpected response from server [%" B_PRId32 "]",
|
HDERROR("[%s] unexpected response from server [%" B_PRId32 "]", Name(), statusCode);
|
||||||
Name(), statusCode);
|
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,9 +629,9 @@ AbstractServerProcess::DeleteLocalFile(const BPath& currentFilePath)
|
|||||||
|
|
||||||
|
|
||||||
/*! When a file is damaged or corrupted in some way, the file should be 'moved
|
/*! When a file is damaged or corrupted in some way, the file should be 'moved
|
||||||
aside' so that it is not involved in the next update. This method will
|
aside' so that it is not involved in the next update. This method will
|
||||||
create such an alternative 'damaged' file location and move this file to
|
create such an alternative 'damaged' file location and move this file to
|
||||||
that location.
|
that location.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
@@ -449,19 +645,20 @@ AbstractServerProcess::MoveDamagedFileAside(const BPath& currentFilePath)
|
|||||||
damagedFilePath.Append(damagedLeaf.String());
|
damagedFilePath.Append(damagedLeaf.String());
|
||||||
|
|
||||||
if (0 != rename(currentFilePath.Path(), damagedFilePath.Path())) {
|
if (0 != rename(currentFilePath.Path(), damagedFilePath.Path())) {
|
||||||
HDERROR("[%s] unable to move damaged file [%s] aside to [%s]",
|
HDERROR("[%s] unable to move damaged file [%s] aside to [%s]", Name(),
|
||||||
Name(), currentFilePath.Path(), damagedFilePath.Path());
|
currentFilePath.Path(), damagedFilePath.Path());
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
HDINFO("[%s] did move damaged file [%s] aside to [%s]",
|
HDINFO("[%s] did move damaged file [%s] aside to [%s]", Name(), currentFilePath.Path(),
|
||||||
Name(), currentFilePath.Path(), damagedFilePath.Path());
|
damagedFilePath.Path());
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AbstractServerProcess::IsSuccess(status_t e) {
|
AbstractServerProcess::IsSuccess(status_t e)
|
||||||
|
{
|
||||||
return e == B_OK || e == HD_ERR_NOT_MODIFIED;
|
return e == B_OK || e == HD_ERR_NOT_MODIFIED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef ABSTRACT_SERVER_PROCESS_H
|
#ifndef ABSTRACT_SERVER_PROCESS_H
|
||||||
@@ -34,6 +34,11 @@ public:
|
|||||||
AbstractServerProcess(uint32 options);
|
AbstractServerProcess(uint32 options);
|
||||||
virtual ~AbstractServerProcess();
|
virtual ~AbstractServerProcess();
|
||||||
|
|
||||||
|
virtual float Progress();
|
||||||
|
|
||||||
|
void SetDownloadProgress(float value);
|
||||||
|
void SetDataProcessingProgress(float value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual status_t GetStandardMetaDataPath(
|
virtual status_t GetStandardMetaDataPath(
|
||||||
BPath& path) const = 0;
|
BPath& path) const = 0;
|
||||||
@@ -41,11 +46,11 @@ protected:
|
|||||||
BString& jsonPath) const = 0;
|
BString& jsonPath) const = 0;
|
||||||
|
|
||||||
virtual status_t IfModifiedSinceHeaderValue(
|
virtual status_t IfModifiedSinceHeaderValue(
|
||||||
BString& headerValue) const;
|
BString& headerValue);
|
||||||
status_t IfModifiedSinceHeaderValue(
|
status_t IfModifiedSinceHeaderValue(
|
||||||
BString& headerValue,
|
BString& headerValue,
|
||||||
const BPath& metaDataPath,
|
const BPath& metaDataPath,
|
||||||
const BString& jsonPath) const;
|
const BString& jsonPath);
|
||||||
static void SetIfModifiedSinceHeaderValueFromMetaData(
|
static void SetIfModifiedSinceHeaderValueFromMetaData(
|
||||||
BString& headerValue,
|
BString& headerValue,
|
||||||
const StandardMetaData& metaData);
|
const StandardMetaData& metaData);
|
||||||
@@ -53,11 +58,11 @@ protected:
|
|||||||
status_t PopulateMetaData(
|
status_t PopulateMetaData(
|
||||||
StandardMetaData& metaData,
|
StandardMetaData& metaData,
|
||||||
const BPath& path,
|
const BPath& path,
|
||||||
const BString& jsonPath) const;
|
const BString& jsonPath);
|
||||||
|
|
||||||
status_t ParseJsonFromFileWithListener(
|
status_t ParseJsonFromFileWithListener(
|
||||||
BJsonEventListener *listener,
|
BJsonEventListener *listener,
|
||||||
const BPath& path) const;
|
const BPath& path);
|
||||||
|
|
||||||
virtual status_t DownloadToLocalFileAtomically(
|
virtual status_t DownloadToLocalFileAtomically(
|
||||||
const BPath& targetFilePath,
|
const BPath& targetFilePath,
|
||||||
@@ -81,13 +86,16 @@ private:
|
|||||||
const BUrl& url,
|
const BUrl& url,
|
||||||
uint32 redirects, uint32 failures);
|
uint32 redirects, uint32 failures);
|
||||||
|
|
||||||
static bool _LooksLikeGzip(const char *pathStr);
|
static bool _LooksLikeGzip(const char *pathStr);
|
||||||
static status_t _DeGzipInSitu(const BPath& path);
|
static status_t _DeGzipInSitu(const BPath& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 fOptions;
|
uint32 fOptions;
|
||||||
|
|
||||||
BHttpRequest* fRequest;
|
BHttpRequest* fRequest;
|
||||||
|
|
||||||
|
float fDownloadProgress;
|
||||||
|
float fDataProcessingProgress;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ABSTRACT_SERVER_PROCESS_H
|
#endif // ABSTRACT_SERVER_PROCESS_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2022, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -16,12 +16,11 @@
|
|||||||
#include "StorageUtils.h"
|
#include "StorageUtils.h"
|
||||||
|
|
||||||
|
|
||||||
AbstractSingleFileServerProcess::AbstractSingleFileServerProcess(
|
AbstractSingleFileServerProcess::AbstractSingleFileServerProcess(uint32 options)
|
||||||
uint32 options)
|
|
||||||
:
|
:
|
||||||
AbstractServerProcess(options),
|
AbstractServerProcess(options),
|
||||||
fDownloadDurationSeconds(0.0),
|
fDownloadDurationSeconds(0.0),
|
||||||
fProcessLocalDataDurationSeconds(0.0)
|
fProcessLocalDataDurationSeconds(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,25 +55,25 @@ AbstractSingleFileServerProcess::RunInternal()
|
|||||||
|
|
||||||
if (IsSuccess(result) && ShouldAttemptNetworkDownload(hasData)) {
|
if (IsSuccess(result) && ShouldAttemptNetworkDownload(hasData)) {
|
||||||
BStopWatch stopWatch("download", true);
|
BStopWatch stopWatch("download", true);
|
||||||
result = DownloadToLocalFileAtomically(
|
result = DownloadToLocalFileAtomically(localPath,
|
||||||
localPath,
|
|
||||||
ServerSettings::CreateFullUrl(urlPathComponent));
|
ServerSettings::CreateFullUrl(urlPathComponent));
|
||||||
fDownloadDurationSeconds = ((double) stopWatch.ElapsedTime() / 1000000.0);
|
fDownloadDurationSeconds = ((double)stopWatch.ElapsedTime() / 1000000.0);
|
||||||
|
|
||||||
if (!IsSuccess(result)) {
|
if (!IsSuccess(result)) {
|
||||||
if (hasData) {
|
if (hasData) {
|
||||||
HDINFO("[%s] failed to update data, but have old data "
|
HDINFO("[%s] failed to update data, but have old data anyway so carry on with that",
|
||||||
"anyway so carry on with that", Name());
|
Name());
|
||||||
result = B_OK;
|
result = B_OK;
|
||||||
} else
|
} else {
|
||||||
HDERROR("[%s] failed to obtain data", Name());
|
HDERROR("[%s] failed to obtain data", Name());
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
HDINFO("[%s] did fetch data", Name());
|
HDINFO("[%s] did fetch data", Name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsSuccess(result)) {
|
if (IsSuccess(result)) {
|
||||||
status_t hasDataResult = StorageUtils::ExistsObject(
|
status_t hasDataResult = StorageUtils::ExistsObject(localPath, &hasData, NULL, &size);
|
||||||
localPath, &hasData, NULL, &size);
|
|
||||||
|
|
||||||
hasData = hasData && size > 0;
|
hasData = hasData && size > 0;
|
||||||
|
|
||||||
@@ -89,7 +88,7 @@ AbstractSingleFileServerProcess::RunInternal()
|
|||||||
|
|
||||||
BStopWatch stopWatch("process local data", true);
|
BStopWatch stopWatch("process local data", true);
|
||||||
result = ProcessLocalData();
|
result = ProcessLocalData();
|
||||||
fProcessLocalDataDurationSeconds = ((double) stopWatch.ElapsedTime() / 1000000.0);
|
fProcessLocalDataDurationSeconds = ((double)stopWatch.ElapsedTime() / 1000000.0);
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case B_OK:
|
case B_OK:
|
||||||
@@ -124,8 +123,7 @@ AbstractSingleFileServerProcess::LogReport()
|
|||||||
if (ProcessState() == PROCESS_COMPLETE) {
|
if (ProcessState() == PROCESS_COMPLETE) {
|
||||||
BString downloadLogLine;
|
BString downloadLogLine;
|
||||||
BString localDataLogLine;
|
BString localDataLogLine;
|
||||||
downloadLogLine.SetToFormat("\n - download %6.3f",
|
downloadLogLine.SetToFormat("\n - download %6.3f", fDownloadDurationSeconds);
|
||||||
fDownloadDurationSeconds);
|
|
||||||
localDataLogLine.SetToFormat("\n - process local data %6.3f",
|
localDataLogLine.SetToFormat("\n - process local data %6.3f",
|
||||||
fProcessLocalDataDurationSeconds);
|
fProcessLocalDataDurationSeconds);
|
||||||
result.Append(downloadLogLine);
|
result.Append(downloadLogLine);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2021-2023, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2021-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "IncrementViewCounterProcess.h"
|
#include "IncrementViewCounterProcess.h"
|
||||||
@@ -20,14 +20,14 @@
|
|||||||
#define B_TRANSLATION_CONTEXT "IncrementViewCounterProcess"
|
#define B_TRANSLATION_CONTEXT "IncrementViewCounterProcess"
|
||||||
|
|
||||||
|
|
||||||
IncrementViewCounterProcess::IncrementViewCounterProcess(
|
IncrementViewCounterProcess::IncrementViewCounterProcess(Model* model,
|
||||||
Model* model, const PackageInfoRef& package)
|
const PackageInfoRef& package)
|
||||||
:
|
:
|
||||||
fPackage(package),
|
fPackage(package),
|
||||||
fModel(model)
|
fModel(model)
|
||||||
{
|
{
|
||||||
fDescription = BString(B_TRANSLATE("Recording view of \"%PackageName%\""))
|
fDescription = BString(B_TRANSLATE("Recording view of \"%PackageName%\""))
|
||||||
.ReplaceAll("%PackageName%", fPackage->Name());
|
.ReplaceAll("%PackageName%", fPackage->Name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -77,8 +77,8 @@ IncrementViewCounterProcess::RunInternal()
|
|||||||
|
|
||||||
while (attempts > 0 && !WasStopped()) {
|
while (attempts > 0 && !WasStopped()) {
|
||||||
BMessage resultEnvelope;
|
BMessage resultEnvelope;
|
||||||
WebAppInterface* webAppInterface = fModel->GetWebAppInterface();
|
WebAppInterfaceRef webApp = fModel->WebApp();
|
||||||
result = webAppInterface->IncrementViewCounter(fPackage, depot, resultEnvelope);
|
result = webApp->IncrementViewCounter(fPackage, depot, resultEnvelope);
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(resultEnvelope);
|
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(resultEnvelope);
|
||||||
@@ -97,8 +97,9 @@ IncrementViewCounterProcess::RunInternal()
|
|||||||
result = B_ERROR;
|
result = B_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
HDERROR("an error has arisen incrementing the view counter");
|
HDERROR("an error has arisen incrementing the view counter");
|
||||||
|
}
|
||||||
|
|
||||||
attempts--;
|
attempts--;
|
||||||
_SpinBetweenAttempts();
|
_SpinBetweenAttempts();
|
||||||
@@ -115,4 +116,3 @@ IncrementViewCounterProcess::_SpinBetweenAttempts()
|
|||||||
for (int32 i = 0; i < 10 && !WasStopped(); i++)
|
for (int32 i = 0; i < 10 && !WasStopped(); i++)
|
||||||
usleep(miniSpinDelays);
|
usleep(miniSpinDelays);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2022, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2018-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef LOCAL_PKG_DATA_LOAD_PROCESS__H
|
#ifndef LOCAL_PKG_DATA_LOAD_PROCESS__H
|
||||||
#define LOCAL_PKG_DATA_LOAD_PROCESS__H
|
#define LOCAL_PKG_DATA_LOAD_PROCESS__H
|
||||||
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "AbstractProcess.h"
|
#include "AbstractProcess.h"
|
||||||
|
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
@@ -29,9 +31,7 @@ class PkgDataLoadState;
|
|||||||
|
|
||||||
class LocalPkgDataLoadProcess : public AbstractProcess {
|
class LocalPkgDataLoadProcess : public AbstractProcess {
|
||||||
public:
|
public:
|
||||||
LocalPkgDataLoadProcess(
|
LocalPkgDataLoadProcess(Model *model, bool force = false);
|
||||||
PackageInfoListenerRef packageInfoListener,
|
|
||||||
Model *model, bool force = false);
|
|
||||||
virtual ~LocalPkgDataLoadProcess();
|
virtual ~LocalPkgDataLoadProcess();
|
||||||
|
|
||||||
const char* Name() const;
|
const char* Name() const;
|
||||||
@@ -41,14 +41,11 @@ protected:
|
|||||||
virtual status_t RunInternal();
|
virtual status_t RunInternal();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _NotifyError(const BString& messageText) const;
|
static void _NotifyError(const BString& messageText);
|
||||||
off_t _DeriveSize(const PackageInfoRef modelInfo) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model* fModel;
|
Model* fModel;
|
||||||
bool fForce;
|
bool fForce;
|
||||||
PackageInfoListenerRef
|
|
||||||
fPackageInfoListener;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LOCAL_PKG_DATA_LOAD_PROCESS__H
|
#endif // LOCAL_PKG_DATA_LOAD_PROCESS__H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2016-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Note that this file included code earlier from `Model.cpp` and
|
* Note that this file included code earlier from `Model.cpp` and
|
||||||
@@ -21,10 +21,10 @@
|
|||||||
|
|
||||||
|
|
||||||
PopulatePkgChangelogFromServerProcess::PopulatePkgChangelogFromServerProcess(
|
PopulatePkgChangelogFromServerProcess::PopulatePkgChangelogFromServerProcess(
|
||||||
PackageInfoRef packageInfo, Model* model)
|
const BString& packageName, Model* model)
|
||||||
:
|
:
|
||||||
fModel(model),
|
fModel(model),
|
||||||
fPackageInfo(packageInfo)
|
fPackageName(packageName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,10 +54,9 @@ PopulatePkgChangelogFromServerProcess::RunInternal()
|
|||||||
// TODO; use API spec to code generation techniques instead of this manually written client.
|
// TODO; use API spec to code generation techniques instead of this manually written client.
|
||||||
|
|
||||||
BMessage responsePayload;
|
BMessage responsePayload;
|
||||||
BString packageName = fPackageInfo->Name();
|
|
||||||
status_t result;
|
status_t result;
|
||||||
|
|
||||||
result = fModel->GetWebAppInterface()->GetChangelog(packageName, responsePayload);
|
result = fModel->WebApp()->GetChangelog(fPackageName, responsePayload);
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
BMessage resultMessage;
|
BMessage resultMessage;
|
||||||
@@ -67,31 +66,11 @@ PopulatePkgChangelogFromServerProcess::RunInternal()
|
|||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
if (resultMessage.FindString("content", &content) == B_OK) {
|
if (resultMessage.FindString("content", &content) == B_OK) {
|
||||||
content.Trim();
|
result = _UpdateChangelog(content.Trim());
|
||||||
|
HDDEBUG("changelog populated for [%s]", fPackageName.String());
|
||||||
PackageLocalizedTextRef localizedText = fPackageInfo->LocalizedText();
|
|
||||||
|
|
||||||
if (localizedText.IsSet()) {
|
|
||||||
localizedText = PackageLocalizedTextRef(
|
|
||||||
new PackageLocalizedText(*(localizedText.Get())), true);
|
|
||||||
} else {
|
|
||||||
localizedText = PackageLocalizedTextRef(new PackageLocalizedText(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
localizedText->SetChangelog(content);
|
|
||||||
|
|
||||||
// TODO; later work to make the `PackageInfo` immutable to avoid this locking
|
|
||||||
BAutolock locker(fModel->Lock());
|
|
||||||
fPackageInfo->SetLocalizedText(localizedText);
|
|
||||||
HDDEBUG("changelog populated for [%s]", packageName.String());
|
|
||||||
} else {
|
} else {
|
||||||
HDDEBUG("no changelog present for [%s]", packageName.String());
|
HDDEBUG("no changelog present for [%s]", fPackageName.String());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(responsePayload);
|
|
||||||
|
|
||||||
if (errorCode != ERROR_CODE_NONE)
|
|
||||||
ServerHelper::NotifyServerJsonRpcError(responsePayload);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ServerHelper::NotifyTransportError(result);
|
ServerHelper::NotifyTransportError(result);
|
||||||
@@ -99,3 +78,25 @@ PopulatePkgChangelogFromServerProcess::RunInternal()
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PopulatePkgChangelogFromServerProcess::_UpdateChangelog(const BString& value)
|
||||||
|
{
|
||||||
|
PackageInfoRef package = fModel->PackageForName(fPackageName);
|
||||||
|
|
||||||
|
if (!package.IsSet()) {
|
||||||
|
HDERROR("the package [%s] was not found", fPackageName.String());
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageLocalizedTextRef localizedText
|
||||||
|
= PackageLocalizedTextBuilder(package->LocalizedText()).WithChangelog(value).BuildRef();
|
||||||
|
|
||||||
|
PackageInfoRef updatedPackage
|
||||||
|
= PackageInfoBuilder(package).WithLocalizedText(localizedText).BuildRef();
|
||||||
|
|
||||||
|
fModel->AddPackage(updatedPackage);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2024-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@@ -31,7 +31,7 @@ class PkgDataLoadState;
|
|||||||
class PopulatePkgChangelogFromServerProcess : public AbstractProcess
|
class PopulatePkgChangelogFromServerProcess : public AbstractProcess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PopulatePkgChangelogFromServerProcess(PackageInfoRef packageInfo,
|
PopulatePkgChangelogFromServerProcess(const BString& packageName,
|
||||||
Model *model);
|
Model *model);
|
||||||
virtual ~PopulatePkgChangelogFromServerProcess();
|
virtual ~PopulatePkgChangelogFromServerProcess();
|
||||||
|
|
||||||
@@ -41,9 +41,12 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual status_t RunInternal();
|
virtual status_t RunInternal();
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _UpdateChangelog(const BString& value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model* fModel;
|
Model* fModel;
|
||||||
PackageInfoRef fPackageInfo;
|
BString fPackageName;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // POPULATE_PKG_CHANGELOG_FROM_SERVER_PROCESS__H
|
#endif // POPULATE_PKG_CHANGELOG_FROM_SERVER_PROCESS__H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2018-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -23,7 +23,8 @@
|
|||||||
|
|
||||||
PopulatePkgSizesProcess::PopulatePkgSizesProcess(Model* model)
|
PopulatePkgSizesProcess::PopulatePkgSizesProcess(Model* model)
|
||||||
:
|
:
|
||||||
fModel(model)
|
fModel(model),
|
||||||
|
fProgress(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,55 +48,97 @@ PopulatePkgSizesProcess::Description() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
PopulatePkgSizesProcess::Progress()
|
||||||
|
{
|
||||||
|
return fProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PopulatePkgSizesProcess::RunInternal()
|
PopulatePkgSizesProcess::RunInternal()
|
||||||
{
|
{
|
||||||
int32 countPkgs = 0;
|
int32 countPkgs;
|
||||||
int32 countPkgSized = 0;
|
int32 countPkgSized = 0;
|
||||||
int32 countPkgUnsized = 0;
|
int32 countPkgUnsized = 0;
|
||||||
|
|
||||||
HDINFO("[%s] will populate size for pkgs without a size", Name());
|
HDINFO("[%s] will populate size for pkgs without a size", Name());
|
||||||
|
|
||||||
for (int32 d = 0; d < fModel->CountDepots() && !WasStopped(); d++) {
|
const std::vector<PackageInfoRef> packages = _SnapshotOfPackages();
|
||||||
DepotInfoRef depotInfo = fModel->DepotAtIndex(d);
|
std::vector<PackageInfoRef> updatedPackages;
|
||||||
countPkgs += depotInfo->CountPackages();
|
|
||||||
|
|
||||||
for (int32 p = 0; p < depotInfo->CountPackages(); p++) {
|
countPkgs = static_cast<int32>(packages.size());
|
||||||
PackageInfoRef packageInfo = depotInfo->PackageAtIndex(p);
|
|
||||||
|
|
||||||
if (!packageInfo.IsSet())
|
for (int32 i = 0; i < countPkgs; i++) {
|
||||||
HDFATAL("package is not set");
|
PackageInfoRef package = packages[i];
|
||||||
|
const char* packageName = package->Name().String();
|
||||||
|
|
||||||
PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(packageInfo);
|
if (!package.IsSet())
|
||||||
PackageState state = localInfo->State();
|
HDFATAL("package is not set");
|
||||||
|
|
||||||
if (localInfo->Size() <= 0 && (state == ACTIVATED || state == INSTALLED)) {
|
PackageLocalInfoRef localInfo = package->LocalInfo();
|
||||||
off_t derivedSize = _DeriveSize(packageInfo);
|
|
||||||
|
|
||||||
if (derivedSize > 0) {
|
if (_ShouldDeriveSize(localInfo)) {
|
||||||
localInfo->SetSize(derivedSize);
|
off_t derivedSize = _DeriveSize(package);
|
||||||
countPkgSized++;
|
|
||||||
HDDEBUG("[%s] did derive a size for package [%s]", Name(),
|
if (derivedSize > 0) {
|
||||||
packageInfo->Name().String());
|
PackageLocalInfoBuilder localInfoBuilder;
|
||||||
} else {
|
|
||||||
countPkgUnsized++;
|
if (localInfo.IsSet())
|
||||||
HDDEBUG("[%s] unable to derive a size for package [%s]", Name(),
|
localInfoBuilder = PackageLocalInfoBuilder(localInfo);
|
||||||
packageInfo->Name().String());
|
|
||||||
}
|
localInfoBuilder.WithSize(derivedSize);
|
||||||
|
|
||||||
|
PackageLocalInfoRef localInfo = localInfoBuilder.BuildRef();
|
||||||
|
|
||||||
|
updatedPackages.push_back(
|
||||||
|
PackageInfoBuilder(package).WithLocalInfo(localInfo).BuildRef());
|
||||||
|
|
||||||
|
countPkgSized++;
|
||||||
|
HDDEBUG("[%s] did derive a size for package [%s]", Name(), packageName);
|
||||||
|
} else {
|
||||||
|
countPkgUnsized++;
|
||||||
|
HDDEBUG("[%s] unable to derive a size for package [%s]", Name(), packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
packageInfo->SetLocalInfo(localInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_SetProgress(static_cast<float>(i) / static_cast<float>(countPkgs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fModel->AddPackagesWithChange(updatedPackages, PKG_CHANGED_LOCAL_INFO);
|
||||||
|
|
||||||
|
_SetProgress(1.0);
|
||||||
|
|
||||||
HDINFO("[%s] did populate size for %" B_PRId32 " packages with %" B_PRId32
|
HDINFO("[%s] did populate size for %" B_PRId32 " packages with %" B_PRId32
|
||||||
" already having a size and %" B_PRId32 " unable to derive a size",
|
" already having a size and %" B_PRId32 " unable to derive a size",
|
||||||
Name(), countPkgSized, countPkgs - countPkgSized, countPkgUnsized);
|
Name(), countPkgSized, countPkgs - (countPkgSized + countPkgUnsized), countPkgUnsized);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector<PackageInfoRef>
|
||||||
|
PopulatePkgSizesProcess::_SnapshotOfPackages() const
|
||||||
|
{
|
||||||
|
return fModel->Packages();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PopulatePkgSizesProcess::_ShouldDeriveSize(PackageLocalInfoRef localInfo) const
|
||||||
|
{
|
||||||
|
if (!localInfo.IsSet())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (localInfo->Size() > 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PackageState state = localInfo->State();
|
||||||
|
|
||||||
|
return state == ACTIVATED || state == INSTALLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
off_t
|
off_t
|
||||||
PopulatePkgSizesProcess::_DeriveSize(const PackageInfoRef package) const
|
PopulatePkgSizesProcess::_DeriveSize(const PackageInfoRef package) const
|
||||||
{
|
{
|
||||||
@@ -111,4 +154,14 @@ PopulatePkgSizesProcess::_DeriveSize(const PackageInfoRef package) const
|
|||||||
HDDEBUG("unable to get the local file of package [%s]", package->Name().String());
|
HDDEBUG("unable to get the local file of package [%s]", package->Name().String());
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PopulatePkgSizesProcess::_SetProgress(float value)
|
||||||
|
{
|
||||||
|
if (!_ShouldProcessProgress() && value != 1.0 && (value - fProgress) < 0.1)
|
||||||
|
return;
|
||||||
|
fProgress = value;
|
||||||
|
_NotifyChanged();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2023, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2023-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef POPULATE_PKG_SIZES_PROCESS_H
|
#ifndef POPULATE_PKG_SIZES_PROCESS_H
|
||||||
#define POPULATE_PKG_SIZES_PROCESS_H
|
#define POPULATE_PKG_SIZES_PROCESS_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include "AbstractProcess.h"
|
#include "AbstractProcess.h"
|
||||||
@@ -23,15 +25,22 @@ public:
|
|||||||
|
|
||||||
virtual const char* Name() const;
|
virtual const char* Name() const;
|
||||||
virtual const char* Description() const;
|
virtual const char* Description() const;
|
||||||
|
virtual float Progress();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual status_t RunInternal();
|
virtual status_t RunInternal();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const std::vector<PackageInfoRef>
|
||||||
|
_SnapshotOfPackages() const;
|
||||||
|
bool _ShouldDeriveSize(PackageLocalInfoRef localInfo) const;
|
||||||
off_t _DeriveSize(const PackageInfoRef modelInfo) const;
|
off_t _DeriveSize(const PackageInfoRef modelInfo) const;
|
||||||
|
|
||||||
|
void _SetProgress(float value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model* fModel;
|
Model* fModel;
|
||||||
|
float fProgress;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2016-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
|
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -23,10 +23,10 @@
|
|||||||
|
|
||||||
|
|
||||||
PopulatePkgUserRatingsFromServerProcess::PopulatePkgUserRatingsFromServerProcess(
|
PopulatePkgUserRatingsFromServerProcess::PopulatePkgUserRatingsFromServerProcess(
|
||||||
PackageInfoRef packageInfo, Model* model)
|
const BString& packageName, Model* model)
|
||||||
:
|
:
|
||||||
fModel(model),
|
fModel(model),
|
||||||
fPackageInfo(packageInfo)
|
fPackageName(packageName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,29 +59,21 @@ PopulatePkgUserRatingsFromServerProcess::RunInternal()
|
|||||||
|
|
||||||
// Retrieve info from web-app
|
// Retrieve info from web-app
|
||||||
BMessage info;
|
BMessage info;
|
||||||
|
BString webAppRepositoryCode = _WebAppRepositoryCode();
|
||||||
|
|
||||||
BString packageName;
|
if (webAppRepositoryCode.IsEmpty()) {
|
||||||
BString webAppRepositoryCode;
|
HDERROR("unable to get the web app repository code for pkg [%s]", fPackageName.String());
|
||||||
|
status = B_ERROR;
|
||||||
{
|
|
||||||
BAutolock locker(&fLock);
|
|
||||||
packageName = fPackageInfo->Name();
|
|
||||||
|
|
||||||
BString depotName = PackageUtils::DepotName(fPackageInfo);
|
|
||||||
const DepotInfo* depot = fModel->DepotForName(depotName);
|
|
||||||
|
|
||||||
if (depot != NULL)
|
|
||||||
webAppRepositoryCode = depot->WebAppRepositoryCode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
status = fModel->GetWebAppInterface()->RetrieveUserRatingsForPackageForDisplay(packageName,
|
status = fModel->WebApp()->RetrieveUserRatingsForPackageForDisplay(fPackageName,
|
||||||
webAppRepositoryCode, BString(), 0, PACKAGE_INFO_MAX_USER_RATINGS, info);
|
webAppRepositoryCode, BString(), 0, PACKAGE_INFO_MAX_USER_RATINGS, info);
|
||||||
// ^ note intentionally not using the repository source code as this would then show
|
// ^ note intentionally not using the repository source code as this would then show
|
||||||
// too few results as it would be architecture specific.
|
// too few results as it would be architecture specific.
|
||||||
}
|
}
|
||||||
|
|
||||||
UserRatingInfoRef userRatingInfo(new UserRatingInfo(), true);
|
PackageUserRatingInfoBuilder userRatingInfoBuilder;
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
// Parse message
|
// Parse message
|
||||||
@@ -112,7 +104,7 @@ PopulatePkgUserRatingsFromServerProcess::RunInternal()
|
|||||||
BString user;
|
BString user;
|
||||||
BMessage userInfo;
|
BMessage userInfo;
|
||||||
if (item.FindMessage("user", &userInfo) != B_OK
|
if (item.FindMessage("user", &userInfo) != B_OK
|
||||||
|| userInfo.FindString("nickname", &user) != B_OK) {
|
|| userInfo.FindString("nickname", &user) != B_OK) {
|
||||||
HDERROR("ignored user rating [%s] without a user nickname", code.String());
|
HDERROR("ignored user rating [%s] without a user nickname", code.String());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -170,15 +162,15 @@ PopulatePkgUserRatingsFromServerProcess::RunInternal()
|
|||||||
UserRatingRef userRating(
|
UserRatingRef userRating(
|
||||||
new UserRating(UserInfo(user), rating, comment, languageCode,
|
new UserRating(UserInfo(user), rating, comment, languageCode,
|
||||||
// note that language identifiers are "code" in HDS and "id" in Haiku
|
// note that language identifiers are "code" in HDS and "id" in Haiku
|
||||||
versionString, (uint64) createTimestamp),
|
versionString, static_cast<uint64>(createTimestamp)),
|
||||||
true);
|
true);
|
||||||
userRatingInfo->AddUserRating(userRating);
|
userRatingInfoBuilder.AddUserRating(userRating);
|
||||||
HDDEBUG("rating [%s] retrieved from server", code.String());
|
HDDEBUG("rating [%s] retrieved from server", code.String());
|
||||||
}
|
}
|
||||||
|
|
||||||
userRatingInfo->SetUserRatingsPopulated();
|
userRatingInfoBuilder.WithUserRatingsPopulated();
|
||||||
HDDEBUG("did retrieve %" B_PRIi32 " user ratings for [%s]", index - 1,
|
HDDEBUG("did retrieve %" B_PRIi32 " user ratings for [%s]", index - 1,
|
||||||
packageName.String());
|
fPackageName.String());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(info);
|
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(info);
|
||||||
@@ -197,14 +189,13 @@ PopulatePkgUserRatingsFromServerProcess::RunInternal()
|
|||||||
BMessage summaryResponse;
|
BMessage summaryResponse;
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
status = fModel->GetWebAppInterface()->RetrieveUserRatingSummaryForPackage(packageName,
|
status = fModel->WebApp()->RetrieveUserRatingSummaryForPackage(fPackageName,
|
||||||
webAppRepositoryCode, summaryResponse);
|
webAppRepositoryCode, summaryResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
// Parse message
|
// Parse message
|
||||||
|
UserRatingSummaryBuilder userRatingSummaryBuilder;
|
||||||
UserRatingSummaryRef userRatingSummary(new UserRatingSummary(), true);
|
|
||||||
|
|
||||||
BMessage result;
|
BMessage result;
|
||||||
|
|
||||||
@@ -214,15 +205,18 @@ PopulatePkgUserRatingsFromServerProcess::RunInternal()
|
|||||||
status = summaryResponse.FindMessage("result", &result);
|
status = summaryResponse.FindMessage("result", &result);
|
||||||
|
|
||||||
double sampleSizeF;
|
double sampleSizeF;
|
||||||
|
int sampleSize = 0;
|
||||||
bool hasData;
|
bool hasData;
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = result.FindDouble("sampleSize", &sampleSizeF);
|
status = result.FindDouble("sampleSize", &sampleSizeF);
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK) {
|
||||||
userRatingSummary->SetRatingCount(static_cast<int>(sampleSizeF));
|
sampleSize = static_cast<int>(sampleSizeF);
|
||||||
|
userRatingSummaryBuilder.WithRatingCount(sampleSize);
|
||||||
|
}
|
||||||
|
|
||||||
hasData = status == B_OK && userRatingSummary->RatingCount() > 0;
|
hasData = status == B_OK && sampleSize > 0;
|
||||||
|
|
||||||
if (hasData) {
|
if (hasData) {
|
||||||
double ratingF;
|
double ratingF;
|
||||||
@@ -231,7 +225,7 @@ PopulatePkgUserRatingsFromServerProcess::RunInternal()
|
|||||||
status = result.FindDouble("rating", &ratingF);
|
status = result.FindDouble("rating", &ratingF);
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
userRatingSummary->SetAverageRating(ratingF);
|
userRatingSummaryBuilder.WithAverageRating(ratingF);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasData) {
|
if (hasData) {
|
||||||
@@ -261,11 +255,12 @@ PopulatePkgUserRatingsFromServerProcess::RunInternal()
|
|||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = ratingDistributionItem.FindDouble("total", &ratingDistributionTotalF);
|
status = ratingDistributionItem.FindDouble("total", &ratingDistributionTotalF);
|
||||||
|
|
||||||
userRatingSummary->SetRatingByStar(static_cast<int>(ratingDistributionRatingF),
|
userRatingSummaryBuilder.AddRatingByStar(
|
||||||
|
static_cast<int>(ratingDistributionRatingF),
|
||||||
static_cast<int>(ratingDistributionTotalF));
|
static_cast<int>(ratingDistributionTotalF));
|
||||||
}
|
}
|
||||||
|
|
||||||
userRatingInfo->SetSummary(userRatingSummary);
|
userRatingInfoBuilder.WithSummary(userRatingSummaryBuilder.BuildRef());
|
||||||
} else {
|
} else {
|
||||||
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(summaryResponse);
|
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(summaryResponse);
|
||||||
|
|
||||||
@@ -277,10 +272,28 @@ PopulatePkgUserRatingsFromServerProcess::RunInternal()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
// TODO; later make the PackageInfo immutable to avoid the need for locking here.
|
PackageInfoRef package = fModel->PackageForName(fPackageName);
|
||||||
BAutolock locker(&fLock);
|
|
||||||
fPackageInfo->SetUserRatingInfo(userRatingInfo);
|
PackageInfoRef updatedPackage = PackageInfoBuilder(package)
|
||||||
|
.WithUserRatingInfo(userRatingInfoBuilder.BuildRef())
|
||||||
|
.BuildRef();
|
||||||
|
|
||||||
|
fModel->AddPackage(updatedPackage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BString
|
||||||
|
PopulatePkgUserRatingsFromServerProcess::_WebAppRepositoryCode() const
|
||||||
|
{
|
||||||
|
const PackageInfoRef package = fModel->PackageForName(fPackageName);
|
||||||
|
const BString depotName = PackageUtils::DepotName(package);
|
||||||
|
const DepotInfoRef depot = fModel->DepotForName(depotName);
|
||||||
|
|
||||||
|
if (depot.IsSet())
|
||||||
|
return depot->WebAppRepositoryCode();
|
||||||
|
|
||||||
|
return BString();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2024-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef POPULATE_PKG_USER_RATINGS_FROM_SERVER_PROCESS__H
|
#ifndef POPULATE_PKG_USER_RATINGS_FROM_SERVER_PROCESS__H
|
||||||
@@ -29,7 +29,7 @@ class PkgDataLoadState;
|
|||||||
class PopulatePkgUserRatingsFromServerProcess : public AbstractProcess
|
class PopulatePkgUserRatingsFromServerProcess : public AbstractProcess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PopulatePkgUserRatingsFromServerProcess(PackageInfoRef packageInfo,
|
PopulatePkgUserRatingsFromServerProcess(const BString& packageName,
|
||||||
Model *model);
|
Model *model);
|
||||||
virtual ~PopulatePkgUserRatingsFromServerProcess();
|
virtual ~PopulatePkgUserRatingsFromServerProcess();
|
||||||
|
|
||||||
@@ -39,9 +39,12 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual status_t RunInternal();
|
virtual status_t RunInternal();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const BString _WebAppRepositoryCode() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model* fModel;
|
Model* fModel;
|
||||||
PackageInfoRef fPackageInfo;
|
BString fPackageName;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // POPULATE_PKG_USER_RATINGS_FROM_SERVER_PROCESS__H
|
#endif // POPULATE_PKG_USER_RATINGS_FROM_SERVER_PROCESS__H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2021, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "ServerIconExportUpdateProcess.h"
|
#include "ServerIconExportUpdateProcess.h"
|
||||||
@@ -8,13 +8,14 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
#include <AutoLocker.h>
|
#include <BufferIO.h>
|
||||||
#include <Catalog.h>
|
#include <Catalog.h>
|
||||||
#include <FileIO.h>
|
#include <FileIO.h>
|
||||||
|
|
||||||
#include "DataIOUtils.h"
|
#include "DataIOUtils.h"
|
||||||
#include "HaikuDepotConstants.h"
|
#include "HaikuDepotConstants.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "PackageIconTarRepository.h"
|
||||||
#include "ServerHelper.h"
|
#include "ServerHelper.h"
|
||||||
#include "StandardMetaDataJsonEventListener.h"
|
#include "StandardMetaDataJsonEventListener.h"
|
||||||
#include "StorageUtils.h"
|
#include "StorageUtils.h"
|
||||||
@@ -55,6 +56,7 @@ InfoJsonExtractEntryListener::InfoJsonExtractEntryListener()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
InfoJsonExtractEntryListener::~InfoJsonExtractEntryListener()
|
InfoJsonExtractEntryListener::~InfoJsonExtractEntryListener()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -68,14 +70,12 @@ InfoJsonExtractEntryListener::GetInfoJsonData()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
InfoJsonExtractEntryListener::Handle( const TarArchiveHeader& header,
|
InfoJsonExtractEntryListener::Handle(const TarArchiveHeader& header, size_t offset, BDataIO* data)
|
||||||
size_t offset, BDataIO *data)
|
|
||||||
{
|
{
|
||||||
if (header.Length() > 0 && header.FileName() == ENTRY_PATH_METADATA) {
|
if (header.Length() > 0 && header.FileName() == ENTRY_PATH_METADATA) {
|
||||||
status_t copyResult = DataIOUtils::CopyAll(&fInfoJsonData, data);
|
status_t copyResult = DataIOUtils::CopyAll(&fInfoJsonData, data);
|
||||||
if (copyResult == B_OK) {
|
if (copyResult == B_OK) {
|
||||||
HDINFO("[InfoJsonExtractEntryListener] did extract [%s]",
|
HDINFO("[InfoJsonExtractEntryListener] did extract [%s]", ENTRY_PATH_METADATA);
|
||||||
ENTRY_PATH_METADATA);
|
|
||||||
fInfoJsonData.Seek(0, SEEK_SET);
|
fInfoJsonData.Seek(0, SEEK_SET);
|
||||||
return B_CANCELED;
|
return B_CANCELED;
|
||||||
// this will prevent further scanning of the tar file
|
// this will prevent further scanning of the tar file
|
||||||
@@ -88,10 +88,8 @@ InfoJsonExtractEntryListener::Handle( const TarArchiveHeader& header,
|
|||||||
|
|
||||||
|
|
||||||
/*! This constructor will locate the cached data in a standardized location
|
/*! This constructor will locate the cached data in a standardized location
|
||||||
*/
|
*/
|
||||||
|
ServerIconExportUpdateProcess::ServerIconExportUpdateProcess(Model* model,
|
||||||
ServerIconExportUpdateProcess::ServerIconExportUpdateProcess(
|
|
||||||
Model* model,
|
|
||||||
uint32 serverProcessOptions)
|
uint32 serverProcessOptions)
|
||||||
:
|
:
|
||||||
AbstractSingleFileServerProcess(serverProcessOptions),
|
AbstractSingleFileServerProcess(serverProcessOptions),
|
||||||
@@ -122,8 +120,20 @@ ServerIconExportUpdateProcess::Description() const
|
|||||||
status_t
|
status_t
|
||||||
ServerIconExportUpdateProcess::ProcessLocalData()
|
ServerIconExportUpdateProcess::ProcessLocalData()
|
||||||
{
|
{
|
||||||
status_t result = fModel->InitPackageIconRepository();
|
BPath tarPath;
|
||||||
_NotifyPackagesWithIconsInDepots();
|
status_t result = GetLocalPath(tarPath);
|
||||||
|
|
||||||
|
if (result == B_OK) {
|
||||||
|
PackageIconTarRepository* tarRepository = new PackageIconTarRepository(tarPath);
|
||||||
|
|
||||||
|
result = tarRepository->Init();
|
||||||
|
|
||||||
|
if (result == B_OK)
|
||||||
|
fModel->SetIconRepository(PackageIconRepositoryRef(tarRepository, true));
|
||||||
|
else
|
||||||
|
delete tarRepository;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +154,7 @@ ServerIconExportUpdateProcess::GetLocalPath(BPath& path) const
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ServerIconExportUpdateProcess::IfModifiedSinceHeaderValue(BString& headerValue) const
|
ServerIconExportUpdateProcess::IfModifiedSinceHeaderValue(BString& headerValue)
|
||||||
{
|
{
|
||||||
headerValue.SetTo("");
|
headerValue.SetTo("");
|
||||||
|
|
||||||
@@ -164,13 +174,13 @@ ServerIconExportUpdateProcess::IfModifiedSinceHeaderValue(BString& headerValue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
BFile *tarIo = new BFile(tarPath.Path(), O_RDONLY);
|
BFile* tarIo = new BFile(tarPath.Path(), O_RDONLY);
|
||||||
ObjectDeleter<BFile> tarIoDeleter(tarIo);
|
BBufferIO* bufferTarIo = new BBufferIO(tarIo, 10 * 1024, true);
|
||||||
InfoJsonExtractEntryListener* extractDataListener
|
ObjectDeleter<BBufferIO> tarIoDeleter(bufferTarIo);
|
||||||
= new InfoJsonExtractEntryListener();
|
|
||||||
ObjectDeleter<InfoJsonExtractEntryListener> extractDataListenerDeleter(
|
InfoJsonExtractEntryListener* extractDataListener = new InfoJsonExtractEntryListener();
|
||||||
extractDataListener);
|
ObjectDeleter<InfoJsonExtractEntryListener> extractDataListenerDeleter(extractDataListener);
|
||||||
result = TarArchiveService::ForEachEntry(*tarIo, extractDataListener);
|
result = TarArchiveService::ForEachEntry(*bufferTarIo, extractDataListener);
|
||||||
|
|
||||||
if (result == B_CANCELED) {
|
if (result == B_CANCELED) {
|
||||||
// the cancellation is expected because it will cancel when it finds
|
// the cancellation is expected because it will cancel when it finds
|
||||||
@@ -181,26 +191,20 @@ ServerIconExportUpdateProcess::IfModifiedSinceHeaderValue(BString& headerValue)
|
|||||||
StandardMetaData metaData;
|
StandardMetaData metaData;
|
||||||
BString metaDataJsonPath;
|
BString metaDataJsonPath;
|
||||||
GetStandardMetaDataJsonPath(metaDataJsonPath);
|
GetStandardMetaDataJsonPath(metaDataJsonPath);
|
||||||
StandardMetaDataJsonEventListener parseInfoJsonListener(
|
StandardMetaDataJsonEventListener parseInfoJsonListener(metaDataJsonPath, metaData);
|
||||||
metaDataJsonPath, metaData);
|
BPrivate::BJson::Parse(&(extractDataListener->GetInfoJsonData()),
|
||||||
BPrivate::BJson::Parse(
|
|
||||||
&(extractDataListener->GetInfoJsonData()),
|
|
||||||
&parseInfoJsonListener);
|
&parseInfoJsonListener);
|
||||||
|
|
||||||
result = parseInfoJsonListener.ErrorStatus();
|
result = parseInfoJsonListener.ErrorStatus();
|
||||||
|
|
||||||
// An example of this output would be; 'Fri, 24 Oct 2014 19:32:27 +0000'
|
// An example of this output would be; 'Fri, 24 Oct 2014 19:32:27 +0000'
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK)
|
||||||
SetIfModifiedSinceHeaderValueFromMetaData(
|
SetIfModifiedSinceHeaderValueFromMetaData(headerValue, metaData);
|
||||||
headerValue, metaData);
|
else
|
||||||
} else {
|
HDERROR("[%s] unable to parse the meta data from the tar file", Name());
|
||||||
HDERROR("[%s] unable to parse the meta data from the tar file",
|
|
||||||
Name());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
HDERROR("[%s] did not find the metadata [%s] in the tar",
|
HDERROR("[%s] did not find the metadata [%s] in the tar", Name(), ENTRY_PATH_METADATA);
|
||||||
Name(), ENTRY_PATH_METADATA);
|
|
||||||
result = B_BAD_DATA;
|
result = B_BAD_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,8 +222,7 @@ ServerIconExportUpdateProcess::GetStandardMetaDataPath(BPath& path) const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerIconExportUpdateProcess::GetStandardMetaDataJsonPath(
|
ServerIconExportUpdateProcess::GetStandardMetaDataJsonPath(BString& jsonPath) const
|
||||||
BString& jsonPath) const
|
|
||||||
{
|
{
|
||||||
jsonPath.SetTo("$");
|
jsonPath.SetTo("$");
|
||||||
// the "$" here indicates that the data is at the top level.
|
// the "$" here indicates that the data is at the top level.
|
||||||
@@ -231,27 +234,3 @@ ServerIconExportUpdateProcess::UrlPathComponent()
|
|||||||
{
|
{
|
||||||
return "/__pkgicon/all.tar.gz";
|
return "/__pkgicon/all.tar.gz";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ServerIconExportUpdateProcess::_NotifyPackagesWithIconsInDepots() const
|
|
||||||
{
|
|
||||||
for (int32 d = 0; d < fModel->CountDepots(); d++) {
|
|
||||||
_NotifyPackagesWithIconsInDepot(fModel->DepotAtIndex(d));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ServerIconExportUpdateProcess::_NotifyPackagesWithIconsInDepot(
|
|
||||||
const DepotInfoRef& depot) const
|
|
||||||
{
|
|
||||||
PackageIconRepository& packageIconRepository
|
|
||||||
= fModel->GetPackageIconRepository();
|
|
||||||
for (int32 p = 0; p < depot->CountPackages(); p++) {
|
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
|
||||||
const PackageInfoRef& packageInfoRef = depot->PackageAtIndex(p);
|
|
||||||
if (packageIconRepository.HasAnyIcon(packageInfoRef->Name()))
|
|
||||||
packageInfoRef->NotifyChangedIcon();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef SERVER_ICON_EXPORT_UPDATE_PROCESS_H
|
#ifndef SERVER_ICON_EXPORT_UPDATE_PROCESS_H
|
||||||
@@ -32,7 +32,7 @@ public:
|
|||||||
|
|
||||||
virtual status_t GetLocalPath(BPath& path) const;
|
virtual status_t GetLocalPath(BPath& path) const;
|
||||||
virtual status_t IfModifiedSinceHeaderValue(
|
virtual status_t IfModifiedSinceHeaderValue(
|
||||||
BString& headerValue) const;
|
BString& headerValue);
|
||||||
|
|
||||||
|
|
||||||
virtual status_t GetStandardMetaDataPath(BPath& path) const;
|
virtual status_t GetStandardMetaDataPath(BPath& path) const;
|
||||||
@@ -42,11 +42,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual BString UrlPathComponent();
|
virtual BString UrlPathComponent();
|
||||||
|
|
||||||
private:
|
|
||||||
void _NotifyPackagesWithIconsInDepots() const;
|
|
||||||
void _NotifyPackagesWithIconsInDepot(
|
|
||||||
const DepotInfoRef& depotInfo) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model* fModel;
|
Model* fModel;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -33,18 +33,22 @@
|
|||||||
#define B_TRANSLATION_CONTEXT "ServerPkgDataUpdateProcess"
|
#define B_TRANSLATION_CONTEXT "ServerPkgDataUpdateProcess"
|
||||||
|
|
||||||
|
|
||||||
/*! This package listener (not at the JSON level) is feeding in the
|
static std::size_t kPackageBatchSize = 100;
|
||||||
packages as they are parsed and processing them.
|
|
||||||
|
static uint32 kPackageChangeMask = PKG_CHANGED_RATINGS | PKG_CHANGED_SCREENSHOTS
|
||||||
|
| PKG_CHANGED_CLASSIFICATION | PKG_CHANGED_LOCALIZED_TEXT | PKG_CHANGED_LOCAL_INFO
|
||||||
|
| PKG_CHANGED_CORE_INFO;
|
||||||
|
|
||||||
|
|
||||||
|
/*! This package listener (not at the JSON level) is feeding in the
|
||||||
|
packages as they are parsed and processing them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PackageFillingPkgListener : public DumpExportPkgListener {
|
class PackageFillingPkgListener : public DumpExportPkgListener {
|
||||||
public:
|
public:
|
||||||
PackageFillingPkgListener(Model *model,
|
PackageFillingPkgListener(Model *model, Stoppable* stoppable);
|
||||||
BString& depotName, Stoppable* stoppable);
|
|
||||||
virtual ~PackageFillingPkgListener();
|
virtual ~PackageFillingPkgListener();
|
||||||
|
|
||||||
virtual bool ConsumePackage(const PackageInfoRef& package,
|
|
||||||
DumpExportPkg* pkg);
|
|
||||||
virtual bool Handle(DumpExportPkg* item);
|
virtual bool Handle(DumpExportPkg* item);
|
||||||
virtual void Complete();
|
virtual void Complete();
|
||||||
|
|
||||||
@@ -53,26 +57,36 @@ public:
|
|||||||
private:
|
private:
|
||||||
static ScreenshotInfoRef _CreateScreenshot(DumpExportPkgScreenshot* screenshot);
|
static ScreenshotInfoRef _CreateScreenshot(DumpExportPkgScreenshot* screenshot);
|
||||||
|
|
||||||
|
void _FlushUpdatedPackages();
|
||||||
|
|
||||||
|
const PackageInfoRef
|
||||||
|
_PackageForName(const BString& name) const;
|
||||||
|
const PackageInfoRef
|
||||||
|
_CreateUpdatePackage(const PackageInfoRef& package,
|
||||||
|
const DumpExportPkg* pkg);
|
||||||
|
|
||||||
|
void _InitCategories();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BString fDepotName;
|
|
||||||
Model* fModel;
|
Model* fModel;
|
||||||
std::vector<CategoryRef>
|
std::map<BString, CategoryRef>
|
||||||
fCategories;
|
fCategories;
|
||||||
|
std::vector<PackageInfoRef>
|
||||||
|
fUpdatedPackages;
|
||||||
Stoppable* fStoppable;
|
Stoppable* fStoppable;
|
||||||
uint32 fCount;
|
uint32 fCount;
|
||||||
bool fDebugEnabled;
|
bool fDebugEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PackageFillingPkgListener::PackageFillingPkgListener(Model* model,
|
PackageFillingPkgListener::PackageFillingPkgListener(Model* model, Stoppable* stoppable)
|
||||||
BString& depotName, Stoppable* stoppable)
|
|
||||||
:
|
:
|
||||||
fDepotName(depotName),
|
|
||||||
fModel(model),
|
fModel(model),
|
||||||
fStoppable(stoppable),
|
fStoppable(stoppable),
|
||||||
fCount(0),
|
fCount(0),
|
||||||
fDebugEnabled(Logger::IsDebugEnabled())
|
fDebugEnabled(Logger::IsDebugEnabled())
|
||||||
{
|
{
|
||||||
|
_InitCategories();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -81,110 +95,133 @@ PackageFillingPkgListener::~PackageFillingPkgListener()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
void
|
||||||
PackageFillingPkgListener::ConsumePackage(const PackageInfoRef& package,
|
PackageFillingPkgListener::_InitCategories()
|
||||||
DumpExportPkg* pkg)
|
{
|
||||||
|
std::vector<CategoryRef> categories = fModel->Categories();
|
||||||
|
std::vector<CategoryRef>::const_iterator it;
|
||||||
|
|
||||||
|
for (it = categories.begin(); it != categories.end(); it++) {
|
||||||
|
const CategoryRef& category = *it;
|
||||||
|
fCategories[category->Code()] = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fCategories.empty())
|
||||||
|
HDERROR("there are no categories present");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PackageInfoRef
|
||||||
|
PackageFillingPkgListener::_PackageForName(const BString& name) const
|
||||||
|
{
|
||||||
|
return fModel->PackageForName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFillingPkgListener::_FlushUpdatedPackages()
|
||||||
|
{
|
||||||
|
fModel->AddPackagesWithChange(fUpdatedPackages, kPackageChangeMask);
|
||||||
|
fUpdatedPackages.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! This method will produce a new package with the data provided by the
|
||||||
|
server.
|
||||||
|
*/
|
||||||
|
const PackageInfoRef
|
||||||
|
PackageFillingPkgListener::_CreateUpdatePackage(const PackageInfoRef& package,
|
||||||
|
const DumpExportPkg* pkg)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
|
|
||||||
// Collects all of the changes here into one set of notifications to
|
PackageClassificationInfoBuilder classificationInfoBuilder(
|
||||||
// the package's listeners. This way the quantity of BMessages
|
package->PackageClassificationInfo());
|
||||||
// communicated back to listeners is considerably reduced. See stop
|
PackageLocalizedTextBuilder localizedTextBuilder(package->LocalizedText());
|
||||||
// invocation later in this method.
|
PackageLocalInfoBuilder localInfoBuilder(package->LocalInfo());
|
||||||
|
PackageCoreInfoBuilder coreInfoBuilder(package->CoreInfo());
|
||||||
|
PackageScreenshotInfoBuilder screenshotInfoBuilder;
|
||||||
|
// don't want to start with the existing data; just take what comes from the server.
|
||||||
|
PackageUserRatingInfoBuilder userRatingBuilder;
|
||||||
|
|
||||||
package->StartCollatingChanges();
|
localizedTextBuilder.WithHasChangelog(pkg->HasChangelog());
|
||||||
|
|
||||||
PackageClassificationInfoRef packageClassificationInfo(new PackageClassificationInfo(), true);
|
|
||||||
|
|
||||||
PackageLocalizedTextRef localizedText = PackageUtils::NewLocalizedText(package);
|
|
||||||
PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(package);
|
|
||||||
PackageCoreInfoRef coreInfo = PackageUtils::NewCoreInfo(package);
|
|
||||||
|
|
||||||
localizedText->SetHasChangelog(pkg->HasChangelog());
|
|
||||||
|
|
||||||
if (0 != pkg->CountPkgVersions()) {
|
if (0 != pkg->CountPkgVersions()) {
|
||||||
|
|
||||||
// this makes the assumption that the only version will be the
|
// this makes the assumption that the only version will be the
|
||||||
// latest one.
|
// latest one.
|
||||||
|
|
||||||
DumpExportPkgVersion* pkgVersion = pkg->PkgVersionsItemAt(0);
|
DumpExportPkgVersion* pkgVersion = pkg->PkgVersionsItemAt(0);
|
||||||
|
|
||||||
if (!pkgVersion->TitleIsNull())
|
if (!pkgVersion->TitleIsNull())
|
||||||
localizedText->SetTitle(*(pkgVersion->Title()));
|
localizedTextBuilder.WithTitle(*(pkgVersion->Title()));
|
||||||
|
|
||||||
if (!pkgVersion->SummaryIsNull())
|
if (!pkgVersion->SummaryIsNull())
|
||||||
localizedText->SetSummary(*(pkgVersion->Summary()));
|
localizedTextBuilder.WithSummary(*(pkgVersion->Summary()));
|
||||||
|
|
||||||
if (!pkgVersion->DescriptionIsNull())
|
if (!pkgVersion->DescriptionIsNull())
|
||||||
localizedText->SetDescription(*(pkgVersion->Description()));
|
localizedTextBuilder.WithDescription(*(pkgVersion->Description()));
|
||||||
|
|
||||||
if (!pkgVersion->PayloadLengthIsNull())
|
if (!pkgVersion->PayloadLengthIsNull())
|
||||||
localInfo->SetSize(static_cast<off_t>(pkgVersion->PayloadLength()));
|
localInfoBuilder.WithSize(static_cast<off_t>(pkgVersion->PayloadLength()));
|
||||||
|
|
||||||
if (!pkgVersion->CreateTimestampIsNull()) {
|
if (!pkgVersion->CreateTimestampIsNull()) {
|
||||||
PackageVersionRef version = coreInfo->Version();
|
PackageVersionRef versionRef = PackageUtils::Version(package);
|
||||||
|
|
||||||
if (!version.IsSet()) {
|
if (versionRef.IsSet()) {
|
||||||
version = PackageVersionRef(new PackageVersion(), true);
|
PackageVersion* version = versionRef.Get();
|
||||||
coreInfo->SetVersion(version);
|
versionRef = PackageVersionRef(
|
||||||
|
new PackageVersion(*version, pkgVersion->CreateTimestamp()), true);
|
||||||
|
} else {
|
||||||
|
versionRef
|
||||||
|
= PackageVersionRef(new PackageVersion(pkgVersion->CreateTimestamp()), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
version->SetCreateTimestamp(pkgVersion->CreateTimestamp());
|
coreInfoBuilder.WithVersion(versionRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pkg->DerivedRatingIsNull()) {
|
||||||
|
// TODO; unify the naming here!
|
||||||
|
userRatingBuilder.WithSummary(UserRatingSummaryBuilder()
|
||||||
|
.WithAverageRating(pkg->DerivedRating())
|
||||||
|
.WithRatingCount(pkg->DerivedRatingSampleSize())
|
||||||
|
.BuildRef());
|
||||||
|
}
|
||||||
|
|
||||||
int32 countPkgCategories = pkg->CountPkgCategories();
|
int32 countPkgCategories = pkg->CountPkgCategories();
|
||||||
|
|
||||||
for (i = 0; i < countPkgCategories; i++) {
|
for (i = 0; i < countPkgCategories; i++) {
|
||||||
BString* categoryCode = pkg->PkgCategoriesItemAt(i)->Code();
|
BString* categoryCode = pkg->PkgCategoriesItemAt(i)->Code();
|
||||||
CategoryRef category = fModel->CategoryByCode(*categoryCode);
|
CategoryRef category = fCategories[*categoryCode];
|
||||||
|
|
||||||
if (!category.IsSet()) {
|
if (!category.IsSet())
|
||||||
HDERROR("unable to find the category for [%s]",
|
HDERROR("unable to find the category for [%s]", categoryCode->String());
|
||||||
categoryCode->String());
|
else
|
||||||
} else
|
classificationInfoBuilder.AddCategory(category);
|
||||||
packageClassificationInfo->AddCategory(category);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pkg->DerivedRatingIsNull()) {
|
|
||||||
UserRatingInfoRef userRatingInfo(new UserRatingInfo(), true);
|
|
||||||
UserRatingSummaryRef userRatingSummary(new UserRatingSummary(), true);
|
|
||||||
// TODO; unify the naming here!
|
|
||||||
userRatingSummary->SetAverageRating(pkg->DerivedRating());
|
|
||||||
userRatingSummary->SetRatingCount(pkg->DerivedRatingSampleSize());
|
|
||||||
userRatingInfo->SetSummary(userRatingSummary);
|
|
||||||
package->SetUserRatingInfo(userRatingInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pkg->ProminenceOrderingIsNull())
|
if (!pkg->ProminenceOrderingIsNull())
|
||||||
packageClassificationInfo->SetProminence(static_cast<uint32>(pkg->ProminenceOrdering()));
|
classificationInfoBuilder.WithProminence(static_cast<uint32>(pkg->ProminenceOrdering()));
|
||||||
|
|
||||||
if (!pkg->IsNativeDesktopIsNull())
|
if (!pkg->IsNativeDesktopIsNull())
|
||||||
packageClassificationInfo->SetIsNativeDesktop(pkg->IsNativeDesktop());
|
classificationInfoBuilder.WithIsNativeDesktop(pkg->IsNativeDesktop());
|
||||||
|
|
||||||
int32 countPkgScreenshots = pkg->CountPkgScreenshots();
|
int32 countPkgScreenshots = pkg->CountPkgScreenshots();
|
||||||
PackageScreenshotInfoRef screenshotInfo(new PackageScreenshotInfo(), true);
|
|
||||||
|
|
||||||
for (i = 0; i < countPkgScreenshots; i++) {
|
for (i = 0; i < countPkgScreenshots; i++) {
|
||||||
DumpExportPkgScreenshot* screenshot = pkg->PkgScreenshotsItemAt(i);
|
DumpExportPkgScreenshot* screenshot = pkg->PkgScreenshotsItemAt(i);
|
||||||
screenshotInfo->AddScreenshot(_CreateScreenshot(screenshot));
|
screenshotInfoBuilder.AddScreenshot(_CreateScreenshot(screenshot));
|
||||||
}
|
}
|
||||||
|
|
||||||
package->SetScreenshotInfo(screenshotInfo);
|
return PackageInfoBuilder(package)
|
||||||
package->SetLocalizedText(localizedText);
|
.WithScreenshotInfo(screenshotInfoBuilder.BuildRef())
|
||||||
package->SetLocalInfo(localInfo);
|
.WithUserRatingInfo(userRatingBuilder.BuildRef())
|
||||||
package->SetCoreInfo(coreInfo);
|
.WithLocalizedText(localizedTextBuilder.BuildRef())
|
||||||
|
.WithLocalInfo(localInfoBuilder.BuildRef())
|
||||||
HDTRACE("did populate data for [%s] (%s)", pkg->Name()->String(),
|
.WithCoreInfo(coreInfoBuilder.BuildRef())
|
||||||
fDepotName.String());
|
.WithPackageClassificationInfo(classificationInfoBuilder.BuildRef())
|
||||||
|
.BuildRef();
|
||||||
fCount++;
|
|
||||||
|
|
||||||
package->SetPackageClassificationInfo(packageClassificationInfo);
|
|
||||||
|
|
||||||
package->EndCollatingChanges();
|
|
||||||
|
|
||||||
return !fStoppable->WasStopped();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -208,23 +245,20 @@ PackageFillingPkgListener::Count()
|
|||||||
bool
|
bool
|
||||||
PackageFillingPkgListener::Handle(DumpExportPkg* pkg)
|
PackageFillingPkgListener::Handle(DumpExportPkg* pkg)
|
||||||
{
|
{
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
const BString packageName = *(pkg->Name());
|
||||||
DepotInfoRef depot = fModel->DepotForName(fDepotName);
|
PackageInfoRef package = _PackageForName(packageName);
|
||||||
|
|
||||||
if (depot.Get() != NULL) {
|
if (package.IsSet()) {
|
||||||
const BString packageName = *(pkg->Name());
|
fUpdatedPackages.push_back(_CreateUpdatePackage(package, pkg));
|
||||||
PackageInfoRef package = depot->PackageByName(packageName);
|
HDTRACE("did populate data for [%s]", pkg->Name()->String());
|
||||||
if (package.Get() != NULL)
|
fCount++;
|
||||||
ConsumePackage(package, pkg);
|
|
||||||
else {
|
|
||||||
HDINFO("[PackageFillingPkgListener] unable to find the pkg [%s]",
|
|
||||||
packageName.String());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
HDINFO("[PackageFillingPkgListener] unable to find the depot [%s]",
|
HDINFO("[PackageFillingPkgListener] unable to find the pkg [%s]", packageName.String());
|
||||||
fDepotName.String());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fUpdatedPackages.size() > kPackageBatchSize)
|
||||||
|
_FlushUpdatedPackages();
|
||||||
|
|
||||||
return !fStoppable->WasStopped();
|
return !fStoppable->WasStopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,12 +266,11 @@ PackageFillingPkgListener::Handle(DumpExportPkg* pkg)
|
|||||||
void
|
void
|
||||||
PackageFillingPkgListener::Complete()
|
PackageFillingPkgListener::Complete()
|
||||||
{
|
{
|
||||||
|
_FlushUpdatedPackages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ServerPkgDataUpdateProcess::ServerPkgDataUpdateProcess(
|
ServerPkgDataUpdateProcess::ServerPkgDataUpdateProcess(BString depotName, Model* model,
|
||||||
BString depotName,
|
|
||||||
Model *model,
|
|
||||||
uint32 serverProcessOptions)
|
uint32 serverProcessOptions)
|
||||||
:
|
:
|
||||||
AbstractSingleFileServerProcess(serverProcessOptions),
|
AbstractSingleFileServerProcess(serverProcessOptions),
|
||||||
@@ -245,9 +278,7 @@ ServerPkgDataUpdateProcess::ServerPkgDataUpdateProcess(
|
|||||||
fDepotName(depotName)
|
fDepotName(depotName)
|
||||||
{
|
{
|
||||||
fName.SetToFormat("ServerPkgDataUpdateProcess<%s>", depotName.String());
|
fName.SetToFormat("ServerPkgDataUpdateProcess<%s>", depotName.String());
|
||||||
fDescription.SetTo(
|
fDescription.SetTo(B_TRANSLATE("Synchronizing package data for repository '%REPO_NAME%'"));
|
||||||
B_TRANSLATE("Synchronizing package data for repository "
|
|
||||||
"'%REPO_NAME%'"));
|
|
||||||
fDescription.ReplaceAll("%REPO_NAME%", depotName.String());
|
fDescription.ReplaceAll("%REPO_NAME%", depotName.String());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +318,6 @@ ServerPkgDataUpdateProcess::GetLocalPath(BPath& path) const
|
|||||||
BString webAppRepositorySourceCode = _DeriveWebAppRepositorySourceCode();
|
BString webAppRepositorySourceCode = _DeriveWebAppRepositorySourceCode();
|
||||||
|
|
||||||
if (!webAppRepositorySourceCode.IsEmpty()) {
|
if (!webAppRepositorySourceCode.IsEmpty()) {
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
|
||||||
return StorageUtils::DumpExportPkgDataPath(path, webAppRepositorySourceCode,
|
return StorageUtils::DumpExportPkgDataPath(path, webAppRepositorySourceCode,
|
||||||
fModel->PreferredLanguage());
|
fModel->PreferredLanguage());
|
||||||
}
|
}
|
||||||
@@ -301,15 +331,12 @@ ServerPkgDataUpdateProcess::ProcessLocalData()
|
|||||||
{
|
{
|
||||||
BStopWatch watch("ServerPkgDataUpdateProcess::ProcessLocalData", true);
|
BStopWatch watch("ServerPkgDataUpdateProcess::ProcessLocalData", true);
|
||||||
|
|
||||||
PackageFillingPkgListener* itemListener =
|
PackageFillingPkgListener* itemListener = new PackageFillingPkgListener(fModel, this);
|
||||||
new PackageFillingPkgListener(fModel, fDepotName, this);
|
ObjectDeleter<PackageFillingPkgListener> itemListenerDeleter(itemListener);
|
||||||
ObjectDeleter<PackageFillingPkgListener>
|
|
||||||
itemListenerDeleter(itemListener);
|
|
||||||
|
|
||||||
BulkContainerDumpExportPkgJsonListener* listener =
|
BulkContainerDumpExportPkgJsonListener* listener
|
||||||
new BulkContainerDumpExportPkgJsonListener(itemListener);
|
= new BulkContainerDumpExportPkgJsonListener(itemListener);
|
||||||
ObjectDeleter<BulkContainerDumpExportPkgJsonListener>
|
ObjectDeleter<BulkContainerDumpExportPkgJsonListener> listenerDeleter(listener);
|
||||||
listenerDeleter(listener);
|
|
||||||
|
|
||||||
BPath localPath;
|
BPath localPath;
|
||||||
status_t result = GetLocalPath(localPath);
|
status_t result = GetLocalPath(localPath);
|
||||||
@@ -324,8 +351,8 @@ ServerPkgDataUpdateProcess::ProcessLocalData()
|
|||||||
|
|
||||||
if (Logger::IsInfoEnabled()) {
|
if (Logger::IsInfoEnabled()) {
|
||||||
double secs = watch.ElapsedTime() / 1000000.0;
|
double secs = watch.ElapsedTime() / 1000000.0;
|
||||||
HDINFO("[%s] did process %" B_PRIi32 " packages' data "
|
HDINFO("[%s] did process %" B_PRIi32 " packages' data in (%6.3g secs)", Name(),
|
||||||
"in (%6.3g secs)", Name(), itemListener->Count(), secs);
|
itemListener->Count(), secs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return listener->ErrorStatus();
|
return listener->ErrorStatus();
|
||||||
@@ -340,8 +367,7 @@ ServerPkgDataUpdateProcess::GetStandardMetaDataPath(BPath& path) const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerPkgDataUpdateProcess::GetStandardMetaDataJsonPath(
|
ServerPkgDataUpdateProcess::GetStandardMetaDataJsonPath(BString& jsonPath) const
|
||||||
BString& jsonPath) const
|
|
||||||
{
|
{
|
||||||
jsonPath.SetTo("$.info");
|
jsonPath.SetTo("$.info");
|
||||||
}
|
}
|
||||||
@@ -352,9 +378,8 @@ ServerPkgDataUpdateProcess::_DeriveWebAppRepositorySourceCode() const
|
|||||||
{
|
{
|
||||||
const DepotInfo* depot = fModel->DepotForName(fDepotName);
|
const DepotInfo* depot = fModel->DepotForName(fDepotName);
|
||||||
|
|
||||||
if (depot == NULL) {
|
if (depot == NULL)
|
||||||
return BString();
|
return BString();
|
||||||
}
|
|
||||||
|
|
||||||
return depot->WebAppRepositorySourceCode();
|
return depot->WebAppRepositorySourceCode();
|
||||||
}
|
}
|
||||||
@@ -364,8 +389,8 @@ status_t
|
|||||||
ServerPkgDataUpdateProcess::RunInternal()
|
ServerPkgDataUpdateProcess::RunInternal()
|
||||||
{
|
{
|
||||||
if (_DeriveWebAppRepositorySourceCode().IsEmpty()) {
|
if (_DeriveWebAppRepositorySourceCode().IsEmpty()) {
|
||||||
HDINFO("[%s] am not updating data for depot [%s] as there is no"
|
HDINFO("[%s] am not updating data for depot [%s] as there is no web app repository source "
|
||||||
" web app repository source code available",
|
"code available",
|
||||||
Name(), fDepotName.String());
|
Name(), fDepotName.String());
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2019-2020, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2019-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -32,8 +32,7 @@
|
|||||||
#define B_TRANSLATION_CONTEXT "ServerReferenceDataUpdateProcess"
|
#define B_TRANSLATION_CONTEXT "ServerReferenceDataUpdateProcess"
|
||||||
|
|
||||||
|
|
||||||
ServerReferenceDataUpdateProcess::ServerReferenceDataUpdateProcess(
|
ServerReferenceDataUpdateProcess::ServerReferenceDataUpdateProcess(Model* model,
|
||||||
Model* model,
|
|
||||||
uint32 serverProcessOptions)
|
uint32 serverProcessOptions)
|
||||||
:
|
:
|
||||||
AbstractSingleFileServerProcess(serverProcessOptions),
|
AbstractSingleFileServerProcess(serverProcessOptions),
|
||||||
@@ -65,7 +64,6 @@ BString
|
|||||||
ServerReferenceDataUpdateProcess::UrlPathComponent()
|
ServerReferenceDataUpdateProcess::UrlPathComponent()
|
||||||
{
|
{
|
||||||
BString result;
|
BString result;
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
|
||||||
result.SetToFormat("/__reference/all-%s.json.gz", fModel->PreferredLanguage()->ID());
|
result.SetToFormat("/__reference/all-%s.json.gz", fModel->PreferredLanguage()->ID());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -74,7 +72,6 @@ ServerReferenceDataUpdateProcess::UrlPathComponent()
|
|||||||
status_t
|
status_t
|
||||||
ServerReferenceDataUpdateProcess::GetLocalPath(BPath& path) const
|
ServerReferenceDataUpdateProcess::GetLocalPath(BPath& path) const
|
||||||
{
|
{
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
|
||||||
return StorageUtils::DumpExportReferenceDataPath(path, fModel->PreferredLanguage());
|
return StorageUtils::DumpExportReferenceDataPath(path, fModel->PreferredLanguage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,8 +79,7 @@ ServerReferenceDataUpdateProcess::GetLocalPath(BPath& path) const
|
|||||||
status_t
|
status_t
|
||||||
ServerReferenceDataUpdateProcess::ProcessLocalData()
|
ServerReferenceDataUpdateProcess::ProcessLocalData()
|
||||||
{
|
{
|
||||||
SingleDumpExportReferenceJsonListener* listener =
|
SingleDumpExportReferenceJsonListener* listener = new SingleDumpExportReferenceJsonListener();
|
||||||
new SingleDumpExportReferenceJsonListener();
|
|
||||||
|
|
||||||
BPath localPath;
|
BPath localPath;
|
||||||
status_t result = GetLocalPath(localPath);
|
status_t result = GetLocalPath(localPath);
|
||||||
@@ -120,91 +116,68 @@ ServerReferenceDataUpdateProcess::_ProcessData(DumpExportReference* data)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ServerReferenceDataUpdateProcess::_ProcessNaturalLanguages(
|
ServerReferenceDataUpdateProcess::_ProcessNaturalLanguages(DumpExportReference* data)
|
||||||
DumpExportReference* data)
|
|
||||||
{
|
{
|
||||||
HDINFO("[%s] will populate from %" B_PRId32 " possible natural languages",
|
HDINFO("[%s] will populate from %" B_PRId32 " possible natural languages", Name(),
|
||||||
Name(), data->CountNaturalLanguages());
|
data->CountNaturalLanguages());
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
|
||||||
|
|
||||||
LanguageRepository* languageRepository = fModel->Languages();
|
std::vector<LanguageRef> languages;
|
||||||
languageRepository->Clear();
|
|
||||||
int32 count = 0;
|
int32 count = 0;
|
||||||
|
|
||||||
for (int32 i = 0; i < data->CountNaturalLanguages(); i++) {
|
for (int32 i = data->CountNaturalLanguages() - 1; i > 0; i--) {
|
||||||
DumpExportReferenceNaturalLanguage* naturalLanguage =
|
DumpExportReferenceNaturalLanguage* naturalLanguage = data->NaturalLanguagesItemAt(i);
|
||||||
data->NaturalLanguagesItemAt(i);
|
Language* language = new Language(*(naturalLanguage->Code()), *(naturalLanguage->Name()),
|
||||||
languageRepository->AddLanguage(
|
naturalLanguage->IsPopular());
|
||||||
LanguageRef(new Language(*(naturalLanguage->Code()), *(naturalLanguage->Name()),
|
languages.push_back(LanguageRef(language, true));
|
||||||
naturalLanguage->IsPopular()),
|
|
||||||
true));
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// it could be that the preferred language does not exist in the
|
if (!languages.empty()) {
|
||||||
// list. In this case it is necessary to choose one from the list.
|
fModel->SetLanguagesAndPreferred(languages, LocaleUtils::DeriveDefaultLanguage(languages));
|
||||||
fModel->SetPreferredLanguage(LocaleUtils::DeriveDefaultLanguage(fModel->Languages()));
|
HDINFO("[%s] did add %" B_PRId32 " supported languages", Name(), count);
|
||||||
|
}
|
||||||
HDINFO("[%s] did add %" B_PRId32 " supported languages", Name(), count);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ServerReferenceDataUpdateProcess::_ProcessPkgCategories(
|
ServerReferenceDataUpdateProcess::_ProcessPkgCategories(DumpExportReference* data)
|
||||||
DumpExportReference* data)
|
|
||||||
{
|
{
|
||||||
HDINFO("[%s] will populate %" B_PRId32 " pkg categories",
|
HDINFO("[%s] will populate %" B_PRId32 " pkg categories", Name(), data->CountPkgCategories());
|
||||||
Name(), data->CountPkgCategories());
|
|
||||||
|
|
||||||
std::vector<CategoryRef> assembledCategories;
|
std::vector<CategoryRef> assembledCategories;
|
||||||
|
|
||||||
for (int32 i = 0; i < data->CountPkgCategories(); i++) {
|
for (int32 i = 0; i < data->CountPkgCategories(); i++) {
|
||||||
DumpExportReferencePkgCategory* pkgCategory =
|
DumpExportReferencePkgCategory* pkgCategory = data->PkgCategoriesItemAt(i);
|
||||||
data->PkgCategoriesItemAt(i);
|
assembledCategories.push_back(
|
||||||
assembledCategories.push_back(CategoryRef(
|
CategoryRef(new PackageCategory(*(pkgCategory->Code()), *(pkgCategory->Name())), true));
|
||||||
new PackageCategory(
|
|
||||||
*(pkgCategory->Code()),
|
|
||||||
*(pkgCategory->Name())
|
|
||||||
),
|
|
||||||
true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
fModel->SetCategories(assembledCategories);
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
|
||||||
fModel->AddCategories(assembledCategories);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ServerReferenceDataUpdateProcess::_ProcessRatingStabilities(
|
ServerReferenceDataUpdateProcess::_ProcessRatingStabilities(DumpExportReference* data)
|
||||||
DumpExportReference* data)
|
|
||||||
{
|
{
|
||||||
HDINFO("[%s] will populate %" B_PRId32 " rating stabilities",
|
HDINFO("[%s] will populate %" B_PRId32 " rating stabilities", Name(),
|
||||||
Name(), data->CountUserRatingStabilities());
|
data->CountUserRatingStabilities());
|
||||||
|
|
||||||
std::vector<RatingStabilityRef> assembledRatingStabilities;
|
std::vector<RatingStabilityRef> assembledRatingStabilities;
|
||||||
|
|
||||||
for (int32 i = 0; i < data->CountUserRatingStabilities(); i++) {
|
for (int32 i = 0; i < data->CountUserRatingStabilities(); i++) {
|
||||||
DumpExportReferenceUserRatingStability* ratingStability =
|
DumpExportReferenceUserRatingStability* ratingStability
|
||||||
data->UserRatingStabilitiesItemAt(i);
|
= data->UserRatingStabilitiesItemAt(i);
|
||||||
assembledRatingStabilities.push_back(RatingStabilityRef(
|
assembledRatingStabilities.push_back(
|
||||||
new RatingStability(
|
RatingStabilityRef(new RatingStability(*(ratingStability->Code()),
|
||||||
*(ratingStability->Code()),
|
*(ratingStability->Name()), ratingStability->Ordering()),
|
||||||
*(ratingStability->Name()),
|
true));
|
||||||
ratingStability->Ordering()
|
|
||||||
),
|
|
||||||
true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
fModel->SetRatingStabilities(assembledRatingStabilities);
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
|
||||||
fModel->AddRatingStabilities(assembledRatingStabilities);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -218,8 +191,7 @@ ServerReferenceDataUpdateProcess::GetStandardMetaDataPath(BPath& path) const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerReferenceDataUpdateProcess::GetStandardMetaDataJsonPath(
|
ServerReferenceDataUpdateProcess::GetStandardMetaDataJsonPath(BString& jsonPath) const
|
||||||
BString& jsonPath) const
|
|
||||||
{
|
{
|
||||||
jsonPath.SetTo("$.info");
|
jsonPath.SetTo("$.info");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2023, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "ServerRepositoryDataUpdateProcess.h"
|
#include "ServerRepositoryDataUpdateProcess.h"
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
#include "DumpExportRepository.h"
|
#include "DumpExportRepository.h"
|
||||||
#include "DumpExportRepositoryJsonListener.h"
|
#include "DumpExportRepositoryJsonListener.h"
|
||||||
#include "DumpExportRepositorySource.h"
|
#include "DumpExportRepositorySource.h"
|
||||||
|
#include "Logger.h"
|
||||||
#include "PackageInfo.h"
|
#include "PackageInfo.h"
|
||||||
#include "ServerSettings.h"
|
#include "ServerSettings.h"
|
||||||
#include "StorageUtils.h"
|
#include "StorageUtils.h"
|
||||||
#include "Logger.h"
|
|
||||||
|
|
||||||
|
|
||||||
#undef B_TRANSLATION_CONTEXT
|
#undef B_TRANSLATION_CONTEXT
|
||||||
@@ -28,13 +28,12 @@
|
|||||||
|
|
||||||
|
|
||||||
/*! This repository listener (not at the JSON level) is feeding in the
|
/*! This repository listener (not at the JSON level) is feeding in the
|
||||||
repositories as they are parsed and processing them. Processing
|
repositories as they are parsed and processing them. Processing
|
||||||
includes finding the matching depot record and coupling the data
|
includes finding the matching depot record and coupling the data
|
||||||
from the server with the data about the depot.
|
from the server with the data about the depot.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DepotMatchingRepositoryListener :
|
class DepotMatchingRepositoryListener : public DumpExportRepositoryListener {
|
||||||
public DumpExportRepositoryListener {
|
|
||||||
public:
|
public:
|
||||||
DepotMatchingRepositoryListener(Model* model,
|
DepotMatchingRepositoryListener(Model* model,
|
||||||
Stoppable* stoppable);
|
Stoppable* stoppable);
|
||||||
@@ -60,14 +59,16 @@ private:
|
|||||||
private:
|
private:
|
||||||
Model* fModel;
|
Model* fModel;
|
||||||
Stoppable* fStoppable;
|
Stoppable* fStoppable;
|
||||||
|
std::vector<DepotInfoRef>
|
||||||
|
fDepots;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
DepotMatchingRepositoryListener::DepotMatchingRepositoryListener(
|
DepotMatchingRepositoryListener::DepotMatchingRepositoryListener(Model* model, Stoppable* stoppable)
|
||||||
Model* model, Stoppable* stoppable)
|
|
||||||
:
|
:
|
||||||
fModel(model),
|
fModel(model),
|
||||||
fStoppable(stoppable)
|
fStoppable(stoppable),
|
||||||
|
fDepots()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,43 +80,41 @@ DepotMatchingRepositoryListener::~DepotMatchingRepositoryListener()
|
|||||||
|
|
||||||
void
|
void
|
||||||
DepotMatchingRepositoryListener::_SetupRepositoryData(DepotInfoRef& depot,
|
DepotMatchingRepositoryListener::_SetupRepositoryData(DepotInfoRef& depot,
|
||||||
DumpExportRepository* repository,
|
DumpExportRepository* repository, DumpExportRepositorySource* repositorySource)
|
||||||
DumpExportRepositorySource* repositorySource)
|
|
||||||
{
|
{
|
||||||
BString* repositoryCode = repository->Code();
|
BString* repositoryCode = repository->Code();
|
||||||
BString* repositorySourceCode = repositorySource->Code();
|
BString* repositorySourceCode = repositorySource->Code();
|
||||||
|
|
||||||
depot->SetWebAppRepositoryCode(*repositoryCode);
|
DepotInfoBuilder depotBuilder(depot);
|
||||||
depot->SetWebAppRepositorySourceCode(*repositorySourceCode);
|
|
||||||
|
depotBuilder.WithWebAppRepositoryCode(*repositoryCode);
|
||||||
|
depotBuilder.WithWebAppRepositorySourceCode(*repositorySourceCode);
|
||||||
|
|
||||||
|
DepotInfoRef depotInfo = depotBuilder.BuildRef();
|
||||||
|
fDepots.push_back(depotInfo);
|
||||||
|
|
||||||
if (Logger::IsDebugEnabled()) {
|
if (Logger::IsDebugEnabled()) {
|
||||||
HDDEBUG("[DepotMatchingRepositoryListener] associated depot [%s] (%s) "
|
HDDEBUG("[DepotMatchingRepositoryListener] associated depot [%s] (%s) "
|
||||||
"with server repository source [%s] (%s)",
|
"with server repository source [%s] (%s)",
|
||||||
depot->Name().String(),
|
depot->Name().String(), depot->Identifier().String(), repositorySourceCode->String(),
|
||||||
depot->Identifier().String(),
|
|
||||||
repositorySourceCode->String(),
|
|
||||||
repositorySource->Identifier()->String());
|
repositorySource->Identifier()->String());
|
||||||
} else {
|
} else {
|
||||||
HDINFO("[DepotMatchingRepositoryListener] associated depot [%s] with "
|
HDINFO("[DepotMatchingRepositoryListener] associated depot [%s] with "
|
||||||
"server repository source [%s]",
|
"server repository source [%s]",
|
||||||
depot->Name().String(),
|
depot->Name().String(), repositorySourceCode->String());
|
||||||
repositorySourceCode->String());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DepotMatchingRepositoryListener::Handle(const BString& identifier,
|
DepotMatchingRepositoryListener::Handle(const BString& identifier, DumpExportRepository* repository,
|
||||||
DumpExportRepository* repository,
|
|
||||||
DumpExportRepositorySource* repositorySource)
|
DumpExportRepositorySource* repositorySource)
|
||||||
{
|
{
|
||||||
if (!identifier.IsEmpty()) {
|
if (!identifier.IsEmpty()) {
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
DepotInfoRef depotForIdentifier = fModel->DepotForIdentifier(identifier);
|
||||||
for (int32 i = 0; i < fModel->CountDepots(); i++) {
|
|
||||||
DepotInfoRef depot = fModel->DepotAtIndex(i);
|
if (depotForIdentifier.IsSet())
|
||||||
if (identifier == depot->Identifier())
|
_SetupRepositoryData(depotForIdentifier, repository, repositorySource);
|
||||||
_SetupRepositoryData(depot, repository, repositorySource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,13 +129,8 @@ DepotMatchingRepositoryListener::Handle(DumpExportRepository* repository,
|
|||||||
// there may be additional identifiers for the remote repository and
|
// there may be additional identifiers for the remote repository and
|
||||||
// these should also be taken into consideration.
|
// these should also be taken into consideration.
|
||||||
|
|
||||||
for(int32 i = 0;
|
for (int32 i = 0; i < repositorySource->CountExtraIdentifiers(); i++)
|
||||||
i < repositorySource->CountExtraIdentifiers();
|
Handle(*(repositorySource->ExtraIdentifiersItemAt(i)), repository, repositorySource);
|
||||||
i++)
|
|
||||||
{
|
|
||||||
Handle(*(repositorySource->ExtraIdentifiersItemAt(i)), repository,
|
|
||||||
repositorySource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -153,11 +147,11 @@ DepotMatchingRepositoryListener::Handle(DumpExportRepository* repository)
|
|||||||
void
|
void
|
||||||
DepotMatchingRepositoryListener::Complete()
|
DepotMatchingRepositoryListener::Complete()
|
||||||
{
|
{
|
||||||
|
fModel->SetDepots(fDepots);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ServerRepositoryDataUpdateProcess::ServerRepositoryDataUpdateProcess(
|
ServerRepositoryDataUpdateProcess::ServerRepositoryDataUpdateProcess(Model* model,
|
||||||
Model* model,
|
|
||||||
uint32 serverProcessOptions)
|
uint32 serverProcessOptions)
|
||||||
:
|
:
|
||||||
AbstractSingleFileServerProcess(serverProcessOptions),
|
AbstractSingleFileServerProcess(serverProcessOptions),
|
||||||
@@ -189,7 +183,6 @@ BString
|
|||||||
ServerRepositoryDataUpdateProcess::UrlPathComponent()
|
ServerRepositoryDataUpdateProcess::UrlPathComponent()
|
||||||
{
|
{
|
||||||
BString result;
|
BString result;
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
|
||||||
result.SetToFormat("/__repository/all-%s.json.gz", fModel->PreferredLanguage()->ID());
|
result.SetToFormat("/__repository/all-%s.json.gz", fModel->PreferredLanguage()->ID());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -198,7 +191,6 @@ ServerRepositoryDataUpdateProcess::UrlPathComponent()
|
|||||||
status_t
|
status_t
|
||||||
ServerRepositoryDataUpdateProcess::GetLocalPath(BPath& path) const
|
ServerRepositoryDataUpdateProcess::GetLocalPath(BPath& path) const
|
||||||
{
|
{
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
|
||||||
return StorageUtils::DumpExportRepositoryDataPath(path, fModel->PreferredLanguage());
|
return StorageUtils::DumpExportRepositoryDataPath(path, fModel->PreferredLanguage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,15 +198,13 @@ ServerRepositoryDataUpdateProcess::GetLocalPath(BPath& path) const
|
|||||||
status_t
|
status_t
|
||||||
ServerRepositoryDataUpdateProcess::ProcessLocalData()
|
ServerRepositoryDataUpdateProcess::ProcessLocalData()
|
||||||
{
|
{
|
||||||
DepotMatchingRepositoryListener* itemListener =
|
DepotMatchingRepositoryListener* itemListener
|
||||||
new DepotMatchingRepositoryListener(fModel, this);
|
= new DepotMatchingRepositoryListener(fModel, this);
|
||||||
ObjectDeleter<DepotMatchingRepositoryListener>
|
ObjectDeleter<DepotMatchingRepositoryListener> itemListenerDeleter(itemListener);
|
||||||
itemListenerDeleter(itemListener);
|
|
||||||
|
|
||||||
BulkContainerDumpExportRepositoryJsonListener* listener =
|
BulkContainerDumpExportRepositoryJsonListener* listener
|
||||||
new BulkContainerDumpExportRepositoryJsonListener(itemListener);
|
= new BulkContainerDumpExportRepositoryJsonListener(itemListener);
|
||||||
ObjectDeleter<BulkContainerDumpExportRepositoryJsonListener>
|
ObjectDeleter<BulkContainerDumpExportRepositoryJsonListener> listenerDeleter(listener);
|
||||||
listenerDeleter(listener);
|
|
||||||
|
|
||||||
BPath localPath;
|
BPath localPath;
|
||||||
status_t result = GetLocalPath(localPath);
|
status_t result = GetLocalPath(localPath);
|
||||||
@@ -239,8 +229,7 @@ ServerRepositoryDataUpdateProcess::GetStandardMetaDataPath(BPath& path) const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerRepositoryDataUpdateProcess::GetStandardMetaDataJsonPath(
|
ServerRepositoryDataUpdateProcess::GetStandardMetaDataJsonPath(BString& jsonPath) const
|
||||||
BString& jsonPath) const
|
|
||||||
{
|
{
|
||||||
jsonPath.SetTo("$.info");
|
jsonPath.SetTo("$.info");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ UserDetailVerifierProcess::RunInternal()
|
|||||||
case B_OK:
|
case B_OK:
|
||||||
if (!userDetail.Agreement().IsLatest()) {
|
if (!userDetail.Agreement().IsLatest()) {
|
||||||
HDINFO("the user has not agreed to the latest user usage"
|
HDINFO("the user has not agreed to the latest user usage"
|
||||||
" conditions.");
|
" conditions.");
|
||||||
fListener->UserUsageConditionsNotLatest(userDetail);
|
fListener->UserUsageConditionsNotLatest(userDetail);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -84,12 +84,9 @@ UserDetailVerifierProcess::_ShouldVerify()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (fModel->Nickname().IsEmpty()) {
|
||||||
AutoLocker<BLocker> locker(fModel->Lock());
|
HDINFO("no nickname --> will not verify user");
|
||||||
if (fModel->Nickname().IsEmpty()) {
|
return false;
|
||||||
HDINFO("no nickname --> will not verify user");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -99,16 +96,14 @@ UserDetailVerifierProcess::_ShouldVerify()
|
|||||||
status_t
|
status_t
|
||||||
UserDetailVerifierProcess::_TryFetchUserDetail(UserDetail& userDetail)
|
UserDetailVerifierProcess::_TryFetchUserDetail(UserDetail& userDetail)
|
||||||
{
|
{
|
||||||
WebAppInterface* interface = fModel->GetWebAppInterface();
|
WebAppInterfaceRef interface = fModel->WebApp();
|
||||||
BMessage userDetailResponse;
|
BMessage userDetailResponse;
|
||||||
status_t result;
|
status_t result;
|
||||||
|
|
||||||
result = interface->RetrieveCurrentUserDetail(userDetailResponse);
|
result = interface->RetrieveCurrentUserDetail(userDetailResponse);
|
||||||
|
|
||||||
if (result != B_OK) {
|
if (result != B_OK)
|
||||||
HDERROR("a problem has arisen retrieving the current user detail: %s",
|
HDERROR("a problem has arisen retrieving the current user detail: %s", strerror(result));
|
||||||
strerror(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(userDetailResponse);
|
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(userDetailResponse);
|
||||||
@@ -120,7 +115,7 @@ UserDetailVerifierProcess::_TryFetchUserDetail(UserDetail& userDetail)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
HDERROR("a problem has arisen retrieving the current user "
|
HDERROR("a problem has arisen retrieving the current user "
|
||||||
"detail for user [%s]: jrpc error code %" B_PRId32 "",
|
"detail for user [%s]: jrpc error code %" B_PRId32 "",
|
||||||
fModel->Nickname().String(), errorCode);
|
fModel->Nickname().String(), errorCode);
|
||||||
result = B_ERROR;
|
result = B_ERROR;
|
||||||
break;
|
break;
|
||||||
@@ -139,4 +134,4 @@ UserDetailVerifierProcess::_TryFetchUserDetail(UserDetail& userDetail)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2016-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "WebAppInterface.h"
|
#include "WebAppInterface.h"
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
#include <HttpHeaders.h>
|
#include <HttpHeaders.h>
|
||||||
#include <HttpRequest.h>
|
#include <HttpRequest.h>
|
||||||
#include <Json.h>
|
#include <Json.h>
|
||||||
#include <JsonTextWriter.h>
|
|
||||||
#include <JsonMessageWriter.h>
|
#include <JsonMessageWriter.h>
|
||||||
|
#include <JsonTextWriter.h>
|
||||||
#include <UrlContext.h>
|
#include <UrlContext.h>
|
||||||
#include <UrlProtocolListener.h>
|
#include <UrlProtocolListener.h>
|
||||||
#include <UrlProtocolRoster.h>
|
#include <UrlProtocolRoster.h>
|
||||||
@@ -89,12 +89,10 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
static BHttpRequest*
|
static BHttpRequest*
|
||||||
make_http_request(const BUrl& url, BDataIO* output,
|
make_http_request(const BUrl& url, BDataIO* output, BUrlProtocolListener* listener = NULL,
|
||||||
BUrlProtocolListener* listener = NULL,
|
|
||||||
BUrlContext* context = NULL)
|
BUrlContext* context = NULL)
|
||||||
{
|
{
|
||||||
BUrlRequest* request = BUrlProtocolRoster::MakeRequest(url, output,
|
BUrlRequest* request = BUrlProtocolRoster::MakeRequest(url, output, listener, context);
|
||||||
listener, context);
|
|
||||||
BHttpRequest* httpRequest = dynamic_cast<BHttpRequest*>(request);
|
BHttpRequest* httpRequest = dynamic_cast<BHttpRequest*>(request);
|
||||||
if (httpRequest == NULL) {
|
if (httpRequest == NULL) {
|
||||||
delete request;
|
delete request;
|
||||||
@@ -109,8 +107,9 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
WebAppInterface::WebAppInterface()
|
WebAppInterface::WebAppInterface(const UserCredentials& value)
|
||||||
{
|
{
|
||||||
|
_SetCredentials(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -120,9 +119,8 @@ WebAppInterface::~WebAppInterface()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WebAppInterface::SetCredentials(const UserCredentials& value)
|
WebAppInterface::_SetCredentials(const UserCredentials& value)
|
||||||
{
|
{
|
||||||
AutoLocker<BLocker> lock(&fLock);
|
|
||||||
if (fCredentials != value) {
|
if (fCredentials != value) {
|
||||||
fCredentials = value;
|
fCredentials = value;
|
||||||
fAccessToken.Clear();
|
fAccessToken.Clear();
|
||||||
@@ -133,7 +131,6 @@ WebAppInterface::SetCredentials(const UserCredentials& value)
|
|||||||
const BString&
|
const BString&
|
||||||
WebAppInterface::Nickname()
|
WebAppInterface::Nickname()
|
||||||
{
|
{
|
||||||
AutoLocker<BLocker> lock(&fLock);
|
|
||||||
return fCredentials.Nickname();
|
return fCredentials.Nickname();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,21 +209,18 @@ WebAppInterface::RetrieveUserRatingsForPackageForDisplay(
|
|||||||
|
|
||||||
requestEnvelopeWriter.WriteObjectEnd();
|
requestEnvelopeWriter.WriteObjectEnd();
|
||||||
|
|
||||||
return _SendJsonRequest("user-rating/search-user-ratings",
|
return _SendJsonRequest("user-rating/search-user-ratings", requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), 0, message);
|
||||||
0, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::RetrieveUserRatingForPackageAndVersionByUser(
|
WebAppInterface::RetrieveUserRatingForPackageAndVersionByUser(const BString& packageName,
|
||||||
const BString& packageName, const BPackageVersion& version,
|
const BPackageVersion& version, const BString& architecture,
|
||||||
const BString& architecture,
|
const BString& webAppRepositoryCode, const BString& webAppRepositorySourceCode,
|
||||||
const BString& webAppRepositoryCode,
|
|
||||||
const BString& webAppRepositorySourceCode,
|
|
||||||
const BString& userNickname, BMessage& message)
|
const BString& userNickname, BMessage& message)
|
||||||
{
|
{
|
||||||
// BHttpRequest later takes ownership of this.
|
// BHttpRequest later takes ownership of this.
|
||||||
BMallocIO* requestEnvelopeData = new BMallocIO();
|
BMallocIO* requestEnvelopeData = new BMallocIO();
|
||||||
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
||||||
|
|
||||||
@@ -270,10 +264,8 @@ WebAppInterface::RetrieveUserRatingForPackageAndVersionByUser(
|
|||||||
|
|
||||||
requestEnvelopeWriter.WriteObjectEnd();
|
requestEnvelopeWriter.WriteObjectEnd();
|
||||||
|
|
||||||
return _SendJsonRequest(
|
return _SendJsonRequest("user-rating/get-user-rating-by-user-and-pkg-version",
|
||||||
"user-rating/get-user-rating-by-user-and-pkg-version",
|
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData), NEEDS_AUTHORIZATION,
|
||||||
requestEnvelopeData,
|
|
||||||
_LengthAndSeekToZero(requestEnvelopeData), NEEDS_AUTHORIZATION,
|
|
||||||
message);
|
message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,12 +277,12 @@ WebAppInterface::RetrieveUserRatingForPackageAndVersionByUser(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::RetrieveUserDetailForCredentials(
|
WebAppInterface::RetrieveUserDetailForCredentials(const UserCredentials& credentials,
|
||||||
const UserCredentials& credentials, BMessage& message)
|
BMessage& message)
|
||||||
{
|
{
|
||||||
if (!credentials.IsValid()) {
|
if (!credentials.IsValid()) {
|
||||||
debugger("the credentials supplied are invalid so it is not possible "
|
debugger("the credentials supplied are invalid so it is not possible "
|
||||||
"to obtain the user detail");
|
"to obtain the user detail");
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
@@ -301,9 +293,7 @@ WebAppInterface::RetrieveUserDetailForCredentials(
|
|||||||
BMessage authenticateResponseEnvelopeMessage;
|
BMessage authenticateResponseEnvelopeMessage;
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
result = AuthenticateUser(
|
result = AuthenticateUser(credentials.Nickname(), credentials.PasswordClear(),
|
||||||
credentials.Nickname(),
|
|
||||||
credentials.PasswordClear(),
|
|
||||||
authenticateResponseEnvelopeMessage);
|
authenticateResponseEnvelopeMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,7 +303,7 @@ WebAppInterface::RetrieveUserDetailForCredentials(
|
|||||||
result = UnpackAccessToken(authenticateResponseEnvelopeMessage, accessToken);
|
result = UnpackAccessToken(authenticateResponseEnvelopeMessage, accessToken);
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
// BHttpRequest later takes ownership of this.
|
// BHttpRequest later takes ownership of this.
|
||||||
BMallocIO* requestEnvelopeData = new BMallocIO();
|
BMallocIO* requestEnvelopeData = new BMallocIO();
|
||||||
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
||||||
|
|
||||||
@@ -322,9 +312,8 @@ WebAppInterface::RetrieveUserDetailForCredentials(
|
|||||||
requestEnvelopeWriter.WriteString(credentials.Nickname().String());
|
requestEnvelopeWriter.WriteString(credentials.Nickname().String());
|
||||||
requestEnvelopeWriter.WriteObjectEnd();
|
requestEnvelopeWriter.WriteObjectEnd();
|
||||||
|
|
||||||
result = _SendJsonRequest("user/get-user", accessToken,
|
result = _SendJsonRequest("user/get-user", accessToken, requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), NEEDS_AUTHORIZATION, message);
|
||||||
NEEDS_AUTHORIZATION, message);
|
|
||||||
// note that the credentials used here are passed in as args.
|
// note that the credentials used here are passed in as args.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,12 +339,10 @@ WebAppInterface::RetrieveCurrentUserDetail(BMessage& message)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
WebAppInterface::UnpackUserDetail(BMessage& responseEnvelopeMessage,
|
WebAppInterface::UnpackUserDetail(BMessage& responseEnvelopeMessage, UserDetail& userDetail)
|
||||||
UserDetail& userDetail)
|
|
||||||
{
|
{
|
||||||
BMessage resultMessage;
|
BMessage resultMessage;
|
||||||
status_t result = responseEnvelopeMessage.FindMessage(
|
status_t result = responseEnvelopeMessage.FindMessage("result", &resultMessage);
|
||||||
"result", &resultMessage);
|
|
||||||
|
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
HDERROR("bad response envelope missing 'result' entry");
|
HDERROR("bad response envelope missing 'result' entry");
|
||||||
@@ -367,29 +354,24 @@ WebAppInterface::UnpackUserDetail(BMessage& responseEnvelopeMessage,
|
|||||||
userDetail.SetNickname(nickname);
|
userDetail.SetNickname(nickname);
|
||||||
|
|
||||||
BMessage agreementMessage;
|
BMessage agreementMessage;
|
||||||
if (resultMessage.FindMessage("userUsageConditionsAgreement",
|
if (resultMessage.FindMessage("userUsageConditionsAgreement", &agreementMessage) == B_OK) {
|
||||||
&agreementMessage) == B_OK) {
|
|
||||||
BString code;
|
BString code;
|
||||||
BDateTime agreedToTimestamp;
|
BDateTime agreedToTimestamp;
|
||||||
BString userUsageConditionsCode;
|
BString userUsageConditionsCode;
|
||||||
UserUsageConditionsAgreement agreement = userDetail.Agreement();
|
UserUsageConditionsAgreement agreement = userDetail.Agreement();
|
||||||
bool isLatest;
|
bool isLatest;
|
||||||
|
|
||||||
if (agreementMessage.FindString("userUsageConditionsCode",
|
if (agreementMessage.FindString("userUsageConditionsCode", &userUsageConditionsCode)
|
||||||
&userUsageConditionsCode) == B_OK) {
|
== B_OK) {
|
||||||
agreement.SetCode(userUsageConditionsCode);
|
agreement.SetCode(userUsageConditionsCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
double timestampAgreedMillis;
|
double timestampAgreedMillis;
|
||||||
if (agreementMessage.FindDouble("timestampAgreed",
|
if (agreementMessage.FindDouble("timestampAgreed", ×tampAgreedMillis) == B_OK)
|
||||||
×tampAgreedMillis) == B_OK) {
|
agreement.SetTimestampAgreed((uint64)timestampAgreedMillis);
|
||||||
agreement.SetTimestampAgreed((uint64) timestampAgreedMillis);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (agreementMessage.FindBool("isLatest", &isLatest)
|
if (agreementMessage.FindBool("isLatest", &isLatest) == B_OK)
|
||||||
== B_OK) {
|
|
||||||
agreement.SetIsLatest(isLatest);
|
agreement.SetIsLatest(isLatest);
|
||||||
}
|
|
||||||
|
|
||||||
userDetail.SetAgreement(agreement);
|
userDetail.SetAgreement(agreement);
|
||||||
}
|
}
|
||||||
@@ -399,20 +381,18 @@ WebAppInterface::UnpackUserDetail(BMessage& responseEnvelopeMessage,
|
|||||||
|
|
||||||
|
|
||||||
/*! When an authentication API call is made, the response (if successful) will
|
/*! When an authentication API call is made, the response (if successful) will
|
||||||
return an access token in the response. This method will take the response
|
return an access token in the response. This method will take the response
|
||||||
from the server and will parse out the access token data into the supplied
|
from the server and will parse out the access token data into the supplied
|
||||||
object.
|
object.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
WebAppInterface::UnpackAccessToken(BMessage& responseEnvelopeMessage,
|
WebAppInterface::UnpackAccessToken(BMessage& responseEnvelopeMessage, AccessToken& accessToken)
|
||||||
AccessToken& accessToken)
|
|
||||||
{
|
{
|
||||||
status_t result;
|
status_t result;
|
||||||
|
|
||||||
BMessage resultMessage;
|
BMessage resultMessage;
|
||||||
result = responseEnvelopeMessage.FindMessage(
|
result = responseEnvelopeMessage.FindMessage("result", &resultMessage);
|
||||||
"result", &resultMessage);
|
|
||||||
|
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
HDERROR("bad response envelope missing 'result' entry");
|
HDERROR("bad response envelope missing 'result' entry");
|
||||||
@@ -469,12 +449,10 @@ WebAppInterface::UnpackAccessToken(BMessage& responseEnvelopeMessage,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::RetrieveUserUsageConditions(const BString& code,
|
WebAppInterface::RetrieveUserUsageConditions(const BString& code, UserUsageConditions& conditions)
|
||||||
UserUsageConditions& conditions)
|
|
||||||
{
|
{
|
||||||
BMessage responseEnvelopeMessage;
|
BMessage responseEnvelopeMessage;
|
||||||
status_t result = _RetrieveUserUsageConditionsMeta(code,
|
status_t result = _RetrieveUserUsageConditionsMeta(code, responseEnvelopeMessage);
|
||||||
responseEnvelopeMessage);
|
|
||||||
|
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -489,11 +467,10 @@ WebAppInterface::RetrieveUserUsageConditions(const BString& code,
|
|||||||
double metaDataMinimumAge;
|
double metaDataMinimumAge;
|
||||||
BString copyMarkdown;
|
BString copyMarkdown;
|
||||||
|
|
||||||
if ( (resultMessage.FindString("code", &metaDataCode) != B_OK)
|
if ((resultMessage.FindString("code", &metaDataCode) != B_OK)
|
||||||
|| (resultMessage.FindDouble(
|
|| (resultMessage.FindDouble("minimumAge", &metaDataMinimumAge) != B_OK)) {
|
||||||
"minimumAge", &metaDataMinimumAge) != B_OK) ) {
|
|
||||||
HDERROR("unexpected response from server with missing user usage "
|
HDERROR("unexpected response from server with missing user usage "
|
||||||
"conditions data");
|
"conditions data");
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,17 +482,15 @@ WebAppInterface::RetrieveUserUsageConditions(const BString& code,
|
|||||||
|
|
||||||
conditions.SetCode(metaDataCode);
|
conditions.SetCode(metaDataCode);
|
||||||
conditions.SetMinimumAge(metaDataMinimumAge);
|
conditions.SetMinimumAge(metaDataMinimumAge);
|
||||||
conditions.SetCopyMarkdown(
|
conditions.SetCopyMarkdown(BString(static_cast<const char*>(copyMarkdownData->Buffer()),
|
||||||
BString(static_cast<const char*>(copyMarkdownData->Buffer()),
|
copyMarkdownData->BufferLength()));
|
||||||
copyMarkdownData->BufferLength()));
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::AgreeUserUsageConditions(const BString& code,
|
WebAppInterface::AgreeUserUsageConditions(const BString& code, BMessage& responsePayload)
|
||||||
BMessage& responsePayload)
|
|
||||||
{
|
{
|
||||||
BMallocIO* requestEnvelopeData = new BMallocIO();
|
BMallocIO* requestEnvelopeData = new BMallocIO();
|
||||||
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
||||||
@@ -529,15 +504,13 @@ WebAppInterface::AgreeUserUsageConditions(const BString& code,
|
|||||||
|
|
||||||
// now fetch this information into an object.
|
// now fetch this information into an object.
|
||||||
|
|
||||||
return _SendJsonRequest("user/agree-user-usage-conditions",
|
return _SendJsonRequest("user/agree-user-usage-conditions", requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), NEEDS_AUTHORIZATION, responsePayload);
|
||||||
NEEDS_AUTHORIZATION, responsePayload);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::_RetrieveUserUsageConditionsMeta(const BString& code,
|
WebAppInterface::_RetrieveUserUsageConditionsMeta(const BString& code, BMessage& message)
|
||||||
BMessage& message)
|
|
||||||
{
|
{
|
||||||
BMallocIO* requestEnvelopeData = new BMallocIO();
|
BMallocIO* requestEnvelopeData = new BMallocIO();
|
||||||
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
||||||
@@ -553,33 +526,26 @@ WebAppInterface::_RetrieveUserUsageConditionsMeta(const BString& code,
|
|||||||
|
|
||||||
// now fetch this information into an object.
|
// now fetch this information into an object.
|
||||||
|
|
||||||
return _SendJsonRequest("user/get-user-usage-conditions",
|
return _SendJsonRequest("user/get-user-usage-conditions", requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), 0, message);
|
||||||
0, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::_RetrieveUserUsageConditionsCopy(const BString& code,
|
WebAppInterface::_RetrieveUserUsageConditionsCopy(const BString& code, BDataIO* stream)
|
||||||
BDataIO* stream)
|
|
||||||
{
|
{
|
||||||
return _SendRawGetRequest(
|
return _SendRawGetRequest(BString("/__user/usageconditions/") << code << "/document.md",
|
||||||
BString("/__user/usageconditions/") << code << "/document.md",
|
|
||||||
stream);
|
stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::CreateUserRating(const BString& packageName,
|
WebAppInterface::CreateUserRating(const BString& packageName, const BPackageVersion& version,
|
||||||
const BPackageVersion& version,
|
const BString& architecture, const BString& webAppRepositoryCode,
|
||||||
const BString& architecture,
|
const BString& webAppRepositorySourceCode, const BString& naturalLanguageCode,
|
||||||
const BString& webAppRepositoryCode,
|
// This is the "ID" in the ICU system; the term `code` is used with the
|
||||||
const BString& webAppRepositorySourceCode,
|
// server system.
|
||||||
const BString& naturalLanguageCode,
|
const BString& comment, const BString& stability, int rating, BMessage& message)
|
||||||
// This is the "ID" in the ICU system; the term `code` is used with the
|
|
||||||
// server system.
|
|
||||||
const BString& comment,
|
|
||||||
const BString& stability, int rating, BMessage& message)
|
|
||||||
{
|
{
|
||||||
BMallocIO* requestEnvelopeData = new BMallocIO();
|
BMallocIO* requestEnvelopeData = new BMallocIO();
|
||||||
// BHttpRequest later takes ownership of this.
|
// BHttpRequest later takes ownership of this.
|
||||||
@@ -628,7 +594,7 @@ WebAppInterface::CreateUserRating(const BString& packageName,
|
|||||||
|
|
||||||
if (rating > 0.0f) {
|
if (rating > 0.0f) {
|
||||||
requestEnvelopeWriter.WriteObjectName("rating");
|
requestEnvelopeWriter.WriteObjectName("rating");
|
||||||
requestEnvelopeWriter.WriteInteger(rating);
|
requestEnvelopeWriter.WriteInteger(rating);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stability.Length() > 0) {
|
if (stability.Length() > 0) {
|
||||||
@@ -643,19 +609,16 @@ WebAppInterface::CreateUserRating(const BString& packageName,
|
|||||||
|
|
||||||
requestEnvelopeWriter.WriteObjectEnd();
|
requestEnvelopeWriter.WriteObjectEnd();
|
||||||
|
|
||||||
return _SendJsonRequest("user-rating/create-user-rating",
|
return _SendJsonRequest("user-rating/create-user-rating", requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), NEEDS_AUTHORIZATION, message);
|
||||||
NEEDS_AUTHORIZATION, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::UpdateUserRating(const BString& ratingID,
|
WebAppInterface::UpdateUserRating(const BString& ratingID, const BString& naturalLanguageCode,
|
||||||
const BString& naturalLanguageCode,
|
// This is the "ID" in the ICU system; the term `code` is used with the
|
||||||
// This is the "ID" in the ICU system; the term `code` is used with the
|
// server system.
|
||||||
// server system.
|
const BString& comment, const BString& stability, int rating, bool active, BMessage& message)
|
||||||
const BString& comment,
|
|
||||||
const BString& stability, int rating, bool active, BMessage& message)
|
|
||||||
{
|
{
|
||||||
BMallocIO* requestEnvelopeData = new BMallocIO();
|
BMallocIO* requestEnvelopeData = new BMallocIO();
|
||||||
// BHttpRequest later takes ownership of this.
|
// BHttpRequest later takes ownership of this.
|
||||||
@@ -696,23 +659,21 @@ WebAppInterface::UpdateUserRating(const BString& ratingID,
|
|||||||
|
|
||||||
requestEnvelopeWriter.WriteObjectEnd();
|
requestEnvelopeWriter.WriteObjectEnd();
|
||||||
|
|
||||||
return _SendJsonRequest("user-rating/update-user-rating",
|
return _SendJsonRequest("user-rating/update-user-rating", requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), NEEDS_AUTHORIZATION, message);
|
||||||
NEEDS_AUTHORIZATION, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This method will call to the server to get a screenshot that will fit into
|
/*! This method will call to the server to get a screenshot that will fit into
|
||||||
the specified width and height.
|
the specified width and height.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::RetrieveScreenshot(const BString& code,
|
WebAppInterface::RetrieveScreenshot(const BString& code, int32 width, int32 height, BDataIO* stream)
|
||||||
int32 width, int32 height, BDataIO* stream)
|
|
||||||
{
|
{
|
||||||
return _SendRawGetRequest(
|
return _SendRawGetRequest(BString("/__pkgscreenshot/")
|
||||||
BString("/__pkgscreenshot/") << code << ".png" << "?tw="
|
<< code << ".png" << "?tw=" << width << "&th=" << height,
|
||||||
<< width << "&th=" << height, stream);
|
stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -726,25 +687,20 @@ WebAppInterface::RequestCaptcha(BMessage& message)
|
|||||||
requestEnvelopeWriter.WriteObjectStart();
|
requestEnvelopeWriter.WriteObjectStart();
|
||||||
requestEnvelopeWriter.WriteObjectEnd();
|
requestEnvelopeWriter.WriteObjectEnd();
|
||||||
|
|
||||||
return _SendJsonRequest("captcha/generate-captcha",
|
return _SendJsonRequest("captcha/generate-captcha", requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), 0, message);
|
||||||
0, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::CreateUser(const BString& nickName,
|
WebAppInterface::CreateUser(const BString& nickName, const BString& passwordClear,
|
||||||
const BString& passwordClear,
|
const BString& email, const BString& captchaToken, const BString& captchaResponse,
|
||||||
const BString& email,
|
|
||||||
const BString& captchaToken,
|
|
||||||
const BString& captchaResponse,
|
|
||||||
const BString& naturalLanguageCode,
|
const BString& naturalLanguageCode,
|
||||||
// This is the "ID" in the ICU system; the term `code` is used with the
|
// This is the "ID" in the ICU system; the term `code` is used with the
|
||||||
// server system.
|
// server system.
|
||||||
const BString& userUsageConditionsCode,
|
const BString& userUsageConditionsCode, BMessage& message)
|
||||||
BMessage& message)
|
|
||||||
{
|
{
|
||||||
// BHttpRequest later takes ownership of this.
|
// BHttpRequest later takes ownership of this.
|
||||||
BMallocIO* requestEnvelopeData = new BMallocIO();
|
BMallocIO* requestEnvelopeData = new BMallocIO();
|
||||||
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
BJsonTextWriter requestEnvelopeWriter(requestEnvelopeData);
|
||||||
|
|
||||||
@@ -776,7 +732,7 @@ WebAppInterface::CreateUser(const BString& nickName,
|
|||||||
|
|
||||||
|
|
||||||
/*! This method will authenticate the user set in the credentials and will
|
/*! This method will authenticate the user set in the credentials and will
|
||||||
retain the resultant access token for authenticating any latter API calls.
|
retain the resultant access token for authenticating any latter API calls.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
@@ -796,7 +752,8 @@ WebAppInterface::AuthenticateUserRetainingAccessToken()
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::_AuthenticateUserRetainingAccessToken(const BString& nickName,
|
WebAppInterface::_AuthenticateUserRetainingAccessToken(const BString& nickName,
|
||||||
const BString& passwordClear) {
|
const BString& passwordClear)
|
||||||
|
{
|
||||||
AutoLocker<BLocker> lock(&fLock);
|
AutoLocker<BLocker> lock(&fLock);
|
||||||
|
|
||||||
fAccessToken.Clear();
|
fAccessToken.Clear();
|
||||||
@@ -817,8 +774,8 @@ WebAppInterface::_AuthenticateUserRetainingAccessToken(const BString& nickName,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::AuthenticateUser(const BString& nickName,
|
WebAppInterface::AuthenticateUser(const BString& nickName, const BString& passwordClear,
|
||||||
const BString& passwordClear, BMessage& message)
|
BMessage& message)
|
||||||
{
|
{
|
||||||
BMallocIO* requestEnvelopeData = new BMallocIO();
|
BMallocIO* requestEnvelopeData = new BMallocIO();
|
||||||
// BHttpRequest later takes ownership of this.
|
// BHttpRequest later takes ownership of this.
|
||||||
@@ -833,9 +790,8 @@ WebAppInterface::AuthenticateUser(const BString& nickName,
|
|||||||
|
|
||||||
requestEnvelopeWriter.WriteObjectEnd();
|
requestEnvelopeWriter.WriteObjectEnd();
|
||||||
|
|
||||||
return _SendJsonRequest("user/authenticate-user",
|
return _SendJsonRequest("user/authenticate-user", requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), 0, message);
|
||||||
0, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -893,19 +849,16 @@ WebAppInterface::IncrementViewCounter(const PackageInfoRef package, const DepotI
|
|||||||
|
|
||||||
requestEnvelopeWriter.WriteObjectEnd();
|
requestEnvelopeWriter.WriteObjectEnd();
|
||||||
|
|
||||||
return _SendJsonRequest("pkg/increment-view-counter",
|
return _SendJsonRequest("pkg/increment-view-counter", requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), 0, message);
|
||||||
0, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::RetrievePasswordRequirements(
|
WebAppInterface::RetrievePasswordRequirements(PasswordRequirements& passwordRequirements)
|
||||||
PasswordRequirements& passwordRequirements)
|
|
||||||
{
|
{
|
||||||
BMessage responseEnvelopeMessage;
|
BMessage responseEnvelopeMessage;
|
||||||
status_t result = _RetrievePasswordRequirementsMeta(
|
status_t result = _RetrievePasswordRequirementsMeta(responseEnvelopeMessage);
|
||||||
responseEnvelopeMessage);
|
|
||||||
|
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -922,13 +875,13 @@ WebAppInterface::RetrievePasswordRequirements(
|
|||||||
double value;
|
double value;
|
||||||
|
|
||||||
if (resultMessage.FindDouble("minPasswordLength", &value) == B_OK)
|
if (resultMessage.FindDouble("minPasswordLength", &value) == B_OK)
|
||||||
passwordRequirements.SetMinPasswordLength((uint32) value);
|
passwordRequirements.SetMinPasswordLength((uint32)value);
|
||||||
|
|
||||||
if (resultMessage.FindDouble("minPasswordUppercaseChar", &value) == B_OK)
|
if (resultMessage.FindDouble("minPasswordUppercaseChar", &value) == B_OK)
|
||||||
passwordRequirements.SetMinPasswordUppercaseChar((uint32) value);
|
passwordRequirements.SetMinPasswordUppercaseChar((uint32)value);
|
||||||
|
|
||||||
if (resultMessage.FindDouble("minPasswordDigitsChar", &value) == B_OK)
|
if (resultMessage.FindDouble("minPasswordDigitsChar", &value) == B_OK)
|
||||||
passwordRequirements.SetMinPasswordDigitsChar((uint32) value);
|
passwordRequirements.SetMinPasswordDigitsChar((uint32)value);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -944,9 +897,8 @@ WebAppInterface::_RetrievePasswordRequirementsMeta(BMessage& message)
|
|||||||
requestEnvelopeWriter.WriteObjectStart();
|
requestEnvelopeWriter.WriteObjectStart();
|
||||||
requestEnvelopeWriter.WriteObjectEnd();
|
requestEnvelopeWriter.WriteObjectEnd();
|
||||||
|
|
||||||
return _SendJsonRequest("user/get-password-requirements",
|
return _SendJsonRequest("user/get-password-requirements", requestEnvelopeData,
|
||||||
requestEnvelopeData, _LengthAndSeekToZero(requestEnvelopeData),
|
_LengthAndSeekToZero(requestEnvelopeData), 0, message);
|
||||||
0, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -966,7 +918,7 @@ WebAppInterface::ErrorCodeFromResponse(BMessage& responseEnvelopeMessage)
|
|||||||
|
|
||||||
if (responseEnvelopeMessage.FindMessage("error", &error) == B_OK
|
if (responseEnvelopeMessage.FindMessage("error", &error) == B_OK
|
||||||
&& error.FindDouble("code", &code) == B_OK) {
|
&& error.FindDouble("code", &code) == B_OK) {
|
||||||
return (int32) code;
|
return (int32)code;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -977,9 +929,8 @@ WebAppInterface::ErrorCodeFromResponse(BMessage& responseEnvelopeMessage)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
WebAppInterface::_SendJsonRequest(const char* urlPathComponents, BPositionIO* requestData,
|
||||||
BPositionIO* requestData, size_t requestDataSize, uint32 flags,
|
size_t requestDataSize, uint32 flags, BMessage& reply)
|
||||||
BMessage& reply)
|
|
||||||
{
|
{
|
||||||
bool needsAuthorization = (flags & NEEDS_AUTHORIZATION) != 0;
|
bool needsAuthorization = (flags & NEEDS_AUTHORIZATION) != 0;
|
||||||
AccessToken accessToken;
|
AccessToken accessToken;
|
||||||
@@ -987,15 +938,14 @@ WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
|||||||
if (needsAuthorization)
|
if (needsAuthorization)
|
||||||
accessToken = _ObtainValidAccessToken();
|
accessToken = _ObtainValidAccessToken();
|
||||||
|
|
||||||
return _SendJsonRequest(urlPathComponents, accessToken, requestData,
|
return _SendJsonRequest(urlPathComponents, accessToken, requestData, requestDataSize, flags,
|
||||||
requestDataSize, flags, reply);
|
reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
WebAppInterface::_SendJsonRequest(const char* urlPathComponents, const AccessToken& accessToken,
|
||||||
const AccessToken& accessToken, BPositionIO* requestData,
|
BPositionIO* requestData, size_t requestDataSize, uint32 flags, BMessage& reply)
|
||||||
size_t requestDataSize, uint32 flags, BMessage& reply)
|
|
||||||
{
|
{
|
||||||
if (requestDataSize == 0) {
|
if (requestDataSize == 0) {
|
||||||
HDINFO("%s; empty request payload", PROTOCOL_NAME);
|
HDINFO("%s; empty request payload", PROTOCOL_NAME);
|
||||||
@@ -1004,14 +954,15 @@ WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
|||||||
|
|
||||||
if (!ServerHelper::IsNetworkAvailable()) {
|
if (!ServerHelper::IsNetworkAvailable()) {
|
||||||
HDDEBUG("%s; dropping request to ...[%s] as network is not"
|
HDDEBUG("%s; dropping request to ...[%s] as network is not"
|
||||||
" available", PROTOCOL_NAME, urlPathComponents);
|
" available",
|
||||||
|
PROTOCOL_NAME, urlPathComponents);
|
||||||
delete requestData;
|
delete requestData;
|
||||||
return HD_NETWORK_INACCESSIBLE;
|
return HD_NETWORK_INACCESSIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ServerSettings::IsClientTooOld()) {
|
if (ServerSettings::IsClientTooOld()) {
|
||||||
HDDEBUG("%s; dropping request to ...[%s] as client is too old",
|
HDDEBUG("%s; dropping request to ...[%s] as client is too old", PROTOCOL_NAME,
|
||||||
PROTOCOL_NAME, urlPathComponents);
|
urlPathComponents);
|
||||||
delete requestData;
|
delete requestData;
|
||||||
return HD_CLIENT_TOO_OLD;
|
return HD_CLIENT_TOO_OLD;
|
||||||
}
|
}
|
||||||
@@ -1019,16 +970,14 @@ WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
|||||||
bool needsAuthorization = (flags & NEEDS_AUTHORIZATION) != 0;
|
bool needsAuthorization = (flags & NEEDS_AUTHORIZATION) != 0;
|
||||||
|
|
||||||
if (needsAuthorization && !accessToken.IsValid()) {
|
if (needsAuthorization && !accessToken.IsValid()) {
|
||||||
HDDEBUG("%s; dropping request to ...[%s] as access token is not valid",
|
HDDEBUG("%s; dropping request to ...[%s] as access token is not valid", PROTOCOL_NAME,
|
||||||
PROTOCOL_NAME, urlPathComponents);
|
urlPathComponents);
|
||||||
delete requestData;
|
delete requestData;
|
||||||
return B_NOT_ALLOWED;
|
return B_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
BUrl url = ServerSettings::CreateFullUrl(BString("/__api/v2/")
|
BUrl url = ServerSettings::CreateFullUrl(BString("/__api/v2/") << urlPathComponents);
|
||||||
<< urlPathComponents);
|
HDDEBUG("%s; will make request to [%s]", PROTOCOL_NAME, url.UrlString().String());
|
||||||
HDDEBUG("%s; will make request to [%s]", PROTOCOL_NAME,
|
|
||||||
url.UrlString().String());
|
|
||||||
|
|
||||||
// If the request payload is logged then it must be copied to local memory
|
// If the request payload is logged then it must be copied to local memory
|
||||||
// from the stream. This then requires that the request data is then
|
// from the stream. This then requires that the request data is then
|
||||||
@@ -1071,13 +1020,12 @@ WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
|||||||
thread_id thread = request->Run();
|
thread_id thread = request->Run();
|
||||||
wait_for_thread(thread, NULL);
|
wait_for_thread(thread, NULL);
|
||||||
|
|
||||||
const BHttpResult& result = dynamic_cast<const BHttpResult&>(
|
const BHttpResult& result = dynamic_cast<const BHttpResult&>(request->Result());
|
||||||
request->Result());
|
|
||||||
|
|
||||||
int32 statusCode = result.StatusCode();
|
int32 statusCode = result.StatusCode();
|
||||||
|
|
||||||
HDDEBUG("%s; did receive http-status [%" B_PRId32 "] from [%s]",
|
HDDEBUG("%s; did receive http-status [%" B_PRId32 "] from [%s]", PROTOCOL_NAME, statusCode,
|
||||||
PROTOCOL_NAME, statusCode, url.UrlString().String());
|
url.UrlString().String());
|
||||||
|
|
||||||
switch (statusCode) {
|
switch (statusCode) {
|
||||||
case B_HTTP_STATUS_OK:
|
case B_HTTP_STATUS_OK:
|
||||||
@@ -1089,8 +1037,8 @@ WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
HDERROR("%s; request to endpoint [.../%s] failed with http "
|
HDERROR("%s; request to endpoint [.../%s] failed with http "
|
||||||
"status [%" B_PRId32 "]\n", PROTOCOL_NAME, urlPathComponents,
|
"status [%" B_PRId32 "]\n",
|
||||||
statusCode);
|
PROTOCOL_NAME, urlPathComponents, statusCode);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1108,7 +1056,7 @@ WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
|||||||
status_t status = jsonMessageWriter.ErrorStatus();
|
status_t status = jsonMessageWriter.ErrorStatus();
|
||||||
|
|
||||||
if (Logger::IsTraceEnabled() && status == B_BAD_DATA) {
|
if (Logger::IsTraceEnabled() && status == B_BAD_DATA) {
|
||||||
BString resultString(static_cast<const char *>(replyData.Buffer()),
|
BString resultString(static_cast<const char*>(replyData.Buffer()),
|
||||||
replyData.BufferLength());
|
replyData.BufferLength());
|
||||||
HDERROR("Parser choked on JSON:\n%s", resultString.String());
|
HDERROR("Parser choked on JSON:\n%s", resultString.String());
|
||||||
}
|
}
|
||||||
@@ -1117,33 +1065,29 @@ WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::_SendJsonRequest(const char* urlPathComponents,
|
WebAppInterface::_SendJsonRequest(const char* urlPathComponents, const BString& jsonString,
|
||||||
const BString& jsonString, uint32 flags, BMessage& reply)
|
uint32 flags, BMessage& reply)
|
||||||
{
|
{
|
||||||
// gets 'adopted' by the subsequent http request.
|
// gets 'adopted' by the subsequent http request.
|
||||||
BMemoryIO* data = new BMemoryIO(jsonString.String(),
|
BMemoryIO* data = new BMemoryIO(jsonString.String(), jsonString.Length() - 1);
|
||||||
jsonString.Length() - 1);
|
|
||||||
|
|
||||||
return _SendJsonRequest(urlPathComponents, data, jsonString.Length() - 1,
|
return _SendJsonRequest(urlPathComponents, data, jsonString.Length() - 1, flags, reply);
|
||||||
flags, reply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
WebAppInterface::_SendRawGetRequest(const BString urlPathComponents,
|
WebAppInterface::_SendRawGetRequest(const BString urlPathComponents, BDataIO* stream)
|
||||||
BDataIO* stream)
|
|
||||||
{
|
{
|
||||||
BUrl url = ServerSettings::CreateFullUrl(urlPathComponents);
|
BUrl url = ServerSettings::CreateFullUrl(urlPathComponents);
|
||||||
|
|
||||||
HDDEBUG("http-get; will make request to [%s]",
|
HDDEBUG("http-get; will make request to [%s]", url.UrlString().String());
|
||||||
url.UrlString().String());
|
|
||||||
|
|
||||||
ProtocolListener listener;
|
ProtocolListener listener;
|
||||||
|
|
||||||
BHttpHeaders headers;
|
BHttpHeaders headers;
|
||||||
ServerSettings::AugmentHeaders(headers);
|
ServerSettings::AugmentHeaders(headers);
|
||||||
|
|
||||||
BHttpRequest *request = make_http_request(url, stream, &listener);
|
BHttpRequest* request = make_http_request(url, stream, &listener);
|
||||||
ObjectDeleter<BHttpRequest> _(request);
|
ObjectDeleter<BHttpRequest> _(request);
|
||||||
if (request == NULL)
|
if (request == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -1153,19 +1097,17 @@ WebAppInterface::_SendRawGetRequest(const BString urlPathComponents,
|
|||||||
thread_id thread = request->Run();
|
thread_id thread = request->Run();
|
||||||
wait_for_thread(thread, NULL);
|
wait_for_thread(thread, NULL);
|
||||||
|
|
||||||
const BHttpResult& result = dynamic_cast<const BHttpResult&>(
|
const BHttpResult& result = dynamic_cast<const BHttpResult&>(request->Result());
|
||||||
request->Result());
|
|
||||||
|
|
||||||
int32 statusCode = result.StatusCode();
|
int32 statusCode = result.StatusCode();
|
||||||
|
|
||||||
HDDEBUG("http-get; did receive http-status [%" B_PRId32 "] from [%s]",
|
HDDEBUG("http-get; did receive http-status [%" B_PRId32 "] from [%s]", statusCode,
|
||||||
statusCode, url.UrlString().String());
|
url.UrlString().String());
|
||||||
|
|
||||||
if (statusCode == 200)
|
if (statusCode == 200)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
HDERROR("failed to get data from '%s': %" B_PRIi32 "",
|
HDERROR("failed to get data from '%s': %" B_PRIi32 "", url.UrlString().String(), statusCode);
|
||||||
url.UrlString().String(), statusCode);
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1183,17 +1125,16 @@ WebAppInterface::_LogPayload(BPositionIO* requestData, size_t size)
|
|||||||
printf("%s; error logging payload", PROTOCOL_NAME);
|
printf("%s; error logging payload", PROTOCOL_NAME);
|
||||||
} else {
|
} else {
|
||||||
for (uint32 i = 0; i < size; i++) {
|
for (uint32 i = 0; i < size; i++) {
|
||||||
bool esc = buffer[i] > 126 ||
|
bool esc = buffer[i] > 126 || (buffer[i] < 0x20 && buffer[i] != 0x0a);
|
||||||
(buffer[i] < 0x20 && buffer[i] != 0x0a);
|
|
||||||
|
|
||||||
if (esc)
|
if (esc)
|
||||||
printf("\\u%02x", buffer[i]);
|
printf("\\u%02x", buffer[i]);
|
||||||
else
|
else
|
||||||
putchar(buffer[i]);
|
putchar(buffer[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == LOG_PAYLOAD_LIMIT)
|
if (size == LOG_PAYLOAD_LIMIT)
|
||||||
printf("...(continues)");
|
printf("...(continues)");
|
||||||
}
|
}
|
||||||
|
|
||||||
requestData->Seek(requestDataOffset, SEEK_SET);
|
requestData->Seek(requestDataOffset, SEEK_SET);
|
||||||
@@ -1209,15 +1150,14 @@ off_t
|
|||||||
WebAppInterface::_LengthAndSeekToZero(BPositionIO* data)
|
WebAppInterface::_LengthAndSeekToZero(BPositionIO* data)
|
||||||
{
|
{
|
||||||
off_t dataSize = data->Position();
|
off_t dataSize = data->Position();
|
||||||
data->Seek(0, SEEK_SET);
|
data->Seek(0, SEEK_SET);
|
||||||
return dataSize;
|
return dataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UserCredentials
|
UserCredentials
|
||||||
WebAppInterface::_Credentials()
|
WebAppInterface::_Credentials()
|
||||||
{
|
{
|
||||||
AutoLocker<BLocker> lock(&fLock);
|
|
||||||
return fCredentials;
|
return fCredentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Copyright 2016-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2016-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef WEB_APP_INTERFACE_H
|
#ifndef WEB_APP_INTERFACE_H
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <JsonWriter.h>
|
#include <JsonWriter.h>
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
|
#include <Referenceable.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <package/PackageVersion.h>
|
#include <package/PackageVersion.h>
|
||||||
|
|
||||||
@@ -43,12 +44,12 @@ using BPackageKit::BPackageVersion;
|
|||||||
#define RATING_NONE -1
|
#define RATING_NONE -1
|
||||||
|
|
||||||
|
|
||||||
class WebAppInterface {
|
class WebAppInterface : public BReferenceable
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
WebAppInterface();
|
WebAppInterface(const UserCredentials& value);
|
||||||
virtual ~WebAppInterface();
|
virtual ~WebAppInterface();
|
||||||
|
|
||||||
void SetCredentials(const UserCredentials& value);
|
|
||||||
const BString& Nickname();
|
const BString& Nickname();
|
||||||
|
|
||||||
status_t GetChangelog(
|
status_t GetChangelog(
|
||||||
@@ -157,6 +158,7 @@ public:
|
|||||||
BMessage& responseEnvelopeMessage,
|
BMessage& responseEnvelopeMessage,
|
||||||
AccessToken& accessToken);
|
AccessToken& accessToken);
|
||||||
private:
|
private:
|
||||||
|
void _SetCredentials(const UserCredentials& value);
|
||||||
UserCredentials _Credentials();
|
UserCredentials _Credentials();
|
||||||
|
|
||||||
AccessToken _ObtainValidAccessToken();
|
AccessToken _ObtainValidAccessToken();
|
||||||
@@ -199,4 +201,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef BReference<WebAppInterface> WebAppInterfaceRef;
|
||||||
|
|
||||||
|
|
||||||
#endif // WEB_APP_INTERFACE_H
|
#endif // WEB_APP_INTERFACE_H
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "TarArchiveService.h"
|
#include "TarArchiveService.h"
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
data for the parsed entry.
|
data for the parsed entry.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
TarArchiveService::GetEntry(BPositionIO& tarIo, TarArchiveHeader& header)
|
TarArchiveService::GetEntry(BPositionIO& tarIo, TarArchiveHeader& header)
|
||||||
{
|
{
|
||||||
uint8 buffer[LENGTH_BLOCK];
|
uint8 buffer[LENGTH_BLOCK];
|
||||||
@@ -46,7 +46,7 @@ TarArchiveService::GetEntry(BPositionIO& tarIo, TarArchiveHeader& header)
|
|||||||
useful for obtaining a catalog of items in the tar file for example.
|
useful for obtaining a catalog of items in the tar file for example.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*status*/ status_t
|
/*status*/ status_t
|
||||||
TarArchiveService::ForEachEntry(BPositionIO& tarIo, TarEntryListener* listener)
|
TarArchiveService::ForEachEntry(BPositionIO& tarIo, TarEntryListener* listener)
|
||||||
{
|
{
|
||||||
uint8 buffer[LENGTH_BLOCK];
|
uint8 buffer[LENGTH_BLOCK];
|
||||||
@@ -58,21 +58,17 @@ TarArchiveService::ForEachEntry(BPositionIO& tarIo, TarEntryListener* listener)
|
|||||||
memset(zero_buffer, 0, sizeof zero_buffer);
|
memset(zero_buffer, 0, sizeof zero_buffer);
|
||||||
tarIo.Seek(offset, SEEK_SET);
|
tarIo.Seek(offset, SEEK_SET);
|
||||||
|
|
||||||
while (result == B_OK
|
while (result == B_OK && B_OK == (result = tarIo.ReadExactly(buffer, LENGTH_BLOCK))) {
|
||||||
&& B_OK == (result = tarIo.ReadExactly(
|
|
||||||
buffer, LENGTH_BLOCK))) {
|
|
||||||
|
|
||||||
if (memcmp(zero_buffer, buffer, sizeof zero_buffer) == 0) {
|
if (memcmp(zero_buffer, buffer, sizeof zero_buffer) == 0) {
|
||||||
HDDEBUG("detected end of tar-ball after %" B_PRIu32 " items",
|
HDTRACE("detected end of tar-ball after %" B_PRIu32 " items", countItemsRead);
|
||||||
countItemsRead);
|
|
||||||
return B_OK; // end of tar-ball.
|
return B_OK; // end of tar-ball.
|
||||||
}
|
}
|
||||||
|
|
||||||
TarArchiveHeader header;
|
TarArchiveHeader header;
|
||||||
result = _ReadHeader(buffer, header);
|
result = _ReadHeader(buffer, header);
|
||||||
|
|
||||||
HDTRACE("did read tar entry header for [%s]",
|
HDTRACE("did read tar entry header for [%s]", header.FileName().String());
|
||||||
header.FileName().String());
|
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
countItemsRead++;
|
countItemsRead++;
|
||||||
@@ -81,8 +77,7 @@ TarArchiveService::ForEachEntry(BPositionIO& tarIo, TarEntryListener* listener)
|
|||||||
// and/or just process the header information.
|
// and/or just process the header information.
|
||||||
|
|
||||||
if (listener != NULL) {
|
if (listener != NULL) {
|
||||||
BDataIO *entryData = new ConstraintedDataIO(&tarIo,
|
BDataIO* entryData = new ConstraintedDataIO(&tarIo, header.Length());
|
||||||
header.Length());
|
|
||||||
ObjectDeleter<BDataIO> entryDataDeleter(entryData);
|
ObjectDeleter<BDataIO> entryDataDeleter(entryData);
|
||||||
result = listener->Handle(header, offset, entryData);
|
result = listener->Handle(header, offset, entryData);
|
||||||
}
|
}
|
||||||
@@ -105,7 +100,8 @@ TarArchiveService::ForEachEntry(BPositionIO& tarIo, TarEntryListener* listener)
|
|||||||
|
|
||||||
|
|
||||||
tar_file_type
|
tar_file_type
|
||||||
TarArchiveService::_ReadHeaderFileType(unsigned char data) {
|
TarArchiveService::_ReadHeaderFileType(unsigned char data)
|
||||||
|
{
|
||||||
switch (data) {
|
switch (data) {
|
||||||
case 0:
|
case 0:
|
||||||
case '0':
|
case '0':
|
||||||
@@ -117,22 +113,20 @@ TarArchiveService::_ReadHeaderFileType(unsigned char data) {
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ int32
|
/*static*/ int32
|
||||||
TarArchiveService::_ReadHeaderStringLength(const uint8* data,
|
TarArchiveService::_ReadHeaderStringLength(const uint8* data, size_t maxStringLength)
|
||||||
size_t maxStringLength)
|
|
||||||
{
|
{
|
||||||
int32 actualLength = 0;
|
size_t actualLength = 0;
|
||||||
while (actualLength < (int32) maxStringLength && data[actualLength] != 0)
|
|
||||||
|
while (actualLength < maxStringLength && data[actualLength] != 0)
|
||||||
actualLength++;
|
actualLength++;
|
||||||
return actualLength;
|
return static_cast<int32>(actualLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TarArchiveService::_ReadHeaderString(const uint8 *data, size_t maxStringLength,
|
TarArchiveService::_ReadHeaderString(const uint8* data, size_t maxStringLength, BString& result)
|
||||||
BString& result)
|
|
||||||
{
|
{
|
||||||
result.SetTo((const char *) data,
|
result.SetTo((const char*)data, _ReadHeaderStringLength(data, maxStringLength));
|
||||||
_ReadHeaderStringLength(data, maxStringLength));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -140,7 +134,8 @@ TarArchiveService::_ReadHeaderString(const uint8 *data, size_t maxStringLength,
|
|||||||
character in an number expressed in octal.
|
character in an number expressed in octal.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool tar_is_octal_digit(unsigned char c)
|
static bool
|
||||||
|
tar_is_octal_digit(unsigned char c)
|
||||||
{
|
{
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '0':
|
case '0':
|
||||||
@@ -159,7 +154,7 @@ static bool tar_is_octal_digit(unsigned char c)
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ uint32
|
/*static*/ uint32
|
||||||
TarArchiveService::_ReadHeaderNumeric(const uint8 *data, size_t dataLength)
|
TarArchiveService::_ReadHeaderNumeric(const uint8* data, size_t dataLength)
|
||||||
{
|
{
|
||||||
uint32 actualLength = 0;
|
uint32 actualLength = 0;
|
||||||
|
|
||||||
@@ -187,7 +182,7 @@ TarArchiveService::_CalculateBlockChecksum(const uint8* block)
|
|||||||
if (i >= OFFSET_CHECKSUM && i < OFFSET_CHECKSUM + LENGTH_CHECKSUM)
|
if (i >= OFFSET_CHECKSUM && i < OFFSET_CHECKSUM + LENGTH_CHECKSUM)
|
||||||
result += 32;
|
result += 32;
|
||||||
else
|
else
|
||||||
result += (uint32) block[i];
|
result += static_cast<uint32>(block[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -198,12 +193,10 @@ TarArchiveService::_CalculateBlockChecksum(const uint8* block)
|
|||||||
TarArchiveService::_ReadHeader(const uint8* block, TarArchiveHeader& header)
|
TarArchiveService::_ReadHeader(const uint8* block, TarArchiveHeader& header)
|
||||||
{
|
{
|
||||||
uint32 actualChecksum = _CalculateBlockChecksum(block);
|
uint32 actualChecksum = _CalculateBlockChecksum(block);
|
||||||
uint32 expectedChecksum = _ReadHeaderNumeric(&block[OFFSET_CHECKSUM],
|
uint32 expectedChecksum = _ReadHeaderNumeric(&block[OFFSET_CHECKSUM], LENGTH_CHECKSUM);
|
||||||
LENGTH_CHECKSUM);
|
|
||||||
|
|
||||||
if(actualChecksum != expectedChecksum) {
|
if (actualChecksum != expectedChecksum) {
|
||||||
HDERROR("tar archive header has bad checksum;"
|
HDERROR("tar archive header has bad checksum; expected %" B_PRIu32 " actual %" B_PRIu32,
|
||||||
"expected %" B_PRIu32 " actual %" B_PRIu32,
|
|
||||||
expectedChecksum, actualChecksum);
|
expectedChecksum, actualChecksum);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
@@ -212,10 +205,8 @@ TarArchiveService::_ReadHeader(const uint8* block, TarArchiveHeader& header)
|
|||||||
_ReadHeaderString(&block[OFFSET_FILENAME], LENGTH_FILENAME, fileName);
|
_ReadHeaderString(&block[OFFSET_FILENAME], LENGTH_FILENAME, fileName);
|
||||||
|
|
||||||
header.SetFileName(fileName);
|
header.SetFileName(fileName);
|
||||||
header.SetLength(
|
header.SetLength(_ReadHeaderNumeric(&block[OFFSET_LENGTH], LENGTH_LENGTH));
|
||||||
_ReadHeaderNumeric(&block[OFFSET_LENGTH], LENGTH_LENGTH));
|
header.SetFileType(_ReadHeaderFileType(block[OFFSET_FILETYPE]));
|
||||||
header.SetFileType(
|
|
||||||
_ReadHeaderFileType(block[OFFSET_FILETYPE]));
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
+80
-113
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
|
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Copyright 2017-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -13,19 +13,20 @@
|
|||||||
#include <Catalog.h>
|
#include <Catalog.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <package/PackageDefs.h>
|
|
||||||
#include <package/PackageInfo.h>
|
|
||||||
#include <package/PackageRoster.h>
|
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
#include <Screen.h>
|
#include <Screen.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
#include <package/PackageDefs.h>
|
||||||
|
#include <package/PackageInfo.h>
|
||||||
|
#include <package/PackageRoster.h>
|
||||||
|
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
|
||||||
#include "AppUtils.h"
|
#include "AppUtils.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
#include "PackageKitUtils.h"
|
||||||
#include "PackageUtils.h"
|
#include "PackageUtils.h"
|
||||||
#include "ServerHelper.h"
|
#include "ServerHelper.h"
|
||||||
#include "ServerSettings.h"
|
#include "ServerSettings.h"
|
||||||
@@ -44,7 +45,7 @@ App::App()
|
|||||||
fWindowCount(0),
|
fWindowCount(0),
|
||||||
fSettingsRead(false)
|
fSettingsRead(false)
|
||||||
{
|
{
|
||||||
srand((unsigned int) time(NULL));
|
srand(static_cast<unsigned int>(time(NULL)));
|
||||||
_CheckPackageDaemonRuns();
|
_CheckPackageDaemonRuns();
|
||||||
fIsFirstRun = _CheckIsFirstRun();
|
fIsFirstRun = _CheckIsFirstRun();
|
||||||
}
|
}
|
||||||
@@ -62,13 +63,10 @@ App::~App()
|
|||||||
bool
|
bool
|
||||||
App::QuitRequested()
|
App::QuitRequested()
|
||||||
{
|
{
|
||||||
if (fMainWindow != NULL
|
if (fMainWindow != NULL && fMainWindow->LockLooperWithTimeout(1500000) == B_OK) {
|
||||||
&& fMainWindow->LockLooperWithTimeout(1500000) == B_OK) {
|
|
||||||
BMessage windowSettings;
|
BMessage windowSettings;
|
||||||
fMainWindow->StoreSettings(windowSettings);
|
fMainWindow->StoreSettings(windowSettings);
|
||||||
|
|
||||||
fMainWindow->UnlockLooper();
|
fMainWindow->UnlockLooper();
|
||||||
|
|
||||||
_StoreSettings(windowSettings);
|
_StoreSettings(windowSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,10 +109,8 @@ App::MessageReceived(BMessage* message)
|
|||||||
case MSG_MAIN_WINDOW_CLOSED:
|
case MSG_MAIN_WINDOW_CLOSED:
|
||||||
{
|
{
|
||||||
BMessage windowSettings;
|
BMessage windowSettings;
|
||||||
if (message->FindMessage(KEY_WINDOW_SETTINGS,
|
if (message->FindMessage(KEY_WINDOW_SETTINGS, &windowSettings) == B_OK)
|
||||||
&windowSettings) == B_OK) {
|
|
||||||
_StoreSettings(windowSettings);
|
_StoreSettings(windowSettings);
|
||||||
}
|
|
||||||
|
|
||||||
fWindowCount--;
|
fWindowCount--;
|
||||||
if (fWindowCount == 0)
|
if (fWindowCount == 0)
|
||||||
@@ -199,7 +195,7 @@ app_print_help()
|
|||||||
|
|
||||||
|
|
||||||
static arg_switch
|
static arg_switch
|
||||||
app_resolve_switch(char *arg)
|
app_resolve_switch(char* arg)
|
||||||
{
|
{
|
||||||
int arglen = strlen(arg);
|
int arglen = strlen(arg);
|
||||||
|
|
||||||
@@ -223,18 +219,14 @@ app_resolve_switch(char *arg)
|
|||||||
|
|
||||||
if (0 == strcmp(&arg[2], "dropcache"))
|
if (0 == strcmp(&arg[2], "dropcache"))
|
||||||
return DROP_CACHE_SWITCH;
|
return DROP_CACHE_SWITCH;
|
||||||
} else {
|
} else if (arglen == 2) { // short form
|
||||||
if (arglen == 2) { // short form
|
switch (arg[1]) {
|
||||||
switch (arg[1]) {
|
case 'h':
|
||||||
case 'u':
|
return HELP_SWITCH;
|
||||||
return WEB_APP_BASE_URL_SWITCH;
|
case 'u':
|
||||||
|
return WEB_APP_BASE_URL_SWITCH;
|
||||||
case 'h':
|
case 'v':
|
||||||
return HELP_SWITCH;
|
return VERBOSITY_SWITCH;
|
||||||
|
|
||||||
case 'v':
|
|
||||||
return VERBOSITY_SWITCH;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,15 +242,14 @@ App::ArgvReceived(int32 argc, char* argv[])
|
|||||||
{
|
{
|
||||||
for (int i = 1; i < argc;) {
|
for (int i = 1; i < argc;) {
|
||||||
|
|
||||||
// check to make sure that if there is a value for the switch,
|
// check to make sure that if there is a value for the switch,
|
||||||
// that the value is in fact supplied.
|
// that the value is in fact supplied.
|
||||||
|
|
||||||
switch (app_resolve_switch(argv[i])) {
|
switch (app_resolve_switch(argv[i])) {
|
||||||
case VERBOSITY_SWITCH:
|
case VERBOSITY_SWITCH:
|
||||||
case WEB_APP_BASE_URL_SWITCH:
|
case WEB_APP_BASE_URL_SWITCH:
|
||||||
if (i == argc-1) {
|
if (i == argc - 1) {
|
||||||
fprintf(stdout, "unexpected end of arguments; missing "
|
HDERROR("unexpected end of arguments; missing value for switch [%s]", argv[i]);
|
||||||
"value for switch [%s]\n", argv[i]);
|
|
||||||
Quit();
|
Quit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -268,12 +259,12 @@ App::ArgvReceived(int32 argc, char* argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now process each switch.
|
// now process each switch.
|
||||||
|
|
||||||
switch (app_resolve_switch(argv[i])) {
|
switch (app_resolve_switch(argv[i])) {
|
||||||
|
|
||||||
case VERBOSITY_SWITCH:
|
case VERBOSITY_SWITCH:
|
||||||
if (!Logger::SetLevelByName(argv[i+1])) {
|
if (!Logger::SetLevelByName(argv[i + 1])) {
|
||||||
fprintf(stdout, "unknown log level [%s]\n", argv[i + 1]);
|
fprintf(stdout, "unknown log level [%s]\n", argv[i + 1]);
|
||||||
Quit();
|
Quit();
|
||||||
}
|
}
|
||||||
@@ -287,13 +278,10 @@ App::ArgvReceived(int32 argc, char* argv[])
|
|||||||
|
|
||||||
case WEB_APP_BASE_URL_SWITCH:
|
case WEB_APP_BASE_URL_SWITCH:
|
||||||
if (ServerSettings::SetBaseUrl(BUrl(argv[i + 1])) != B_OK) {
|
if (ServerSettings::SetBaseUrl(BUrl(argv[i + 1])) != B_OK) {
|
||||||
fprintf(stdout, "malformed web app base url; %s\n",
|
HDERROR("malformed web app base url; %s", argv[i + 1]);
|
||||||
argv[i + 1]);
|
|
||||||
Quit();
|
Quit();
|
||||||
}
|
} else {
|
||||||
else {
|
HDERROR("did configure the web base url; %s", argv[i + 1]);
|
||||||
fprintf(stdout, "did configure the web base url; %s\n",
|
|
||||||
argv[i + 1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i++; // also move past the url value
|
i++; // also move past the url value
|
||||||
@@ -330,8 +318,8 @@ App::ArgvReceived(int32 argc, char* argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This method will display an alert based on a message. This message arrives
|
/*! This method will display an alert based on a message. This message arrives
|
||||||
from a number of possible background threads / processes in the application.
|
from a number of possible background threads / processes in the application.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -350,8 +338,8 @@ App::_AlertSimpleError(BMessage* message)
|
|||||||
if (message->FindInt32(KEY_ALERT_TYPE, &typeInt) != B_OK)
|
if (message->FindInt32(KEY_ALERT_TYPE, &typeInt) != B_OK)
|
||||||
typeInt = B_INFO_ALERT;
|
typeInt = B_INFO_ALERT;
|
||||||
|
|
||||||
BAlert* alert = new BAlert(alertTitle, alertText, B_TRANSLATE("OK"),
|
BAlert* alert = new BAlert(alertTitle, alertText, B_TRANSLATE("OK"), NULL, NULL,
|
||||||
NULL, NULL, B_WIDTH_AS_USUAL, static_cast<alert_type>(typeInt));
|
B_WIDTH_AS_USUAL, static_cast<alert_type>(typeInt));
|
||||||
|
|
||||||
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
||||||
alert->Go();
|
alert->Go();
|
||||||
@@ -366,7 +354,7 @@ App::_Open(const BEntry& entry)
|
|||||||
{
|
{
|
||||||
BPath path;
|
BPath path;
|
||||||
if (!entry.Exists() || entry.GetPath(&path) != B_OK) {
|
if (!entry.Exists() || entry.GetPath(&path) != B_OK) {
|
||||||
fprintf(stderr, "Package file not found: %s\n", path.Path());
|
HDERROR("package file not found: %s", path.Path());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,20 +362,16 @@ App::_Open(const BEntry& entry)
|
|||||||
BPackageKit::BPackageInfo info;
|
BPackageKit::BPackageInfo info;
|
||||||
status_t status = info.ReadFromPackageFile(path.Path());
|
status_t status = info.ReadFromPackageFile(path.Path());
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "Failed to parse package file: %s\n",
|
HDERROR("failed to parse package file: %s", strerror(status));
|
||||||
strerror(status));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer information into PackageInfo
|
// Transfer information into PackageInfo
|
||||||
PackageInfoRef package(new(std::nothrow) PackageInfo(info), true);
|
PackageInfoRef filePackageInfo = PackageKitUtils::CreatePackageInfo(info);
|
||||||
if (!package.IsSet()) {
|
PackageInfoBuilder packageBuilder(filePackageInfo);
|
||||||
fprintf(stderr, "Could not allocate PackageInfo\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageLocalInfoRef localInfo = PackageUtils::NewLocalInfo(package);
|
PackageLocalInfoBuilder localInfoBuilder(filePackageInfo->LocalInfo());
|
||||||
localInfo->SetLocalFilePath(path.Path());
|
localInfoBuilder.WithLocalFilePath(path.Path());
|
||||||
|
|
||||||
// Set if the package is active
|
// Set if the package is active
|
||||||
//
|
//
|
||||||
@@ -396,33 +380,30 @@ App::_Open(const BEntry& entry)
|
|||||||
// package kit have to know about these locations?
|
// package kit have to know about these locations?
|
||||||
bool active = false;
|
bool active = false;
|
||||||
BPackageKit::BPackageRoster roster;
|
BPackageKit::BPackageRoster roster;
|
||||||
status = roster.IsPackageActive(
|
status = roster.IsPackageActive(BPackageKit::B_PACKAGE_INSTALLATION_LOCATION_SYSTEM, info,
|
||||||
BPackageKit::B_PACKAGE_INSTALLATION_LOCATION_SYSTEM, info, &active);
|
&active);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "Could not check if package was active in system: %s\n",
|
HDERROR("could not check if package was active in system: %s", strerror(status));
|
||||||
strerror(status));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!active) {
|
if (!active) {
|
||||||
status = roster.IsPackageActive(
|
status = roster.IsPackageActive(BPackageKit::B_PACKAGE_INSTALLATION_LOCATION_HOME, info,
|
||||||
BPackageKit::B_PACKAGE_INSTALLATION_LOCATION_HOME, info, &active);
|
&active);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
fprintf(stderr,
|
HDERROR("could not check if package was active in home: %s", strerror(status));
|
||||||
"Could not check if package was active in home: %s\n",
|
|
||||||
strerror(status));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
localInfo->SetState(ACTIVATED);
|
localInfoBuilder.WithState(ACTIVATED);
|
||||||
|
|
||||||
package->SetLocalInfo(localInfo);
|
packageBuilder.WithLocalInfo(localInfoBuilder.BuildRef());
|
||||||
|
|
||||||
BMessage settings;
|
BMessage settings;
|
||||||
_LoadSettings(settings);
|
_LoadSettings(settings);
|
||||||
|
|
||||||
MainWindow* window = new MainWindow(settings, package);
|
MainWindow* window = new MainWindow(settings, packageBuilder.BuildRef());
|
||||||
_ShowWindow(window);
|
_ShowWindow(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,21 +459,19 @@ App::_StoreSettings(const BMessage& settings)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
static const char* kPackageDaemonSignature
|
static const char* kPackageDaemonSignature = "application/x-vnd.haiku-package_daemon";
|
||||||
= "application/x-vnd.haiku-package_daemon";
|
|
||||||
|
|
||||||
void
|
void
|
||||||
App::_CheckPackageDaemonRuns()
|
App::_CheckPackageDaemonRuns()
|
||||||
{
|
{
|
||||||
while (!be_roster->IsRunning(kPackageDaemonSignature)) {
|
while (!be_roster->IsRunning(kPackageDaemonSignature)) {
|
||||||
BAlert* alert = new BAlert(
|
BAlert* alert = new BAlert(B_TRANSLATE("Start package daemon"),
|
||||||
B_TRANSLATE("Start package daemon"),
|
|
||||||
B_TRANSLATE("HaikuDepot needs the package daemon to function, "
|
B_TRANSLATE("HaikuDepot needs the package daemon to function, "
|
||||||
"and it appears to be not running.\n"
|
"and it appears to be not running.\n"
|
||||||
"Would you like to start it now?"),
|
"Would you like to start it now?"),
|
||||||
B_TRANSLATE("No, quit HaikuDepot"),
|
B_TRANSLATE("No, quit HaikuDepot"), B_TRANSLATE("Start package daemon"), NULL,
|
||||||
B_TRANSLATE("Start package daemon"), NULL, B_WIDTH_AS_USUAL,
|
B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
||||||
B_WARNING_ALERT);
|
|
||||||
alert->SetShortcut(0, B_ESCAPE);
|
alert->SetShortcut(0, B_ESCAPE);
|
||||||
|
|
||||||
if (alert->Go() == 0)
|
if (alert->Go() == 0)
|
||||||
@@ -509,14 +488,11 @@ App::_LaunchPackageDaemon()
|
|||||||
{
|
{
|
||||||
status_t ret = be_roster->Launch(kPackageDaemonSignature);
|
status_t ret = be_roster->Launch(kPackageDaemonSignature);
|
||||||
if (ret != B_OK) {
|
if (ret != B_OK) {
|
||||||
BString errorMessage
|
BString errorMessage = B_TRANSLATE("Starting the package daemon failed:\n\n%Error%");
|
||||||
= B_TRANSLATE("Starting the package daemon failed:\n\n%Error%");
|
|
||||||
errorMessage.ReplaceAll("%Error%", strerror(ret));
|
errorMessage.ReplaceAll("%Error%", strerror(ret));
|
||||||
|
|
||||||
BAlert* alert = new BAlert(
|
BAlert* alert = new BAlert(B_TRANSLATE("Package daemon problem"), errorMessage,
|
||||||
B_TRANSLATE("Package daemon problem"), errorMessage,
|
B_TRANSLATE("Quit HaikuDepot"), B_TRANSLATE("Try again"), NULL, B_WIDTH_AS_USUAL,
|
||||||
B_TRANSLATE("Quit HaikuDepot"),
|
|
||||||
B_TRANSLATE("Try again"), NULL, B_WIDTH_AS_USUAL,
|
|
||||||
B_WARNING_ALERT);
|
B_WARNING_ALERT);
|
||||||
alert->SetShortcut(0, B_ESCAPE);
|
alert->SetShortcut(0, B_ESCAPE);
|
||||||
|
|
||||||
@@ -535,20 +511,18 @@ App::_CheckIsFirstRun()
|
|||||||
{
|
{
|
||||||
BPath testFilePath;
|
BPath testFilePath;
|
||||||
bool exists = false;
|
bool exists = false;
|
||||||
status_t status = StorageUtils::LocalWorkingFilesPath("testfile.txt",
|
status_t status = StorageUtils::LocalWorkingFilesPath("testfile.txt", testFilePath, false);
|
||||||
testFilePath, false);
|
if (status != B_OK)
|
||||||
if (status != B_OK) {
|
|
||||||
HDERROR("unable to establish the location of the test file");
|
HDERROR("unable to establish the location of the test file");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
status = StorageUtils::ExistsObject(testFilePath, &exists, NULL, NULL);
|
status = StorageUtils::ExistsObject(testFilePath, &exists, NULL, NULL);
|
||||||
return !exists;
|
return !exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Checks to ensure that a working file is able to be written.
|
/*! \brief Checks to ensure that a working file is able to be written.
|
||||||
\return false if the startup should be stopped and the application should
|
\return false if the startup should be stopped and the application should
|
||||||
quit.
|
quit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -556,8 +530,7 @@ App::_CheckTestFile()
|
|||||||
{
|
{
|
||||||
BPath testFilePath;
|
BPath testFilePath;
|
||||||
BString pathDescription = "???";
|
BString pathDescription = "???";
|
||||||
status_t result = StorageUtils::LocalWorkingFilesPath("testfile.txt",
|
status_t result = StorageUtils::LocalWorkingFilesPath("testfile.txt", testFilePath, false);
|
||||||
testFilePath, false);
|
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
pathDescription = testFilePath.Path();
|
pathDescription = testFilePath.Path();
|
||||||
@@ -567,19 +540,18 @@ App::_CheckTestFile()
|
|||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
StorageUtils::SetWorkingFilesUnavailable();
|
StorageUtils::SetWorkingFilesUnavailable();
|
||||||
|
|
||||||
BString msg = B_TRANSLATE("This application writes and reads some"
|
BString msg
|
||||||
" working files on your computer in order to function. It appears"
|
= B_TRANSLATE("This application writes and reads some"
|
||||||
" that there are problems writing a test file at [%TestFilePath%]."
|
" working files on your computer in order to function. It appears"
|
||||||
" Check that there are no issues with your local disk or"
|
" that there are problems writing a test file at [%TestFilePath%]."
|
||||||
" permissions that might prevent this application from writing"
|
" Check that there are no issues with your local disk or"
|
||||||
" files into that directory location. You may choose to acknowledge"
|
" permissions that might prevent this application from writing"
|
||||||
" this problem and continue, but some functionality may be"
|
" files into that directory location. You may choose to acknowledge"
|
||||||
" disabled.");
|
" this problem and continue, but some functionality may be"
|
||||||
|
" disabled.");
|
||||||
msg.ReplaceAll("%TestFilePath%", pathDescription);
|
msg.ReplaceAll("%TestFilePath%", pathDescription);
|
||||||
|
|
||||||
BAlert* alert = new(std::nothrow) BAlert(
|
BAlert* alert = new(std::nothrow) BAlert(B_TRANSLATE("Problem with working files"), msg,
|
||||||
B_TRANSLATE("Problem with working files"),
|
|
||||||
msg,
|
|
||||||
B_TRANSLATE("Quit"), B_TRANSLATE("Continue"));
|
B_TRANSLATE("Quit"), B_TRANSLATE("Continue"));
|
||||||
|
|
||||||
if (alert->Go() == 0)
|
if (alert->Go() == 0)
|
||||||
@@ -611,8 +583,7 @@ App::_ClearCacheOnVersionChange()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BPath lastVersionPath;
|
BPath lastVersionPath;
|
||||||
if (StorageUtils::LocalWorkingFilesPath(
|
if (StorageUtils::LocalWorkingFilesPath("version.txt", lastVersionPath) != B_OK) {
|
||||||
"version.txt", lastVersionPath) != B_OK) {
|
|
||||||
HDERROR("clear cache; unable to get version file path");
|
HDERROR("clear cache; unable to get version file path");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -620,30 +591,26 @@ App::_ClearCacheOnVersionChange()
|
|||||||
bool exists;
|
bool exists;
|
||||||
off_t size;
|
off_t size;
|
||||||
|
|
||||||
if (StorageUtils::ExistsObject(
|
if (StorageUtils::ExistsObject(lastVersionPath, &exists, NULL, &size) != B_OK) {
|
||||||
lastVersionPath, &exists, NULL, &size) != B_OK) {
|
|
||||||
HDERROR("clear cache; unable to check version file exists");
|
HDERROR("clear cache; unable to check version file exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BString lastVersion;
|
BString lastVersion;
|
||||||
|
|
||||||
if (exists && StorageUtils::AppendToString(lastVersionPath, lastVersion)
|
if (exists && StorageUtils::AppendToString(lastVersionPath, lastVersion) != B_OK) {
|
||||||
!= B_OK) {
|
HDERROR("clear cache; unable to read the version from [%s]", lastVersionPath.Path());
|
||||||
HDERROR("clear cache; unable to read the version from [%s]",
|
|
||||||
lastVersionPath.Path());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastVersion != version) {
|
if (lastVersion != version) {
|
||||||
HDINFO("last version [%s] and current version [%s] do not match"
|
HDINFO("last version [%s] and current version [%s] do not match -> will flush cache",
|
||||||
" -> will flush cache", lastVersion.String(), version.String());
|
lastVersion.String(), version.String());
|
||||||
StorageUtils::RemoveWorkingDirectoryContents();
|
StorageUtils::RemoveWorkingDirectoryContents();
|
||||||
HDINFO("will write version [%s] to [%s]",
|
HDINFO("will write version [%s] to [%s]", version.String(), lastVersionPath.Path());
|
||||||
version.String(), lastVersionPath.Path());
|
|
||||||
StorageUtils::AppendToFile(version, lastVersionPath);
|
StorageUtils::AppendToFile(version, lastVersionPath);
|
||||||
} else {
|
} else {
|
||||||
HDINFO("last version [%s] and current version [%s] match"
|
HDINFO("last version [%s] and current version [%s] match -> cache retained",
|
||||||
" -> cache retained", lastVersion.String(), version.String());
|
lastVersion.String(), version.String());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013-214, Stephan Aßmus <superstippi@gmx.de>.
|
* Copyright 2013-214, Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>.
|
* Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>.
|
||||||
* Copyright 2020-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "MarkupTextView.h"
|
#include "MarkupTextView.h"
|
||||||
#include "MessagePackageListener.h"
|
|
||||||
#include "PackageUtils.h"
|
#include "PackageUtils.h"
|
||||||
#include "RatingUtils.h"
|
#include "RatingUtils.h"
|
||||||
#include "RatingView.h"
|
#include "RatingView.h"
|
||||||
@@ -55,8 +54,7 @@
|
|||||||
// #pragma mark - PackageView
|
// #pragma mark - PackageView
|
||||||
|
|
||||||
|
|
||||||
class StackedFeaturesPackageBandMetrics
|
class StackedFeaturesPackageBandMetrics {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
StackedFeaturesPackageBandMetrics(float width, BFont* titleFont, BFont* metadataFont)
|
StackedFeaturesPackageBandMetrics(float width, BFont* titleFont, BFont* metadataFont)
|
||||||
{
|
{
|
||||||
@@ -69,8 +67,7 @@ public:
|
|||||||
metadataFont->GetHeight(&metadataFontHeight);
|
metadataFont->GetHeight(&metadataFontHeight);
|
||||||
|
|
||||||
float totalTitleAndMetadataHeight = titleFontHeight.ascent + titleFontHeight.descent
|
float totalTitleAndMetadataHeight = titleFontHeight.ascent + titleFontHeight.descent
|
||||||
+ titleFontHeight.leading
|
+ titleFontHeight.leading + metadataFontHeight.leading
|
||||||
+ metadataFontHeight.leading
|
|
||||||
+ 2.0 * (metadataFontHeight.ascent + metadataFontHeight.descent);
|
+ 2.0 * (metadataFontHeight.ascent + metadataFontHeight.descent);
|
||||||
|
|
||||||
fHeight = fmaxf(totalTitleAndMetadataHeight, iconSize.Height()) + 2.0 * padding;
|
fHeight = fmaxf(totalTitleAndMetadataHeight, iconSize.Height()) + 2.0 * padding;
|
||||||
@@ -85,41 +82,43 @@ public:
|
|||||||
float titleWidthM = titleFont->StringWidth("M");
|
float titleWidthM = titleFont->StringWidth("M");
|
||||||
|
|
||||||
float leftTitlePublisherAndChronologicalInfo = fIconRect.right + padding;
|
float leftTitlePublisherAndChronologicalInfo = fIconRect.right + padding;
|
||||||
float rightTitlePublisherAndChronologicalInfo = fminf(width, fIconRect.Size().Width()
|
float rightTitlePublisherAndChronologicalInfo = fminf(width,
|
||||||
+ (2.0 * padding) + (titleWidthM * M_COUNT_TITLE));
|
fIconRect.Size().Width() + (2.0 * padding) + (titleWidthM * M_COUNT_TITLE));
|
||||||
|
|
||||||
|
// left, top, right bottom
|
||||||
|
|
||||||
// left, top, right bottom
|
|
||||||
fTitleRect = BRect(leftTitlePublisherAndChronologicalInfo,
|
fTitleRect = BRect(leftTitlePublisherAndChronologicalInfo,
|
||||||
(fHeight - totalTitleAndMetadataHeight) / 2.0,
|
(fHeight - totalTitleAndMetadataHeight) / 2.0,
|
||||||
rightTitlePublisherAndChronologicalInfo,
|
rightTitlePublisherAndChronologicalInfo,
|
||||||
((fHeight - totalTitleAndMetadataHeight) / 2.0)
|
((fHeight - totalTitleAndMetadataHeight) / 2.0) + titleFontHeight.ascent
|
||||||
+ titleFontHeight.ascent + titleFontHeight.descent);
|
+ titleFontHeight.descent);
|
||||||
|
|
||||||
fPublisherRect = BRect(leftTitlePublisherAndChronologicalInfo,
|
fPublisherRect = BRect(leftTitlePublisherAndChronologicalInfo,
|
||||||
fTitleRect.bottom + titleFontHeight.leading,
|
fTitleRect.bottom + titleFontHeight.leading,
|
||||||
rightTitlePublisherAndChronologicalInfo,
|
rightTitlePublisherAndChronologicalInfo,
|
||||||
fTitleRect.bottom + titleFontHeight.leading
|
fTitleRect.bottom + titleFontHeight.leading + metadataFontHeight.ascent
|
||||||
+ metadataFontHeight.ascent + metadataFontHeight.descent);
|
+ metadataFontHeight.descent);
|
||||||
|
|
||||||
fChronologicalInfoRect = BRect(leftTitlePublisherAndChronologicalInfo,
|
fChronologicalInfoRect = BRect(leftTitlePublisherAndChronologicalInfo,
|
||||||
fPublisherRect.bottom + metadataFontHeight.leading,
|
fPublisherRect.bottom + metadataFontHeight.leading,
|
||||||
rightTitlePublisherAndChronologicalInfo,
|
rightTitlePublisherAndChronologicalInfo,
|
||||||
fPublisherRect.bottom + metadataFontHeight.leading
|
fPublisherRect.bottom + metadataFontHeight.leading + metadataFontHeight.ascent
|
||||||
+ metadataFontHeight.ascent + metadataFontHeight.descent);
|
+ metadataFontHeight.descent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort out the ratings display
|
// sort out the ratings display
|
||||||
|
|
||||||
{
|
{
|
||||||
BSize ratingStarSize = SharedIcons::IconStarBlue16Scaled()->Bitmap()->Bounds().Size();
|
BSize ratingStarSize = SharedIcons::IconStarBlue16Scaled()->Bitmap()->Bounds().Size();
|
||||||
RatingStarsMetrics ratingStarsMetrics(ratingStarSize);
|
RatingStarsMetrics ratingStarsMetrics(ratingStarSize);
|
||||||
|
|
||||||
fRatingStarsRect = BRect(BPoint(fTitleRect.right + padding,
|
fRatingStarsRect = BRect(BPoint(fTitleRect.right + padding,
|
||||||
(fHeight - ratingStarsMetrics.Size().Height()) / 2), ratingStarsMetrics.Size());
|
(fHeight - ratingStarsMetrics.Size().Height()) / 2),
|
||||||
|
ratingStarsMetrics.Size());
|
||||||
|
|
||||||
if (fRatingStarsRect.right > width)
|
if (fRatingStarsRect.right > width) {
|
||||||
fRatingStarsRect = BRect();
|
fRatingStarsRect = BRect();
|
||||||
else {
|
} else {
|
||||||
// Now sort out the position for the summary. This is reckoned as a container
|
// Now sort out the position for the summary. This is reckoned as a container
|
||||||
// rect because it would be nice to layout the text with newlines and not just a
|
// rect because it would be nice to layout the text with newlines and not just a
|
||||||
// single line.
|
// single line.
|
||||||
@@ -190,10 +189,7 @@ public:
|
|||||||
:
|
:
|
||||||
BView("stacked featured packages view", B_WILL_DRAW | B_FRAME_EVENTS),
|
BView("stacked featured packages view", B_WILL_DRAW | B_FRAME_EVENTS),
|
||||||
fModel(model),
|
fModel(model),
|
||||||
fSelectedIndex(-1),
|
fSelectedIndex(-1)
|
||||||
fPackageListener(
|
|
||||||
new(std::nothrow) OnePackageMessagePackageListener(this)),
|
|
||||||
fLowestIndexAddedOrRemoved(-1)
|
|
||||||
{
|
{
|
||||||
SetEventMask(B_POINTER_EVENTS);
|
SetEventMask(B_POINTER_EVENTS);
|
||||||
|
|
||||||
@@ -208,29 +204,17 @@ public:
|
|||||||
|
|
||||||
virtual ~StackedFeaturedPackagesView()
|
virtual ~StackedFeaturedPackagesView()
|
||||||
{
|
{
|
||||||
fPackageListener->SetPackage(PackageInfoRef(NULL));
|
|
||||||
fPackageListener->ReleaseReference();
|
|
||||||
delete fBandMetrics;
|
delete fBandMetrics;
|
||||||
delete fTitleFont;
|
delete fTitleFont;
|
||||||
delete fMetadataFont;
|
delete fMetadataFont;
|
||||||
delete fSummaryFont;
|
delete fSummaryFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #pragma mark - message handling and events
|
// #pragma mark - message handling and events
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message)
|
virtual void MessageReceived(BMessage* message)
|
||||||
{
|
{
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case MSG_UPDATE_PACKAGE:
|
|
||||||
{
|
|
||||||
BString name;
|
|
||||||
if (message->FindString("name", &name) != B_OK)
|
|
||||||
HDINFO("expected 'name' key on package update message");
|
|
||||||
else
|
|
||||||
_HandleUpdatePackage(name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_COLORS_UPDATED:
|
case B_COLORS_UPDATED:
|
||||||
{
|
{
|
||||||
Invalidate();
|
Invalidate();
|
||||||
@@ -268,16 +252,14 @@ public:
|
|||||||
case B_DOWN_ARROW:
|
case B_DOWN_ARROW:
|
||||||
{
|
{
|
||||||
int32 lastIndex = static_cast<int32>(fPackages.size()) - 1;
|
int32 lastIndex = static_cast<int32>(fPackages.size()) - 1;
|
||||||
if (!IsEmpty() && fSelectedIndex != -1
|
if (!IsEmpty() && fSelectedIndex != -1 && fSelectedIndex < lastIndex)
|
||||||
&& fSelectedIndex < lastIndex) {
|
|
||||||
_MessageSelectIndex(fSelectedIndex + 1);
|
_MessageSelectIndex(fSelectedIndex + 1);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case B_LEFT_ARROW:
|
case B_LEFT_ARROW:
|
||||||
case B_UP_ARROW:
|
case B_UP_ARROW:
|
||||||
if (fSelectedIndex > 0)
|
if (fSelectedIndex > 0)
|
||||||
_MessageSelectIndex( fSelectedIndex - 1);
|
_MessageSelectIndex(fSelectedIndex - 1);
|
||||||
break;
|
break;
|
||||||
case B_PAGE_UP:
|
case B_PAGE_UP:
|
||||||
{
|
{
|
||||||
@@ -328,13 +310,26 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - update / add / remove / clear data
|
// #pragma mark - update / add / remove / clear data
|
||||||
|
|
||||||
|
|
||||||
void UpdatePackage(uint32 changeMask, const PackageInfoRef& package)
|
void HandlePackagesChanged(const PackageInfoEvents& events)
|
||||||
{
|
{
|
||||||
// TODO; could optimize the invalidation?
|
for (int32 i = events.CountEvents() - 1; i >= 0; i--)
|
||||||
|
_HandlePackageChanged(events.EventAtIndex(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _HandlePackageChanged(const PackageInfoEvent& event)
|
||||||
|
{
|
||||||
|
uint32 changes = event.Changes();
|
||||||
|
PackageInfoRef package = event.Package();
|
||||||
|
|
||||||
|
if (!package.IsSet() || 0 == changes)
|
||||||
|
return;
|
||||||
|
|
||||||
int32 index = _IndexOfPackage(package);
|
int32 index = _IndexOfPackage(package);
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
fPackages[index] = package;
|
fPackages[index] = package;
|
||||||
Invalidate(_RectOfIndex(index));
|
Invalidate(_RectOfIndex(index));
|
||||||
@@ -344,10 +339,6 @@ public:
|
|||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
for (std::vector<PackageInfoRef>::iterator it = fPackages.begin();
|
|
||||||
it != fPackages.end(); it++) {
|
|
||||||
(*it)->RemoveListener(fPackageListener);
|
|
||||||
}
|
|
||||||
fPackages.clear();
|
fPackages.clear();
|
||||||
fSelectedIndex = -1;
|
fSelectedIndex = -1;
|
||||||
|
|
||||||
@@ -367,8 +358,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static BFont* CreateMetadataFont()
|
static BFont* CreateMetadataFont()
|
||||||
{
|
{
|
||||||
BFont* font = new BFont(be_plain_font);
|
BFont* font = new BFont(be_plain_font);
|
||||||
font_family family;
|
font_family family;
|
||||||
font_style style;
|
font_style style;
|
||||||
@@ -396,14 +387,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _HandleUpdatePackage(const BString& name)
|
|
||||||
{
|
|
||||||
int32 index = _IndexOfName(name);
|
|
||||||
if (index != -1)
|
|
||||||
Invalidate(_RectOfIndex(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int _CmpProminences(int64 a, int64 b)
|
static int _CmpProminences(int64 a, int64 b)
|
||||||
{
|
{
|
||||||
if (a <= 0)
|
if (a <= 0)
|
||||||
@@ -456,68 +439,110 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BeginAddRemove()
|
void _InvalidateFromIndex(int32 index)
|
||||||
{
|
{
|
||||||
fLowestIndexAddedOrRemoved = INT32_MAX;
|
if (index != -1) {
|
||||||
}
|
if (fPackages.empty()) {
|
||||||
|
|
||||||
|
|
||||||
void EndAddRemove()
|
|
||||||
{
|
|
||||||
if (fLowestIndexAddedOrRemoved < INT32_MAX) {
|
|
||||||
if (fPackages.empty())
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
else {
|
} else {
|
||||||
BRect invalidRect = Bounds();
|
BRect invalidRect = Bounds();
|
||||||
invalidRect.top = _YOfIndex(fLowestIndexAddedOrRemoved);
|
invalidRect.top = _YOfIndex(index);
|
||||||
Invalidate(invalidRect);
|
Invalidate(invalidRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AddPackage(const PackageInfoRef& package)
|
/*! Finds the index of the first difference between the current list of
|
||||||
|
packages and the provided list of packages. Returns -1 if there is
|
||||||
|
no difference. This is used with the `RetainPackages` method.
|
||||||
|
*/
|
||||||
|
int32 _IndexOfFirstDifference(const std::vector<PackageInfoRef>& packages)
|
||||||
|
{
|
||||||
|
size_t result = 0;
|
||||||
|
size_t packagesLen = packages.size();
|
||||||
|
size_t currentPackagesLen = fPackages.size();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (result == packagesLen && result == currentPackagesLen)
|
||||||
|
return -1;
|
||||||
|
if (result >= packagesLen || result >= currentPackagesLen)
|
||||||
|
return static_cast<int32>(result);
|
||||||
|
if (packages[result] != fPackages[result])
|
||||||
|
return static_cast<int32>(result);
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RetainPackages(const std::vector<PackageInfoRef>& packages)
|
||||||
|
{
|
||||||
|
int32 lowestIndexAddedOrRemoved = _IndexOfFirstDifference(packages);
|
||||||
|
fPackages = packages;
|
||||||
|
_InvalidateFromIndex(lowestIndexAddedOrRemoved);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _AddPackage(const PackageInfoRef& package, int32* lowestIndexAddedOrRemoved)
|
||||||
{
|
{
|
||||||
// fPackages is sorted and for this reason it is possible to find the
|
// fPackages is sorted and for this reason it is possible to find the
|
||||||
// insertion point by identifying the first item in fPackages that does
|
// insertion point by identifying the first item in fPackages that does
|
||||||
// not return true from the method '_IsPackageBefore'.
|
// not return true from the method '_IsPackageBefore'.
|
||||||
|
|
||||||
std::vector<PackageInfoRef>::iterator itInsertionPt
|
std::vector<PackageInfoRef>::iterator itInsertionPt
|
||||||
= std::lower_bound(fPackages.begin(), fPackages.end(), package,
|
= std::lower_bound(fPackages.begin(), fPackages.end(), package, &_IsPackageBefore);
|
||||||
&_IsPackageBefore);
|
|
||||||
|
if (itInsertionPt == fPackages.end() || package->Name() != (*itInsertionPt)->Name()) {
|
||||||
|
int32 insertionIndex = std::distance<std::vector<PackageInfoRef>::const_iterator>(
|
||||||
|
fPackages.begin(), itInsertionPt);
|
||||||
|
|
||||||
if (itInsertionPt == fPackages.end()
|
|
||||||
|| package->Name() != (*itInsertionPt)->Name()) {
|
|
||||||
int32 insertionIndex =
|
|
||||||
std::distance<std::vector<PackageInfoRef>::const_iterator>(
|
|
||||||
fPackages.begin(), itInsertionPt);
|
|
||||||
if (fSelectedIndex >= insertionIndex)
|
if (fSelectedIndex >= insertionIndex)
|
||||||
fSelectedIndex++;
|
fSelectedIndex++;
|
||||||
|
|
||||||
fPackages.insert(itInsertionPt, package);
|
fPackages.insert(itInsertionPt, package);
|
||||||
package->AddListener(fPackageListener);
|
|
||||||
if (insertionIndex < fLowestIndexAddedOrRemoved)
|
if (insertionIndex > *lowestIndexAddedOrRemoved)
|
||||||
fLowestIndexAddedOrRemoved = insertionIndex;
|
*lowestIndexAddedOrRemoved = insertionIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RemovePackage(const PackageInfoRef& package)
|
void _RemovePackage(const PackageInfoRef& package, int32* lowestIndexAddedOrRemoved)
|
||||||
{
|
{
|
||||||
int32 index = _IndexOfPackage(package);
|
int32 removalIndex = _IndexOfPackage(package);
|
||||||
if (index >= 0) {
|
if (removalIndex >= 0) {
|
||||||
if (fSelectedIndex == index)
|
|
||||||
|
if (fSelectedIndex == removalIndex)
|
||||||
fSelectedIndex = -1;
|
fSelectedIndex = -1;
|
||||||
if (fSelectedIndex > index)
|
|
||||||
|
if (fSelectedIndex > removalIndex)
|
||||||
fSelectedIndex--;
|
fSelectedIndex--;
|
||||||
fPackages[index]->RemoveListener(fPackageListener);
|
|
||||||
fPackages.erase(fPackages.begin() + index);
|
fPackages.erase(fPackages.begin() + removalIndex);
|
||||||
if (index < fLowestIndexAddedOrRemoved)
|
|
||||||
fLowestIndexAddedOrRemoved = index;
|
if (removalIndex > *lowestIndexAddedOrRemoved)
|
||||||
|
*lowestIndexAddedOrRemoved = removalIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - selection and index handling
|
void AddRemovePackages(const std::vector<PackageInfoRef>& addedPackages,
|
||||||
|
const std::vector<PackageInfoRef>& removedPackages)
|
||||||
|
{
|
||||||
|
int32 lowestIndexAddedOrRemoved = -1;
|
||||||
|
std::vector<PackageInfoRef>::const_iterator it;
|
||||||
|
|
||||||
|
for (it = addedPackages.begin(); it != addedPackages.end(); it++)
|
||||||
|
_AddPackage(*it, &lowestIndexAddedOrRemoved);
|
||||||
|
|
||||||
|
for (it = removedPackages.begin(); it != removedPackages.end(); it++)
|
||||||
|
_RemovePackage(*it, &lowestIndexAddedOrRemoved);
|
||||||
|
|
||||||
|
_InvalidateFromIndex(lowestIndexAddedOrRemoved);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - selection and index handling
|
||||||
|
|
||||||
|
|
||||||
void SelectPackage(const PackageInfoRef& package)
|
void SelectPackage(const PackageInfoRef& package)
|
||||||
@@ -543,11 +568,12 @@ public:
|
|||||||
int32 _IndexOfPackage(PackageInfoRef package) const
|
int32 _IndexOfPackage(PackageInfoRef package) const
|
||||||
{
|
{
|
||||||
std::vector<PackageInfoRef>::const_iterator it
|
std::vector<PackageInfoRef>::const_iterator it
|
||||||
= std::lower_bound(fPackages.begin(), fPackages.end(), package,
|
= std::lower_bound(fPackages.begin(), fPackages.end(), package, &_IsPackageBefore);
|
||||||
&_IsPackageBefore);
|
|
||||||
|
|
||||||
return (it == fPackages.end() || (*it)->Name() != package->Name())
|
if (it == fPackages.end() || (*it)->Name() != package->Name())
|
||||||
? -1 : it - fPackages.begin();
|
return -1;
|
||||||
|
|
||||||
|
return it - fPackages.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -564,7 +590,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - drawing and rendering
|
// #pragma mark - drawing and rendering
|
||||||
|
|
||||||
|
|
||||||
virtual void Draw(BRect updateRect)
|
virtual void Draw(BRect updateRect)
|
||||||
@@ -626,9 +652,14 @@ public:
|
|||||||
if (!iconRect.IsValid())
|
if (!iconRect.IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
PackageIconRepositoryRef iconRepository = fModel.IconRepository();
|
||||||
|
|
||||||
|
if (!iconRepository.IsSet())
|
||||||
|
return;
|
||||||
|
|
||||||
BitmapHolderRef icon;
|
BitmapHolderRef icon;
|
||||||
status_t iconResult = fModel.GetPackageIconRepository().GetIcon(pkg->Name(),
|
|
||||||
iconRect.Width(), icon);
|
status_t iconResult = iconRepository->GetIcon(pkg->Name(), iconRect.Width(), icon);
|
||||||
|
|
||||||
if (iconResult == B_OK) {
|
if (iconResult == B_OK) {
|
||||||
if (icon.IsSet()) {
|
if (icon.IsSet()) {
|
||||||
@@ -659,9 +690,9 @@ public:
|
|||||||
float trailingIconsWidth = 0.0f;
|
float trailingIconsWidth = 0.0f;
|
||||||
|
|
||||||
for (std::vector<BitmapHolderRef>::iterator it = trailingIconBitmaps.begin();
|
for (std::vector<BitmapHolderRef>::iterator it = trailingIconBitmaps.begin();
|
||||||
it != trailingIconBitmaps.end(); it++) {
|
it != trailingIconBitmaps.end(); it++) {
|
||||||
trailingIconsWidth += (*it)->Bitmap()->Bounds().Width()
|
trailingIconsWidth
|
||||||
* (1.0 + TRAILING_ICON_PADDING_LEFT_FACTOR);
|
+= (*it)->Bitmap()->Bounds().Width() * (1.0 + TRAILING_ICON_PADDING_LEFT_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDrawingMode(B_OP_COPY);
|
SetDrawingMode(B_OP_COPY);
|
||||||
@@ -671,20 +702,20 @@ public:
|
|||||||
float titleRightTrailingIconsPadding = 0.0f;
|
float titleRightTrailingIconsPadding = 0.0f;
|
||||||
|
|
||||||
if (!trailingIconBitmaps.empty()) {
|
if (!trailingIconBitmaps.empty()) {
|
||||||
titleRightTrailingIconsPadding = StringWidth("M")
|
titleRightTrailingIconsPadding
|
||||||
* TITLE_RIGHT_TRAILING_ICON_PADDING_M_FACTOR;
|
= StringWidth("M") * TITLE_RIGHT_TRAILING_ICON_PADDING_M_FACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
font_height fontHeight;
|
font_height fontHeight;
|
||||||
fTitleFont->GetHeight(&fontHeight);
|
fTitleFont->GetHeight(&fontHeight);
|
||||||
BPoint pt = textRect.LeftTop() + BPoint(0.0, + fontHeight.ascent);
|
BPoint pt = textRect.LeftTop() + BPoint(0.0, +fontHeight.ascent);
|
||||||
|
|
||||||
BString title;
|
BString title;
|
||||||
PackageUtils::TitleOrName(pkg, title);
|
PackageUtils::TitleOrName(pkg, title);
|
||||||
|
|
||||||
BString renderedText = title;
|
BString renderedText = title;
|
||||||
TruncateString(&renderedText, B_TRUNCATE_END, textRect.Width()
|
TruncateString(&renderedText, B_TRUNCATE_END,
|
||||||
- (titleRightTrailingIconsPadding + trailingIconsWidth));
|
textRect.Width() - (titleRightTrailingIconsPadding + trailingIconsWidth));
|
||||||
|
|
||||||
DrawString(renderedText, pt);
|
DrawString(renderedText, pt);
|
||||||
|
|
||||||
@@ -697,14 +728,15 @@ public:
|
|||||||
SetDrawingMode(B_OP_ALPHA);
|
SetDrawingMode(B_OP_ALPHA);
|
||||||
|
|
||||||
for (std::vector<BitmapHolderRef>::iterator it = trailingIconBitmaps.begin();
|
for (std::vector<BitmapHolderRef>::iterator it = trailingIconBitmaps.begin();
|
||||||
it != trailingIconBitmaps.end(); it++) {
|
it != trailingIconBitmaps.end(); it++) {
|
||||||
const BBitmap* bitmap = (*it)->Bitmap();
|
const BBitmap* bitmap = (*it)->Bitmap();
|
||||||
BRect bitmapBounds = bitmap->Bounds();
|
BRect bitmapBounds = bitmap->Bounds();
|
||||||
|
|
||||||
float trailingIconTopLeftPtX = ceilf(
|
float trailingIconTopLeftPtX
|
||||||
trailingIconX + (bitmapBounds.Width() * TRAILING_ICON_PADDING_LEFT_FACTOR)) + 0.5;
|
= ceilf(trailingIconX + (bitmapBounds.Width() * TRAILING_ICON_PADDING_LEFT_FACTOR))
|
||||||
float trailingIconTopLeftPtY = ceilf(
|
+ 0.5;
|
||||||
trailingIconMidY - (bitmapBounds.Height() / 2.0)) + 0.5;
|
float trailingIconTopLeftPtY
|
||||||
|
= ceilf(trailingIconMidY - (bitmapBounds.Height() / 2.0)) + 0.5;
|
||||||
|
|
||||||
BRect trailingIconRect(BPoint(trailingIconTopLeftPtX, trailingIconTopLeftPtY),
|
BRect trailingIconRect(BPoint(trailingIconTopLeftPtX, trailingIconTopLeftPtY),
|
||||||
bitmap->Bounds().Size());
|
bitmap->Bounds().Size());
|
||||||
@@ -727,7 +759,7 @@ public:
|
|||||||
|
|
||||||
font_height fontHeight;
|
font_height fontHeight;
|
||||||
fMetadataFont->GetHeight(&fontHeight);
|
fMetadataFont->GetHeight(&fontHeight);
|
||||||
BPoint pt = textRect.LeftTop() + BPoint(0.0, + fontHeight.ascent);
|
BPoint pt = textRect.LeftTop() + BPoint(0.0, +fontHeight.ascent);
|
||||||
|
|
||||||
BString renderedText(text);
|
BString renderedText(text);
|
||||||
TruncateString(&renderedText, B_TRUNCATE_END, textRect.Width());
|
TruncateString(&renderedText, B_TRUNCATE_END, textRect.Width());
|
||||||
@@ -762,7 +794,7 @@ public:
|
|||||||
if (!ratingRect.IsValid())
|
if (!ratingRect.IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UserRatingInfoRef userRatingInfo = pkg->UserRatingInfo();
|
PackageUserRatingInfoRef userRatingInfo = pkg->UserRatingInfo();
|
||||||
|
|
||||||
if (userRatingInfo.IsSet()) {
|
if (userRatingInfo.IsSet()) {
|
||||||
UserRatingSummaryRef userRatingSummary = userRatingInfo->Summary();
|
UserRatingSummaryRef userRatingSummary = userRatingInfo->Summary();
|
||||||
@@ -789,9 +821,10 @@ public:
|
|||||||
// The text rect is a container into which later text can be made to flow multi-line. For
|
// The text rect is a container into which later text can be made to flow multi-line. For
|
||||||
// now just draw one line of the summary.
|
// now just draw one line of the summary.
|
||||||
|
|
||||||
BPoint pt = textRect.LeftTop() + BPoint(0.0,
|
BPoint pt = textRect.LeftTop()
|
||||||
(textRect.Size().Height() / 2.0) - ((fontHeight.ascent + fontHeight.descent) / 2.0)
|
+ BPoint(0.0,
|
||||||
+ fontHeight.ascent);
|
(textRect.Size().Height() / 2.0) - ((fontHeight.ascent + fontHeight.descent) / 2.0)
|
||||||
|
+ fontHeight.ascent);
|
||||||
|
|
||||||
BString summary;
|
BString summary;
|
||||||
PackageUtils::Summary(pkg, summary);
|
PackageUtils::Summary(pkg, summary);
|
||||||
@@ -801,7 +834,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - geometry and scrolling
|
// #pragma mark - geometry and scrolling
|
||||||
|
|
||||||
|
|
||||||
/*! This method will make sure that the package at the given index is
|
/*! This method will make sure that the package at the given index is
|
||||||
@@ -816,9 +849,9 @@ public:
|
|||||||
if (!_IsIndexEntirelyVisible(index)) {
|
if (!_IsIndexEntirelyVisible(index)) {
|
||||||
BRect bounds = Bounds();
|
BRect bounds = Bounds();
|
||||||
int32 indexOfCentreVisible = _IndexOfY(bounds.top + bounds.Height() / 2);
|
int32 indexOfCentreVisible = _IndexOfY(bounds.top + bounds.Height() / 2);
|
||||||
if (index < indexOfCentreVisible)
|
if (index < indexOfCentreVisible) {
|
||||||
ScrollTo(0, _YOfIndex(index));
|
ScrollTo(0, _YOfIndex(index));
|
||||||
else {
|
} else {
|
||||||
float scrollPointY = (_YOfIndex(index) + fBandMetrics->Height()) - bounds.Height();
|
float scrollPointY = (_YOfIndex(index) + fBandMetrics->Height()) - bounds.Height();
|
||||||
ScrollTo(0, scrollPointY);
|
ScrollTo(0, scrollPointY);
|
||||||
}
|
}
|
||||||
@@ -902,7 +935,7 @@ public:
|
|||||||
int32 i = static_cast<int32>(y / fBandMetrics->Height());
|
int32 i = static_cast<int32>(y / fBandMetrics->Height());
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
return 0;
|
return 0;
|
||||||
return std::min(i, (int32) (fPackages.size() - 1));
|
return std::min(i, (int32)(fPackages.size() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -918,9 +951,6 @@ private:
|
|||||||
std::vector<PackageInfoRef>
|
std::vector<PackageInfoRef>
|
||||||
fPackages;
|
fPackages;
|
||||||
int32 fSelectedIndex;
|
int32 fSelectedIndex;
|
||||||
OnePackageMessagePackageListener*
|
|
||||||
fPackageListener;
|
|
||||||
int32 fLowestIndexAddedOrRemoved;
|
|
||||||
StackedFeaturesPackageBandMetrics*
|
StackedFeaturesPackageBandMetrics*
|
||||||
fBandMetrics;
|
fBandMetrics;
|
||||||
|
|
||||||
@@ -940,11 +970,10 @@ FeaturedPackagesView::FeaturedPackagesView(Model& model)
|
|||||||
{
|
{
|
||||||
fPackagesView = new StackedFeaturedPackagesView(fModel);
|
fPackagesView = new StackedFeaturedPackagesView(fModel);
|
||||||
|
|
||||||
fScrollView = new BScrollView("featured packages scroll view",
|
fScrollView = new BScrollView("featured packages scroll view", fPackagesView, 0, false, true,
|
||||||
fPackagesView, 0, false, true, B_FANCY_BORDER);
|
B_FANCY_BORDER);
|
||||||
|
|
||||||
BLayoutBuilder::Group<>(this)
|
BLayoutBuilder::Group<>(this).Add(fScrollView, 1.0f);
|
||||||
.Add(fScrollView, 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -954,35 +983,21 @@ FeaturedPackagesView::~FeaturedPackagesView()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FeaturedPackagesView::BeginAddRemove()
|
FeaturedPackagesView::RetainPackages(const std::vector<PackageInfoRef>& packages)
|
||||||
{
|
{
|
||||||
fPackagesView->BeginAddRemove();
|
fPackagesView->RetainPackages(packages);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
FeaturedPackagesView::EndAddRemove()
|
|
||||||
{
|
|
||||||
fPackagesView->EndAddRemove();
|
|
||||||
_AdjustViews();
|
_AdjustViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! This method will add the package into the list to be displayed. The
|
|
||||||
insertion will occur in alphabetical order.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FeaturedPackagesView::AddPackage(const PackageInfoRef& package)
|
FeaturedPackagesView::AddRemovePackages(const std::vector<PackageInfoRef>& addedPackages,
|
||||||
|
const std::vector<PackageInfoRef>& removedPackages)
|
||||||
{
|
{
|
||||||
fPackagesView->AddPackage(package);
|
if (!addedPackages.empty() || !removedPackages.empty()) {
|
||||||
}
|
fPackagesView->AddRemovePackages(addedPackages, removedPackages);
|
||||||
|
_AdjustViews();
|
||||||
|
}
|
||||||
void
|
|
||||||
FeaturedPackagesView::RemovePackage(const PackageInfoRef& package)
|
|
||||||
{
|
|
||||||
fPackagesView->RemovePackage(package);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -996,8 +1011,7 @@ FeaturedPackagesView::Clear()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FeaturedPackagesView::SelectPackage(const PackageInfoRef& package,
|
FeaturedPackagesView::SelectPackage(const PackageInfoRef& package, bool scrollToEntry)
|
||||||
bool scrollToEntry)
|
|
||||||
{
|
{
|
||||||
fPackagesView->SelectPackage(package);
|
fPackagesView->SelectPackage(package);
|
||||||
|
|
||||||
@@ -1017,9 +1031,22 @@ FeaturedPackagesView::DoLayout()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FeaturedPackagesView::HandleIconsChanged()
|
||||||
|
{
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FeaturedPackagesView::HandlePackagesChanged(const PackageInfoEvents& events)
|
||||||
|
{
|
||||||
|
fPackagesView->HandlePackagesChanged(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FeaturedPackagesView::_AdjustViews()
|
FeaturedPackagesView::_AdjustViews()
|
||||||
{
|
{
|
||||||
fScrollView->FrameResized(fScrollView->Frame().Width(),
|
fScrollView->FrameResized(fScrollView->Frame().Width(), fScrollView->Frame().Height());
|
||||||
fScrollView->Frame().Height());
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Copyright 2020-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef FEATURED_PACKAGES_VIEW_H
|
#ifndef FEATURED_PACKAGES_VIEW_H
|
||||||
#define FEATURED_PACKAGES_VIEW_H
|
#define FEATURED_PACKAGES_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <View.h>
|
#include <View.h>
|
||||||
|
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
@@ -24,17 +26,21 @@ public:
|
|||||||
|
|
||||||
virtual void DoLayout();
|
virtual void DoLayout();
|
||||||
|
|
||||||
void BeginAddRemove();
|
void RetainPackages(const std::vector<PackageInfoRef>& packages);
|
||||||
void EndAddRemove();
|
void AddRemovePackages(const std::vector<PackageInfoRef>& addedPackages,
|
||||||
void AddPackage(const PackageInfoRef& package);
|
const std::vector<PackageInfoRef>& removedPackages);
|
||||||
void RemovePackage(const PackageInfoRef& package);
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
void SelectPackage(const PackageInfoRef& package,
|
void SelectPackage(const PackageInfoRef& package,
|
||||||
bool scrollToEntry = false);
|
bool scrollToEntry = false);
|
||||||
|
|
||||||
|
void HandleIconsChanged();
|
||||||
|
|
||||||
|
void HandlePackagesChanged(const PackageInfoEvents& events);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _AdjustViews();
|
void _AdjustViews();
|
||||||
|
void _HandlePackageChanged(const PackageInfoEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model& fModel;
|
Model& fModel;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
|
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Copyright 2019-2020, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2019-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -36,15 +36,12 @@ FilterView::FilterView()
|
|||||||
fShowField = new BMenuField("category", B_TRANSLATE("Category:"), showMenu);
|
fShowField = new BMenuField("category", B_TRANSLATE("Category:"), showMenu);
|
||||||
|
|
||||||
// Construct search terms field
|
// Construct search terms field
|
||||||
fSearchTermsText = new BTextControl("search terms",
|
fSearchTermsText = new BTextControl("search terms", B_TRANSLATE("Search terms:"), "", NULL);
|
||||||
B_TRANSLATE("Search terms:"), "", NULL);
|
fSearchTermsText->SetModificationMessage(new BMessage(MSG_SEARCH_TERMS_MODIFIED));
|
||||||
fSearchTermsText->SetModificationMessage(
|
|
||||||
new BMessage(MSG_SEARCH_TERMS_MODIFIED));
|
|
||||||
|
|
||||||
BSize minSearchSize = fSearchTermsText->MinSize();
|
BSize minSearchSize = fSearchTermsText->MinSize();
|
||||||
float minSearchWidth
|
float minSearchWidth = be_plain_font->StringWidth(fSearchTermsText->Label())
|
||||||
= be_plain_font->StringWidth(fSearchTermsText->Label())
|
+ be_plain_font->StringWidth("XXX") * 6;
|
||||||
+ be_plain_font->StringWidth("XXX") * 6;
|
|
||||||
minSearchWidth = std::max(minSearchSize.width, minSearchWidth);
|
minSearchWidth = std::max(minSearchSize.width, minSearchWidth);
|
||||||
minSearchSize.width = minSearchWidth;
|
minSearchSize.width = minSearchWidth;
|
||||||
fSearchTermsText->SetExplicitMinSize(minSearchSize);
|
fSearchTermsText->SetExplicitMinSize(minSearchSize);
|
||||||
@@ -107,27 +104,25 @@ FilterView::AdoptModel(Model& model)
|
|||||||
BMenu* showMenu = fShowField->Menu();
|
BMenu* showMenu = fShowField->Menu();
|
||||||
showMenu->RemoveItems(0, showMenu->CountItems(), true);
|
showMenu->RemoveItems(0, showMenu->CountItems(), true);
|
||||||
|
|
||||||
showMenu->AddItem(new BMenuItem(B_TRANSLATE("All categories"),
|
showMenu->AddItem(
|
||||||
new BMessage(MSG_CATEGORY_SELECTED)));
|
new BMenuItem(B_TRANSLATE("All categories"), new BMessage(MSG_CATEGORY_SELECTED)));
|
||||||
|
|
||||||
AutoLocker<BLocker> locker(model.Lock());
|
if (model.HasCategories()) {
|
||||||
int32 categoryCount = model.CountCategories();
|
|
||||||
|
|
||||||
if (categoryCount > 0) {
|
|
||||||
showMenu->AddItem(new BSeparatorItem());
|
showMenu->AddItem(new BSeparatorItem());
|
||||||
_AddCategoriesToMenu(model, showMenu);
|
_AddCategoriesToMenu(model, showMenu);
|
||||||
|
showMenu->SetEnabled(true);
|
||||||
|
} else {
|
||||||
|
showMenu->SetEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
showMenu->SetEnabled(categoryCount > 0);
|
if (!_SelectCategoryCode(showMenu, model.FilterSpecification()->Category()))
|
||||||
|
|
||||||
if (!_SelectCategoryCode(showMenu, model.PackageFilter()->Category()))
|
|
||||||
showMenu->ItemAt(0)->SetMarked(true);
|
showMenu->ItemAt(0)->SetMarked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Tries to mark the menu item that corresponds to the supplied
|
/*! Tries to mark the menu item that corresponds to the supplied
|
||||||
category code. If the supplied code was found and the item marked
|
category code. If the supplied code was found and the item marked
|
||||||
then the method will return true.
|
then the method will return true.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*static*/ bool
|
/*static*/ bool
|
||||||
@@ -159,9 +154,10 @@ FilterView::_MatchesCategoryCode(BMenuItem* item, const BString& code)
|
|||||||
/*static*/ void
|
/*static*/ void
|
||||||
FilterView::_AddCategoriesToMenu(Model& model, BMenu* menu)
|
FilterView::_AddCategoriesToMenu(Model& model, BMenu* menu)
|
||||||
{
|
{
|
||||||
int count = model.CountCategories();
|
std::vector<CategoryRef> categories = model.Categories();
|
||||||
for (int i = 0; i < count; i++) {
|
std::vector<CategoryRef>::const_iterator it;
|
||||||
const CategoryRef& category = model.CategoryAtIndex(i);
|
for (it = categories.begin(); it != categories.end(); it++) {
|
||||||
|
const CategoryRef& category = *it;
|
||||||
BMessage* message = new BMessage(MSG_CATEGORY_SELECTED);
|
BMessage* message = new BMessage(MSG_CATEGORY_SELECTED);
|
||||||
message->AddString("code", category->Code());
|
message->AddString("code", category->Code());
|
||||||
BMenuItem* item = new BMenuItem(category->Name(), message);
|
BMenuItem* item = new BMenuItem(category->Name(), message);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
|||||||
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
|
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Copyright 2013, Rene Gollent <rene@gollent.com>.
|
* Copyright 2013, Rene Gollent <rene@gollent.com>.
|
||||||
* Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>.
|
* Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>.
|
||||||
* Copyright 2017-2024, Andrew Lindesay <apl@lindesay.co.nz>.
|
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>.
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef MAIN_WINDOW_H
|
#ifndef MAIN_WINDOW_H
|
||||||
@@ -41,7 +41,7 @@ class MainWindow :
|
|||||||
public:
|
public:
|
||||||
MainWindow(const BMessage& settings);
|
MainWindow(const BMessage& settings);
|
||||||
MainWindow(const BMessage& settings,
|
MainWindow(const BMessage& settings,
|
||||||
PackageInfoRef& package);
|
const PackageInfoRef package);
|
||||||
virtual ~MainWindow();
|
virtual ~MainWindow();
|
||||||
|
|
||||||
// BWindow interface
|
// BWindow interface
|
||||||
@@ -63,12 +63,13 @@ public:
|
|||||||
const UserDetail& userDetail);
|
const UserDetail& userDetail);
|
||||||
|
|
||||||
// services PackageInfoListener via MainWindowPackageInfoListener
|
// services PackageInfoListener via MainWindowPackageInfoListener
|
||||||
void PackageChanged(
|
void PackagesChanged(const PackageInfoEvents& events);
|
||||||
const PackageInfoEvent& event);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const BString _WindowTitleForPackage(const PackageInfoRef& pkg);
|
static const BString _WindowTitleForPackage(const PackageInfoRef& pkg);
|
||||||
|
|
||||||
|
const std::vector<PackageInfoRef>
|
||||||
|
_CreateSnapshotOfFilteredPackages();
|
||||||
std::vector<DepotInfoRef>
|
std::vector<DepotInfoRef>
|
||||||
_CreateSnapshotOfDepots();
|
_CreateSnapshotOfDepots();
|
||||||
|
|
||||||
@@ -95,8 +96,6 @@ private:
|
|||||||
|
|
||||||
void _AdoptModelControls();
|
void _AdoptModelControls();
|
||||||
void _AdoptModel();
|
void _AdoptModel();
|
||||||
void _AddRemovePackageFromLists(
|
|
||||||
const PackageInfoRef& package);
|
|
||||||
|
|
||||||
void _AdoptPackage(const PackageInfoRef& package);
|
void _AdoptPackage(const PackageInfoRef& package);
|
||||||
void _ClearPackage();
|
void _ClearPackage();
|
||||||
@@ -128,6 +127,9 @@ private:
|
|||||||
void _HandleProcessCoordinatorChanged(
|
void _HandleProcessCoordinatorChanged(
|
||||||
ProcessCoordinatorState& coordinatorState);
|
ProcessCoordinatorState& coordinatorState);
|
||||||
|
|
||||||
|
void _HandlePackagesChanged(const BMessage* message);
|
||||||
|
void _HandlePackagesChanged(const PackageInfoEvents& events);
|
||||||
|
|
||||||
static status_t _RefreshModelThreadWorker(void* arg);
|
static status_t _RefreshModelThreadWorker(void* arg);
|
||||||
static status_t _PopulatePackageWorker(void* arg);
|
static status_t _PopulatePackageWorker(void* arg);
|
||||||
static status_t _PackagesToShowWorker(void* arg);
|
static status_t _PackagesToShowWorker(void* arg);
|
||||||
@@ -148,6 +150,11 @@ private:
|
|||||||
const UserDetail& userDetail);
|
const UserDetail& userDetail);
|
||||||
|
|
||||||
void _HandleScreenshotCached(const BMessage* message);
|
void _HandleScreenshotCached(const BMessage* message);
|
||||||
|
void _HandleIconsChanged();
|
||||||
|
|
||||||
|
void _SetStateForPackagesByName(
|
||||||
|
BStringList& packageNames,
|
||||||
|
PackageState state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FilterView* fFilterView;
|
FilterView* fFilterView;
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "MessagePackageListener.h"
|
|
||||||
|
|
||||||
#include <Messenger.h>
|
|
||||||
#include <View.h>
|
|
||||||
|
|
||||||
#include "PackageInfo.h"
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - MessagePackageListener
|
|
||||||
|
|
||||||
|
|
||||||
MessagePackageListener::MessagePackageListener(BHandler* target)
|
|
||||||
:
|
|
||||||
fTarget(target),
|
|
||||||
fChangesMask(0xffffffff)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MessagePackageListener::~MessagePackageListener()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MessagePackageListener::PackageChanged(const PackageInfoEvent& event)
|
|
||||||
{
|
|
||||||
if ((event.Changes() & fChangesMask) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BMessenger messenger(fTarget);
|
|
||||||
if (!messenger.IsValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
BMessage message(MSG_UPDATE_PACKAGE);
|
|
||||||
message.AddString("name", event.Package()->Name());
|
|
||||||
message.AddUInt32("changes", event.Changes());
|
|
||||||
|
|
||||||
messenger.SendMessage(&message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MessagePackageListener::SetChangesMask(uint32 mask)
|
|
||||||
{
|
|
||||||
fChangesMask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - OnePackageMessagePackageListener
|
|
||||||
|
|
||||||
|
|
||||||
OnePackageMessagePackageListener::OnePackageMessagePackageListener(BHandler* target)
|
|
||||||
:
|
|
||||||
MessagePackageListener(target)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
OnePackageMessagePackageListener::~OnePackageMessagePackageListener()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
OnePackageMessagePackageListener::SetPackage(const PackageInfoRef& package)
|
|
||||||
{
|
|
||||||
if (fPackage == package)
|
|
||||||
return;
|
|
||||||
|
|
||||||
PackageInfoListenerRef listener(this);
|
|
||||||
|
|
||||||
if (fPackage.IsSet())
|
|
||||||
fPackage->RemoveListener(listener);
|
|
||||||
|
|
||||||
fPackage = package;
|
|
||||||
|
|
||||||
if (fPackage.IsSet())
|
|
||||||
fPackage->AddListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const PackageInfoRef&
|
|
||||||
OnePackageMessagePackageListener::Package() const
|
|
||||||
{
|
|
||||||
return fPackage;
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user