HaikuDepot: Clean Message Keys

This change will remove any string-literal keys from
non-API `BMessage` assembly and interpretation logic.
It will also make the keys consistently use lower-
snake string format and will setup the key constants
in a common style.

Change-Id: I246613d1e88a54fd275f45c55a52c4e9b2ac67e9
Reviewed-on: https://review.haiku-os.org/c/haiku/+/10216
Reviewed-by: Adrien Destugues <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Andrew Lindesay
2026-01-18 09:16:09 +00:00
committed by Adrien Destugues
parent e7ff15b674
commit 439cbbfff1
51 changed files with 1050 additions and 683 deletions
@@ -0,0 +1,10 @@
/*
* Copyright 2026, Andrew Lindesay <[email protected]>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "HaikuDepotConstants.h"
const char* const shared_message_keys::kKeyPackageName = "package_name";
const char* const shared_message_keys::kKeyDepotName = "depot_name";
const char* const shared_message_keys::kKeyCode = "code";
const char* const shared_message_keys::kKeyLanguageId = "language_id";
+12 -11
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2025, Andrew Lindesay <[email protected]>. * Copyright 2018-2026, 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
@@ -63,19 +63,20 @@ enum BitmapSize {
#define REPOSITORY_NAME_SYSTEM "system" #define REPOSITORY_NAME_SYSTEM "system"
#define REPOSITORY_NAME_INSTALLED "installed" #define REPOSITORY_NAME_INSTALLED "installed"
/*! Namespace to contain keys that are used for data inside `BMessage` instances
*/
namespace shared_message_keys {
#define KEY_ALERT_TEXT "alert_text" extern const char* const kKeyPackageName;
#define KEY_ALERT_TITLE "alert_title" extern const char* const kKeyDepotName;
#define KEY_ALERT_TYPE "alert_type" extern const char* const kKeyCode;
#define KEY_WORK_STATUS_TEXT "work_status_text" extern const char* const kKeyLanguageId;
#define KEY_WORK_STATUS_PROGRESS "work_status_progress"
#define KEY_WINDOW_SETTINGS "window_settings" }; // namespace shared_message_keys
#define KEY_MAIN_SETTINGS "main_settings"
#define KEY_PACKAGE_NAME "package_name"
#define KEY_TITLE "title"
#define KEY_DESKBAR_LINK "deskbar_link"
#define SETTING_NICKNAME "username"
// historical difference
#define SETTING_SHOW_DESKTOP_PACKAGES "show only desktop packages" #define SETTING_SHOW_DESKTOP_PACKAGES "show only desktop packages"
#define SETTING_SHOW_NATIVE_DESKTOP_PACKAGES "show only native desktop packages" #define SETTING_SHOW_NATIVE_DESKTOP_PACKAGES "show only native desktop packages"
#define SETTING_SHOW_AVAILABLE_PACKAGES "show available packages" #define SETTING_SHOW_AVAILABLE_PACKAGES "show available packages"
+2
View File
@@ -125,6 +125,7 @@ local applicationSources =
FeaturedPackagesView.cpp FeaturedPackagesView.cpp
FilterView.cpp FilterView.cpp
GeneralContentScrollView.cpp GeneralContentScrollView.cpp
HaikuDepotConstants.cpp
IdentityAndAccessUtils.cpp IdentityAndAccessUtils.cpp
IncrementViewCounterProcess.cpp IncrementViewCounterProcess.cpp
JobStateListener.cpp JobStateListener.cpp
@@ -152,6 +153,7 @@ local applicationSources =
ScrollableGroupView.cpp ScrollableGroupView.cpp
SettingsWindow.cpp SettingsWindow.cpp
SharedIcons.cpp SharedIcons.cpp
SimpleAlert.cpp
ShuttingDownWindow.cpp ShuttingDownWindow.cpp
ToLatestUserUsageConditionsWindow.cpp ToLatestUserUsageConditionsWindow.cpp
UserCredentials.cpp UserCredentials.cpp
+10 -12
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2023, Andrew Lindesay <[email protected]>. * Copyright 2023-2026, 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 "AccessToken.h" #include "AccessToken.h"
@@ -9,8 +9,8 @@
// These are keys that are used to store this object's data into a BMessage instance. // These are keys that are used to store this object's data into a BMessage instance.
#define KEY_TOKEN "token" static const char* const kKeyToken = "token";
#define KEY_EXPIRY_TIMESTAMP "expiryTimestamp" static const char* const kKeyExpiryLanguage = "expiry_language";
AccessToken::AccessToken(BMessage* from) AccessToken::AccessToken(BMessage* from)
@@ -18,14 +18,12 @@ AccessToken::AccessToken(BMessage* from)
fToken(""), fToken(""),
fExpiryTimestamp(0) fExpiryTimestamp(0)
{ {
if (from->FindString(KEY_TOKEN, &fToken) != B_OK) { if (from->FindString(kKeyToken, &fToken) != B_OK)
HDERROR("expected key [%s] in the message data when creating an access" HDERROR("expected key [%s] in the message data when creating an access token", kKeyToken);
" token", KEY_TOKEN);
}
if (from->FindUInt64(KEY_EXPIRY_TIMESTAMP, &fExpiryTimestamp) != B_OK) { if (from->FindUInt64(kKeyExpiryLanguage, &fExpiryTimestamp) != B_OK) {
HDERROR("expected key [%s] in the message data when creating an access" HDERROR("expected key [%s] in the message data when creating an access token",
" token", KEY_EXPIRY_TIMESTAMP); kKeyExpiryLanguage);
} }
} }
@@ -127,8 +125,8 @@ AccessToken::Archive(BMessage* into, bool deep) const
if (result == B_OK && into == NULL) if (result == B_OK && into == NULL)
result = B_ERROR; result = B_ERROR;
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_TOKEN, fToken); result = into->AddString(kKeyToken, fToken);
if (result == B_OK) if (result == B_OK)
result = into->AddUInt64(KEY_EXPIRY_TIMESTAMP, fExpiryTimestamp); result = into->AddUInt64(kKeyExpiryLanguage, fExpiryTimestamp);
return result; return result;
} }
+10 -12
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2019-2020, Andrew Lindesay <[email protected]>. * Copyright 2019-2026, 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 "Captcha.h" #include "Captcha.h"
@@ -11,8 +11,8 @@
// These are keys that are used to store this object's data into a BMessage // These are keys that are used to store this object's data into a BMessage
// instance. // instance.
#define KEY_TOKEN "token" static const char* const kKeyToken = "token";
#define KEY_PNG_IMAGE_DATA "pngImageData" static const char* const kKeyPngImageData = "png_image_data";
Captcha::Captcha(BMessage* from) Captcha::Captcha(BMessage* from)
@@ -20,16 +20,14 @@ Captcha::Captcha(BMessage* from)
fToken(""), fToken(""),
fPngImageData(NULL) fPngImageData(NULL)
{ {
if (from->FindString(KEY_TOKEN, &fToken) != B_OK) { if (from->FindString(kKeyToken, &fToken) != B_OK)
HDERROR("expected key [%s] in the message data when creating a " HDERROR("expected key [%s] in the message data when creating a captcha", kKeyToken);
"captcha", KEY_TOKEN);
}
const void* data; const void* data;
ssize_t len; ssize_t len;
if (from->FindData(KEY_PNG_IMAGE_DATA, B_ANY_TYPE, &data, &len) != B_OK) if (from->FindData(kKeyPngImageData, B_ANY_TYPE, &data, &len) != B_OK)
HDERROR("expected key [%s] in the message data", KEY_PNG_IMAGE_DATA); HDERROR("expected key [%s] in the message data", kKeyPngImageData);
else else
SetPngImageData(data, len); SetPngImageData(data, len);
} }
@@ -90,10 +88,10 @@ Captcha::Archive(BMessage* into, bool deep) const
if (result == B_OK && into == NULL) if (result == B_OK && into == NULL)
result = B_ERROR; result = B_ERROR;
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_TOKEN, fToken); result = into->AddString(kKeyToken, fToken);
if (result == B_OK && fPngImageData != NULL) { if (result == B_OK && fPngImageData != NULL) {
result = into->AddData(KEY_PNG_IMAGE_DATA, B_ANY_TYPE, result = into->AddData(kKeyPngImageData, B_ANY_TYPE, fPngImageData->Buffer(),
fPngImageData->Buffer(), fPngImageData->BufferLength()); fPngImageData->BufferLength());
} }
return result; return result;
} }
+29 -32
View File
@@ -1,33 +1,32 @@
/* /*
* Copyright 2019-2024, Andrew Lindesay <[email protected]>. * Copyright 2019-2026, 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 "CreateUserDetail.h" #include "CreateUserDetail.h"
// These are keys that are used to store this object's data into a BMessage // These are keys that are used to store this object's data into a BMessage
// instance. // instance.
#define KEY_NICKNAME "nickname" static const char* const kKeyNickname = "nickname";
#define KEY_PASSWORD_CLEAR "passwordClear" static const char* const kKeyPasswordClear = "password_clear";
#define KEY_IS_PASSWORD_REPEATED "isPasswordRepeated" static const char* const kKeyIsPasswordRepeated = "is_password_repeated";
#define KEY_EMAIL "email" static const char* const kKeyEmail = "email";
#define KEY_CAPTCHA_TOKEN "captchaToken" static const char* const kKeyCaptchaToken = "captcha_token";
#define KEY_CAPTCHA_RESPONSE "captchaResponse" static const char* const kKeyCaptchaResponse = "captcha_response";
#define KEY_LANGUAGE_ID "languageId" static const char* const kKeyLanguageId = "language_id";
#define KEY_AGREED_USER_USAGE_CONDITIONS_CODE "agreedUserUsageConditionsCode" static const char* const kKeyAgreedUserUsageConditionsCode = "agreed_user_usage_conditions_code";
CreateUserDetail::CreateUserDetail(BMessage* from) CreateUserDetail::CreateUserDetail(BMessage* from)
{ {
from->FindString(KEY_NICKNAME, &fNickname); from->FindString(kKeyNickname, &fNickname);
from->FindString(KEY_PASSWORD_CLEAR, &fPasswordClear); from->FindString(kKeyPasswordClear, &fPasswordClear);
from->FindBool(KEY_IS_PASSWORD_REPEATED, &fIsPasswordRepeated); from->FindBool(kKeyIsPasswordRepeated, &fIsPasswordRepeated);
from->FindString(KEY_EMAIL, &fEmail); from->FindString(kKeyEmail, &fEmail);
from->FindString(KEY_CAPTCHA_TOKEN, &fCaptchaToken); from->FindString(kKeyCaptchaToken, &fCaptchaToken);
from->FindString(KEY_CAPTCHA_RESPONSE, &fCaptchaResponse); from->FindString(kKeyCaptchaResponse, &fCaptchaResponse);
from->FindString(KEY_LANGUAGE_ID, &fLanguageId); from->FindString(kKeyLanguageId, &fLanguageId);
from->FindString(KEY_AGREED_USER_USAGE_CONDITIONS_CODE, from->FindString(kKeyAgreedUserUsageConditionsCode, &fAgreedUserUsageConditionsCode);
&fAgreedUserUsageConditionsCode);
} }
@@ -160,22 +159,20 @@ CreateUserDetail::Archive(BMessage* into, bool deep) const
{ {
status_t result = B_OK; status_t result = B_OK;
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_NICKNAME, fNickname); result = into->AddString(kKeyNickname, fNickname);
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_PASSWORD_CLEAR, fPasswordClear); result = into->AddString(kKeyPasswordClear, fPasswordClear);
if (result == B_OK) if (result == B_OK)
result = into->AddBool(KEY_IS_PASSWORD_REPEATED, fIsPasswordRepeated); result = into->AddBool(kKeyIsPasswordRepeated, fIsPasswordRepeated);
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_EMAIL, fEmail); result = into->AddString(kKeyEmail, fEmail);
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_CAPTCHA_TOKEN, fCaptchaToken); result = into->AddString(kKeyCaptchaToken, fCaptchaToken);
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_CAPTCHA_RESPONSE, fCaptchaResponse); result = into->AddString(kKeyCaptchaResponse, fCaptchaResponse);
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_LANGUAGE_ID, fLanguageId); result = into->AddString(kKeyLanguageId, fLanguageId);
if (result == B_OK) { if (result == B_OK)
result = into->AddString(KEY_AGREED_USER_USAGE_CONDITIONS_CODE, result = into->AddString(kKeyAgreedUserUsageConditionsCode, fAgreedUserUsageConditionsCode);
fAgreedUserUsageConditionsCode);
}
return result; return result;
} }
+17 -14
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2024, Haiku, Inc. All Rights Reserved. * Copyright 2013-2026, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -19,8 +19,8 @@
#include "Logger.h" #include "Logger.h"
#define kPathKey "path" static const char* const kKeyPath = "path";
#define kLinkKey "link" static const char* const kKeyLink = "link";
DeskbarLink::DeskbarLink() DeskbarLink::DeskbarLink()
@@ -44,17 +44,13 @@ DeskbarLink::DeskbarLink(const DeskbarLink& other)
} }
DeskbarLink::DeskbarLink(BMessage* from) DeskbarLink::DeskbarLink(const BMessage* from)
{ {
if (from->FindString(kPathKey, &fPath) != B_OK) { if (from->FindString(kKeyPath, &fPath) != B_OK)
HDERROR("expected key [%s] in the message data when creating a " HDERROR("expected key [%s] in the message data when creating a captcha", kKeyPath);
"captcha", kPathKey);
}
if (from->FindString(kLinkKey, &fLink) != B_OK) { if (from->FindString(kKeyLink, &fLink) != B_OK)
HDERROR("expected key [%s] in the message data when creating a " HDERROR("expected key [%s] in the message data when creating a captcha", kKeyLink);
"captcha", kLinkKey);
}
} }
@@ -96,6 +92,13 @@ DeskbarLink::Title() const
} }
bool
DeskbarLink::IsValid() const
{
return !fPath.IsEmpty() && !fLink.IsEmpty();
}
status_t status_t
DeskbarLink::Archive(BMessage* into, bool deep) const DeskbarLink::Archive(BMessage* into, bool deep) const
{ {
@@ -103,9 +106,9 @@ DeskbarLink::Archive(BMessage* into, bool deep) const
if (result == B_OK && into == NULL) if (result == B_OK && into == NULL)
result = B_ERROR; result = B_ERROR;
if (result == B_OK) if (result == B_OK)
result = into->AddString(kPathKey, fPath); result = into->AddString(kKeyPath, fPath);
if (result == B_OK) if (result == B_OK)
result = into->AddString(kLinkKey, fLink); result = into->AddString(kKeyLink, fLink);
return result; return result;
} }
+3 -1
View File
@@ -24,7 +24,7 @@ public:
DeskbarLink(const BString& path, DeskbarLink(const BString& path,
const BString& link); const BString& link);
DeskbarLink(const DeskbarLink& other); DeskbarLink(const DeskbarLink& other);
DeskbarLink(BMessage* from); DeskbarLink(const BMessage* from);
virtual ~DeskbarLink(); virtual ~DeskbarLink();
@@ -36,6 +36,8 @@ public:
bool operator!=(const DeskbarLink& other); bool operator!=(const DeskbarLink& other);
DeskbarLink& operator=(const DeskbarLink& other); DeskbarLink& operator=(const DeskbarLink& other);
bool IsValid() const;
status_t Archive(BMessage* into, bool deep = true) const; status_t Archive(BMessage* into, bool deep = true) const;
private: private:
+9 -51
View File
@@ -1,7 +1,7 @@
/* /*
* 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-2025, Andrew Lindesay <[email protected]>. * Copyright 2016-2026, 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"
@@ -235,48 +235,6 @@ Model::AddPackageListener(const PackageInfoListenerRef& 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 const LanguageRef
Model::PreferredLanguage() const Model::PreferredLanguage() const
{ {
@@ -423,7 +381,7 @@ Model::AddPackage(const PackageInfoRef& package)
BAutolock locker(&fLock); BAutolock locker(&fLock);
uint32 changeMask = _ChangeDiff(package); uint32 changeMask = _ChangeDiff(package);
fPackages[package->Name()] = package; fPackages[package->Name()] = package;
_NotifyPackageChange(PackageInfoEvent(package, changeMask)); _NotifyPackageChange(PackageChangeEvent(package, changeMask));
} }
@@ -434,12 +392,12 @@ Model::AddPackages(const std::vector<PackageInfoRef>& packages)
return; return;
BAutolock locker(&fLock); BAutolock locker(&fLock);
PackageInfoEvents events; PackageChangeEvents events;
std::vector<PackageInfoRef>::const_iterator it; std::vector<PackageInfoRef>::const_iterator it;
for (it = packages.begin(); it != packages.end(); it++) { for (it = packages.begin(); it != packages.end(); it++) {
PackageInfoRef package = *it; PackageInfoRef package = *it;
events.AddEvent(PackageInfoEvent(package, _ChangeDiff(package))); events.AddEvent(PackageChangeEvent(package, _ChangeDiff(package)));
fPackages[package->Name()] = package; fPackages[package->Name()] = package;
} }
@@ -454,12 +412,12 @@ Model::AddPackagesWithChange(const std::vector<PackageInfoRef>& packages, uint32
return; return;
BAutolock locker(&fLock); BAutolock locker(&fLock);
PackageInfoEvents events; PackageChangeEvents events;
std::vector<PackageInfoRef>::const_iterator it; std::vector<PackageInfoRef>::const_iterator it;
for (it = packages.begin(); it != packages.end(); it++) { for (it = packages.begin(); it != packages.end(); it++) {
PackageInfoRef package = *it; PackageInfoRef package = *it;
events.AddEvent(PackageInfoEvent(package, changeMask)); events.AddEvent(PackageChangeEvent(package, changeMask));
fPackages[package->Name()] = package; fPackages[package->Name()] = package;
} }
@@ -652,20 +610,20 @@ Model::_NotifyCategoryListChanged()
void void
Model::_NotifyPackageChange(const PackageInfoEvent& event) Model::_NotifyPackageChange(const PackageChangeEvent& event)
{ {
std::vector<PackageInfoListenerRef>::const_iterator it; std::vector<PackageInfoListenerRef>::const_iterator it;
for (it = fPackageListeners.begin(); it != fPackageListeners.end(); it++) { for (it = fPackageListeners.begin(); it != fPackageListeners.end(); it++) {
const PackageInfoListenerRef& listener = *it; const PackageInfoListenerRef& listener = *it;
if (listener.IsSet()) if (listener.IsSet())
listener->PackagesChanged(PackageInfoEvents(event)); listener->PackagesChanged(PackageChangeEvents(event));
} }
} }
// TODO: future work to optimize how this is conveyed to the listener in one go. // TODO: future work to optimize how this is conveyed to the listener in one go.
void void
Model::_NotifyPackageChanges(const PackageInfoEvents& events) Model::_NotifyPackageChanges(const PackageChangeEvents& events)
{ {
if (events.IsEmpty()) if (events.IsEmpty())
return; return;
+2 -5
View File
@@ -95,9 +95,6 @@ public:
void AddListener(const ModelListenerRef& listener); void AddListener(const ModelListenerRef& listener);
void AddPackageListener(const PackageInfoListenerRef& packageListener); void AddPackageListener(const PackageInfoListenerRef& packageListener);
status_t DearchiveInfoEvents(const BMessage* message,
PackageInfoEvents& packageInfoEvents) const;
PackageScreenshotRepository* PackageScreenshotRepository*
GetPackageScreenshotRepository(); GetPackageScreenshotRepository();
@@ -178,8 +175,8 @@ private:
void _NotifyIconsChanged(); void _NotifyIconsChanged();
void _NotifyAuthorizationChanged(); void _NotifyAuthorizationChanged();
void _NotifyCategoryListChanged(); void _NotifyCategoryListChanged();
void _NotifyPackageChange(const PackageInfoEvent& event); void _NotifyPackageChange(const PackageChangeEvent& event);
void _NotifyPackageChanges(const PackageInfoEvents& events); void _NotifyPackageChanges(const PackageChangeEvents& events);
private: private:
mutable BLocker fLock; mutable BLocker fLock;
+101 -41
View File
@@ -1,31 +1,24 @@
/* /*
* Copyright 2013-2025, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2013-2025, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2026, 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 "PackageInfoListener.h" #include "PackageInfoListener.h"
#include <stdio.h> #include <stdio.h>
#include "HaikuDepotConstants.h"
#include "Logger.h"
#include "PackageInfo.h" #include "PackageInfo.h"
const char* kPackageInfoChangesKey = "change"; static const char* const kKeyEvents = "events";
const char* kPackageInfoPackageNameKey = "packageName"; static const char* const kKeyChanges = "changes";
const char* kPackageInfoEventsKey = "events";
// #pragma mark - PackageInfoChangeEvent
// #pragma mark - PackageInfoEvent PackageInfoChangeEvent::PackageInfoChangeEvent(PackageInfoRef package, uint32 changes)
PackageInfoEvent::PackageInfoEvent()
:
fPackage(),
fChanges(0)
{
}
PackageInfoEvent::PackageInfoEvent(const PackageInfoRef& package, uint32 changes)
: :
fPackage(package), fPackage(package),
fChanges(changes) fChanges(changes)
@@ -33,40 +26,87 @@ PackageInfoEvent::PackageInfoEvent(const PackageInfoRef& package, uint32 changes
} }
PackageInfoEvent::PackageInfoEvent(const PackageInfoEvent& other) PackageInfoChangeEvent::~PackageInfoChangeEvent()
{
}
// #pragma mark - PackageChangeEvent
PackageChangeEvent::PackageChangeEvent()
: :
fPackage(other.fPackage), fPackageName(),
fChanges(0)
{
}
PackageChangeEvent::PackageChangeEvent(const BString& packageName, uint32 changes)
:
fPackageName(packageName),
fChanges(changes)
{
}
PackageChangeEvent::PackageChangeEvent(const PackageInfoRef& package, uint32 changes)
:
PackageChangeEvent(package->Name(), changes)
{
}
PackageChangeEvent::PackageChangeEvent(const PackageChangeEvent& other)
:
fPackageName(other.fPackageName),
fChanges(other.fChanges) fChanges(other.fChanges)
{ {
} }
PackageInfoEvent::~PackageInfoEvent() PackageChangeEvent::PackageChangeEvent(const BMessage* from)
{
if (from->FindString(shared_message_keys::kKeyPackageName, &fPackageName) != B_OK)
HDERROR("expected key [%s] in the message data", shared_message_keys::kKeyPackageName);
if (from->FindUInt32(kKeyChanges, &fChanges) != B_OK)
HDERROR("expected key [%s] in the message data", kKeyChanges);
}
PackageChangeEvent::~PackageChangeEvent()
{ {
} }
bool bool
PackageInfoEvent::operator==(const PackageInfoEvent& other) PackageChangeEvent::IsValid() const
{
return !fPackageName.IsEmpty();
}
bool
PackageChangeEvent::operator==(const PackageChangeEvent& other)
{ {
if (this == &other) if (this == &other)
return true; return true;
return fPackage == other.fPackage && fChanges == other.fChanges; return fPackageName == other.fPackageName && fChanges == other.fChanges;
} }
bool bool
PackageInfoEvent::operator!=(const PackageInfoEvent& other) PackageChangeEvent::operator!=(const PackageChangeEvent& other)
{ {
return !(*this == other); return !(*this == other);
} }
PackageInfoEvent& PackageChangeEvent&
PackageInfoEvent::operator=(const PackageInfoEvent& other) PackageChangeEvent::operator=(const PackageChangeEvent& other)
{ {
if (this != &other) { if (this != &other) {
fPackage = other.fPackage; fPackageName = other.fPackageName;
fChanges = other.fChanges; fChanges = other.fChanges;
} }
@@ -75,78 +115,98 @@ PackageInfoEvent::operator=(const PackageInfoEvent& other)
status_t status_t
PackageInfoEvent::Archive(BMessage* into, bool deep) const PackageChangeEvent::Archive(BMessage* into, bool deep) const
{ {
status_t result = B_OK; status_t result = B_OK;
if (result == B_OK && into == NULL)
result = B_ERROR;
if (result == B_OK) if (result == B_OK)
result = into->AddUInt32(kPackageInfoChangesKey, fChanges); result = into->AddUInt32(kKeyChanges, fChanges);
if (result == B_OK) if (result == B_OK)
result = into->AddString(kPackageInfoPackageNameKey, fPackage->Name()); result = into->AddString(shared_message_keys::kKeyPackageName, fPackageName);
return result; return result;
} }
// #pragma mark - PackageInfoEvents // #pragma mark - PackageChangeEvents
PackageInfoEvents::PackageInfoEvents() PackageChangeEvents::PackageChangeEvents()
{ {
} }
PackageInfoEvents::PackageInfoEvents(const PackageInfoEvent& event) PackageChangeEvents::PackageChangeEvents(const PackageChangeEvent& event)
{ {
fEvents.push_back(event); AddEvent(event);
} }
PackageInfoEvents::PackageInfoEvents(const PackageInfoEvents& other) PackageChangeEvents::PackageChangeEvents(const PackageChangeEvents& other)
{ {
for (int32 i = other.CountEvents() - 1; i >= 0; i--) for (int32 i = other.CountEvents() - 1; i >= 0; i--)
fEvents.push_back(other.EventAtIndex(i)); AddEvent(other.EventAtIndex(i));
}
PackageChangeEvents::PackageChangeEvents(const BMessage* from)
{
int32 i = 0;
BMessage eventMessage;
while (from->FindMessage(kKeyEvents, i, &eventMessage) == B_OK) {
PackageChangeEvent event = PackageChangeEvent(&eventMessage);
if (event.IsValid())
AddEvent(event);
else
HDERROR("unable to deserialize package info event");
i++;
}
} }
void void
PackageInfoEvents::AddEvent(const PackageInfoEvent event) PackageChangeEvents::AddEvent(const PackageChangeEvent event)
{ {
fEvents.push_back(event); fEvents.push_back(event);
} }
bool bool
PackageInfoEvents::IsEmpty() const PackageChangeEvents::IsEmpty() const
{ {
return fEvents.empty(); return fEvents.empty();
} }
int32 int32
PackageInfoEvents::CountEvents() const PackageChangeEvents::CountEvents() const
{ {
return fEvents.size(); return fEvents.size();
} }
const PackageInfoEvent& const PackageChangeEvent&
PackageInfoEvents::EventAtIndex(int32 index) const PackageChangeEvents::EventAtIndex(int32 index) const
{ {
return fEvents[index]; return fEvents[index];
} }
status_t status_t
PackageInfoEvents::Archive(BMessage* into, bool deep) const PackageChangeEvents::Archive(BMessage* into, bool deep) const
{ {
status_t result = B_OK; status_t result = B_OK;
BString indexString; BString indexString;
std::vector<PackageInfoEvent>::const_iterator it; std::vector<PackageChangeEvent>::const_iterator it;
for (it = fEvents.begin(); it != fEvents.end(); it++) { for (it = fEvents.begin(); it != fEvents.end(); it++) {
BMessage eventMessage; BMessage eventMessage;
result = (*it).Archive(&eventMessage); result = (*it).Archive(&eventMessage);
if (result == B_OK) if (result == B_OK)
result = into->AddMessage(kPackageInfoEventsKey, &eventMessage); result = into->AddMessage(kKeyEvents, &eventMessage);
} }
return result; return result;
+60 -30
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2022-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2022-2026, 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_INFO_LISTENER_H #ifndef PACKAGE_INFO_LISTENER_H
@@ -14,11 +14,6 @@
#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.
@@ -37,58 +32,93 @@ class PackageInfo;
typedef BReference<PackageInfo> PackageInfoRef; typedef BReference<PackageInfo> PackageInfoRef;
class PackageInfoEvent : public BArchivable { /*! PackageInfoChangeEvent is akin to the PackageChangeEvent but couples a
change-mask together with the actual PackageInfo class rather than just the
name.
*/
class PackageInfoChangeEvent {
public: public:
PackageInfoEvent(); PackageInfoChangeEvent(PackageInfoRef package, uint32 change);
PackageInfoEvent(const PackageInfoRef& package, uint32 changes); virtual ~PackageInfoChangeEvent();
PackageInfoEvent(const PackageInfoEvent& other);
virtual ~PackageInfoEvent();
bool operator==(const PackageInfoEvent& other); const PackageInfoRef Package() const
bool operator!=(const PackageInfoEvent& other);
PackageInfoEvent& operator=(const PackageInfoEvent& other);
inline const PackageInfoRef&
Package() const
{ return fPackage; } { return fPackage; }
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 { /*! Couples together the name of a package together with a mask which describes
the change that has occurred against that package.
*/
class PackageChangeEvent : public BArchivable
{
public: public:
PackageInfoEvents(); PackageChangeEvent();
PackageInfoEvents(const PackageInfoEvent& event); PackageChangeEvent(const PackageInfoRef& package, uint32 changes);
PackageInfoEvents(const PackageInfoEvents& other); PackageChangeEvent(const BString& packageName, uint32 changes);
PackageChangeEvent(const PackageChangeEvent& other);
PackageChangeEvent(const BMessage* from);
virtual ~PackageChangeEvent();
bool operator==(const PackageChangeEvent& other);
bool operator!=(const PackageChangeEvent& other);
PackageChangeEvent& operator=(const PackageChangeEvent& other);
inline const BString& PackageName() const
{ return fPackageName; }
inline uint32 Changes() const
{ return fChanges; }
bool IsValid() const;
status_t Archive(BMessage* into, bool deep = true) const;
private:
BString fPackageName;
uint32 fChanges;
};
/*! This is a collection class designed to carry a number of `PackageChangeEvent`
instances. It can conveniently serialize and deserialize to and from a
`BMessage`.
*/
class PackageChangeEvents : public BArchivable
{
public:
PackageChangeEvents();
PackageChangeEvents(const PackageChangeEvent& event);
PackageChangeEvents(const PackageChangeEvents& other);
PackageChangeEvents(const BMessage* from);
bool IsEmpty() const; bool IsEmpty() const;
void AddEvent(const PackageInfoEvent event); void AddEvent(const PackageChangeEvent event);
int32 CountEvents() const; int32 CountEvents() const;
const PackageInfoEvent& const PackageChangeEvent&
EventAtIndex(int32 index) const; EventAtIndex(int32 index) const;
status_t Archive(BMessage* into, bool deep = true) const; status_t Archive(BMessage* into, bool deep = true) const;
private: private:
std::vector<PackageInfoEvent> std::vector<PackageChangeEvent>
fEvents; fEvents;
}; };
class PackageInfoListener : public BReferenceable { class PackageInfoListener : public BReferenceable
{
public: public:
PackageInfoListener(); PackageInfoListener();
virtual ~PackageInfoListener(); virtual ~PackageInfoListener();
virtual void PackagesChanged(const PackageInfoEvents& events) = 0; virtual void PackagesChanged(const PackageChangeEvents& events) = 0;
}; };
@@ -1,13 +1,16 @@
/* /*
* Copyright 2024, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2026, 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 "ScreenshotCoordinate.h" #include "ScreenshotCoordinate.h"
static const char* kCodeKey = "code"; #include "Logger.h"
static const char* kWidthKey = "width";
static const char* kHeightKey = "height";
static const char* const kKeyCode = "code";
static const char* const kKeyWidth = "width";
static const char* const kKeyHeight = "height";
ScreenshotCoordinate::ScreenshotCoordinate() ScreenshotCoordinate::ScreenshotCoordinate()
@@ -21,9 +24,12 @@ ScreenshotCoordinate::ScreenshotCoordinate()
ScreenshotCoordinate::ScreenshotCoordinate(const BMessage* from) ScreenshotCoordinate::ScreenshotCoordinate(const BMessage* from)
{ {
from->FindString(kCodeKey, &fCode); if (from->FindString(kKeyCode, &fCode) != B_OK)
from->FindUInt32(kWidthKey, &fWidth); HDERROR("expected key [%s] in the message data", kKeyCode);
from->FindUInt32(kHeightKey, &fHeight); if (from->FindUInt32(kKeyWidth, &fWidth) != B_OK)
HDERROR("expected key [%s] in the message data", kKeyWidth);
if (from->FindUInt32(kKeyHeight, &fHeight) != B_OK)
HDERROR("expected key [%s] in the message data", kKeyHeight);
} }
@@ -97,10 +103,10 @@ ScreenshotCoordinate::Archive(BMessage* into, bool deep) const
{ {
status_t result = B_OK; status_t result = B_OK;
if (result == B_OK) if (result == B_OK)
result = into->AddString(kCodeKey, fCode); result = into->AddString(kKeyCode, fCode);
if (result == B_OK) if (result == B_OK)
result = into->AddUInt32(kWidthKey, fWidth); result = into->AddUInt32(kKeyWidth, fWidth);
if (result == B_OK) if (result == B_OK)
result = into->AddUInt32(kHeightKey, fHeight); result = into->AddUInt32(kKeyHeight, fHeight);
return result; return result;
} }
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright 2026, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "SimpleAlert.h"
#include <Catalog.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "SimpleAlert"
static const char* const kKeyAlertText = "text";
static const char* const kKeyAlertTitle = "title";
static const char* const kKeyAlertType = "type";
SimpleAlert::SimpleAlert()
:
fTitle(B_TRANSLATE("Error")),
fText("?"),
fType(B_INFO_ALERT)
{
}
SimpleAlert::SimpleAlert(const BMessage* from)
{
if (from->FindString(kKeyAlertTitle, &fTitle) != B_OK)
fTitle = B_TRANSLATE("Error");
if (from->FindString(kKeyAlertText, &fText) != B_OK)
fText = "?";
uint32 typeInt;
if (from->FindUInt32(kKeyAlertType, &typeInt) == B_OK)
fType = static_cast<alert_type>(typeInt);
else
fType = B_INFO_ALERT;
}
SimpleAlert::SimpleAlert(const BString& title, const BString& text, alert_type type)
:
fTitle(title),
fText(text),
fType(type)
{
if (fTitle.IsEmpty())
fTitle = B_TRANSLATE("Error");
if (fText.IsEmpty())
fText = "?";
}
SimpleAlert::~SimpleAlert()
{
}
const BString
SimpleAlert::Title() const
{
return fTitle;
}
const BString
SimpleAlert::Text() const
{
return fText;
}
alert_type
SimpleAlert::Type() const
{
return fType;
}
bool
SimpleAlert::operator==(const SimpleAlert& other) const
{
return fTitle == other.fTitle && fText == other.fText && fType == other.fType;
}
status_t
SimpleAlert::Archive(BMessage* into, bool deep) const
{
status_t result = B_OK;
if (result == B_OK)
result = into->AddString(kKeyAlertTitle, fTitle);
if (result == B_OK)
result = into->AddString(kKeyAlertText, fText);
if (result == B_OK)
result = into->AddUInt32(kKeyAlertType, static_cast<uint32>(fType));
return result;
}
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright 2026, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef SIMPLE_ALERT_H
#define SIMPLE_ALERT_H
#include <Alert.h>
#include <Archivable.h>
#include <String.h>
/*! A model for conveying a simple alert. This can be passed from background
processes to the application for display in the UI.
*/
class SimpleAlert : public BArchivable {
public:
SimpleAlert(const BMessage* from);
SimpleAlert(const BString& title, const BString& text,
alert_type type = B_INFO_ALERT);
SimpleAlert();
virtual ~SimpleAlert();
const BString Title() const;
const BString Text() const;
alert_type Type() const;
bool operator==(const SimpleAlert& other) const;
status_t Archive(BMessage* into, bool deep = true) const;
private:
BString fTitle;
BString fText;
alert_type fType;
};
#endif // SIMPLE_ALERT_H
+10 -10
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2019-2026, 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.
*/ */
@@ -9,16 +9,16 @@
// These are keys that are used to store this object's data into a BMessage // These are keys that are used to store this object's data into a BMessage
// instance. // instance.
#define KEY_NICKNAME "nickname" static const char* const kKeyNickname = "nickname";
#define KEY_PASSWORD_CLEAR "passwordClear" static const char* const kKeyPasswordClear = "password_clear";
#define KEY_IS_SUCCESSFUL "isSuccessful" static const char* const kKeyIsSuccessful = "is_successful";
UserCredentials::UserCredentials(BMessage* from) UserCredentials::UserCredentials(BMessage* from)
{ {
from->FindString(KEY_NICKNAME, &fNickname); from->FindString(kKeyNickname, &fNickname);
from->FindString(KEY_PASSWORD_CLEAR, &fPasswordClear); from->FindString(kKeyPasswordClear, &fPasswordClear);
from->FindBool(KEY_IS_SUCCESSFUL, &fIsSuccessful); from->FindBool(kKeyIsSuccessful, &fIsSuccessful);
} }
@@ -133,10 +133,10 @@ UserCredentials::Archive(BMessage* into, bool deep) const
{ {
status_t result = B_OK; status_t result = B_OK;
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_NICKNAME, fNickname); result = into->AddString(kKeyNickname, fNickname);
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_PASSWORD_CLEAR, fPasswordClear); result = into->AddString(kKeyPasswordClear, fPasswordClear);
if (result == B_OK) if (result == B_OK)
result = into->AddBool(KEY_IS_SUCCESSFUL, fIsSuccessful); result = into->AddBool(kKeyIsSuccessful, fIsSuccessful);
return result; return result;
} }
+16 -18
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2019-2026, 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.
*/ */
@@ -9,18 +9,18 @@
// These are keys that are used to store this object's data into a BMessage // These are keys that are used to store this object's data into a BMessage
// instance. // instance.
#define KEY_NICKNAME "nickname" static const char* const kKeyNickname = "nickname";
#define KEY_AGREEMENT "agreement" static const char* const kKeyAgreement = "agreement";
#define KEY_IS_LATEST "isLatest" static const char* const kKeyIsLatest = "is_latest";
#define KEY_CODE "code" static const char* const kKeyCode = "code";
#define KEY_TIMESTAMP_AGREED "timestampAgreed" static const char* const kKeyTimestampAgreed = "timestamp_agreed";
UserUsageConditionsAgreement::UserUsageConditionsAgreement(BMessage* from) UserUsageConditionsAgreement::UserUsageConditionsAgreement(BMessage* from)
{ {
from->FindUInt64(KEY_TIMESTAMP_AGREED, &fTimestampAgreed); from->FindUInt64(kKeyTimestampAgreed, &fTimestampAgreed);
from->FindString(KEY_CODE, &fCode); from->FindString(kKeyCode, &fCode);
from->FindBool(KEY_IS_LATEST, &fIsLatest); from->FindBool(kKeyIsLatest, &fIsLatest);
} }
@@ -96,11 +96,11 @@ UserUsageConditionsAgreement::Archive(BMessage* into, bool deep) const
{ {
status_t result = B_OK; status_t result = B_OK;
if (result == B_OK) if (result == B_OK)
result = into->AddUInt64(KEY_TIMESTAMP_AGREED, fTimestampAgreed); result = into->AddUInt64(kKeyTimestampAgreed, fTimestampAgreed);
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_CODE, fCode); result = into->AddString(kKeyCode, fCode);
if (result == B_OK) if (result == B_OK)
result = into->AddBool(KEY_IS_LATEST, fIsLatest); result = into->AddBool(kKeyIsLatest, fIsLatest);
return result; return result;
} }
@@ -108,11 +108,9 @@ UserUsageConditionsAgreement::Archive(BMessage* into, bool deep) const
UserDetail::UserDetail(BMessage* from) UserDetail::UserDetail(BMessage* from)
{ {
BMessage agreementMessage; BMessage agreementMessage;
if (from->FindMessage(KEY_AGREEMENT, if (from->FindMessage(kKeyAgreement, &agreementMessage) == B_OK)
&agreementMessage) == B_OK) {
fAgreement = UserUsageConditionsAgreement(&agreementMessage); fAgreement = UserUsageConditionsAgreement(&agreementMessage);
} from->FindString(kKeyNickname, &fNickname);
from->FindString(KEY_NICKNAME, &fNickname);
} }
@@ -175,9 +173,9 @@ UserDetail::Archive(BMessage* into, bool deep) const
BMessage agreementMessage; BMessage agreementMessage;
result = fAgreement.Archive(&agreementMessage, true); result = fAgreement.Archive(&agreementMessage, true);
if (result == B_OK) if (result == B_OK)
result = into->AddMessage(KEY_AGREEMENT, &agreementMessage); result = into->AddMessage(kKeyAgreement, &agreementMessage);
} }
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_NICKNAME, fNickname); result = into->AddString(kKeyNickname, fNickname);
return result; return result;
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2019-2020, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2019-2026, 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.
*/ */
@@ -10,9 +10,9 @@
// These are keys that are used to store this object's data into a BMessage // These are keys that are used to store this object's data into a BMessage
// instance. // instance.
#define KEY_COPY_MARKDOWN "copyMarkdown" static const char* const kKeyCode = "code";
#define KEY_CODE "code" static const char* const kKeyCopyMarkdown = "copy_markdown";
#define KEY_MINIMUM_AGE "minimumAge" static const char* const kKeyMinimumAge = "minimum_age";
UserUsageConditions::UserUsageConditions(BMessage* from) UserUsageConditions::UserUsageConditions(BMessage* from)
@@ -23,14 +23,14 @@ UserUsageConditions::UserUsageConditions(BMessage* from)
{ {
int16 minimumAge; int16 minimumAge;
if (from->FindInt16(KEY_MINIMUM_AGE, &minimumAge) != B_OK) if (from->FindInt16(kKeyMinimumAge, &minimumAge) != B_OK)
HDERROR("expected key [%s] in the message data", KEY_MINIMUM_AGE); HDERROR("expected key [%s] in the message data", kKeyMinimumAge);
fMinimumAge = (uint8) minimumAge; fMinimumAge = (uint8) minimumAge;
if (from->FindString(KEY_CODE, &fCode) != B_OK) if (from->FindString(kKeyCode, &fCode) != B_OK)
HDERROR("expected key [%s] in the message data", KEY_CODE); HDERROR("expected key [%s] in the message data", kKeyCode);
if (from->FindString(KEY_COPY_MARKDOWN, &fCopyMarkdown) != B_OK) if (from->FindString(kKeyCopyMarkdown, &fCopyMarkdown) != B_OK)
HDERROR("expected key [%s] in the message data", KEY_COPY_MARKDOWN); HDERROR("expected key [%s] in the message data", kKeyCopyMarkdown);
} }
@@ -93,8 +93,12 @@ UserUsageConditions::SetCopyMarkdown(const BString& copyMarkdown)
status_t status_t
UserUsageConditions::Archive(BMessage* into, bool deep) const UserUsageConditions::Archive(BMessage* into, bool deep) const
{ {
into->AddInt16(KEY_MINIMUM_AGE, (int16) fMinimumAge); status_t result = B_OK;
into->AddString(KEY_CODE, fCode); if (result == B_OK)
into->AddString(KEY_COPY_MARKDOWN, fCopyMarkdown); result = into->AddInt16(kKeyMinimumAge, (int16)fMinimumAge);
return B_OK; if (result == B_OK)
result = into->AddString(kKeyCode, fCode);
if (result == B_OK)
result = into->AddString(kKeyCopyMarkdown, fCopyMarkdown);
return result;
} }
+10 -10
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2019, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2019-2026, 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.
*/ */
@@ -8,9 +8,9 @@
// These are keys that are used to store this object's data into a BMessage // These are keys that are used to store this object's data into a BMessage
// instance. // instance.
#define KEY_PROPERTY "property" static const char* const kKeyProperty = "property";
#define KEY_PREFIX_MESSAGE "message_" static const char* const kKeyPrefixMessage = "message_";
#define KEY_PREFIX_ITEM "item_" static const char* const kKeyPrefixItem = "item_";
// #pragma mark - Single Validation Failure // #pragma mark - Single Validation Failure
@@ -18,7 +18,7 @@
ValidationFailure::ValidationFailure(BMessage* from) ValidationFailure::ValidationFailure(BMessage* from)
{ {
from->FindString(KEY_PROPERTY, &fProperty); from->FindString(kKeyProperty, &fProperty);
if (fProperty.IsEmpty()) if (fProperty.IsEmpty())
debugger("illegal state; missing property in message"); debugger("illegal state; missing property in message");
@@ -28,7 +28,7 @@ ValidationFailure::ValidationFailure(BMessage* from)
BString message; BString message;
for (int32 i = 0; result == B_OK; i++) { for (int32 i = 0; result == B_OK; i++) {
name.SetToFormat("%s%" B_PRId32, KEY_PREFIX_MESSAGE, i); name.SetToFormat("%s%" B_PRId32, kKeyPrefixMessage, i);
result = from->FindString(name, &message); result = from->FindString(name, &message);
if (result == B_OK) if (result == B_OK)
@@ -89,9 +89,9 @@ ValidationFailure::Archive(BMessage* into, bool deep) const
status_t result = B_OK; status_t result = B_OK;
BString key; BString key;
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_PROPERTY, fProperty); result = into->AddString(kKeyProperty, fProperty);
for (int32 i = 0; result == B_OK && i < fMessages.CountStrings(); i++) { for (int32 i = 0; result == B_OK && i < fMessages.CountStrings(); i++) {
key.SetToFormat("%s%" B_PRId32, KEY_PREFIX_MESSAGE, i); key.SetToFormat("%s%" B_PRId32, kKeyPrefixMessage, i);
result = into->AddString(key, fMessages.StringAt(i)); result = into->AddString(key, fMessages.StringAt(i));
} }
return result; return result;
@@ -177,7 +177,7 @@ ValidationFailures::Archive(BMessage* into, bool deep) const
BMessage itemMessage; BMessage itemMessage;
result = item->Archive(&itemMessage); result = item->Archive(&itemMessage);
if (result == B_OK) { if (result == B_OK) {
key.SetToFormat("%s%" B_PRId32, KEY_PREFIX_ITEM, i); key.SetToFormat("%s%" B_PRId32, kKeyPrefixItem, i);
result = into->AddMessage(key, &itemMessage); result = into->AddMessage(key, &itemMessage);
} }
} }
@@ -221,7 +221,7 @@ ValidationFailures::_AddFromMessage(const BMessage* from)
while (true) { while (true) {
BMessage itemMessage; BMessage itemMessage;
key.SetToFormat("%s%" B_PRId32, KEY_PREFIX_ITEM, i); key.SetToFormat("%s%" B_PRId32, kKeyPrefixItem, i);
if (from->FindMessage(key, &itemMessage) != B_OK) if (from->FindMessage(key, &itemMessage) != B_OK)
return; return;
fItems.AddItem(new ValidationFailure(&itemMessage)); fItems.AddItem(new ValidationFailure(&itemMessage));
@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2025, Haiku, Inc. All Rights Reserved. * Copyright 2013-2026, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -181,7 +181,8 @@ InstallPackageProcess::RunInternal()
BString errorString; BString errorString;
errorString.SetToFormat("Fatal error occurred while installing package %s: %s (%s)\n", errorString.SetToFormat("Fatal error occurred while installing package %s: %s (%s)\n",
packageNameString, ex.Message().String(), ex.Details().String()); packageNameString, ex.Message().String(), ex.Details().String());
AppUtils::NotifySimpleError(B_TRANSLATE("Fatal error"), errorString, B_STOP_ALERT); AppUtils::NotifySimpleError(
SimpleAlert(B_TRANSLATE("Fatal error"), errorString, B_STOP_ALERT));
_SetDownloadedPackagesState(NONE); _SetDownloadedPackagesState(NONE);
SetPackageState(fPackageName, state); SetPackageState(fPackageName, state);
return ex.Error(); return ex.Error();
@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2025, Haiku, Inc. All Rights Reserved. * Copyright 2013-2026, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -137,6 +137,10 @@ OpenPackageProcess::RunInternal()
{ {
status_t status; status_t status;
BPath path; BPath path;
HDDEBUG("open package action from deskbar link [%s], path [%s]", fDeskbarLink.Link().String(),
fDeskbarLink.Path().String());
if (fDeskbarLink.Link().FindFirst('/') == 0) { if (fDeskbarLink.Link().FindFirst('/') == 0) {
status = path.SetTo(fDeskbarLink.Link()); status = path.SetTo(fDeskbarLink.Link());
HDINFO("trying to launch (absolute link): %s", path.Path()); HDINFO("trying to launch (absolute link): %s", path.Path());
@@ -1,20 +1,43 @@
/* /*
* Copyright 2021, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2021-2026, 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 "PackageAction.h" #include "PackageAction.h"
#include <Catalog.h>
PackageAction::PackageAction(const BString& title, const BMessage& message) #include "HaikuDepotConstants.h"
#include "Logger.h"
#include "PackageUtils.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "PackageAction"
static const char* const kKeyTitle = "title";
static const char* const kKeyDeskbarLink = "deskbar_link";
/*! An abstract superclass of the various sorts of package actions which can be
undertaken on a package.
*/
PackageAction::PackageAction(const BString& title, const BString& packageName)
: :
fTitle(title), fTitle(title),
fMessage(message) fPackageName(packageName)
{ {
} }
PackageAction::PackageAction(const BMessage* from)
{
if (from->FindString(kKeyTitle, &fTitle) != B_OK)
HDFATAL("expected key [%s] in message", kKeyTitle);
if (from->FindString(shared_message_keys::kKeyPackageName, &fPackageName) != B_OK)
HDFATAL("expected key [%s] in message", shared_message_keys::kKeyPackageName);
}
PackageAction::~PackageAction() PackageAction::~PackageAction()
{ {
} }
@@ -27,8 +50,150 @@ PackageAction::Title() const
} }
const BMessage& const BString&
PackageAction::PackageName() const
{
return fPackageName;
}
/*! Returns a `BMessage` which can be used in BView action to cause the action
to get executed by some UI logic.
*/
const BMessage
PackageAction::Message() const PackageAction::Message() const
{ {
return fMessage; BMessage message(MessageWhat());
if (Archive(&message) != B_OK)
HDFATAL("unable to archive the action message.");
return message;
}
status_t
PackageAction::Archive(BMessage* into, bool deep) const
{
status_t result = B_OK;
if (result == B_OK && into == NULL)
result = B_ERROR;
if (result == B_OK)
result = into->AddString(kKeyTitle, fTitle);
if (result == B_OK)
result = into->AddString(shared_message_keys::kKeyPackageName, fPackageName);
return result;
}
UninstallPackageAction::UninstallPackageAction(const BString& packageName,
const BString& packageTitle)
:
PackageAction("Uninstall", packageName)
{
fTitle = B_TRANSLATE("Uninstall %PackageTitle%");
fTitle.ReplaceAll("%PackageTitle%", packageTitle);
}
UninstallPackageAction::UninstallPackageAction(const BMessage* from)
:
PackageAction(from)
{
}
UninstallPackageAction::~UninstallPackageAction()
{
}
const uint32
UninstallPackageAction::MessageWhat() const
{
return MSG_PKG_UNINSTALL;
}
InstallPackageAction::InstallPackageAction(const BString& packageName,
const BString& packageTitle)
:
PackageAction("Install", packageName)
{
fTitle = B_TRANSLATE("Install %PackageTitle%");
fTitle.ReplaceAll("%PackageTitle%", packageTitle);
}
InstallPackageAction::InstallPackageAction(const BMessage* from)
:
PackageAction(from)
{
}
InstallPackageAction::~InstallPackageAction()
{
}
const uint32
InstallPackageAction::MessageWhat() const
{
return MSG_PKG_INSTALL;
}
OpenPackageAction::OpenPackageAction(const BString& packageName, const DeskbarLink& deskbarLink)
:
PackageAction("Open", packageName),
fLink(deskbarLink)
{
fTitle = B_TRANSLATE("Open %DeskbarLink%");
fTitle.ReplaceAll("%DeskbarLink%", deskbarLink.Title());
}
OpenPackageAction::OpenPackageAction(const BMessage* from)
:
PackageAction(from)
{
BMessage deskbarLinkMessage;
if (from->FindMessage(kKeyDeskbarLink, &deskbarLinkMessage) == B_OK)
fLink = DeskbarLink(&deskbarLinkMessage);
else
HDFATAL("missing key [%s]", kKeyDeskbarLink);
}
OpenPackageAction::~OpenPackageAction()
{
}
const uint32
OpenPackageAction::MessageWhat() const
{
return MSG_PKG_OPEN;
}
const DeskbarLink
OpenPackageAction::Link() const
{
return fLink;
}
status_t
OpenPackageAction::Archive(BMessage* into, bool deep) const
{
status_t result = PackageAction::Archive(into, deep);
if (result == B_OK) {
BMessage deskbarLinkMessage;
result = fLink.Archive(&deskbarLinkMessage);
if (result == B_OK)
result = into->AddMessage(kKeyDeskbarLink, &deskbarLinkMessage);
}
return result;
} }
@@ -1,32 +1,83 @@
/* /*
* Copyright 2021, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2021-2026, 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_ACTION_H #ifndef PACKAGE_ACTION_H
#define PACKAGE_ACTION_H #define PACKAGE_ACTION_H
#include <Message.h> #include <Message.h>
#include <Referenceable.h> #include <Referenceable.h>
#include <String.h> #include <String.h>
#include "DeskbarLink.h"
class PackageAction : public BReferenceable {
class PackageAction : public BReferenceable, public BArchivable
{
public: public:
PackageAction(const BString& title, PackageAction(const BString& title, const BString& packageName);
const BMessage& message); PackageAction(const BMessage* from);
virtual ~PackageAction(); virtual ~PackageAction();
const BString& Title() const; const BString& Title() const;
const BMessage& Message() const; const BString& PackageName() const;
private: const BMessage Message() const;
virtual const uint32 MessageWhat() const = 0;
virtual status_t Archive(BMessage* into, bool deep = true) const;
protected:
BString fTitle; BString fTitle;
BMessage fMessage; BString fPackageName;
}; };
typedef BReference<PackageAction> PackageActionRef; typedef BReference<PackageAction> PackageActionRef;
class UninstallPackageAction : public PackageAction
{
public:
UninstallPackageAction(const BString& packageName,
const BString& packageTitle);
UninstallPackageAction(const BMessage* from);
virtual ~UninstallPackageAction();
virtual const uint32 MessageWhat() const;
};
class InstallPackageAction : public PackageAction
{
public:
InstallPackageAction(const BString& packageName,
const BString& packageTitle);
InstallPackageAction(const BMessage* from);
virtual ~InstallPackageAction();
virtual const uint32 MessageWhat() const;
};
class OpenPackageAction : public PackageAction
{
public:
OpenPackageAction(const BString& packageName,
const DeskbarLink& link);
OpenPackageAction(const BMessage* from);
~OpenPackageAction();
virtual const uint32 MessageWhat() const;
const DeskbarLink Link() const;
virtual status_t Archive(BMessage* into, bool deep = true) const;
private:
DeskbarLink fLink;
};
#endif // PACKAGE_ACTION_H #endif // PACKAGE_ACTION_H
@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2024, Haiku, Inc. All Rights Reserved. * Copyright 2013-2026, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -160,8 +160,13 @@ PackageManager::CollectPackageActions(PackageInfoRef package,
break; break;
case NONE: case NONE:
case UNINSTALLED: case UNINSTALLED:
actionList.Add(_CreateInstallPackageAction(package)); {
BString packageTitle;
PackageUtils::TitleOrName(package, packageTitle);
actionList.Add(
PackageActionRef(new InstallPackageAction(package->Name(), packageTitle), true));
break; break;
}
case DOWNLOADING: case DOWNLOADING:
HDINFO("no package actions for [%s] (downloading)", HDINFO("no package actions for [%s] (downloading)",
package->Name().String()); package->Name().String());
@@ -183,7 +188,11 @@ PackageManager::_CollectPackageActionsForActivatedOrInstalled(
PackageInfoRef package, PackageInfoRef package,
Collector<PackageActionRef>& actionList) Collector<PackageActionRef>& actionList)
{ {
actionList.Add(_CreateUninstallPackageAction(package)); BString packageTitle;
PackageUtils::TitleOrName(package, packageTitle);
actionList.Add(
PackageActionRef(new UninstallPackageAction(package->Name(), packageTitle), true));
// Add OpenPackageActions for each deskbar link found in the // Add OpenPackageActions for each deskbar link found in the
// package // package
@@ -192,60 +201,14 @@ PackageManager::_CollectPackageActionsForActivatedOrInstalled(
std::vector<DeskbarLink>::const_iterator it; std::vector<DeskbarLink>::const_iterator it;
for (it = foundLinks.begin(); it != foundLinks.end(); it++) { for (it = foundLinks.begin(); it != foundLinks.end(); it++) {
const DeskbarLink& aLink = *it; const DeskbarLink& aLink = *it;
actionList.Add(_CreateOpenPackageAction(package, aLink)); if (aLink.IsValid()) {
actionList.Add(
PackageActionRef(new OpenPackageAction(package->Name(), aLink), true));
} else {
HDERROR("broken deskbar link for [%s]", package->Name().String());
}
} }
} }
}
PackageActionRef
PackageManager::_CreateUninstallPackageAction(const PackageInfoRef& package)
{
BString actionTitle = B_TRANSLATE("Uninstall %PackageTitle%");
BString packageTitle;
PackageUtils::TitleOrName(package, packageTitle);
actionTitle.ReplaceAll("%PackageTitle%", packageTitle);
BMessage message(MSG_PKG_UNINSTALL);
message.AddString(KEY_TITLE, actionTitle);
message.AddString(KEY_PACKAGE_NAME, package->Name());
return PackageActionRef(new PackageAction(actionTitle, message), true);
}
PackageActionRef
PackageManager::_CreateInstallPackageAction(const PackageInfoRef& package)
{
BString actionTitle = B_TRANSLATE("Install %PackageTitle%");
BString packageTitle;
PackageUtils::TitleOrName(package, packageTitle);
actionTitle.ReplaceAll("%PackageTitle%", packageTitle);
BMessage message(MSG_PKG_INSTALL);
message.AddString(KEY_TITLE, actionTitle);
message.AddString(KEY_PACKAGE_NAME, package->Name());
return PackageActionRef(new PackageAction(actionTitle, message), true);
}
PackageActionRef
PackageManager::_CreateOpenPackageAction(const PackageInfoRef& package, const DeskbarLink& link)
{
BString title = B_TRANSLATE("Open %DeskbarLink%");
title.ReplaceAll("%DeskbarLink%", link.Title());
BMessage deskbarLinkMessage;
if (link.Archive(&deskbarLinkMessage) != B_OK)
HDFATAL("unable to archive the deskbar link");
BMessage message(MSG_PKG_OPEN);
message.AddString(KEY_TITLE, title);
message.AddMessage(KEY_DESKBAR_LINK, &deskbarLinkMessage);
message.AddString(KEY_PACKAGE_NAME, package->Name());
return PackageActionRef(new PackageAction(title, message), true);
} }
@@ -3,7 +3,7 @@
* Copyright 2011, Ingo Weinhold, <ingo_weinhold@gmx.de> * Copyright 2011, Ingo Weinhold, <ingo_weinhold@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 2021, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2021-2026, 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.
*/ */
@@ -97,13 +97,6 @@ private:
InstalledRepository& repository); InstalledRepository& repository);
private: private:
PackageActionRef _CreateUninstallPackageAction(
const PackageInfoRef& package);
PackageActionRef _CreateInstallPackageAction(
const PackageInfoRef& package);
PackageActionRef _CreateOpenPackageAction(
const PackageInfoRef& package,
const DeskbarLink& link);
void _CollectPackageActionsForActivatedOrInstalled( void _CollectPackageActionsForActivatedOrInstalled(
PackageInfoRef package, PackageInfoRef package,
@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2025, Haiku, Inc. All Rights Reserved. * Copyright 2013-2026, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -93,7 +93,8 @@ UninstallPackageProcess::RunInternal()
BString errorString; BString errorString;
errorString.SetToFormat("Fatal error occurred while uninstalling package %s: %s (%s)\n", errorString.SetToFormat("Fatal error occurred while uninstalling package %s: %s (%s)\n",
fPackageName.String(), ex.Message().String(), ex.Details().String()); fPackageName.String(), ex.Message().String(), ex.Details().String());
AppUtils::NotifySimpleError(B_TRANSLATE("Fatal error"), errorString, B_STOP_ALERT); AppUtils::NotifySimpleError(
SimpleAlert(B_TRANSLATE("Fatal error"), errorString, B_STOP_ALERT));
SetPackageState(fPackageName, state); SetPackageState(fPackageName, state);
return ex.Error(); return ex.Error();
} catch (BAbortedByUserException& ex) { } catch (BAbortedByUserException& ex) {
@@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2022, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2018-2026, 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.
*/ */
@@ -22,11 +22,11 @@
// These are keys that are used to store the ProcessCoordinatorState data into // These are keys that are used to store the ProcessCoordinatorState data into
// a BMessage instance. // a BMessage instance.
#define KEY_PROCESS_COORDINATOR_IDENTIFIER "processCoordinatorIdentifier" static const char* const kKeyIdentifier = "identifier";
#define KEY_PROGRESS "progress" static const char* const kKeyProgress = "progress";
#define KEY_MESSAGE "message" static const char* const kKeyMessage = "message";
#define KEY_IS_RUNNING "isRunning" static const char* const kKeyIsRunning = "is_running";
#define KEY_ERROR_STATUS "errorStatus" static const char* const kKeyErrorStatus = "error_status";
// #pragma mark - ProcessCoordinatorState implementation // #pragma mark - ProcessCoordinatorState implementation
@@ -34,28 +34,18 @@
ProcessCoordinatorState::ProcessCoordinatorState(BMessage* from) ProcessCoordinatorState::ProcessCoordinatorState(BMessage* from)
{ {
if (from->FindString(KEY_PROCESS_COORDINATOR_IDENTIFIER, if (from->FindString(kKeyIdentifier, &fProcessCoordinatorIdentifier) != B_OK)
&fProcessCoordinatorIdentifier) != B_OK) { HDFATAL("unable to find the key [%s]", kKeyIdentifier);
HDFATAL("unable to find the key [%s]", if (from->FindFloat(kKeyProgress, &fProgress) != B_OK)
KEY_PROCESS_COORDINATOR_IDENTIFIER); HDFATAL("unable to find the key [%s]", kKeyProgress);
} if (from->FindString(kKeyMessage, &fMessage) != B_OK)
HDFATAL("unable to find the key [%s]", kKeyMessage);
if (from->FindFloat(KEY_PROGRESS, &fProgress) != B_OK) { if (from->FindBool(kKeyIsRunning, &fIsRunning) != B_OK)
HDFATAL("unable to find the key [%s]", KEY_PROGRESS); HDFATAL("unable to find the key [%s]", kKeyIsRunning);
}
if (from->FindString(KEY_MESSAGE, &fMessage) != B_OK) {
HDFATAL("unable to find the key [%s]", KEY_MESSAGE);
}
if (from->FindBool(KEY_IS_RUNNING, &fIsRunning) != B_OK) {
HDFATAL("unable to find the key [%s]", KEY_IS_RUNNING);
}
int64 errorStatusNumeric; int64 errorStatusNumeric;
if (from->FindInt64(KEY_ERROR_STATUS, &errorStatusNumeric) != B_OK) { if (from->FindInt64(kKeyErrorStatus, &errorStatusNumeric) != B_OK)
HDFATAL("unable to find the key [%s]", KEY_ERROR_STATUS); HDFATAL("unable to find the key [%s]", kKeyErrorStatus);
}
fErrorStatus = static_cast<status_t>(errorStatusNumeric); fErrorStatus = static_cast<status_t>(errorStatusNumeric);
} }
@@ -117,18 +107,16 @@ status_t
ProcessCoordinatorState::Archive(BMessage* into, bool deep) const ProcessCoordinatorState::Archive(BMessage* into, bool deep) const
{ {
status_t result = B_OK; status_t result = B_OK;
if (result == B_OK) {
result = into->AddString(KEY_PROCESS_COORDINATOR_IDENTIFIER,
fProcessCoordinatorIdentifier);
}
if (result == B_OK) if (result == B_OK)
result = into->AddFloat(KEY_PROGRESS, fProgress); result = into->AddString(kKeyIdentifier, fProcessCoordinatorIdentifier);
if (result == B_OK) if (result == B_OK)
result = into->AddString(KEY_MESSAGE, fMessage); result = into->AddFloat(kKeyProgress, fProgress);
if (result == B_OK) if (result == B_OK)
result = into->AddBool(KEY_IS_RUNNING, fIsRunning); result = into->AddString(kKeyMessage, fMessage);
if (result == B_OK) if (result == B_OK)
result = into->AddInt64(KEY_ERROR_STATUS, static_cast<int64>(fErrorStatus)); result = into->AddBool(kKeyIsRunning, fIsRunning);
if (result == B_OK)
result = into->AddInt64(kKeyErrorStatus, static_cast<int64>(fErrorStatus));
return result; return result;
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2018-2026, 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 "ProcessCoordinatorFactory.h" #include "ProcessCoordinatorFactory.h"
@@ -136,22 +136,6 @@ ProcessCoordinatorFactory::CreateBulkLoadCoordinator(Model* model, bool forceLoc
} }
/*static*/ ProcessCoordinator*
ProcessCoordinatorFactory::CreatePackageActionCoordinator(Model* model, BMessage* message)
{
switch (message->what) {
case MSG_PKG_INSTALL:
return _CreateInstallPackageActionCoordinator(model, message);
case MSG_PKG_UNINSTALL:
return _CreateUninstallPackageActionCoordinator(model, message);
case MSG_PKG_OPEN:
return _CreateOpenPackageActionCoordinator(model, message);
default:
HDFATAL("unexpected package action message what");
}
}
/*static*/ ProcessCoordinator* /*static*/ ProcessCoordinator*
ProcessCoordinatorFactory::CacheScreenshotCoordinator(Model* model, ProcessCoordinatorFactory::CacheScreenshotCoordinator(Model* model,
ScreenshotCoordinate& screenshotCoordinate) ScreenshotCoordinate& screenshotCoordinate)
@@ -178,64 +162,41 @@ ProcessCoordinatorFactory::PopulatePkgUserRatingsCoordinator(Model* model,
} }
/*static*/ BString
ProcessCoordinatorFactory::_ExtractPackageNameFromMessage(BMessage* message)
{
BString pkgName;
if (message->FindString(KEY_PACKAGE_NAME, &pkgName) != B_OK)
HDFATAL("malformed message missing key [%s]", KEY_PACKAGE_NAME);
return pkgName;
}
/*static*/ ProcessCoordinator* /*static*/ ProcessCoordinator*
ProcessCoordinatorFactory::_CreateInstallPackageActionCoordinator(Model* model, BMessage* message) ProcessCoordinatorFactory::CreateInstallPackageActionCoordinator(Model* model,
const InstallPackageAction& action)
{ {
ProcessCoordinator* processCoordinator ProcessCoordinator* processCoordinator
= new ProcessCoordinator("InstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE)); = new ProcessCoordinator("InstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
AbstractProcessNode* processNode
AbstractProcessNode* processNode = new ThreadedProcessNode( = new ThreadedProcessNode(new InstallPackageProcess(action.PackageName(), model), 10);
new InstallPackageProcess(_ExtractPackageNameFromMessage(message), model), 10);
processCoordinator->AddNode(processNode); processCoordinator->AddNode(processNode);
return processCoordinator; return processCoordinator;
} }
/*static*/ ProcessCoordinator* /*static*/ ProcessCoordinator*
ProcessCoordinatorFactory::_CreateUninstallPackageActionCoordinator(Model* model, BMessage* message) ProcessCoordinatorFactory::CreateUninstallPackageActionCoordinator(Model* model,
const UninstallPackageAction& action)
{ {
ProcessCoordinator* processCoordinator ProcessCoordinator* processCoordinator
= new ProcessCoordinator("UninstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE)); = new ProcessCoordinator("UninstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
AbstractProcessNode* processNode
AbstractProcessNode* processNode = new ThreadedProcessNode( = new ThreadedProcessNode(new UninstallPackageProcess(action.PackageName(), model), 10);
new UninstallPackageProcess(_ExtractPackageNameFromMessage(message), model), 10);
processCoordinator->AddNode(processNode); processCoordinator->AddNode(processNode);
return processCoordinator; return processCoordinator;
} }
/*static*/ ProcessCoordinator* /*static*/ ProcessCoordinator*
ProcessCoordinatorFactory::_CreateOpenPackageActionCoordinator(Model* model, BMessage* message) ProcessCoordinatorFactory::CreateOpenPackageActionCoordinator(Model* model,
const OpenPackageAction& action)
{ {
ProcessCoordinator* processCoordinator ProcessCoordinator* processCoordinator
= new ProcessCoordinator("OpenPackage", new BMessage(MSG_PACKAGE_ACTION_DONE)); = new ProcessCoordinator("OpenPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
BMessage deskbarLinkMessage;
if (message->FindMessage(KEY_DESKBAR_LINK, &deskbarLinkMessage) != B_OK)
HDFATAL("malformed message missing key [%s]", KEY_DESKBAR_LINK);
DeskbarLink deskbarLink(&deskbarLinkMessage);
AbstractProcessNode* processNode = new ThreadedProcessNode( AbstractProcessNode* processNode = new ThreadedProcessNode(
new OpenPackageProcess(_ExtractPackageNameFromMessage(message), model, deskbarLink)); new OpenPackageProcess(action.PackageName(), model, action.Link()));
processCoordinator->AddNode(processNode); processCoordinator->AddNode(processNode);
return processCoordinator; return processCoordinator;
} }
@@ -8,6 +8,7 @@
#include <SupportDefs.h> #include <SupportDefs.h>
#include "AbstractProcess.h" #include "AbstractProcess.h"
#include "PackageAction.h"
#include "PackageInfo.h" #include "PackageInfo.h"
#include "PackageScreenshotRepository.h" #include "PackageScreenshotRepository.h"
@@ -32,9 +33,6 @@ public:
UserDetailVerifierListener* userDetailVerifierListener, UserDetailVerifierListener* userDetailVerifierListener,
Model* model); Model* model);
static ProcessCoordinator* CreatePackageActionCoordinator(
Model* model, BMessage* message);
static ProcessCoordinator* CacheScreenshotCoordinator( static ProcessCoordinator* CacheScreenshotCoordinator(
Model* model, ScreenshotCoordinate& screenshotCoordinate); Model* model, ScreenshotCoordinate& screenshotCoordinate);
@@ -44,20 +42,18 @@ public:
static ProcessCoordinator* PopulatePkgUserRatingsCoordinator(Model* model, static ProcessCoordinator* PopulatePkgUserRatingsCoordinator(Model* model,
const BString& packageName); const BString& packageName);
static ProcessCoordinator* CreateInstallPackageActionCoordinator(Model* model,
const InstallPackageAction& action);
static ProcessCoordinator* CreateUninstallPackageActionCoordinator(Model* model,
const UninstallPackageAction& action);
static ProcessCoordinator* CreateOpenPackageActionCoordinator(Model* model,
const OpenPackageAction& action);
private: private:
static uint32 _CalculateServerProcessOptions(); static uint32 _CalculateServerProcessOptions();
static BString _ExtractPackageNameFromMessage(BMessage* message);
static ProcessCoordinator* _CreateInstallPackageActionCoordinator(
Model* model, BMessage* message);
static ProcessCoordinator* _CreateUninstallPackageActionCoordinator(
Model* model, BMessage* message);
static ProcessCoordinator* _CreateOpenPackageActionCoordinator(
Model* model, BMessage* message);
static ProcessCoordinator* _CreateSingleProcessCoordinator(const char* name, static ProcessCoordinator* _CreateSingleProcessCoordinator(const char* name,
AbstractProcess *process); AbstractProcess *process);
@@ -741,7 +741,8 @@ LocalPkgDataLoadProcessUtils::_PopulateModel(LocalPkgDataLoadProcessUtilsData& d
LocalPkgDataLoadProcessUtils::_NotifyError(const BString& messageText) LocalPkgDataLoadProcessUtils::_NotifyError(const BString& messageText)
{ {
HDERROR("an error has arisen loading data of packages from local : %s", messageText.String()); HDERROR("an error has arisen loading data of packages from local : %s", messageText.String());
AppUtils::NotifySimpleError(B_TRANSLATE("Local repository load error"), messageText); AppUtils::NotifySimpleError(
SimpleAlert(B_TRANSLATE("Local repository load error"), messageText));
} }
@@ -181,7 +181,5 @@ LocalRepositoryUpdateProcess::_NotifyError(const BString& error,
alertText.Append(")"); alertText.Append(")");
} }
AppUtils::NotifySimpleError( AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Repository update error"), alertText));
B_TRANSLATE("Repository update error"),
alertText);
} }
+10 -6
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2017-2026, 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.
*/ */
@@ -24,8 +24,12 @@
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "ServerHelper" #define B_TRANSLATION_CONTEXT "ServerHelper"
#define KEY_MSG_MINIMUM_VERSION "minimumVersion" static const char* const kKeyMinimumVersion = "minimum_version";
#define KEY_HEADER_MINIMUM_VERSION "X-Desktop-Application-Minimum-Version"
/*! This is an HTTP header that the sever will send back to the client to inform
it about a version limit.
*/
static const char* const kKeyHeaderMinimumVersion = "X-Desktop-Application-Minimum-Version";
/*! \brief This method will cause an alert to be shown to the user regarding a /*! \brief This method will cause an alert to be shown to the user regarding a
@@ -165,11 +169,11 @@ ServerHelper::NotifyClientTooOld(const BHttpHeaders& responseHeaders)
if (!ServerSettings::IsClientTooOld()) { if (!ServerSettings::IsClientTooOld()) {
ServerSettings::SetClientTooOld(); ServerSettings::SetClientTooOld();
const char* minimumVersionC = responseHeaders[KEY_HEADER_MINIMUM_VERSION]; const char* minimumVersionC = responseHeaders[kKeyHeaderMinimumVersion];
BMessage message(MSG_CLIENT_TOO_OLD); BMessage message(MSG_CLIENT_TOO_OLD);
if (minimumVersionC != NULL && strlen(minimumVersionC) != 0) { if (minimumVersionC != NULL && strlen(minimumVersionC) != 0) {
message.AddString(KEY_MSG_MINIMUM_VERSION, minimumVersionC); message.AddString(kKeyMinimumVersion, minimumVersionC);
} }
be_app->PostMessage(&message); be_app->PostMessage(&message);
@@ -183,7 +187,7 @@ ServerHelper::AlertClientTooOld(BMessage* message)
BString minimumVersion; BString minimumVersion;
BString alertText; BString alertText;
if (message->FindString(KEY_MSG_MINIMUM_VERSION, &minimumVersion) != B_OK) if (message->FindString(kKeyMinimumVersion, &minimumVersion) != B_OK)
minimumVersion = "???"; minimumVersion = "???";
alertText.SetToFormat( alertText.SetToFormat(
+10 -20
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2017-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2017-2026, 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.
*/ */
@@ -38,6 +38,9 @@
#define B_TRANSLATION_CONTEXT "App" #define B_TRANSLATION_CONTEXT "App"
static const char* const kKeyMainSettings = "main_settings";
App::App() App::App()
: :
BApplication("application/x-vnd.Haiku-HaikuDepot"), BApplication("application/x-vnd.Haiku-HaikuDepot"),
@@ -109,7 +112,7 @@ App::MessageReceived(BMessage* message)
case MSG_MAIN_WINDOW_CLOSED: case MSG_MAIN_WINDOW_CLOSED:
{ {
BMessage windowSettings; BMessage windowSettings;
if (message->FindMessage(KEY_WINDOW_SETTINGS, &windowSettings) == B_OK) if (message->FindMessage(main_window_keys::kKeyWindowSettings, &windowSettings) == B_OK)
_StoreSettings(windowSettings); _StoreSettings(windowSettings);
fWindowCount--; fWindowCount--;
@@ -325,22 +328,9 @@ App::ArgvReceived(int32 argc, char* argv[])
void void
App::_AlertSimpleError(BMessage* message) App::_AlertSimpleError(BMessage* message)
{ {
BString alertTitle; SimpleAlert simpleAlert(message);
BString alertText; BAlert* alert = new BAlert(simpleAlert.Title(), simpleAlert.Text(), B_TRANSLATE("OK"), NULL,
int32 typeInt; NULL, B_WIDTH_AS_USUAL, simpleAlert.Type());
if (message->FindString(KEY_ALERT_TEXT, &alertText) != B_OK)
alertText = "?";
if (message->FindString(KEY_ALERT_TITLE, &alertTitle) != B_OK)
alertTitle = B_TRANSLATE("Error");
if (message->FindInt32(KEY_ALERT_TYPE, &typeInt) != B_OK)
typeInt = B_INFO_ALERT;
BAlert* alert = new BAlert(alertTitle, alertText, B_TRANSLATE("OK"), NULL, NULL,
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();
} }
@@ -421,7 +411,7 @@ App::_LoadSettings(BMessage& settings)
{ {
if (!fSettingsRead) { if (!fSettingsRead) {
fSettingsRead = true; fSettingsRead = true;
if (load_settings(&fSettings, KEY_MAIN_SETTINGS, "HaikuDepot") != B_OK) if (load_settings(&fSettings, kKeyMainSettings, "HaikuDepot") != B_OK)
fSettings.MakeEmpty(); fSettings.MakeEmpty();
} }
settings = fSettings; settings = fSettings;
@@ -452,7 +442,7 @@ App::_StoreSettings(const BMessage& settings)
} }
} }
save_settings(&fSettings, KEY_MAIN_SETTINGS, "HaikuDepot"); save_settings(&fSettings, kKeyMainSettings, "HaikuDepot");
} }
@@ -1,7 +1,7 @@
/* /*
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2013-2014, 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-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2020-2026, Andrew Lindesay <apl@lindesay.co.nz>.
* Copyright 2025, Pawan Yerramilli <me@pawanyerramilli.com>. * Copyright 2025, Pawan Yerramilli <me@pawanyerramilli.com>.
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@@ -300,7 +300,7 @@ public:
if (index != -1) { if (index != -1) {
BMessage message(MSG_PACKAGE_SELECTED); BMessage message(MSG_PACKAGE_SELECTED);
BString packageName = fPackages[index]->Name(); BString packageName = fPackages[index]->Name();
message.AddString("name", packageName); message.AddString(shared_message_keys::kKeyPackageName, packageName);
Window()->PostMessage(&message); Window()->PostMessage(&message);
} }
} }
@@ -320,17 +320,18 @@ public:
// #pragma mark - update / add / remove / clear data // #pragma mark - update / add / remove / clear data
void HandlePackagesChanged(const PackageInfoEvents& events) void HandlePackagesChanged(const std::vector<PackageInfoChangeEvent>& events)
{ {
for (int32 i = events.CountEvents() - 1; i >= 0; i--) std::vector<PackageInfoChangeEvent>::const_iterator it;
_HandlePackageChanged(events.EventAtIndex(i)); for (it = events.begin(); it != events.end(); it++)
_HandlePackageChanged(*it);
} }
void _HandlePackageChanged(const PackageInfoEvent& event) void _HandlePackageChanged(const PackageInfoChangeEvent& event)
{ {
uint32 changes = event.Changes(); uint32 changes = event.Changes();
PackageInfoRef package = event.Package(); const PackageInfoRef package = event.Package();
if (!package.IsSet() || 0 == changes) if (!package.IsSet() || 0 == changes)
return; return;
@@ -1089,7 +1090,7 @@ FeaturedPackagesView::HandleIconsChanged()
void void
FeaturedPackagesView::HandlePackagesChanged(const PackageInfoEvents& events) FeaturedPackagesView::HandlePackagesChanged(const std::vector<PackageInfoChangeEvent>& events)
{ {
fPackagesView->HandlePackagesChanged(events); fPackagesView->HandlePackagesChanged(events);
} }
@@ -40,13 +40,14 @@ public:
void HandleIconsChanged(); void HandleIconsChanged();
void HandlePackagesChanged(const PackageInfoEvents& events); void HandlePackagesChanged(
const std::vector<PackageInfoChangeEvent>& events);
void SetLoading(bool isLoading); void SetLoading(bool isLoading);
private: private:
void _AdjustViews(); void _AdjustViews();
void _HandlePackageChanged(const PackageInfoEvent& event); void _HandlePackageChanged(const PackageChangeEvent& event);
void _BuildNoResultsView(); void _BuildNoResultsView();
private: private:
+7 -4
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2019-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2019-2026, 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.
*/ */
@@ -27,6 +27,9 @@
#define B_TRANSLATION_CONTEXT "FilterView" #define B_TRANSLATION_CONTEXT "FilterView"
const char* const filter_view_keys::kKeySearchTerms = "search_terms";
FilterView::FilterView() FilterView::FilterView()
: :
BGroupView("filter view", B_VERTICAL) BGroupView("filter view", B_VERTICAL)
@@ -85,7 +88,7 @@ FilterView::MessageReceived(BMessage* message)
case MSG_SEARCH_TERMS_MODIFIED: case MSG_SEARCH_TERMS_MODIFIED:
{ {
BMessage searchTerms(MSG_SEARCH_TERMS_MODIFIED); BMessage searchTerms(MSG_SEARCH_TERMS_MODIFIED);
searchTerms.AddString("search terms", fSearchTermsText->Text()); searchTerms.AddString(filter_view_keys::kKeySearchTerms, fSearchTermsText->Text());
Window()->PostMessage(&searchTerms); Window()->PostMessage(&searchTerms);
break; break;
} }
@@ -146,7 +149,7 @@ FilterView::_MatchesCategoryCode(BMenuItem* item, const BString& code)
if (message == NULL) if (message == NULL)
return false; return false;
BString itemCode; BString itemCode;
message->FindString("code", &itemCode); message->FindString(shared_message_keys::kKeyCode, &itemCode);
return itemCode == code; return itemCode == code;
} }
@@ -159,7 +162,7 @@ FilterView::_AddCategoriesToMenu(Model& model, BMenu* menu)
for (it = categories.begin(); it != categories.end(); it++) { for (it = categories.begin(); it != categories.end(); it++) {
const CategoryRef& category = *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(shared_message_keys::kKeyCode, category->Code());
BMenuItem* item = new BMenuItem(category->Name(), message); BMenuItem* item = new BMenuItem(category->Name(), message);
menu->AddItem(item); menu->AddItem(item);
} }
+8 -1
View File
@@ -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-2026, 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 FILTER_VIEW_H #ifndef FILTER_VIEW_H
@@ -24,6 +24,13 @@ enum {
}; };
/*! Keys used with BMessages */
namespace filter_view_keys {
extern const char* const kKeySearchTerms;
}; // namespace filter_view_keys
class FilterView : public BGroupView { class FilterView : public BGroupView {
public: public:
FilterView(); FilterView();
+104 -54
View File
@@ -3,7 +3,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 2013, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2016-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2016-2026, Andrew Lindesay <apl@lindesay.co.nz>.
* Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>. * Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>.
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@@ -94,6 +94,18 @@ enum {
}; };
const char* const main_window_keys::kKeyWindowSettings = "window_settings";
static const char* const kKeyWorkStatusText = "work_status_text";
static const char* const kKeyWorkStatusProgress = "work_status_progress";
static const char* const kKeyWindowFrame = "window frame";
// use of spaces is historical
static const char* const kKeySinglePackageWindowFrame = "small window frame";
// use of spaces is historical
static const char* const kKeyColumnSettings = "column settings";
// use of spaces is historical
#define KEY_ERROR_STATUS "errorStatus" #define KEY_ERROR_STATUS "errorStatus"
const bigtime_t kIncrementViewCounterDelayMicros = 3 * 1000 * 1000; const bigtime_t kIncrementViewCounterDelayMicros = 3 * 1000 * 1000;
@@ -180,7 +192,7 @@ public:
private: private:
// PackageInfoListener // PackageInfoListener
virtual void PackagesChanged(const PackageInfoEvents& events) virtual void PackagesChanged(const PackageChangeEvents& events)
{ {
fMainWindow->PackagesChanged(events); fMainWindow->PackagesChanged(events);
} }
@@ -261,7 +273,7 @@ MainWindow::MainWindow(const BMessage& settings)
fModel.AddPackageListener(fPackageInfoListener); fModel.AddPackageListener(fPackageInfoListener);
BMessage columnSettings; BMessage columnSettings;
if (settings.FindMessage("column settings", &columnSettings) == B_OK) if (settings.FindMessage(kKeyColumnSettings, &columnSettings) == B_OK)
fPackageListView->LoadState(&columnSettings); fPackageListView->LoadState(&columnSettings);
_RestoreModelSettings(settings); _RestoreModelSettings(settings);
@@ -410,7 +422,7 @@ MainWindow::QuitRequested()
BMessage settings; BMessage settings;
StoreSettings(settings); StoreSettings(settings);
BMessage message(MSG_MAIN_WINDOW_CLOSED); BMessage message(MSG_MAIN_WINDOW_CLOSED);
message.AddMessage(KEY_WINDOW_SETTINGS, &settings); message.AddMessage(main_window_keys::kKeyWindowSettings, &settings);
be_app->PostMessage(&message); be_app->PostMessage(&message);
if (fShuttingDownWindow != NULL) { if (fShuttingDownWindow != NULL) {
@@ -573,7 +585,7 @@ MainWindow::MessageReceived(BMessage* message)
case MSG_SERVER_DATA_CHANGED: case MSG_SERVER_DATA_CHANGED:
{ {
BString name; BString name;
if (message->FindString("name", &name) == B_OK) { if (message->FindString(shared_message_keys::kKeyPackageName, &name) == B_OK) {
if (fPackageInfoView->Package()->Name() == name) { if (fPackageInfoView->Package()->Name() == name) {
_PopulatePackageAsync(true); _PopulatePackageAsync(true);
} else { } else {
@@ -592,7 +604,7 @@ MainWindow::MessageReceived(BMessage* message)
case MSG_PACKAGE_SELECTED: case MSG_PACKAGE_SELECTED:
{ {
BString name; BString name;
if (message->FindString("name", &name) == B_OK) { if (message->FindString(shared_message_keys::kKeyPackageName, &name) == B_OK) {
PackageInfoRef package; PackageInfoRef package;
package = fModel.PackageForName(name); package = fModel.PackageForName(name);
@@ -611,7 +623,7 @@ MainWindow::MessageReceived(BMessage* message)
case MSG_CATEGORY_SELECTED: case MSG_CATEGORY_SELECTED:
{ {
BString code; BString code;
if (message->FindString("code", &code) != B_OK) if (message->FindString(shared_message_keys::kKeyCode, &code) != B_OK)
code = ""; code = "";
fModel.SetFilterSpecification( fModel.SetFilterSpecification(
PackageFilterSpecificationBuilder(fModel.FilterSpecification()) PackageFilterSpecificationBuilder(fModel.FilterSpecification())
@@ -623,7 +635,7 @@ MainWindow::MessageReceived(BMessage* message)
case MSG_DEPOT_SELECTED: case MSG_DEPOT_SELECTED:
{ {
BString name; BString name;
if (message->FindString("name", &name) != B_OK) if (message->FindString(shared_message_keys::kKeyDepotName, &name) != B_OK)
name = ""; name = "";
fModel.SetFilterSpecification( fModel.SetFilterSpecification(
PackageFilterSpecificationBuilder(fModel.FilterSpecification()) PackageFilterSpecificationBuilder(fModel.FilterSpecification())
@@ -637,7 +649,7 @@ MainWindow::MessageReceived(BMessage* message)
{ {
// TODO: Do this with a delay! // TODO: Do this with a delay!
BString searchTerms; BString searchTerms;
if (message->FindString("search terms", &searchTerms) != B_OK) if (message->FindString(filter_view_keys::kKeySearchTerms, &searchTerms) != B_OK)
searchTerms = ""; searchTerms = "";
fModel.SetFilterSpecification( fModel.SetFilterSpecification(
PackageFilterSpecificationBuilder(fModel.FilterSpecification()) PackageFilterSpecificationBuilder(fModel.FilterSpecification())
@@ -657,6 +669,34 @@ MainWindow::MessageReceived(BMessage* message)
break; break;
} }
case MSG_PKG_INSTALL:
{
InstallPackageAction action(message);
ProcessCoordinator* coordinator
= ProcessCoordinatorFactory::CreateInstallPackageActionCoordinator(&fModel, action);
_AddProcessCoordinator(coordinator);
break;
}
case MSG_PKG_UNINSTALL:
{
UninstallPackageAction action(message);
ProcessCoordinator* coordinator
= ProcessCoordinatorFactory::CreateUninstallPackageActionCoordinator(&fModel,
action);
_AddProcessCoordinator(coordinator);
break;
}
case MSG_PKG_OPEN:
{
OpenPackageAction action(message);
ProcessCoordinator* coordinator
= ProcessCoordinatorFactory::CreateOpenPackageActionCoordinator(&fModel, action);
_AddProcessCoordinator(coordinator);
break;
}
case MSG_RATE_PACKAGE: case MSG_RATE_PACKAGE:
_RatePackage(); _RatePackage();
break; break;
@@ -723,13 +763,13 @@ MainWindow::StoreSettings(BMessage& settings)
{ {
settings.AddRect(_WindowFrameName(), Frame()); settings.AddRect(_WindowFrameName(), Frame());
if (!fSinglePackageMode) { if (!fSinglePackageMode) {
settings.AddRect("window frame", Frame()); settings.AddRect(kKeyWindowFrame, Frame());
BMessage columnSettings; BMessage columnSettings;
if (fPackageListView != NULL) if (fPackageListView != NULL)
fPackageListView->SaveState(&columnSettings); fPackageListView->SaveState(&columnSettings);
settings.AddMessage("column settings", &columnSettings); settings.AddMessage(kKeyColumnSettings, &columnSettings);
settings.AddString(SETTING_PACKAGE_LIST_VIEW_MODE, settings.AddString(SETTING_PACKAGE_LIST_VIEW_MODE,
main_window_package_list_view_mode_str(fModel.PackageListViewMode())); main_window_package_list_view_mode_str(fModel.PackageListViewMode()));
@@ -751,7 +791,7 @@ MainWindow::StoreSettings(BMessage& settings)
fModel.CanShareAnonymousUsageData()); fModel.CanShareAnonymousUsageData());
} }
settings.AddString("username", fModel.Nickname()); settings.AddString(SETTING_NICKNAME, fModel.Nickname());
} }
@@ -769,7 +809,7 @@ MainWindow::Consume(ProcessCoordinator* item)
in the GUI. in the GUI.
*/ */
void void
MainWindow::PackagesChanged(const PackageInfoEvents& events) MainWindow::PackagesChanged(const PackageChangeEvents& events)
{ {
BMessage message(MSG_PACKAGES_CHANGED); BMessage message(MSG_PACKAGES_CHANGED);
status_t result = events.Archive(&message); status_t result = events.Archive(&message);
@@ -788,32 +828,35 @@ MainWindow::PackagesChanged(const PackageInfoEvents& events)
void void
MainWindow::_HandlePackagesChanged(const BMessage* message) MainWindow::_HandlePackagesChanged(const BMessage* message)
{ {
PackageInfoEvents events; PackageChangeEvents packageEvents(message);
// Unpack the changes and at the same time marry them back up to the
// package from the model.
if (fModel.DearchiveInfoEvents(message, events) != B_OK) {
HDERROR("unable to de-archive the package info events");
return;
}
_HandlePackagesChanged(events);
}
void
MainWindow::_HandlePackagesChanged(const PackageInfoEvents& events)
{
// if there are no events to process then drop. // if there are no events to process then drop.
if (events.IsEmpty()) { if (packageEvents.IsEmpty()) {
HDINFO("window encountered an empty packages changed"); HDINFO("window encountered an empty packages changed");
return; return;
} }
HDTRACE("window processing %" B_PRIi32 " package changes", events.CountEvents()); HDTRACE("window processing %" B_PRIi32 " package changes", packageEvents.CountEvents());
// Transfer the package change events into package *info* change events so
// that the immutable PackageInfo instances can be used in the processing
// without having to continuously query the model causing lock overhead.
std::vector<PackageInfoChangeEvent> packageInfoEvents;
for (int32 i = packageEvents.CountEvents() - 1; i >= 0; i--) {
const PackageChangeEvent packageEvent = packageEvents.EventAtIndex(i);
const PackageInfoRef packageInfo = fModel.PackageForName(packageEvent.PackageName());
if (packageInfo.IsSet()) {
const PackageInfoChangeEvent packageInfoEvent(packageInfo, packageEvent.Changes());
packageInfoEvents.push_back(packageInfoEvent);
} else {
HDERROR("package [%s] from change event not found",
packageEvent.PackageName().String());
}
}
// now process the messages by adding and removing them from lists. // now process the messages by adding and removing them from lists.
@@ -826,14 +869,17 @@ MainWindow::_HandlePackagesChanged(const PackageInfoEvents& events)
std::vector<PackageInfoRef> addedFeaturedPackages; std::vector<PackageInfoRef> addedFeaturedPackages;
std::vector<PackageInfoRef> removedFeaturedPackages; std::vector<PackageInfoRef> removedFeaturedPackages;
for (int32 i = events.CountEvents() - 1; i >= 0; i--) { std::vector<PackageInfoChangeEvent>::const_iterator it;
const PackageInfoEvent event = events.EventAtIndex(i);
if (event.Changes() & watchedChanges) { for (it = packageInfoEvents.begin(); it != packageInfoEvents.end(); it++) {
const PackageInfoRef package = event.Package(); const PackageInfoChangeEvent packageInfoEvent = *it;
const bool isProminent = PackageUtils::IsProminent(package);
if (packageInfoEvent.Changes() & watchedChanges) {
const PackageInfoRef package = packageInfoEvent.Package();
if (package.IsSet()) { if (package.IsSet()) {
const bool isProminent = PackageUtils::IsProminent(package);
if (filter->AcceptsPackage(package)) { if (filter->AcceptsPackage(package)) {
addedPackages.push_back(package); addedPackages.push_back(package);
@@ -845,6 +891,9 @@ MainWindow::_HandlePackagesChanged(const PackageInfoEvents& events)
if (isProminent) if (isProminent)
removedFeaturedPackages.push_back(package); removedFeaturedPackages.push_back(package);
} }
} else {
HDFATAL("package change event for missing package");
// should have checked earlier so this is an illegal state
} }
} }
} }
@@ -859,11 +908,11 @@ MainWindow::_HandlePackagesChanged(const PackageInfoEvents& events)
// determine which packages are assigned. // determine which packages are assigned.
if (!fSinglePackageMode) { if (!fSinglePackageMode) {
fFeaturedPackagesView->HandlePackagesChanged(events); fFeaturedPackagesView->HandlePackagesChanged(packageInfoEvents);
fPackageListView->HandlePackagesChanged(events); fPackageListView->HandlePackagesChanged(packageInfoEvents);
} }
fPackageInfoView->HandlePackagesChanged(events); fPackageInfoView->HandlePackagesChanged(packageInfoEvents);
} }
@@ -954,7 +1003,7 @@ void
MainWindow::_RestoreNickname(const BMessage& settings) MainWindow::_RestoreNickname(const BMessage& settings)
{ {
BString nickname; BString nickname;
if (settings.FindString("username", &nickname) == B_OK && nickname.Length() > 0) { if (settings.FindString(SETTING_NICKNAME, &nickname) == B_OK && nickname.Length() > 0) {
UserCredentials credentials; UserCredentials credentials;
if (IdentityAndAccessUtils::RetrieveCredentials(nickname, credentials) == B_OK) { if (IdentityAndAccessUtils::RetrieveCredentials(nickname, credentials) == B_OK) {
fModel.SetCredentials(credentials); fModel.SetCredentials(credentials);
@@ -972,9 +1021,9 @@ const char*
MainWindow::_WindowFrameName() const MainWindow::_WindowFrameName() const
{ {
if (fSinglePackageMode) if (fSinglePackageMode)
return "small window frame"; return kKeySinglePackageWindowFrame;
return "window frame"; return kKeyWindowFrame;
} }
@@ -1173,7 +1222,7 @@ MainWindow::_SetupDelayedIncrementViewCounter(const PackageInfoRef package)
delete fIncrementViewCounterDelayedRunner; delete fIncrementViewCounterDelayedRunner;
} }
BMessage message(MSG_INCREMENT_VIEW_COUNTER); BMessage message(MSG_INCREMENT_VIEW_COUNTER);
message.SetString("name", package->Name()); message.SetString(shared_message_keys::kKeyPackageName, package->Name());
fIncrementViewCounterDelayedRunner fIncrementViewCounterDelayedRunner
= new BMessageRunner(BMessenger(this), &message, kIncrementViewCounterDelayMicros, 1); = new BMessageRunner(BMessenger(this), &message, kIncrementViewCounterDelayMicros, 1);
if (fIncrementViewCounterDelayedRunner->InitCheck() != B_OK) if (fIncrementViewCounterDelayedRunner->InitCheck() != B_OK)
@@ -1185,7 +1234,7 @@ void
MainWindow::_HandleIncrementViewCounter(const BMessage* message) MainWindow::_HandleIncrementViewCounter(const BMessage* message)
{ {
BString name; BString name;
if (message->FindString("name", &name) == B_OK) { if (message->FindString(shared_message_keys::kKeyPackageName, &name) == B_OK) {
const PackageInfoRef& viewedPackage = fPackageInfoView->Package(); const PackageInfoRef& viewedPackage = fPackageInfoView->Package();
if (viewedPackage.IsSet()) { if (viewedPackage.IsSet()) {
const BString& viewedPackageName = viewedPackage->Name(); const BString& viewedPackageName = viewedPackage->Name();
@@ -1294,12 +1343,12 @@ MainWindow::_BulkLoadCompleteReceived(status_t errorStatus)
PackagesSummary packagesSummary = fModel.GeneratePackagesSummary(); PackagesSummary packagesSummary = fModel.GeneratePackagesSummary();
if (errorStatus != B_OK) { if (errorStatus != B_OK) {
AppUtils::NotifySimpleError(B_TRANSLATE("Package update error"), AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Package update error"),
B_TRANSLATE("While updating package data, a problem has arisen " B_TRANSLATE("While updating package data, a problem has arisen "
"that may cause data to be outdated or missing from the " "that may cause data to be outdated or missing from the "
"application's display. Additional details regarding this " "application's display. Additional details regarding this "
"problem may be able to be obtained from the application " "problem may be able to be obtained from the application "
"logs." ALERT_MSG_LOGS_USER_GUIDE)); "logs." ALERT_MSG_LOGS_USER_GUIDE)));
} }
// after the bulk load concludes, if there are no desktop applications // after the bulk load concludes, if there are no desktop applications
@@ -1373,8 +1422,8 @@ MainWindow::_NotifyWorkStatusChange(const BString& text, float progress)
BMessage message(MSG_WORK_STATUS_CHANGE); BMessage message(MSG_WORK_STATUS_CHANGE);
if (!text.IsEmpty()) if (!text.IsEmpty())
message.AddString(KEY_WORK_STATUS_TEXT, text); message.AddString(kKeyWorkStatusText, text);
message.AddFloat(KEY_WORK_STATUS_PROGRESS, progress); message.AddFloat(kKeyWorkStatusProgress, progress);
this->PostMessage(&message, this); this->PostMessage(&message, this);
} }
@@ -1413,7 +1462,8 @@ MainWindow::_SetStateForPackagesByName(BStringList& packageNames, PackageState s
if (package.IsSet()) { if (package.IsSet()) {
PackageLocalInfoRef localInfo PackageLocalInfoRef localInfo
= PackageLocalInfoBuilder(package->LocalInfo()).WithState(state).BuildRef(); = PackageLocalInfoBuilder(package->LocalInfo()).WithState(state)
.ClearInstallationLocations().BuildRef();
modifiedPackages.push_back( modifiedPackages.push_back(
PackageInfoBuilder(package).WithLocalInfo(localInfo).BuildRef()); PackageInfoBuilder(package).WithLocalInfo(localInfo).BuildRef());
@@ -1439,10 +1489,10 @@ MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message)
BString text; BString text;
float progress; float progress;
if (message->FindString(KEY_WORK_STATUS_TEXT, &text) == B_OK) if (message->FindString(kKeyWorkStatusText, &text) == B_OK)
fWorkStatusView->SetText(text); fWorkStatusView->SetText(text);
if (message->FindFloat(KEY_WORK_STATUS_PROGRESS, &progress) == B_OK) { if (message->FindFloat(kKeyWorkStatusProgress, &progress) == B_OK) {
if (progress < 0.0f) if (progress < 0.0f)
fWorkStatusView->SetBusy(); fWorkStatusView->SetBusy();
else else
@@ -1590,7 +1640,7 @@ MainWindow::_UpdateAvailableRepositories()
if (depot->Name().Length() != 0) { if (depot->Name().Length() != 0) {
BMessage* message = new BMessage(MSG_DEPOT_SELECTED); BMessage* message = new BMessage(MSG_DEPOT_SELECTED);
message->AddString("name", depot->Name()); message->AddString(shared_message_keys::kKeyDepotName, depot->Name());
BMenuItem* item = new(std::nothrow) BMenuItem(depot->Name(), message); BMenuItem* item = new(std::nothrow) BMenuItem(depot->Name(), message);
if (item == NULL) if (item == NULL)
@@ -1709,7 +1759,7 @@ MainWindow::UserCredentialsFailed()
"and you should login again with your updated password."); "and you should login again with your updated password.");
message.ReplaceAll("%Nickname%", fModel.Nickname()); message.ReplaceAll("%Nickname%", fModel.Nickname());
AppUtils::NotifySimpleError(B_TRANSLATE("Login issue"), message); AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Login issue"), message));
if (IdentityAndAccessUtils::ClearCredentials() != B_OK) if (IdentityAndAccessUtils::ClearCredentials() != B_OK)
HDERROR("unable to remove stored credentials"); HDERROR("unable to remove stored credentials");
+11 -3
View File
@@ -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-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2017-2026, 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
@@ -38,6 +38,14 @@ class WorkStatusView;
enum PackageDesktopFilterMode { DESKTOP, NATIVE_DESKTOP, DESKTOP_AND_NON_DESKTOP }; enum PackageDesktopFilterMode { DESKTOP, NATIVE_DESKTOP, DESKTOP_AND_NON_DESKTOP };
/*! Keys used with BMessages */
namespace main_window_keys {
extern const char* const kKeyWindowSettings;
}; // namespace main_window_keys
class MainWindow : class MainWindow :
private ProcessCoordinatorConsumer, public ProcessCoordinatorListener, private ProcessCoordinatorConsumer, public ProcessCoordinatorListener,
public UserDetailVerifierListener, public BWindow { public UserDetailVerifierListener, public BWindow {
@@ -66,7 +74,7 @@ public:
const UserDetail& userDetail); const UserDetail& userDetail);
// services PackageInfoListener via MainWindowPackageInfoListener // services PackageInfoListener via MainWindowPackageInfoListener
void PackagesChanged(const PackageInfoEvents& events); void PackagesChanged(const PackageChangeEvents& events);
private: private:
static const BString _WindowTitleForPackage(const PackageInfoRef& pkg); static const BString _WindowTitleForPackage(const PackageInfoRef& pkg);
@@ -128,7 +136,7 @@ private:
ProcessCoordinatorState& coordinatorState); ProcessCoordinatorState& coordinatorState);
void _HandlePackagesChanged(const BMessage* message); void _HandlePackagesChanged(const BMessage* message);
void _HandlePackagesChanged(const PackageInfoEvents& events); void _HandlePackagesChanged(const PackageChangeEvents& 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);
+11 -37
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2018-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2018-2026, 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 "PackageInfoView.h" #include "PackageInfoView.h"
@@ -506,13 +506,10 @@ private:
class PackageActionView : public BView { class PackageActionView : public BView {
public: public:
PackageActionView(ProcessCoordinatorConsumer* processCoordinatorConsumer, PackageActionView()
Model* model)
: :
BView("about view", B_WILL_DRAW), BView("about view", B_WILL_DRAW),
fModel(model),
fLayout(new BGroupLayout(B_HORIZONTAL)), fLayout(new BGroupLayout(B_HORIZONTAL)),
fProcessCoordinatorConsumer(processCoordinatorConsumer),
fStatusLabel(NULL), fStatusLabel(NULL),
fStatusBar(NULL) fStatusBar(NULL)
{ {
@@ -526,20 +523,6 @@ public:
Clear(); Clear();
} }
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_PKG_INSTALL:
case MSG_PKG_UNINSTALL:
case MSG_PKG_OPEN:
_RunPackageAction(message);
break;
default:
BView::MessageReceived(message);
break;
}
}
void SetPackage(const PackageInfoRef package) void SetPackage(const PackageInfoRef package)
{ {
if (PackageUtils::State(package) == DOWNLOADING) if (PackageUtils::State(package) == DOWNLOADING)
@@ -626,6 +609,7 @@ private:
BButton* button = (BButton*)fButtons.ItemAtFast(index++); BButton* button = (BButton*)fButtons.ItemAtFast(index++);
button->SetLabel(action->Title()); button->SetLabel(action->Title());
button->SetMessage(message); button->SetMessage(message);
button->SetTarget(Window());
} }
} }
@@ -637,7 +621,7 @@ private:
BButton* button = new BButton(action->Title(), message); BButton* button = new BButton(action->Title(), message);
fLayout->AddView(button); fLayout->AddView(button);
button->SetTarget(this); button->SetTarget(this);
button->SetTarget(Window());
fButtons.AddItem(button); fButtons.AddItem(button);
} }
} }
@@ -666,19 +650,8 @@ private:
} }
} }
void _RunPackageAction(BMessage* message)
{
ProcessCoordinator* processCoordinator
= ProcessCoordinatorFactory::CreatePackageActionCoordinator(fModel, message);
fProcessCoordinatorConsumer->Consume(processCoordinator);
_DisableButtonForPackageActionMessage(message);
}
private: private:
Model* fModel;
BGroupLayout* fLayout; BGroupLayout* fLayout;
ProcessCoordinatorConsumer*
fProcessCoordinatorConsumer;
BList fButtons; BList fButtons;
BStringView* fStatusLabel; BStringView* fStatusLabel;
@@ -1352,7 +1325,7 @@ PackageInfoView::PackageInfoView(Model* model,
fCardLayout->SetVisibleItem((int32)0); fCardLayout->SetVisibleItem((int32)0);
fTitleView = new TitleView(fModel); fTitleView = new TitleView(fModel);
fPackageActionView = new PackageActionView(processCoordinatorConsumer, model); fPackageActionView = new PackageActionView();
fPackageActionView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); fPackageActionView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
fPagesView = new PagesView(model); fPagesView = new PagesView(model);
@@ -1422,7 +1395,7 @@ PackageInfoView::SetPackage(const PackageInfoRef& packageRef)
void void
PackageInfoView::_HandlePackageChanged(const PackageInfoEvent& event) PackageInfoView::_HandlePackageChanged(const PackageInfoChangeEvent& event)
{ {
uint32 changes = event.Changes(); uint32 changes = event.Changes();
@@ -1453,13 +1426,14 @@ PackageInfoView::_HandlePackageChanged(const PackageInfoEvent& event)
void void
PackageInfoView::HandlePackagesChanged(const PackageInfoEvents& events) PackageInfoView::HandlePackagesChanged(const std::vector<PackageInfoChangeEvent>& events)
{ {
if (!fPackage.IsSet()) if (!fPackage.IsSet())
return; return;
for (int32 i = events.CountEvents() - 1; i >= 0; i--) { std::vector<PackageInfoChangeEvent>::const_iterator it;
PackageInfoEvent event = events.EventAtIndex(i); for (it = events.begin(); it != events.end(); it++) {
_HandlePackageChanged(event); const PackageInfoChangeEvent packageInfoChangeEvent = *it;
_HandlePackageChanged(packageInfoChangeEvent);
} }
} }
+6 -3
View File
@@ -1,11 +1,13 @@
/* /*
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz> * Copyright 2020-2026, 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_INFO_VIEW_H #ifndef PACKAGE_INFO_VIEW_H
#define PACKAGE_INFO_VIEW_H #define PACKAGE_INFO_VIEW_H
#include <vector>
#include <GroupView.h> #include <GroupView.h>
#include "Model.h" #include "Model.h"
@@ -43,7 +45,8 @@ public:
void HandleScreenshotCached(const ScreenshotCoordinate& coordinate); void HandleScreenshotCached(const ScreenshotCoordinate& coordinate);
void HandleIconsChanged(); void HandleIconsChanged();
void HandlePackagesChanged(const PackageInfoEvents& events); void HandlePackagesChanged(
const std::vector<PackageInfoChangeEvent>& events);
private: private:
static const ScreenshotCoordinate static const ScreenshotCoordinate
@@ -52,7 +55,7 @@ private:
void _HandleScreenshotCached(const PackageInfoRef& package, void _HandleScreenshotCached(const PackageInfoRef& package,
const ScreenshotCoordinate& coordinate); const ScreenshotCoordinate& coordinate);
void _HandlePackageChanged(const PackageInfoEvent& event); void _HandlePackageChanged(const PackageInfoChangeEvent& event);
private: private:
Model* fModel; Model* fModel;
+8 -7
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2025, Andrew Lindesay, <apl@lindesay.co.nz>. * Copyright 2018-2026, Andrew Lindesay, <apl@lindesay.co.nz>.
* Copyright 2017, Julian Harnath, <julian.harnath@rwth-aachen.de>. * Copyright 2017, Julian Harnath, <julian.harnath@rwth-aachen.de>.
* Copyright 2015, Axel Dörfler, <axeld@pinc-software.de>. * Copyright 2015, Axel Dörfler, <axeld@pinc-software.de>.
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
@@ -1167,18 +1167,19 @@ PackageListView::HandleIconsChanged()
void void
PackageListView::HandlePackagesChanged(const PackageInfoEvents& events) PackageListView::HandlePackagesChanged(const std::vector<PackageInfoChangeEvent>& events)
{ {
for (int32 i = events.CountEvents() - 1; i >= 0; i--) std::vector<PackageInfoChangeEvent>::const_iterator it;
_HandlePackageChanged(events.EventAtIndex(i)); for (it = events.begin(); it != events.end(); it++)
_HandlePackageChanged(*it);
} }
void void
PackageListView::_HandlePackageChanged(const PackageInfoEvent& event) PackageListView::_HandlePackageChanged(const PackageInfoChangeEvent& event)
{ {
uint32 changes = event.Changes(); uint32 changes = event.Changes();
PackageInfoRef package = event.Package(); const PackageInfoRef package = event.Package();
if (!package.IsSet() || 0 == changes) if (!package.IsSet() || 0 == changes)
return; return;
@@ -1221,7 +1222,7 @@ PackageListView::SelectionChanged()
PackageRow* selected = dynamic_cast<PackageRow*>(CurrentSelection()); PackageRow* selected = dynamic_cast<PackageRow*>(CurrentSelection());
if (selected != NULL) if (selected != NULL)
message.AddString("name", selected->Package()->Name()); message.AddString(shared_message_keys::kKeyPackageName, selected->Package()->Name());
Window()->PostMessage(&message); Window()->PostMessage(&message);
} }
+4 -3
View File
@@ -1,7 +1,7 @@
/* /*
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2013, Rene Gollent <rene@gollent.com>. * Copyright 2013, Rene Gollent <rene@gollent.com>.
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz> * Copyright 2020-2026, 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_LIST_VIEW_H #ifndef PACKAGE_LIST_VIEW_H
@@ -41,10 +41,11 @@ public:
void AttachWorkStatusView(WorkStatusView* view); void AttachWorkStatusView(WorkStatusView* view);
void HandleIconsChanged(); void HandleIconsChanged();
void HandlePackagesChanged(const PackageInfoEvents& events); void HandlePackagesChanged(
const std::vector<PackageInfoChangeEvent>& events);
private: private:
void _HandlePackageChanged(const PackageInfoEvent& event); void _HandlePackageChanged(const PackageInfoChangeEvent& event);
void _AddPackage(const PackageInfoRef& package); void _AddPackage(const PackageInfoRef& package);
void _RemovePackage(const PackageInfoRef& package); void _RemovePackage(const PackageInfoRef& package);
+10 -7
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2016-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2016-2026, 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.
*/ */
@@ -46,6 +46,9 @@ enum {
MSG_RATING_DETERMINATE_CHANGED = 'rdch' MSG_RATING_DETERMINATE_CHANGED = 'rdch'
}; };
static const char* const kKeyRating = "rating";
//! Layouts the scrollbar so it looks nice with no border and the document //! Layouts the scrollbar so it looks nice with no border and the document
// window look. // window look.
class ScrollView : public BScrollView { class ScrollView : public BScrollView {
@@ -130,7 +133,7 @@ public:
{ {
SetPermanentRating(_RatingForMousePos(where)); SetPermanentRating(_RatingForMousePos(where));
BMessage message(MSG_PACKAGE_RATED); BMessage message(MSG_PACKAGE_RATED);
message.AddFloat("rating", fPermanentRating); message.AddFloat(kKeyRating, fPermanentRating);
Window()->PostMessage(&message, Window()); Window()->PostMessage(&message, Window());
} }
@@ -286,7 +289,7 @@ RatePackageWindow::_InitStabilitiesMenu(BPopUpMenu* menu)
for (it = ratingStabilities.begin(); it != ratingStabilities.end(); it++) { for (it = ratingStabilities.begin(); it != ratingStabilities.end(); it++) {
const RatingStabilityRef ratingStability = *it; const RatingStabilityRef ratingStability = *it;
BMessage* message = new BMessage(MSG_STABILITY_SELECTED); BMessage* message = new BMessage(MSG_STABILITY_SELECTED);
message->AddString("code", ratingStability->Code()); message->AddString(shared_message_keys::kKeyCode, ratingStability->Code());
BMenuItem* item = new BMenuItem(ratingStability->Name(), message); BMenuItem* item = new BMenuItem(ratingStability->Name(), message);
menu->AddItem(item); menu->AddItem(item);
} }
@@ -301,18 +304,18 @@ RatePackageWindow::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case MSG_PACKAGE_RATED: case MSG_PACKAGE_RATED:
message->FindFloat("rating", &fRating); message->FindFloat(kKeyRating, &fRating);
fRatingDeterminate = true; fRatingDeterminate = true;
fSetRatingView->SetRatingDeterminate(true); fSetRatingView->SetRatingDeterminate(true);
fRatingDeterminateCheckBox->SetValue(B_CONTROL_ON); fRatingDeterminateCheckBox->SetValue(B_CONTROL_ON);
break; break;
case MSG_STABILITY_SELECTED: case MSG_STABILITY_SELECTED:
message->FindString("code", &fStabilityCode); message->FindString(shared_message_keys::kKeyCode, &fStabilityCode);
break; break;
case MSG_LANGUAGE_SELECTED: case MSG_LANGUAGE_SELECTED:
message->FindString("id", &fCommentLanguageId); message->FindString(shared_message_keys::kKeyLanguageId, &fCommentLanguageId);
break; break;
case MSG_RATING_DETERMINATE_CHANGED: case MSG_RATING_DETERMINATE_CHANGED:
@@ -369,7 +372,7 @@ void
RatePackageWindow::_RefreshPackageData() RatePackageWindow::_RefreshPackageData()
{ {
BMessage message(MSG_SERVER_DATA_CHANGED); BMessage message(MSG_SERVER_DATA_CHANGED);
message.AddString("name", fPackage->Name()); message.AddString(shared_message_keys::kKeyPackageName, fPackage->Name());
be_app->PostMessage(&message); be_app->PostMessage(&message);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2020-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2020-2026, Andrew Lindesay <apl@lindesay.co.nz>.
* Copyright 2024 Haiku, Inc. All rights reserved. * Copyright 2024 Haiku, Inc. All rights reserved.
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@@ -305,9 +305,9 @@ ToLatestUserUsageConditionsWindow::_FetchDataPerform()
void void
ToLatestUserUsageConditionsWindow::_NotifyFetchProblem() ToLatestUserUsageConditionsWindow::_NotifyFetchProblem()
{ {
AppUtils::NotifySimpleError(B_TRANSLATE("Usage conditions download problem"), AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Usage conditions download problem"),
B_TRANSLATE("An error has arisen downloading the usage conditions. Check the log for " B_TRANSLATE("An error has arisen downloading the usage conditions. Check the log for "
"details and try again. " ALERT_MSG_LOGS_USER_GUIDE)); "details and try again. " ALERT_MSG_LOGS_USER_GUIDE)));
} }
@@ -358,8 +358,8 @@ ToLatestUserUsageConditionsWindow::_AgreePerform()
} else { } else {
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(responsePayload); int32 errorCode = WebAppInterface::ErrorCodeFromResponse(responsePayload);
if (errorCode == ERROR_CODE_NONE) { if (errorCode == ERROR_CODE_NONE) {
AppUtils::NotifySimpleError(B_TRANSLATE("Usage conditions agreed"), AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Usage conditions agreed"),
B_TRANSLATE("The current usage conditions have been agreed to.")); B_TRANSLATE("The current usage conditions have been agreed to.")));
messenger.SendMessage(B_QUIT_REQUESTED); messenger.SendMessage(B_QUIT_REQUESTED);
} else { } else {
ServerHelper::NotifyServerJsonRpcError(responsePayload); ServerHelper::NotifyServerJsonRpcError(responsePayload);
+39 -37
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2019-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2019-2026, 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.
*/ */
@@ -48,11 +48,11 @@
#define PLACEHOLDER_TEXT B_UTF8_ELLIPSIS #define PLACEHOLDER_TEXT B_UTF8_ELLIPSIS
#define KEY_USER_CREDENTIALS "userCredentials" static const char* const kKeyUserCredentials = "user_credentials";
#define KEY_CAPTCHA_IMAGE "captchaImage" static const char* const kKeyCaptchaImage = "captcha_image";
#define KEY_USER_USAGE_CONDITIONS "userUsageConditions" static const char* const kKeyUserUsageConditions = "user_usage_conditions";
#define KEY_PASSWORD_REQUIREMENTS "passwordRequirements" static const char* const kKeyPasswordRequirements = "password_requirements";
#define KEY_VALIDATION_FAILURES "validationFailures" static const char* const kKeyValidationFailures = "validation_failures";
enum ActionTabs { enum ActionTabs {
@@ -305,7 +305,7 @@ UserLoginWindow::MessageReceived(BMessage* message)
break; break;
case MSG_LANGUAGE_SELECTED: case MSG_LANGUAGE_SELECTED:
message->FindString("id", &fPreferredLanguageId); message->FindString(shared_message_keys::kKeyLanguageId, &fPreferredLanguageId);
break; break;
case MSG_LOGIN_ERROR: case MSG_LOGIN_ERROR:
@@ -319,7 +319,7 @@ UserLoginWindow::MessageReceived(BMessage* message)
case MSG_LOGIN_SUCCESS: case MSG_LOGIN_SUCCESS:
{ {
BMessage credentialsMessage; BMessage credentialsMessage;
if (message->FindMessage(KEY_USER_CREDENTIALS, &credentialsMessage) != B_OK) if (message->FindMessage(kKeyUserCredentials, &credentialsMessage) != B_OK)
debugger("expected key in internal message not found"); debugger("expected key in internal message not found");
_HandleAuthenticationSuccess(UserCredentials(&credentialsMessage)); _HandleAuthenticationSuccess(UserCredentials(&credentialsMessage));
@@ -328,7 +328,7 @@ UserLoginWindow::MessageReceived(BMessage* message)
case MSG_CREATE_ACCOUNT_SUCCESS: case MSG_CREATE_ACCOUNT_SUCCESS:
{ {
BMessage credentialsMessage; BMessage credentialsMessage;
if (message->FindMessage(KEY_USER_CREDENTIALS, &credentialsMessage) != B_OK) if (message->FindMessage(kKeyUserCredentials, &credentialsMessage) != B_OK)
debugger("expected key in internal message not found"); debugger("expected key in internal message not found");
_HandleCreateAccountSuccess(UserCredentials(&credentialsMessage)); _HandleCreateAccountSuccess(UserCredentials(&credentialsMessage));
@@ -337,7 +337,7 @@ UserLoginWindow::MessageReceived(BMessage* message)
case MSG_CREATE_ACCOUNT_FAILED: case MSG_CREATE_ACCOUNT_FAILED:
{ {
BMessage validationFailuresMessage; BMessage validationFailuresMessage;
if (message->FindMessage(KEY_VALIDATION_FAILURES, &validationFailuresMessage) != B_OK) if (message->FindMessage(kKeyValidationFailures, &validationFailuresMessage) != B_OK)
debugger("expected key in internal message not found"); debugger("expected key in internal message not found");
ValidationFailures validationFailures(&validationFailuresMessage); ValidationFailures validationFailures(&validationFailuresMessage);
_HandleCreateAccountFailure(validationFailures); _HandleCreateAccountFailure(validationFailures);
@@ -530,7 +530,7 @@ UserLoginWindow::_AuthenticateThread(UserCredentials& userCredentials)
BMessage credentialsMessage; BMessage credentialsMessage;
status = userCredentials.Archive(&credentialsMessage); status = userCredentials.Archive(&credentialsMessage);
if (status == B_OK) if (status == B_OK)
status = message.AddMessage(KEY_USER_CREDENTIALS, &credentialsMessage); status = message.AddMessage(kKeyUserCredentials, &credentialsMessage);
if (status == B_OK) if (status == B_OK)
messenger.SendMessage(&message); messenger.SendMessage(&message);
} else { } else {
@@ -578,9 +578,9 @@ UserLoginWindow::_HandleAuthenticationError()
void void
UserLoginWindow::_HandleAuthenticationFailed() UserLoginWindow::_HandleAuthenticationFailed()
{ {
AppUtils::NotifySimpleError(B_TRANSLATE("Authentication failed"), AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Authentication failed"),
B_TRANSLATE("The user does not exist or the wrong password was" B_TRANSLATE("The user does not exist or the wrong password was"
" supplied. Check your credentials and try again.")); " supplied. Check your credentials and try again.")));
fPasswordField->SetText(""); fPasswordField->SetText("");
_EnableMutableControls(true); _EnableMutableControls(true);
} }
@@ -737,21 +737,19 @@ UserLoginWindow::_CreateAccountSetupThreadEntry(void* data)
BMessage captchaMessage; BMessage captchaMessage;
result = captcha.Archive(&captchaMessage); result = captcha.Archive(&captchaMessage);
if (result == B_OK) if (result == B_OK)
result = message.AddMessage(KEY_CAPTCHA_IMAGE, &captchaMessage); result = message.AddMessage(kKeyCaptchaImage, &captchaMessage);
} }
if (result == B_OK && shouldFetchUserUsageConditions) { if (result == B_OK && shouldFetchUserUsageConditions) {
BMessage userUsageConditionsMessage; BMessage userUsageConditionsMessage;
result = userUsageConditions.Archive(&userUsageConditionsMessage); result = userUsageConditions.Archive(&userUsageConditionsMessage);
if (result == B_OK) if (result == B_OK)
result = message.AddMessage(KEY_USER_USAGE_CONDITIONS, &userUsageConditionsMessage); result = message.AddMessage(kKeyUserUsageConditions, &userUsageConditionsMessage);
} }
if (result == B_OK && shouldFetchPasswordRequirements) { if (result == B_OK && shouldFetchPasswordRequirements) {
BMessage passwordRequirementsMessage; BMessage passwordRequirementsMessage;
result = passwordRequirements.Archive(&passwordRequirementsMessage); result = passwordRequirements.Archive(&passwordRequirementsMessage);
if (result == B_OK) { if (result == B_OK)
result result = message.AddMessage(kKeyPasswordRequirements, &passwordRequirementsMessage);
= message.AddMessage(KEY_PASSWORD_REQUIREMENTS, &passwordRequirementsMessage);
}
} }
if (result == B_OK) { if (result == B_OK) {
HDDEBUG("successfully completed collection of create account " HDDEBUG("successfully completed collection of create account "
@@ -783,10 +781,10 @@ UserLoginWindow::_CreateAccountUserUsageConditionsSetupThread(
status_t result = interface->RetrieveUserUsageConditions(NULL, userUsageConditions); status_t result = interface->RetrieveUserUsageConditions(NULL, userUsageConditions);
if (result != B_OK) { if (result != B_OK) {
AppUtils::NotifySimpleError(B_TRANSLATE("Usage conditions download problem"), AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Usage conditions download problem"),
B_TRANSLATE("An error has arisen downloading the usage " B_TRANSLATE("An error has arisen downloading the usage "
"conditions required to create a new user. Check the log for " "conditions required to create a new user. Check the log for "
"details and try again. " ALERT_MSG_LOGS_USER_GUIDE)); "details and try again. " ALERT_MSG_LOGS_USER_GUIDE)));
} }
return result; return result;
@@ -801,10 +799,11 @@ UserLoginWindow::_CreateAccountPasswordRequirementsSetupThread(
status_t result = interface->RetrievePasswordRequirements(passwordRequirements); status_t result = interface->RetrievePasswordRequirements(passwordRequirements);
if (result != B_OK) { if (result != B_OK) {
AppUtils::NotifySimpleError(B_TRANSLATE("Password requirements download problem"), AppUtils::NotifySimpleError(
B_TRANSLATE("An error has arisen downloading the password " SimpleAlert(B_TRANSLATE("Password requirements download problem"),
"requirements required to create a new user. Check the log for " B_TRANSLATE("An error has arisen downloading the password requirements required to "
"details and try again. " ALERT_MSG_LOGS_USER_GUIDE)); "create a new user. Check the log for details and try "
"again. " ALERT_MSG_LOGS_USER_GUIDE)));
} }
return result; return result;
@@ -822,9 +821,9 @@ UserLoginWindow::_CreateAccountCaptchaSetupThread(Captcha& captcha)
// check for transport related errors. // check for transport related errors.
if (status != B_OK) { if (status != B_OK) {
AppUtils::NotifySimpleError(B_TRANSLATE("Captcha error"), AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Captcha error"),
B_TRANSLATE("It was not possible to communicate with the server to " B_TRANSLATE("It was not possible to communicate with the server to "
"obtain a captcha image required to create a new user.")); "obtain a captcha image required to create a new user.")));
} }
// check for server-generated errors. // check for server-generated errors.
@@ -841,9 +840,9 @@ UserLoginWindow::_CreateAccountCaptchaSetupThread(Captcha& captcha)
if (status == B_OK) { if (status == B_OK) {
status = _UnpackCaptcha(responsePayload, captcha); status = _UnpackCaptcha(responsePayload, captcha);
if (status != B_OK) { if (status != B_OK) {
AppUtils::NotifySimpleError(B_TRANSLATE("Captcha error"), AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Captcha error"),
B_TRANSLATE("It was not possible to extract necessary captcha " B_TRANSLATE("It was not possible to extract necessary captcha "
"information from the data sent back from the server.")); "information from the data sent back from the server.")));
} }
} }
@@ -910,13 +909,13 @@ UserLoginWindow::_HandleCreateAccountSetupSuccess(BMessage* message)
BMessage userUsageConditionsMessage; BMessage userUsageConditionsMessage;
BMessage passwordRequirementsMessage; BMessage passwordRequirementsMessage;
if (message->FindMessage(KEY_CAPTCHA_IMAGE, &captchaMessage) == B_OK) if (message->FindMessage(kKeyCaptchaImage, &captchaMessage) == B_OK)
_SetCaptcha(new Captcha(&captchaMessage)); _SetCaptcha(new Captcha(&captchaMessage));
if (message->FindMessage(KEY_USER_USAGE_CONDITIONS, &userUsageConditionsMessage) == B_OK) if (message->FindMessage(kKeyUserUsageConditions, &userUsageConditionsMessage) == B_OK)
_SetUserUsageConditions(new UserUsageConditions(&userUsageConditionsMessage)); _SetUserUsageConditions(new UserUsageConditions(&userUsageConditionsMessage));
if (message->FindMessage(KEY_PASSWORD_REQUIREMENTS, &passwordRequirementsMessage) == B_OK) if (message->FindMessage(kKeyPasswordRequirements, &passwordRequirementsMessage) == B_OK)
_SetPasswordRequirements(new PasswordRequirements(&passwordRequirementsMessage)); _SetPasswordRequirements(new PasswordRequirements(&passwordRequirementsMessage));
_EnableMutableControls(true); _EnableMutableControls(true);
@@ -1243,6 +1242,9 @@ UserLoginWindow::_CreateAccountThreadEntry(void* data)
void void
UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail) UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
{ {
if (detail->LanguageId().IsEmpty())
HDFATAL("the language id was not setup when creating a user");
WebAppInterfaceRef interface = fModel.WebApp(); WebAppInterfaceRef interface = fModel.WebApp();
BMessage responsePayload; BMessage responsePayload;
BMessenger messenger(this); BMessenger messenger(this);
@@ -1263,7 +1265,7 @@ UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
UserCredentials userCredentials(detail->Nickname(), detail->PasswordClear()); UserCredentials userCredentials(detail->Nickname(), detail->PasswordClear());
userCredentials.Archive(&userCredentialsMessage); userCredentials.Archive(&userCredentialsMessage);
BMessage message(MSG_CREATE_ACCOUNT_SUCCESS); BMessage message(MSG_CREATE_ACCOUNT_SUCCESS);
message.AddMessage(KEY_USER_CREDENTIALS, &userCredentialsMessage); message.AddMessage(kKeyUserCredentials, &userCredentialsMessage);
messenger.SendMessage(&message); messenger.SendMessage(&message);
break; break;
} }
@@ -1274,7 +1276,7 @@ UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
BMessage validationFailuresMessage; BMessage validationFailuresMessage;
validationFailures.Archive(&validationFailuresMessage); validationFailures.Archive(&validationFailuresMessage);
BMessage message(MSG_CREATE_ACCOUNT_FAILED); BMessage message(MSG_CREATE_ACCOUNT_FAILED);
message.AddMessage(KEY_VALIDATION_FAILURES, &validationFailuresMessage); message.AddMessage(kKeyValidationFailures, &validationFailuresMessage);
messenger.SendMessage(&message); messenger.SendMessage(&message);
break; break;
} }
@@ -1290,7 +1292,7 @@ UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
BMessage validationFailuresMessage; BMessage validationFailuresMessage;
validationFailures.Archive(&validationFailuresMessage); validationFailures.Archive(&validationFailuresMessage);
BMessage message(MSG_CREATE_ACCOUNT_FAILED); BMessage message(MSG_CREATE_ACCOUNT_FAILED);
message.AddMessage(KEY_VALIDATION_FAILURES, &validationFailuresMessage); message.AddMessage(kKeyValidationFailures, &validationFailuresMessage);
messenger.SendMessage(&message); messenger.SendMessage(&message);
break; break;
} }
@@ -1300,8 +1302,8 @@ UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
break; break;
} }
} else { } else {
AppUtils::NotifySimpleError(B_TRANSLATE("User creation error"), AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("User creation error"),
B_TRANSLATE("It was not possible to create the new user.")); B_TRANSLATE("It was not possible to create the new user.")));
messenger.SendMessage(MSG_CREATE_ACCOUNT_ERROR); messenger.SendMessage(MSG_CREATE_ACCOUNT_ERROR);
} }
} }
@@ -280,7 +280,7 @@ UserUsageConditionsWindow::_FetchDataPerform()
BString message = B_TRANSLATE("The user '%Nickname%' has not agreed to any usage " BString message = B_TRANSLATE("The user '%Nickname%' has not agreed to any usage "
"conditions."); "conditions.");
message.ReplaceAll("%Nickname%", userDetail.Nickname()); message.ReplaceAll("%Nickname%", userDetail.Nickname());
AppUtils::NotifySimpleError(B_TRANSLATE("No usage conditions"), message); AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("No usage conditions"), message));
BMessenger(this).SendMessage(B_QUIT_REQUESTED); BMessenger(this).SendMessage(B_QUIT_REQUESTED);
status = B_BAD_DATA; status = B_BAD_DATA;
} }
@@ -378,10 +378,10 @@ UserUsageConditionsWindow::_FetchUserUsageConditionsCodeForUserPerform(UserDetai
void void
UserUsageConditionsWindow::_NotifyFetchProblem() UserUsageConditionsWindow::_NotifyFetchProblem()
{ {
AppUtils::NotifySimpleError(B_TRANSLATE("Usage conditions download problem"), AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Usage conditions download problem"),
B_TRANSLATE( B_TRANSLATE(
"An error has arisen downloading the usage " "An error has arisen downloading the usage "
"conditions. Check the log for details and try again. " ALERT_MSG_LOGS_USER_GUIDE)); "conditions. Check the log for details and try again. " ALERT_MSG_LOGS_USER_GUIDE)));
} }
+5 -12
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2024, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2018-2026, 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,19 +23,12 @@
*/ */
/*static*/ void /*static*/ void
AppUtils::NotifySimpleError(const char* title, const char* text, AppUtils::NotifySimpleError(const SimpleAlert& alertSimple)
alert_type type)
{ {
BMessage message(MSG_ALERT_SIMPLE_ERROR); BMessage message(MSG_ALERT_SIMPLE_ERROR);
if (alertSimple.Archive(&message) != B_OK)
if (title != NULL && strlen(title) != 0) HDERROR("unable to archive alert");
message.AddString(KEY_ALERT_TITLE, title); else
if (text != NULL && strlen(text) != 0)
message.AddString(KEY_ALERT_TEXT, text);
message.AddInt32(KEY_ALERT_TYPE, static_cast<int>(type));
be_app->PostMessage(&message); be_app->PostMessage(&message);
} }
+3 -4
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2024, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2018-2026, 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 APP_UTILS_H #ifndef APP_UTILS_H
@@ -8,14 +8,13 @@
#include "Alert.h" #include "Alert.h"
#include "Menu.h" #include "Menu.h"
#include "SimpleAlert.h"
class AppUtils { class AppUtils {
public: public:
static void NotifySimpleError(const char* title, static void NotifySimpleError(const SimpleAlert& simpleAlert);
const char* text,
alert_type type = B_INFO_ALERT);
static status_t MarkItemWithKeyValueInMenuOrFirst(BMenu* menu, static status_t MarkItemWithKeyValueInMenuOrFirst(BMenu* menu,
const BString& key, const BString& value); const BString& key, const BString& value);
@@ -1,5 +1,5 @@
/* /*
* Copyright 2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2025-2026, 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.
*/ */
@@ -12,9 +12,9 @@
#include "Logger.h" #include "Logger.h"
static const char* kHaikuDepotKeyring = "HaikuDepot"; static const char* const kHaikuDepotKeyring = "HaikuDepot";
static const char* kKeyIdentifierPrefix = "hds.password."; static const char* const kKeyIdentifierPrefix = "hds.password.";
// this prefix is added before the nickname in the keystore // this prefix is added before the nickname in the keystore
// so that HDS username/password pairs can be identified. // so that HDS username/password pairs can be identified.
@@ -1,5 +1,5 @@
/* /*
* Copyright 2019-2025, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2019-2026, 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 "LanguageMenuUtils.h" #include "LanguageMenuUtils.h"
@@ -19,9 +19,6 @@
#include "Logger.h" #include "Logger.h"
static const char* kLanguageIdKey = "id";
/*! This method will add the supplied languages to the menu. It will /*! This method will add the supplied languages to the menu. It will
add first the popular languages, followed by a separator and then add first the popular languages, followed by a separator and then
other less popular languages. other less popular languages.
@@ -57,7 +54,8 @@ LanguageMenuUtils::AddLanguagesToMenu(const std::vector<LanguageRef>& languages,
/* static */ void /* static */ void
LanguageMenuUtils::MarkLanguageInMenu(const BString& languageId, BMenu* menu) LanguageMenuUtils::MarkLanguageInMenu(const BString& languageId, BMenu* menu)
{ {
AppUtils::MarkItemWithKeyValueInMenuOrFirst(menu, kLanguageIdKey, languageId); AppUtils::MarkItemWithKeyValueInMenuOrFirst(menu, shared_message_keys::kKeyLanguageId,
languageId);
} }
@@ -65,7 +63,7 @@ LanguageMenuUtils::MarkLanguageInMenu(const BString& languageId, BMenu* menu)
LanguageMenuUtils::_AddLanguageToMenu(const BString& id, const BString& name, BMenu* menu) LanguageMenuUtils::_AddLanguageToMenu(const BString& id, const BString& name, BMenu* menu)
{ {
BMessage* message = new BMessage(MSG_LANGUAGE_SELECTED); BMessage* message = new BMessage(MSG_LANGUAGE_SELECTED);
message->AddString(kLanguageIdKey, id); message->AddString(shared_message_keys::kKeyLanguageId, id);
BMenuItem* item = new BMenuItem(name, message); BMenuItem* item = new BMenuItem(name, message);
menu->AddItem(item); menu->AddItem(item);
} }