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.
*/
#ifndef HAIKU_DEPOT_CONSTANTS_H
@@ -63,19 +63,20 @@ enum BitmapSize {
#define REPOSITORY_NAME_SYSTEM "system"
#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"
#define KEY_ALERT_TITLE "alert_title"
#define KEY_ALERT_TYPE "alert_type"
#define KEY_WORK_STATUS_TEXT "work_status_text"
#define KEY_WORK_STATUS_PROGRESS "work_status_progress"
#define KEY_WINDOW_SETTINGS "window_settings"
#define KEY_MAIN_SETTINGS "main_settings"
#define KEY_PACKAGE_NAME "package_name"
#define KEY_TITLE "title"
#define KEY_DESKBAR_LINK "deskbar_link"
extern const char* const kKeyPackageName;
extern const char* const kKeyDepotName;
extern const char* const kKeyCode;
extern const char* const kKeyLanguageId;
}; // namespace shared_message_keys
#define SETTING_NICKNAME "username"
// historical difference
#define SETTING_SHOW_DESKTOP_PACKAGES "show only desktop packages"
#define SETTING_SHOW_NATIVE_DESKTOP_PACKAGES "show only native desktop packages"
#define SETTING_SHOW_AVAILABLE_PACKAGES "show available packages"
+2
View File
@@ -125,6 +125,7 @@ local applicationSources =
FeaturedPackagesView.cpp
FilterView.cpp
GeneralContentScrollView.cpp
HaikuDepotConstants.cpp
IdentityAndAccessUtils.cpp
IncrementViewCounterProcess.cpp
JobStateListener.cpp
@@ -152,6 +153,7 @@ local applicationSources =
ScrollableGroupView.cpp
SettingsWindow.cpp
SharedIcons.cpp
SimpleAlert.cpp
ShuttingDownWindow.cpp
ToLatestUserUsageConditionsWindow.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.
*/
#include "AccessToken.h"
@@ -9,8 +9,8 @@
// These are keys that are used to store this object's data into a BMessage instance.
#define KEY_TOKEN "token"
#define KEY_EXPIRY_TIMESTAMP "expiryTimestamp"
static const char* const kKeyToken = "token";
static const char* const kKeyExpiryLanguage = "expiry_language";
AccessToken::AccessToken(BMessage* from)
@@ -18,14 +18,12 @@ AccessToken::AccessToken(BMessage* from)
fToken(""),
fExpiryTimestamp(0)
{
if (from->FindString(KEY_TOKEN, &fToken) != B_OK) {
HDERROR("expected key [%s] in the message data when creating an access"
" token", KEY_TOKEN);
}
if (from->FindString(kKeyToken, &fToken) != B_OK)
HDERROR("expected key [%s] in the message data when creating an access token", kKeyToken);
if (from->FindUInt64(KEY_EXPIRY_TIMESTAMP, &fExpiryTimestamp) != B_OK) {
HDERROR("expected key [%s] in the message data when creating an access"
" token", KEY_EXPIRY_TIMESTAMP);
if (from->FindUInt64(kKeyExpiryLanguage, &fExpiryTimestamp) != B_OK) {
HDERROR("expected key [%s] in the message data when creating an access token",
kKeyExpiryLanguage);
}
}
@@ -127,8 +125,8 @@ AccessToken::Archive(BMessage* into, bool deep) const
if (result == B_OK && into == NULL)
result = B_ERROR;
if (result == B_OK)
result = into->AddString(KEY_TOKEN, fToken);
result = into->AddString(kKeyToken, fToken);
if (result == B_OK)
result = into->AddUInt64(KEY_EXPIRY_TIMESTAMP, fExpiryTimestamp);
result = into->AddUInt64(kKeyExpiryLanguage, fExpiryTimestamp);
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.
*/
#include "Captcha.h"
@@ -11,8 +11,8 @@
// These are keys that are used to store this object's data into a BMessage
// instance.
#define KEY_TOKEN "token"
#define KEY_PNG_IMAGE_DATA "pngImageData"
static const char* const kKeyToken = "token";
static const char* const kKeyPngImageData = "png_image_data";
Captcha::Captcha(BMessage* from)
@@ -20,16 +20,14 @@ Captcha::Captcha(BMessage* from)
fToken(""),
fPngImageData(NULL)
{
if (from->FindString(KEY_TOKEN, &fToken) != B_OK) {
HDERROR("expected key [%s] in the message data when creating a "
"captcha", KEY_TOKEN);
}
if (from->FindString(kKeyToken, &fToken) != B_OK)
HDERROR("expected key [%s] in the message data when creating a captcha", kKeyToken);
const void* data;
ssize_t len;
if (from->FindData(KEY_PNG_IMAGE_DATA, B_ANY_TYPE, &data, &len) != B_OK)
HDERROR("expected key [%s] in the message data", KEY_PNG_IMAGE_DATA);
if (from->FindData(kKeyPngImageData, B_ANY_TYPE, &data, &len) != B_OK)
HDERROR("expected key [%s] in the message data", kKeyPngImageData);
else
SetPngImageData(data, len);
}
@@ -90,10 +88,10 @@ Captcha::Archive(BMessage* into, bool deep) const
if (result == B_OK && into == NULL)
result = B_ERROR;
if (result == B_OK)
result = into->AddString(KEY_TOKEN, fToken);
result = into->AddString(kKeyToken, fToken);
if (result == B_OK && fPngImageData != NULL) {
result = into->AddData(KEY_PNG_IMAGE_DATA, B_ANY_TYPE,
fPngImageData->Buffer(), fPngImageData->BufferLength());
result = into->AddData(kKeyPngImageData, B_ANY_TYPE, fPngImageData->Buffer(),
fPngImageData->BufferLength());
}
return result;
}
+29 -32
View File
@@ -1,33 +1,32 @@
/*
* Copyright 2019-2024, 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.
*/
#include "CreateUserDetail.h"
#include "CreateUserDetail.h"
// 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_NICKNAME "nickname"
#define KEY_PASSWORD_CLEAR "passwordClear"
#define KEY_IS_PASSWORD_REPEATED "isPasswordRepeated"
#define KEY_EMAIL "email"
#define KEY_CAPTCHA_TOKEN "captchaToken"
#define KEY_CAPTCHA_RESPONSE "captchaResponse"
#define KEY_LANGUAGE_ID "languageId"
#define KEY_AGREED_USER_USAGE_CONDITIONS_CODE "agreedUserUsageConditionsCode"
static const char* const kKeyNickname = "nickname";
static const char* const kKeyPasswordClear = "password_clear";
static const char* const kKeyIsPasswordRepeated = "is_password_repeated";
static const char* const kKeyEmail = "email";
static const char* const kKeyCaptchaToken = "captcha_token";
static const char* const kKeyCaptchaResponse = "captcha_response";
static const char* const kKeyLanguageId = "language_id";
static const char* const kKeyAgreedUserUsageConditionsCode = "agreed_user_usage_conditions_code";
CreateUserDetail::CreateUserDetail(BMessage* from)
{
from->FindString(KEY_NICKNAME, &fNickname);
from->FindString(KEY_PASSWORD_CLEAR, &fPasswordClear);
from->FindBool(KEY_IS_PASSWORD_REPEATED, &fIsPasswordRepeated);
from->FindString(KEY_EMAIL, &fEmail);
from->FindString(KEY_CAPTCHA_TOKEN, &fCaptchaToken);
from->FindString(KEY_CAPTCHA_RESPONSE, &fCaptchaResponse);
from->FindString(KEY_LANGUAGE_ID, &fLanguageId);
from->FindString(KEY_AGREED_USER_USAGE_CONDITIONS_CODE,
&fAgreedUserUsageConditionsCode);
from->FindString(kKeyNickname, &fNickname);
from->FindString(kKeyPasswordClear, &fPasswordClear);
from->FindBool(kKeyIsPasswordRepeated, &fIsPasswordRepeated);
from->FindString(kKeyEmail, &fEmail);
from->FindString(kKeyCaptchaToken, &fCaptchaToken);
from->FindString(kKeyCaptchaResponse, &fCaptchaResponse);
from->FindString(kKeyLanguageId, &fLanguageId);
from->FindString(kKeyAgreedUserUsageConditionsCode, &fAgreedUserUsageConditionsCode);
}
@@ -160,22 +159,20 @@ CreateUserDetail::Archive(BMessage* into, bool deep) const
{
status_t result = B_OK;
if (result == B_OK)
result = into->AddString(KEY_NICKNAME, fNickname);
result = into->AddString(kKeyNickname, fNickname);
if (result == B_OK)
result = into->AddString(KEY_PASSWORD_CLEAR, fPasswordClear);
result = into->AddString(kKeyPasswordClear, fPasswordClear);
if (result == B_OK)
result = into->AddBool(KEY_IS_PASSWORD_REPEATED, fIsPasswordRepeated);
result = into->AddBool(kKeyIsPasswordRepeated, fIsPasswordRepeated);
if (result == B_OK)
result = into->AddString(KEY_EMAIL, fEmail);
result = into->AddString(kKeyEmail, fEmail);
if (result == B_OK)
result = into->AddString(KEY_CAPTCHA_TOKEN, fCaptchaToken);
result = into->AddString(kKeyCaptchaToken, fCaptchaToken);
if (result == B_OK)
result = into->AddString(KEY_CAPTCHA_RESPONSE, fCaptchaResponse);
result = into->AddString(kKeyCaptchaResponse, fCaptchaResponse);
if (result == B_OK)
result = into->AddString(KEY_LANGUAGE_ID, fLanguageId);
if (result == B_OK) {
result = into->AddString(KEY_AGREED_USER_USAGE_CONDITIONS_CODE,
fAgreedUserUsageConditionsCode);
}
result = into->AddString(kKeyLanguageId, fLanguageId);
if (result == B_OK)
result = into->AddString(kKeyAgreedUserUsageConditionsCode, fAgreedUserUsageConditionsCode);
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.
*
* Authors:
@@ -19,8 +19,8 @@
#include "Logger.h"
#define kPathKey "path"
#define kLinkKey "link"
static const char* const kKeyPath = "path";
static const char* const kKeyLink = "link";
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) {
HDERROR("expected key [%s] in the message data when creating a "
"captcha", kPathKey);
}
if (from->FindString(kKeyPath, &fPath) != B_OK)
HDERROR("expected key [%s] in the message data when creating a captcha", kKeyPath);
if (from->FindString(kLinkKey, &fLink) != B_OK) {
HDERROR("expected key [%s] in the message data when creating a "
"captcha", kLinkKey);
}
if (from->FindString(kKeyLink, &fLink) != B_OK)
HDERROR("expected key [%s] in the message data when creating a captcha", kKeyLink);
}
@@ -96,6 +92,13 @@ DeskbarLink::Title() const
}
bool
DeskbarLink::IsValid() const
{
return !fPath.IsEmpty() && !fLink.IsEmpty();
}
status_t
DeskbarLink::Archive(BMessage* into, bool deep) const
{
@@ -103,9 +106,9 @@ DeskbarLink::Archive(BMessage* into, bool deep) const
if (result == B_OK && into == NULL)
result = B_ERROR;
if (result == B_OK)
result = into->AddString(kPathKey, fPath);
result = into->AddString(kKeyPath, fPath);
if (result == B_OK)
result = into->AddString(kLinkKey, fLink);
result = into->AddString(kKeyLink, fLink);
return result;
}
+3 -1
View File
@@ -24,7 +24,7 @@ public:
DeskbarLink(const BString& path,
const BString& link);
DeskbarLink(const DeskbarLink& other);
DeskbarLink(BMessage* from);
DeskbarLink(const BMessage* from);
virtual ~DeskbarLink();
@@ -36,6 +36,8 @@ public:
bool operator!=(const DeskbarLink& other);
DeskbarLink& operator=(const DeskbarLink& other);
bool IsValid() const;
status_t Archive(BMessage* into, bool deep = true) const;
private:
+9 -51
View File
@@ -1,7 +1,7 @@
/*
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2014, Axel Dörfler <axeld@pinc-software.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.
*/
#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
Model::PreferredLanguage() const
{
@@ -423,7 +381,7 @@ Model::AddPackage(const PackageInfoRef& package)
BAutolock locker(&fLock);
uint32 changeMask = _ChangeDiff(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;
BAutolock locker(&fLock);
PackageInfoEvents events;
PackageChangeEvents events;
std::vector<PackageInfoRef>::const_iterator it;
for (it = packages.begin(); it != packages.end(); it++) {
PackageInfoRef package = *it;
events.AddEvent(PackageInfoEvent(package, _ChangeDiff(package)));
events.AddEvent(PackageChangeEvent(package, _ChangeDiff(package)));
fPackages[package->Name()] = package;
}
@@ -454,12 +412,12 @@ Model::AddPackagesWithChange(const std::vector<PackageInfoRef>& packages, uint32
return;
BAutolock locker(&fLock);
PackageInfoEvents events;
PackageChangeEvents events;
std::vector<PackageInfoRef>::const_iterator it;
for (it = packages.begin(); it != packages.end(); it++) {
PackageInfoRef package = *it;
events.AddEvent(PackageInfoEvent(package, changeMask));
events.AddEvent(PackageChangeEvent(package, changeMask));
fPackages[package->Name()] = package;
}
@@ -652,20 +610,20 @@ Model::_NotifyCategoryListChanged()
void
Model::_NotifyPackageChange(const PackageInfoEvent& event)
Model::_NotifyPackageChange(const PackageChangeEvent& event)
{
std::vector<PackageInfoListenerRef>::const_iterator it;
for (it = fPackageListeners.begin(); it != fPackageListeners.end(); it++) {
const PackageInfoListenerRef& listener = *it;
if (listener.IsSet())
listener->PackagesChanged(PackageInfoEvents(event));
listener->PackagesChanged(PackageChangeEvents(event));
}
}
// TODO: future work to optimize how this is conveyed to the listener in one go.
void
Model::_NotifyPackageChanges(const PackageInfoEvents& events)
Model::_NotifyPackageChanges(const PackageChangeEvents& events)
{
if (events.IsEmpty())
return;
+2 -5
View File
@@ -95,9 +95,6 @@ public:
void AddListener(const ModelListenerRef& listener);
void AddPackageListener(const PackageInfoListenerRef& packageListener);
status_t DearchiveInfoEvents(const BMessage* message,
PackageInfoEvents& packageInfoEvents) const;
PackageScreenshotRepository*
GetPackageScreenshotRepository();
@@ -178,8 +175,8 @@ private:
void _NotifyIconsChanged();
void _NotifyAuthorizationChanged();
void _NotifyCategoryListChanged();
void _NotifyPackageChange(const PackageInfoEvent& event);
void _NotifyPackageChanges(const PackageInfoEvents& events);
void _NotifyPackageChange(const PackageChangeEvent& event);
void _NotifyPackageChanges(const PackageChangeEvents& events);
private:
mutable BLocker fLock;
+101 -41
View File
@@ -1,31 +1,24 @@
/*
* 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.
*/
#include "PackageInfoListener.h"
#include <stdio.h>
#include "HaikuDepotConstants.h"
#include "Logger.h"
#include "PackageInfo.h"
const char* kPackageInfoChangesKey = "change";
const char* kPackageInfoPackageNameKey = "packageName";
const char* kPackageInfoEventsKey = "events";
static const char* const kKeyEvents = "events";
static const char* const kKeyChanges = "changes";
// #pragma mark - PackageInfoChangeEvent
// #pragma mark - PackageInfoEvent
PackageInfoEvent::PackageInfoEvent()
:
fPackage(),
fChanges(0)
{
}
PackageInfoEvent::PackageInfoEvent(const PackageInfoRef& package, uint32 changes)
PackageInfoChangeEvent::PackageInfoChangeEvent(PackageInfoRef package, uint32 changes)
:
fPackage(package),
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)
{
}
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
PackageInfoEvent::operator==(const PackageInfoEvent& other)
PackageChangeEvent::IsValid() const
{
return !fPackageName.IsEmpty();
}
bool
PackageChangeEvent::operator==(const PackageChangeEvent& other)
{
if (this == &other)
return true;
return fPackage == other.fPackage && fChanges == other.fChanges;
return fPackageName == other.fPackageName && fChanges == other.fChanges;
}
bool
PackageInfoEvent::operator!=(const PackageInfoEvent& other)
PackageChangeEvent::operator!=(const PackageChangeEvent& other)
{
return !(*this == other);
}
PackageInfoEvent&
PackageInfoEvent::operator=(const PackageInfoEvent& other)
PackageChangeEvent&
PackageChangeEvent::operator=(const PackageChangeEvent& other)
{
if (this != &other) {
fPackage = other.fPackage;
fPackageName = other.fPackageName;
fChanges = other.fChanges;
}
@@ -75,78 +115,98 @@ PackageInfoEvent::operator=(const PackageInfoEvent& other)
status_t
PackageInfoEvent::Archive(BMessage* into, bool deep) const
PackageChangeEvent::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->AddUInt32(kPackageInfoChangesKey, fChanges);
result = into->AddUInt32(kKeyChanges, fChanges);
if (result == B_OK)
result = into->AddString(kPackageInfoPackageNameKey, fPackage->Name());
result = into->AddString(shared_message_keys::kKeyPackageName, fPackageName);
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--)
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
PackageInfoEvents::AddEvent(const PackageInfoEvent event)
PackageChangeEvents::AddEvent(const PackageChangeEvent event)
{
fEvents.push_back(event);
}
bool
PackageInfoEvents::IsEmpty() const
PackageChangeEvents::IsEmpty() const
{
return fEvents.empty();
}
int32
PackageInfoEvents::CountEvents() const
PackageChangeEvents::CountEvents() const
{
return fEvents.size();
}
const PackageInfoEvent&
PackageInfoEvents::EventAtIndex(int32 index) const
const PackageChangeEvent&
PackageChangeEvents::EventAtIndex(int32 index) const
{
return fEvents[index];
}
status_t
PackageInfoEvents::Archive(BMessage* into, bool deep) const
PackageChangeEvents::Archive(BMessage* into, bool deep) const
{
status_t result = B_OK;
BString indexString;
std::vector<PackageInfoEvent>::const_iterator it;
std::vector<PackageChangeEvent>::const_iterator it;
for (it = fEvents.begin(); it != fEvents.end(); it++) {
BMessage eventMessage;
result = (*it).Archive(&eventMessage);
if (result == B_OK)
result = into->AddMessage(kPackageInfoEventsKey, &eventMessage);
result = into->AddMessage(kKeyEvents, &eventMessage);
}
return result;
+60 -30
View File
@@ -1,6 +1,6 @@
/*
* 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.
*/
#ifndef PACKAGE_INFO_LISTENER_H
@@ -14,11 +14,6 @@
#include <Referenceable.h>
extern const char* kPackageInfoChangesKey;
extern const char* kPackageInfoPackageNameKey;
extern const char* kPackageInfoEventsKey;
enum {
PKG_CHANGED_LOCALIZED_TEXT = 1 << 0,
// ^ Covers title, summary, description and changelog.
@@ -37,58 +32,93 @@ class PackageInfo;
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:
PackageInfoEvent();
PackageInfoEvent(const PackageInfoRef& package, uint32 changes);
PackageInfoEvent(const PackageInfoEvent& other);
virtual ~PackageInfoEvent();
PackageInfoChangeEvent(PackageInfoRef package, uint32 change);
virtual ~PackageInfoChangeEvent();
bool operator==(const PackageInfoEvent& other);
bool operator!=(const PackageInfoEvent& other);
PackageInfoEvent& operator=(const PackageInfoEvent& other);
inline const PackageInfoRef&
Package() const
const PackageInfoRef Package() const
{ return fPackage; }
inline uint32 Changes() const
uint32 Changes() const
{ return fChanges; }
status_t Archive(BMessage* into, bool deep = true) const;
private:
PackageInfoRef fPackage;
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:
PackageInfoEvents();
PackageInfoEvents(const PackageInfoEvent& event);
PackageInfoEvents(const PackageInfoEvents& other);
PackageChangeEvent();
PackageChangeEvent(const PackageInfoRef& package, uint32 changes);
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;
void AddEvent(const PackageInfoEvent event);
void AddEvent(const PackageChangeEvent event);
int32 CountEvents() const;
const PackageInfoEvent&
const PackageChangeEvent&
EventAtIndex(int32 index) const;
status_t Archive(BMessage* into, bool deep = true) const;
private:
std::vector<PackageInfoEvent>
std::vector<PackageChangeEvent>
fEvents;
};
class PackageInfoListener : public BReferenceable {
class PackageInfoListener : public BReferenceable
{
public:
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.
*/
#include "ScreenshotCoordinate.h"
static const char* kCodeKey = "code";
static const char* kWidthKey = "width";
static const char* kHeightKey = "height";
#include "Logger.h"
static const char* const kKeyCode = "code";
static const char* const kKeyWidth = "width";
static const char* const kKeyHeight = "height";
ScreenshotCoordinate::ScreenshotCoordinate()
@@ -21,9 +24,12 @@ ScreenshotCoordinate::ScreenshotCoordinate()
ScreenshotCoordinate::ScreenshotCoordinate(const BMessage* from)
{
from->FindString(kCodeKey, &fCode);
from->FindUInt32(kWidthKey, &fWidth);
from->FindUInt32(kHeightKey, &fHeight);
if (from->FindString(kKeyCode, &fCode) != B_OK)
HDERROR("expected key [%s] in the message data", kKeyCode);
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;
if (result == B_OK)
result = into->AddString(kCodeKey, fCode);
result = into->AddString(kKeyCode, fCode);
if (result == B_OK)
result = into->AddUInt32(kWidthKey, fWidth);
result = into->AddUInt32(kKeyWidth, fWidth);
if (result == B_OK)
result = into->AddUInt32(kHeightKey, fHeight);
result = into->AddUInt32(kKeyHeight, fHeight);
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.
*/
@@ -9,16 +9,16 @@
// These are keys that are used to store this object's data into a BMessage
// instance.
#define KEY_NICKNAME "nickname"
#define KEY_PASSWORD_CLEAR "passwordClear"
#define KEY_IS_SUCCESSFUL "isSuccessful"
static const char* const kKeyNickname = "nickname";
static const char* const kKeyPasswordClear = "password_clear";
static const char* const kKeyIsSuccessful = "is_successful";
UserCredentials::UserCredentials(BMessage* from)
{
from->FindString(KEY_NICKNAME, &fNickname);
from->FindString(KEY_PASSWORD_CLEAR, &fPasswordClear);
from->FindBool(KEY_IS_SUCCESSFUL, &fIsSuccessful);
from->FindString(kKeyNickname, &fNickname);
from->FindString(kKeyPasswordClear, &fPasswordClear);
from->FindBool(kKeyIsSuccessful, &fIsSuccessful);
}
@@ -133,10 +133,10 @@ UserCredentials::Archive(BMessage* into, bool deep) const
{
status_t result = B_OK;
if (result == B_OK)
result = into->AddString(KEY_NICKNAME, fNickname);
result = into->AddString(kKeyNickname, fNickname);
if (result == B_OK)
result = into->AddString(KEY_PASSWORD_CLEAR, fPasswordClear);
result = into->AddString(kKeyPasswordClear, fPasswordClear);
if (result == B_OK)
result = into->AddBool(KEY_IS_SUCCESSFUL, fIsSuccessful);
result = into->AddBool(kKeyIsSuccessful, fIsSuccessful);
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.
*/
@@ -9,18 +9,18 @@
// These are keys that are used to store this object's data into a BMessage
// instance.
#define KEY_NICKNAME "nickname"
#define KEY_AGREEMENT "agreement"
#define KEY_IS_LATEST "isLatest"
#define KEY_CODE "code"
#define KEY_TIMESTAMP_AGREED "timestampAgreed"
static const char* const kKeyNickname = "nickname";
static const char* const kKeyAgreement = "agreement";
static const char* const kKeyIsLatest = "is_latest";
static const char* const kKeyCode = "code";
static const char* const kKeyTimestampAgreed = "timestamp_agreed";
UserUsageConditionsAgreement::UserUsageConditionsAgreement(BMessage* from)
{
from->FindUInt64(KEY_TIMESTAMP_AGREED, &fTimestampAgreed);
from->FindString(KEY_CODE, &fCode);
from->FindBool(KEY_IS_LATEST, &fIsLatest);
from->FindUInt64(kKeyTimestampAgreed, &fTimestampAgreed);
from->FindString(kKeyCode, &fCode);
from->FindBool(kKeyIsLatest, &fIsLatest);
}
@@ -96,11 +96,11 @@ UserUsageConditionsAgreement::Archive(BMessage* into, bool deep) const
{
status_t result = B_OK;
if (result == B_OK)
result = into->AddUInt64(KEY_TIMESTAMP_AGREED, fTimestampAgreed);
result = into->AddUInt64(kKeyTimestampAgreed, fTimestampAgreed);
if (result == B_OK)
result = into->AddString(KEY_CODE, fCode);
result = into->AddString(kKeyCode, fCode);
if (result == B_OK)
result = into->AddBool(KEY_IS_LATEST, fIsLatest);
result = into->AddBool(kKeyIsLatest, fIsLatest);
return result;
}
@@ -108,11 +108,9 @@ UserUsageConditionsAgreement::Archive(BMessage* into, bool deep) const
UserDetail::UserDetail(BMessage* from)
{
BMessage agreementMessage;
if (from->FindMessage(KEY_AGREEMENT,
&agreementMessage) == B_OK) {
if (from->FindMessage(kKeyAgreement, &agreementMessage) == B_OK)
fAgreement = UserUsageConditionsAgreement(&agreementMessage);
}
from->FindString(KEY_NICKNAME, &fNickname);
from->FindString(kKeyNickname, &fNickname);
}
@@ -175,9 +173,9 @@ UserDetail::Archive(BMessage* into, bool deep) const
BMessage agreementMessage;
result = fAgreement.Archive(&agreementMessage, true);
if (result == B_OK)
result = into->AddMessage(KEY_AGREEMENT, &agreementMessage);
result = into->AddMessage(kKeyAgreement, &agreementMessage);
}
if (result == B_OK)
result = into->AddString(KEY_NICKNAME, fNickname);
result = into->AddString(kKeyNickname, fNickname);
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.
*/
@@ -10,9 +10,9 @@
// These are keys that are used to store this object's data into a BMessage
// instance.
#define KEY_COPY_MARKDOWN "copyMarkdown"
#define KEY_CODE "code"
#define KEY_MINIMUM_AGE "minimumAge"
static const char* const kKeyCode = "code";
static const char* const kKeyCopyMarkdown = "copy_markdown";
static const char* const kKeyMinimumAge = "minimum_age";
UserUsageConditions::UserUsageConditions(BMessage* from)
@@ -23,14 +23,14 @@ UserUsageConditions::UserUsageConditions(BMessage* from)
{
int16 minimumAge;
if (from->FindInt16(KEY_MINIMUM_AGE, &minimumAge) != B_OK)
HDERROR("expected key [%s] in the message data", KEY_MINIMUM_AGE);
if (from->FindInt16(kKeyMinimumAge, &minimumAge) != B_OK)
HDERROR("expected key [%s] in the message data", kKeyMinimumAge);
fMinimumAge = (uint8) minimumAge;
if (from->FindString(KEY_CODE, &fCode) != B_OK)
HDERROR("expected key [%s] in the message data", KEY_CODE);
if (from->FindString(KEY_COPY_MARKDOWN, &fCopyMarkdown) != B_OK)
HDERROR("expected key [%s] in the message data", KEY_COPY_MARKDOWN);
if (from->FindString(kKeyCode, &fCode) != B_OK)
HDERROR("expected key [%s] in the message data", kKeyCode);
if (from->FindString(kKeyCopyMarkdown, &fCopyMarkdown) != B_OK)
HDERROR("expected key [%s] in the message data", kKeyCopyMarkdown);
}
@@ -93,8 +93,12 @@ UserUsageConditions::SetCopyMarkdown(const BString& copyMarkdown)
status_t
UserUsageConditions::Archive(BMessage* into, bool deep) const
{
into->AddInt16(KEY_MINIMUM_AGE, (int16) fMinimumAge);
into->AddString(KEY_CODE, fCode);
into->AddString(KEY_COPY_MARKDOWN, fCopyMarkdown);
return B_OK;
status_t result = B_OK;
if (result == B_OK)
result = into->AddInt16(kKeyMinimumAge, (int16)fMinimumAge);
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.
*/
@@ -8,9 +8,9 @@
// These are keys that are used to store this object's data into a BMessage
// instance.
#define KEY_PROPERTY "property"
#define KEY_PREFIX_MESSAGE "message_"
#define KEY_PREFIX_ITEM "item_"
static const char* const kKeyProperty = "property";
static const char* const kKeyPrefixMessage = "message_";
static const char* const kKeyPrefixItem = "item_";
// #pragma mark - Single Validation Failure
@@ -18,7 +18,7 @@
ValidationFailure::ValidationFailure(BMessage* from)
{
from->FindString(KEY_PROPERTY, &fProperty);
from->FindString(kKeyProperty, &fProperty);
if (fProperty.IsEmpty())
debugger("illegal state; missing property in message");
@@ -28,7 +28,7 @@ ValidationFailure::ValidationFailure(BMessage* from)
BString message;
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);
if (result == B_OK)
@@ -89,9 +89,9 @@ ValidationFailure::Archive(BMessage* into, bool deep) const
status_t result = B_OK;
BString key;
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++) {
key.SetToFormat("%s%" B_PRId32, KEY_PREFIX_MESSAGE, i);
key.SetToFormat("%s%" B_PRId32, kKeyPrefixMessage, i);
result = into->AddString(key, fMessages.StringAt(i));
}
return result;
@@ -177,7 +177,7 @@ ValidationFailures::Archive(BMessage* into, bool deep) const
BMessage itemMessage;
result = item->Archive(&itemMessage);
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);
}
}
@@ -221,7 +221,7 @@ ValidationFailures::_AddFromMessage(const BMessage* from)
while (true) {
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)
return;
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.
*
* Authors:
@@ -181,7 +181,8 @@ InstallPackageProcess::RunInternal()
BString errorString;
errorString.SetToFormat("Fatal error occurred while installing package %s: %s (%s)\n",
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);
SetPackageState(fPackageName, state);
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.
*
* Authors:
@@ -137,6 +137,10 @@ OpenPackageProcess::RunInternal()
{
status_t status;
BPath path;
HDDEBUG("open package action from deskbar link [%s], path [%s]", fDeskbarLink.Link().String(),
fDeskbarLink.Path().String());
if (fDeskbarLink.Link().FindFirst('/') == 0) {
status = path.SetTo(fDeskbarLink.Link());
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.
*/
#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),
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()
{
}
@@ -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
{
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.
*/
#ifndef PACKAGE_ACTION_H
#define PACKAGE_ACTION_H
#include <Message.h>
#include <Referenceable.h>
#include <String.h>
#include "DeskbarLink.h"
class PackageAction : public BReferenceable {
class PackageAction : public BReferenceable, public BArchivable
{
public:
PackageAction(const BString& title,
const BMessage& message);
PackageAction(const BString& title, const BString& packageName);
PackageAction(const BMessage* from);
virtual ~PackageAction();
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;
BMessage fMessage;
BString fPackageName;
};
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
@@ -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.
*
* Authors:
@@ -160,8 +160,13 @@ PackageManager::CollectPackageActions(PackageInfoRef package,
break;
case NONE:
case UNINSTALLED:
actionList.Add(_CreateInstallPackageAction(package));
{
BString packageTitle;
PackageUtils::TitleOrName(package, packageTitle);
actionList.Add(
PackageActionRef(new InstallPackageAction(package->Name(), packageTitle), true));
break;
}
case DOWNLOADING:
HDINFO("no package actions for [%s] (downloading)",
package->Name().String());
@@ -183,7 +188,11 @@ PackageManager::_CollectPackageActionsForActivatedOrInstalled(
PackageInfoRef package,
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
// package
@@ -192,63 +201,17 @@ PackageManager::_CollectPackageActionsForActivatedOrInstalled(
std::vector<DeskbarLink>::const_iterator it;
for (it = foundLinks.begin(); it != foundLinks.end(); 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);
}
void
PackageManager::SetCurrentActionPackage(PackageInfoRef package, bool install)
{
@@ -3,7 +3,7 @@
* Copyright 2011, Ingo Weinhold, <ingo_weinhold@gmx.de>
* Copyright 2013, Rene Gollent, <rene@gollent.com>
* 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.
*/
@@ -97,13 +97,6 @@ private:
InstalledRepository& repository);
private:
PackageActionRef _CreateUninstallPackageAction(
const PackageInfoRef& package);
PackageActionRef _CreateInstallPackageAction(
const PackageInfoRef& package);
PackageActionRef _CreateOpenPackageAction(
const PackageInfoRef& package,
const DeskbarLink& link);
void _CollectPackageActionsForActivatedOrInstalled(
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.
*
* Authors:
@@ -93,7 +93,8 @@ UninstallPackageProcess::RunInternal()
BString errorString;
errorString.SetToFormat("Fatal error occurred while uninstalling package %s: %s (%s)\n",
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);
return ex.Error();
} 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.
*/
@@ -22,11 +22,11 @@
// These are keys that are used to store the ProcessCoordinatorState data into
// a BMessage instance.
#define KEY_PROCESS_COORDINATOR_IDENTIFIER "processCoordinatorIdentifier"
#define KEY_PROGRESS "progress"
#define KEY_MESSAGE "message"
#define KEY_IS_RUNNING "isRunning"
#define KEY_ERROR_STATUS "errorStatus"
static const char* const kKeyIdentifier = "identifier";
static const char* const kKeyProgress = "progress";
static const char* const kKeyMessage = "message";
static const char* const kKeyIsRunning = "is_running";
static const char* const kKeyErrorStatus = "error_status";
// #pragma mark - ProcessCoordinatorState implementation
@@ -34,28 +34,18 @@
ProcessCoordinatorState::ProcessCoordinatorState(BMessage* from)
{
if (from->FindString(KEY_PROCESS_COORDINATOR_IDENTIFIER,
&fProcessCoordinatorIdentifier) != B_OK) {
HDFATAL("unable to find the key [%s]",
KEY_PROCESS_COORDINATOR_IDENTIFIER);
}
if (from->FindFloat(KEY_PROGRESS, &fProgress) != B_OK) {
HDFATAL("unable to find the key [%s]", KEY_PROGRESS);
}
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);
}
if (from->FindString(kKeyIdentifier, &fProcessCoordinatorIdentifier) != B_OK)
HDFATAL("unable to find the key [%s]", kKeyIdentifier);
if (from->FindFloat(kKeyProgress, &fProgress) != B_OK)
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->FindBool(kKeyIsRunning, &fIsRunning) != B_OK)
HDFATAL("unable to find the key [%s]", kKeyIsRunning);
int64 errorStatusNumeric;
if (from->FindInt64(KEY_ERROR_STATUS, &errorStatusNumeric) != B_OK) {
HDFATAL("unable to find the key [%s]", KEY_ERROR_STATUS);
}
if (from->FindInt64(kKeyErrorStatus, &errorStatusNumeric) != B_OK)
HDFATAL("unable to find the key [%s]", kKeyErrorStatus);
fErrorStatus = static_cast<status_t>(errorStatusNumeric);
}
@@ -117,18 +107,16 @@ status_t
ProcessCoordinatorState::Archive(BMessage* into, bool deep) const
{
status_t result = B_OK;
if (result == B_OK) {
result = into->AddString(KEY_PROCESS_COORDINATOR_IDENTIFIER,
fProcessCoordinatorIdentifier);
}
if (result == B_OK)
result = into->AddFloat(KEY_PROGRESS, fProgress);
result = into->AddString(kKeyIdentifier, fProcessCoordinatorIdentifier);
if (result == B_OK)
result = into->AddString(KEY_MESSAGE, fMessage);
result = into->AddFloat(kKeyProgress, fProgress);
if (result == B_OK)
result = into->AddBool(KEY_IS_RUNNING, fIsRunning);
result = into->AddString(kKeyMessage, fMessage);
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;
}
@@ -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.
*/
#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*
ProcessCoordinatorFactory::CacheScreenshotCoordinator(Model* model,
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*
ProcessCoordinatorFactory::_CreateInstallPackageActionCoordinator(Model* model, BMessage* message)
ProcessCoordinatorFactory::CreateInstallPackageActionCoordinator(Model* model,
const InstallPackageAction& action)
{
ProcessCoordinator* processCoordinator
= new ProcessCoordinator("InstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
AbstractProcessNode* processNode = new ThreadedProcessNode(
new InstallPackageProcess(_ExtractPackageNameFromMessage(message), model), 10);
AbstractProcessNode* processNode
= new ThreadedProcessNode(new InstallPackageProcess(action.PackageName(), model), 10);
processCoordinator->AddNode(processNode);
return processCoordinator;
}
/*static*/ ProcessCoordinator*
ProcessCoordinatorFactory::_CreateUninstallPackageActionCoordinator(Model* model, BMessage* message)
ProcessCoordinatorFactory::CreateUninstallPackageActionCoordinator(Model* model,
const UninstallPackageAction& action)
{
ProcessCoordinator* processCoordinator
= new ProcessCoordinator("UninstallPackage", new BMessage(MSG_PACKAGE_ACTION_DONE));
AbstractProcessNode* processNode = new ThreadedProcessNode(
new UninstallPackageProcess(_ExtractPackageNameFromMessage(message), model), 10);
AbstractProcessNode* processNode
= new ThreadedProcessNode(new UninstallPackageProcess(action.PackageName(), model), 10);
processCoordinator->AddNode(processNode);
return processCoordinator;
}
/*static*/ ProcessCoordinator*
ProcessCoordinatorFactory::_CreateOpenPackageActionCoordinator(Model* model, BMessage* message)
ProcessCoordinatorFactory::CreateOpenPackageActionCoordinator(Model* model,
const OpenPackageAction& action)
{
ProcessCoordinator* processCoordinator
= 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(
new OpenPackageProcess(_ExtractPackageNameFromMessage(message), model, deskbarLink));
new OpenPackageProcess(action.PackageName(), model, action.Link()));
processCoordinator->AddNode(processNode);
return processCoordinator;
}
@@ -8,6 +8,7 @@
#include <SupportDefs.h>
#include "AbstractProcess.h"
#include "PackageAction.h"
#include "PackageInfo.h"
#include "PackageScreenshotRepository.h"
@@ -32,9 +33,6 @@ public:
UserDetailVerifierListener* userDetailVerifierListener,
Model* model);
static ProcessCoordinator* CreatePackageActionCoordinator(
Model* model, BMessage* message);
static ProcessCoordinator* CacheScreenshotCoordinator(
Model* model, ScreenshotCoordinate& screenshotCoordinate);
@@ -44,20 +42,18 @@ public:
static ProcessCoordinator* PopulatePkgUserRatingsCoordinator(Model* model,
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:
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,
AbstractProcess *process);
@@ -741,7 +741,8 @@ LocalPkgDataLoadProcessUtils::_PopulateModel(LocalPkgDataLoadProcessUtilsData& d
LocalPkgDataLoadProcessUtils::_NotifyError(const BString& messageText)
{
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(")");
}
AppUtils::NotifySimpleError(
B_TRANSLATE("Repository update error"),
alertText);
AppUtils::NotifySimpleError(SimpleAlert(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.
*/
@@ -24,8 +24,12 @@
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "ServerHelper"
#define KEY_MSG_MINIMUM_VERSION "minimumVersion"
#define KEY_HEADER_MINIMUM_VERSION "X-Desktop-Application-Minimum-Version"
static const char* const kKeyMinimumVersion = "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
@@ -165,11 +169,11 @@ ServerHelper::NotifyClientTooOld(const BHttpHeaders& responseHeaders)
if (!ServerSettings::IsClientTooOld()) {
ServerSettings::SetClientTooOld();
const char* minimumVersionC = responseHeaders[KEY_HEADER_MINIMUM_VERSION];
const char* minimumVersionC = responseHeaders[kKeyHeaderMinimumVersion];
BMessage message(MSG_CLIENT_TOO_OLD);
if (minimumVersionC != NULL && strlen(minimumVersionC) != 0) {
message.AddString(KEY_MSG_MINIMUM_VERSION, minimumVersionC);
message.AddString(kKeyMinimumVersion, minimumVersionC);
}
be_app->PostMessage(&message);
@@ -183,7 +187,7 @@ ServerHelper::AlertClientTooOld(BMessage* message)
BString minimumVersion;
BString alertText;
if (message->FindString(KEY_MSG_MINIMUM_VERSION, &minimumVersion) != B_OK)
if (message->FindString(kKeyMinimumVersion, &minimumVersion) != B_OK)
minimumVersion = "???";
alertText.SetToFormat(
+10 -20
View File
@@ -1,6 +1,6 @@
/*
* 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.
*/
@@ -38,6 +38,9 @@
#define B_TRANSLATION_CONTEXT "App"
static const char* const kKeyMainSettings = "main_settings";
App::App()
:
BApplication("application/x-vnd.Haiku-HaikuDepot"),
@@ -109,7 +112,7 @@ App::MessageReceived(BMessage* message)
case MSG_MAIN_WINDOW_CLOSED:
{
BMessage windowSettings;
if (message->FindMessage(KEY_WINDOW_SETTINGS, &windowSettings) == B_OK)
if (message->FindMessage(main_window_keys::kKeyWindowSettings, &windowSettings) == B_OK)
_StoreSettings(windowSettings);
fWindowCount--;
@@ -325,22 +328,9 @@ App::ArgvReceived(int32 argc, char* argv[])
void
App::_AlertSimpleError(BMessage* message)
{
BString alertTitle;
BString alertText;
int32 typeInt;
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));
SimpleAlert simpleAlert(message);
BAlert* alert = new BAlert(simpleAlert.Title(), simpleAlert.Text(), B_TRANSLATE("OK"), NULL,
NULL, B_WIDTH_AS_USUAL, simpleAlert.Type());
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
alert->Go();
}
@@ -421,7 +411,7 @@ App::_LoadSettings(BMessage& settings)
{
if (!fSettingsRead) {
fSettingsRead = true;
if (load_settings(&fSettings, KEY_MAIN_SETTINGS, "HaikuDepot") != B_OK)
if (load_settings(&fSettings, kKeyMainSettings, "HaikuDepot") != B_OK)
fSettings.MakeEmpty();
}
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 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>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
@@ -300,7 +300,7 @@ public:
if (index != -1) {
BMessage message(MSG_PACKAGE_SELECTED);
BString packageName = fPackages[index]->Name();
message.AddString("name", packageName);
message.AddString(shared_message_keys::kKeyPackageName, packageName);
Window()->PostMessage(&message);
}
}
@@ -320,17 +320,18 @@ public:
// #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--)
_HandlePackageChanged(events.EventAtIndex(i));
std::vector<PackageInfoChangeEvent>::const_iterator it;
for (it = events.begin(); it != events.end(); it++)
_HandlePackageChanged(*it);
}
void _HandlePackageChanged(const PackageInfoEvent& event)
void _HandlePackageChanged(const PackageInfoChangeEvent& event)
{
uint32 changes = event.Changes();
PackageInfoRef package = event.Package();
const PackageInfoRef package = event.Package();
if (!package.IsSet() || 0 == changes)
return;
@@ -1089,7 +1090,7 @@ FeaturedPackagesView::HandleIconsChanged()
void
FeaturedPackagesView::HandlePackagesChanged(const PackageInfoEvents& events)
FeaturedPackagesView::HandlePackagesChanged(const std::vector<PackageInfoChangeEvent>& events)
{
fPackagesView->HandlePackagesChanged(events);
}
@@ -40,13 +40,14 @@ public:
void HandleIconsChanged();
void HandlePackagesChanged(const PackageInfoEvents& events);
void HandlePackagesChanged(
const std::vector<PackageInfoChangeEvent>& events);
void SetLoading(bool isLoading);
private:
void _AdjustViews();
void _HandlePackageChanged(const PackageInfoEvent& event);
void _HandlePackageChanged(const PackageChangeEvent& event);
void _BuildNoResultsView();
private:
+7 -4
View File
@@ -1,6 +1,6 @@
/*
* 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.
*/
@@ -27,6 +27,9 @@
#define B_TRANSLATION_CONTEXT "FilterView"
const char* const filter_view_keys::kKeySearchTerms = "search_terms";
FilterView::FilterView()
:
BGroupView("filter view", B_VERTICAL)
@@ -85,7 +88,7 @@ FilterView::MessageReceived(BMessage* message)
case 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);
break;
}
@@ -146,7 +149,7 @@ FilterView::_MatchesCategoryCode(BMenuItem* item, const BString& code)
if (message == NULL)
return false;
BString itemCode;
message->FindString("code", &itemCode);
message->FindString(shared_message_keys::kKeyCode, &itemCode);
return itemCode == code;
}
@@ -159,7 +162,7 @@ FilterView::_AddCategoriesToMenu(Model& model, BMenu* menu)
for (it = categories.begin(); it != categories.end(); it++) {
const CategoryRef& category = *it;
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);
menu->AddItem(item);
}
+8 -1
View File
@@ -1,6 +1,6 @@
/*
* 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.
*/
#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 {
public:
FilterView();
+104 -54
View File
@@ -3,7 +3,7 @@
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2013, Rene Gollent, rene@gollent.com.
* 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>.
* 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"
const bigtime_t kIncrementViewCounterDelayMicros = 3 * 1000 * 1000;
@@ -180,7 +192,7 @@ public:
private:
// PackageInfoListener
virtual void PackagesChanged(const PackageInfoEvents& events)
virtual void PackagesChanged(const PackageChangeEvents& events)
{
fMainWindow->PackagesChanged(events);
}
@@ -261,7 +273,7 @@ MainWindow::MainWindow(const BMessage& settings)
fModel.AddPackageListener(fPackageInfoListener);
BMessage columnSettings;
if (settings.FindMessage("column settings", &columnSettings) == B_OK)
if (settings.FindMessage(kKeyColumnSettings, &columnSettings) == B_OK)
fPackageListView->LoadState(&columnSettings);
_RestoreModelSettings(settings);
@@ -410,7 +422,7 @@ MainWindow::QuitRequested()
BMessage settings;
StoreSettings(settings);
BMessage message(MSG_MAIN_WINDOW_CLOSED);
message.AddMessage(KEY_WINDOW_SETTINGS, &settings);
message.AddMessage(main_window_keys::kKeyWindowSettings, &settings);
be_app->PostMessage(&message);
if (fShuttingDownWindow != NULL) {
@@ -573,7 +585,7 @@ MainWindow::MessageReceived(BMessage* message)
case MSG_SERVER_DATA_CHANGED:
{
BString name;
if (message->FindString("name", &name) == B_OK) {
if (message->FindString(shared_message_keys::kKeyPackageName, &name) == B_OK) {
if (fPackageInfoView->Package()->Name() == name) {
_PopulatePackageAsync(true);
} else {
@@ -592,7 +604,7 @@ MainWindow::MessageReceived(BMessage* message)
case MSG_PACKAGE_SELECTED:
{
BString name;
if (message->FindString("name", &name) == B_OK) {
if (message->FindString(shared_message_keys::kKeyPackageName, &name) == B_OK) {
PackageInfoRef package;
package = fModel.PackageForName(name);
@@ -611,7 +623,7 @@ MainWindow::MessageReceived(BMessage* message)
case MSG_CATEGORY_SELECTED:
{
BString code;
if (message->FindString("code", &code) != B_OK)
if (message->FindString(shared_message_keys::kKeyCode, &code) != B_OK)
code = "";
fModel.SetFilterSpecification(
PackageFilterSpecificationBuilder(fModel.FilterSpecification())
@@ -623,7 +635,7 @@ MainWindow::MessageReceived(BMessage* message)
case MSG_DEPOT_SELECTED:
{
BString name;
if (message->FindString("name", &name) != B_OK)
if (message->FindString(shared_message_keys::kKeyDepotName, &name) != B_OK)
name = "";
fModel.SetFilterSpecification(
PackageFilterSpecificationBuilder(fModel.FilterSpecification())
@@ -637,7 +649,7 @@ MainWindow::MessageReceived(BMessage* message)
{
// TODO: Do this with a delay!
BString searchTerms;
if (message->FindString("search terms", &searchTerms) != B_OK)
if (message->FindString(filter_view_keys::kKeySearchTerms, &searchTerms) != B_OK)
searchTerms = "";
fModel.SetFilterSpecification(
PackageFilterSpecificationBuilder(fModel.FilterSpecification())
@@ -657,6 +669,34 @@ MainWindow::MessageReceived(BMessage* message)
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:
_RatePackage();
break;
@@ -723,13 +763,13 @@ MainWindow::StoreSettings(BMessage& settings)
{
settings.AddRect(_WindowFrameName(), Frame());
if (!fSinglePackageMode) {
settings.AddRect("window frame", Frame());
settings.AddRect(kKeyWindowFrame, Frame());
BMessage columnSettings;
if (fPackageListView != NULL)
fPackageListView->SaveState(&columnSettings);
settings.AddMessage("column settings", &columnSettings);
settings.AddMessage(kKeyColumnSettings, &columnSettings);
settings.AddString(SETTING_PACKAGE_LIST_VIEW_MODE,
main_window_package_list_view_mode_str(fModel.PackageListViewMode()));
@@ -751,7 +791,7 @@ MainWindow::StoreSettings(BMessage& settings)
fModel.CanShareAnonymousUsageData());
}
settings.AddString("username", fModel.Nickname());
settings.AddString(SETTING_NICKNAME, fModel.Nickname());
}
@@ -769,7 +809,7 @@ MainWindow::Consume(ProcessCoordinator* item)
in the GUI.
*/
void
MainWindow::PackagesChanged(const PackageInfoEvents& events)
MainWindow::PackagesChanged(const PackageChangeEvents& events)
{
BMessage message(MSG_PACKAGES_CHANGED);
status_t result = events.Archive(&message);
@@ -788,32 +828,35 @@ MainWindow::PackagesChanged(const PackageInfoEvents& events)
void
MainWindow::_HandlePackagesChanged(const BMessage* message)
{
PackageInfoEvents events;
// 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)
{
PackageChangeEvents packageEvents(message);
// if there are no events to process then drop.
if (events.IsEmpty()) {
if (packageEvents.IsEmpty()) {
HDINFO("window encountered an empty packages changed");
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.
@@ -826,14 +869,17 @@ MainWindow::_HandlePackagesChanged(const PackageInfoEvents& events)
std::vector<PackageInfoRef> addedFeaturedPackages;
std::vector<PackageInfoRef> removedFeaturedPackages;
for (int32 i = events.CountEvents() - 1; i >= 0; i--) {
const PackageInfoEvent event = events.EventAtIndex(i);
std::vector<PackageInfoChangeEvent>::const_iterator it;
if (event.Changes() & watchedChanges) {
const PackageInfoRef package = event.Package();
const bool isProminent = PackageUtils::IsProminent(package);
for (it = packageInfoEvents.begin(); it != packageInfoEvents.end(); it++) {
const PackageInfoChangeEvent packageInfoEvent = *it;
if (packageInfoEvent.Changes() & watchedChanges) {
const PackageInfoRef package = packageInfoEvent.Package();
if (package.IsSet()) {
const bool isProminent = PackageUtils::IsProminent(package);
if (filter->AcceptsPackage(package)) {
addedPackages.push_back(package);
@@ -845,6 +891,9 @@ MainWindow::_HandlePackagesChanged(const PackageInfoEvents& events)
if (isProminent)
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.
if (!fSinglePackageMode) {
fFeaturedPackagesView->HandlePackagesChanged(events);
fPackageListView->HandlePackagesChanged(events);
fFeaturedPackagesView->HandlePackagesChanged(packageInfoEvents);
fPackageListView->HandlePackagesChanged(packageInfoEvents);
}
fPackageInfoView->HandlePackagesChanged(events);
fPackageInfoView->HandlePackagesChanged(packageInfoEvents);
}
@@ -954,7 +1003,7 @@ void
MainWindow::_RestoreNickname(const BMessage& settings)
{
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;
if (IdentityAndAccessUtils::RetrieveCredentials(nickname, credentials) == B_OK) {
fModel.SetCredentials(credentials);
@@ -972,9 +1021,9 @@ const char*
MainWindow::_WindowFrameName() const
{
if (fSinglePackageMode)
return "small window frame";
return kKeySinglePackageWindowFrame;
return "window frame";
return kKeyWindowFrame;
}
@@ -1173,7 +1222,7 @@ MainWindow::_SetupDelayedIncrementViewCounter(const PackageInfoRef package)
delete fIncrementViewCounterDelayedRunner;
}
BMessage message(MSG_INCREMENT_VIEW_COUNTER);
message.SetString("name", package->Name());
message.SetString(shared_message_keys::kKeyPackageName, package->Name());
fIncrementViewCounterDelayedRunner
= new BMessageRunner(BMessenger(this), &message, kIncrementViewCounterDelayMicros, 1);
if (fIncrementViewCounterDelayedRunner->InitCheck() != B_OK)
@@ -1185,7 +1234,7 @@ void
MainWindow::_HandleIncrementViewCounter(const BMessage* message)
{
BString name;
if (message->FindString("name", &name) == B_OK) {
if (message->FindString(shared_message_keys::kKeyPackageName, &name) == B_OK) {
const PackageInfoRef& viewedPackage = fPackageInfoView->Package();
if (viewedPackage.IsSet()) {
const BString& viewedPackageName = viewedPackage->Name();
@@ -1294,12 +1343,12 @@ MainWindow::_BulkLoadCompleteReceived(status_t errorStatus)
PackagesSummary packagesSummary = fModel.GeneratePackagesSummary();
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 "
"that may cause data to be outdated or missing from the "
"application's display. Additional details regarding this "
"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
@@ -1373,8 +1422,8 @@ MainWindow::_NotifyWorkStatusChange(const BString& text, float progress)
BMessage message(MSG_WORK_STATUS_CHANGE);
if (!text.IsEmpty())
message.AddString(KEY_WORK_STATUS_TEXT, text);
message.AddFloat(KEY_WORK_STATUS_PROGRESS, progress);
message.AddString(kKeyWorkStatusText, text);
message.AddFloat(kKeyWorkStatusProgress, progress);
this->PostMessage(&message, this);
}
@@ -1413,7 +1462,8 @@ MainWindow::_SetStateForPackagesByName(BStringList& packageNames, PackageState s
if (package.IsSet()) {
PackageLocalInfoRef localInfo
= PackageLocalInfoBuilder(package->LocalInfo()).WithState(state).BuildRef();
= PackageLocalInfoBuilder(package->LocalInfo()).WithState(state)
.ClearInstallationLocations().BuildRef();
modifiedPackages.push_back(
PackageInfoBuilder(package).WithLocalInfo(localInfo).BuildRef());
@@ -1439,10 +1489,10 @@ MainWindow::_HandleWorkStatusChangeMessageReceived(const BMessage* message)
BString text;
float progress;
if (message->FindString(KEY_WORK_STATUS_TEXT, &text) == B_OK)
if (message->FindString(kKeyWorkStatusText, &text) == B_OK)
fWorkStatusView->SetText(text);
if (message->FindFloat(KEY_WORK_STATUS_PROGRESS, &progress) == B_OK) {
if (message->FindFloat(kKeyWorkStatusProgress, &progress) == B_OK) {
if (progress < 0.0f)
fWorkStatusView->SetBusy();
else
@@ -1590,7 +1640,7 @@ MainWindow::_UpdateAvailableRepositories()
if (depot->Name().Length() != 0) {
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);
if (item == NULL)
@@ -1709,7 +1759,7 @@ MainWindow::UserCredentialsFailed()
"and you should login again with your updated password.");
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)
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, Rene Gollent <rene@gollent.com>.
* 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.
*/
#ifndef MAIN_WINDOW_H
@@ -38,6 +38,14 @@ class WorkStatusView;
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 :
private ProcessCoordinatorConsumer, public ProcessCoordinatorListener,
public UserDetailVerifierListener, public BWindow {
@@ -66,7 +74,7 @@ public:
const UserDetail& userDetail);
// services PackageInfoListener via MainWindowPackageInfoListener
void PackagesChanged(const PackageInfoEvents& events);
void PackagesChanged(const PackageChangeEvents& events);
private:
static const BString _WindowTitleForPackage(const PackageInfoRef& pkg);
@@ -128,7 +136,7 @@ private:
ProcessCoordinatorState& coordinatorState);
void _HandlePackagesChanged(const BMessage* message);
void _HandlePackagesChanged(const PackageInfoEvents& events);
void _HandlePackagesChanged(const PackageChangeEvents& events);
static status_t _RefreshModelThreadWorker(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 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.
*/
#include "PackageInfoView.h"
@@ -506,13 +506,10 @@ private:
class PackageActionView : public BView {
public:
PackageActionView(ProcessCoordinatorConsumer* processCoordinatorConsumer,
Model* model)
PackageActionView()
:
BView("about view", B_WILL_DRAW),
fModel(model),
fLayout(new BGroupLayout(B_HORIZONTAL)),
fProcessCoordinatorConsumer(processCoordinatorConsumer),
fStatusLabel(NULL),
fStatusBar(NULL)
{
@@ -526,20 +523,6 @@ public:
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)
{
if (PackageUtils::State(package) == DOWNLOADING)
@@ -626,6 +609,7 @@ private:
BButton* button = (BButton*)fButtons.ItemAtFast(index++);
button->SetLabel(action->Title());
button->SetMessage(message);
button->SetTarget(Window());
}
}
@@ -637,7 +621,7 @@ private:
BButton* button = new BButton(action->Title(), message);
fLayout->AddView(button);
button->SetTarget(this);
button->SetTarget(Window());
fButtons.AddItem(button);
}
}
@@ -666,19 +650,8 @@ private:
}
}
void _RunPackageAction(BMessage* message)
{
ProcessCoordinator* processCoordinator
= ProcessCoordinatorFactory::CreatePackageActionCoordinator(fModel, message);
fProcessCoordinatorConsumer->Consume(processCoordinator);
_DisableButtonForPackageActionMessage(message);
}
private:
Model* fModel;
BGroupLayout* fLayout;
ProcessCoordinatorConsumer*
fProcessCoordinatorConsumer;
BList fButtons;
BStringView* fStatusLabel;
@@ -1352,7 +1325,7 @@ PackageInfoView::PackageInfoView(Model* model,
fCardLayout->SetVisibleItem((int32)0);
fTitleView = new TitleView(fModel);
fPackageActionView = new PackageActionView(processCoordinatorConsumer, model);
fPackageActionView = new PackageActionView();
fPackageActionView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
fPagesView = new PagesView(model);
@@ -1422,7 +1395,7 @@ PackageInfoView::SetPackage(const PackageInfoRef& packageRef)
void
PackageInfoView::_HandlePackageChanged(const PackageInfoEvent& event)
PackageInfoView::_HandlePackageChanged(const PackageInfoChangeEvent& event)
{
uint32 changes = event.Changes();
@@ -1453,13 +1426,14 @@ PackageInfoView::_HandlePackageChanged(const PackageInfoEvent& event)
void
PackageInfoView::HandlePackagesChanged(const PackageInfoEvents& events)
PackageInfoView::HandlePackagesChanged(const std::vector<PackageInfoChangeEvent>& events)
{
if (!fPackage.IsSet())
return;
for (int32 i = events.CountEvents() - 1; i >= 0; i--) {
PackageInfoEvent event = events.EventAtIndex(i);
_HandlePackageChanged(event);
std::vector<PackageInfoChangeEvent>::const_iterator it;
for (it = events.begin(); it != events.end(); it++) {
const PackageInfoChangeEvent packageInfoChangeEvent = *it;
_HandlePackageChanged(packageInfoChangeEvent);
}
}
+6 -3
View File
@@ -1,11 +1,13 @@
/*
* 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.
*/
#ifndef PACKAGE_INFO_VIEW_H
#define PACKAGE_INFO_VIEW_H
#include <vector>
#include <GroupView.h>
#include "Model.h"
@@ -43,7 +45,8 @@ public:
void HandleScreenshotCached(const ScreenshotCoordinate& coordinate);
void HandleIconsChanged();
void HandlePackagesChanged(const PackageInfoEvents& events);
void HandlePackagesChanged(
const std::vector<PackageInfoChangeEvent>& events);
private:
static const ScreenshotCoordinate
@@ -52,7 +55,7 @@ private:
void _HandleScreenshotCached(const PackageInfoRef& package,
const ScreenshotCoordinate& coordinate);
void _HandlePackageChanged(const PackageInfoEvent& event);
void _HandlePackageChanged(const PackageInfoChangeEvent& event);
private:
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 2015, Axel Dörfler, <axeld@pinc-software.de>.
* Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
@@ -1167,18 +1167,19 @@ PackageListView::HandleIconsChanged()
void
PackageListView::HandlePackagesChanged(const PackageInfoEvents& events)
PackageListView::HandlePackagesChanged(const std::vector<PackageInfoChangeEvent>& events)
{
for (int32 i = events.CountEvents() - 1; i >= 0; i--)
_HandlePackageChanged(events.EventAtIndex(i));
std::vector<PackageInfoChangeEvent>::const_iterator it;
for (it = events.begin(); it != events.end(); it++)
_HandlePackageChanged(*it);
}
void
PackageListView::_HandlePackageChanged(const PackageInfoEvent& event)
PackageListView::_HandlePackageChanged(const PackageInfoChangeEvent& event)
{
uint32 changes = event.Changes();
PackageInfoRef package = event.Package();
const PackageInfoRef package = event.Package();
if (!package.IsSet() || 0 == changes)
return;
@@ -1221,7 +1222,7 @@ PackageListView::SelectionChanged()
PackageRow* selected = dynamic_cast<PackageRow*>(CurrentSelection());
if (selected != NULL)
message.AddString("name", selected->Package()->Name());
message.AddString(shared_message_keys::kKeyPackageName, selected->Package()->Name());
Window()->PostMessage(&message);
}
+4 -3
View File
@@ -1,7 +1,7 @@
/*
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
* 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.
*/
#ifndef PACKAGE_LIST_VIEW_H
@@ -41,10 +41,11 @@ public:
void AttachWorkStatusView(WorkStatusView* view);
void HandleIconsChanged();
void HandlePackagesChanged(const PackageInfoEvents& events);
void HandlePackagesChanged(
const std::vector<PackageInfoChangeEvent>& events);
private:
void _HandlePackageChanged(const PackageInfoEvent& event);
void _HandlePackageChanged(const PackageInfoChangeEvent& event);
void _AddPackage(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 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.
*/
@@ -46,6 +46,9 @@ enum {
MSG_RATING_DETERMINATE_CHANGED = 'rdch'
};
static const char* const kKeyRating = "rating";
//! Layouts the scrollbar so it looks nice with no border and the document
// window look.
class ScrollView : public BScrollView {
@@ -130,7 +133,7 @@ public:
{
SetPermanentRating(_RatingForMousePos(where));
BMessage message(MSG_PACKAGE_RATED);
message.AddFloat("rating", fPermanentRating);
message.AddFloat(kKeyRating, fPermanentRating);
Window()->PostMessage(&message, Window());
}
@@ -286,7 +289,7 @@ RatePackageWindow::_InitStabilitiesMenu(BPopUpMenu* menu)
for (it = ratingStabilities.begin(); it != ratingStabilities.end(); it++) {
const RatingStabilityRef ratingStability = *it;
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);
menu->AddItem(item);
}
@@ -301,18 +304,18 @@ RatePackageWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_PACKAGE_RATED:
message->FindFloat("rating", &fRating);
message->FindFloat(kKeyRating, &fRating);
fRatingDeterminate = true;
fSetRatingView->SetRatingDeterminate(true);
fRatingDeterminateCheckBox->SetValue(B_CONTROL_ON);
break;
case MSG_STABILITY_SELECTED:
message->FindString("code", &fStabilityCode);
message->FindString(shared_message_keys::kKeyCode, &fStabilityCode);
break;
case MSG_LANGUAGE_SELECTED:
message->FindString("id", &fCommentLanguageId);
message->FindString(shared_message_keys::kKeyLanguageId, &fCommentLanguageId);
break;
case MSG_RATING_DETERMINATE_CHANGED:
@@ -369,7 +372,7 @@ void
RatePackageWindow::_RefreshPackageData()
{
BMessage message(MSG_SERVER_DATA_CHANGED);
message.AddString("name", fPackage->Name());
message.AddString(shared_message_keys::kKeyPackageName, fPackage->Name());
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.
* All rights reserved. Distributed under the terms of the MIT License.
*/
@@ -305,9 +305,9 @@ ToLatestUserUsageConditionsWindow::_FetchDataPerform()
void
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 "
"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 {
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(responsePayload);
if (errorCode == ERROR_CODE_NONE) {
AppUtils::NotifySimpleError(B_TRANSLATE("Usage conditions agreed"),
B_TRANSLATE("The current usage conditions have been agreed to."));
AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("Usage conditions agreed"),
B_TRANSLATE("The current usage conditions have been agreed to.")));
messenger.SendMessage(B_QUIT_REQUESTED);
} else {
ServerHelper::NotifyServerJsonRpcError(responsePayload);
+39 -37
View File
@@ -1,6 +1,6 @@
/*
* 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.
*/
@@ -48,11 +48,11 @@
#define PLACEHOLDER_TEXT B_UTF8_ELLIPSIS
#define KEY_USER_CREDENTIALS "userCredentials"
#define KEY_CAPTCHA_IMAGE "captchaImage"
#define KEY_USER_USAGE_CONDITIONS "userUsageConditions"
#define KEY_PASSWORD_REQUIREMENTS "passwordRequirements"
#define KEY_VALIDATION_FAILURES "validationFailures"
static const char* const kKeyUserCredentials = "user_credentials";
static const char* const kKeyCaptchaImage = "captcha_image";
static const char* const kKeyUserUsageConditions = "user_usage_conditions";
static const char* const kKeyPasswordRequirements = "password_requirements";
static const char* const kKeyValidationFailures = "validation_failures";
enum ActionTabs {
@@ -305,7 +305,7 @@ UserLoginWindow::MessageReceived(BMessage* message)
break;
case MSG_LANGUAGE_SELECTED:
message->FindString("id", &fPreferredLanguageId);
message->FindString(shared_message_keys::kKeyLanguageId, &fPreferredLanguageId);
break;
case MSG_LOGIN_ERROR:
@@ -319,7 +319,7 @@ UserLoginWindow::MessageReceived(BMessage* message)
case MSG_LOGIN_SUCCESS:
{
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");
_HandleAuthenticationSuccess(UserCredentials(&credentialsMessage));
@@ -328,7 +328,7 @@ UserLoginWindow::MessageReceived(BMessage* message)
case MSG_CREATE_ACCOUNT_SUCCESS:
{
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");
_HandleCreateAccountSuccess(UserCredentials(&credentialsMessage));
@@ -337,7 +337,7 @@ UserLoginWindow::MessageReceived(BMessage* message)
case MSG_CREATE_ACCOUNT_FAILED:
{
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");
ValidationFailures validationFailures(&validationFailuresMessage);
_HandleCreateAccountFailure(validationFailures);
@@ -530,7 +530,7 @@ UserLoginWindow::_AuthenticateThread(UserCredentials& userCredentials)
BMessage credentialsMessage;
status = userCredentials.Archive(&credentialsMessage);
if (status == B_OK)
status = message.AddMessage(KEY_USER_CREDENTIALS, &credentialsMessage);
status = message.AddMessage(kKeyUserCredentials, &credentialsMessage);
if (status == B_OK)
messenger.SendMessage(&message);
} else {
@@ -578,9 +578,9 @@ UserLoginWindow::_HandleAuthenticationError()
void
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"
" supplied. Check your credentials and try again."));
" supplied. Check your credentials and try again.")));
fPasswordField->SetText("");
_EnableMutableControls(true);
}
@@ -737,21 +737,19 @@ UserLoginWindow::_CreateAccountSetupThreadEntry(void* data)
BMessage captchaMessage;
result = captcha.Archive(&captchaMessage);
if (result == B_OK)
result = message.AddMessage(KEY_CAPTCHA_IMAGE, &captchaMessage);
result = message.AddMessage(kKeyCaptchaImage, &captchaMessage);
}
if (result == B_OK && shouldFetchUserUsageConditions) {
BMessage userUsageConditionsMessage;
result = userUsageConditions.Archive(&userUsageConditionsMessage);
if (result == B_OK)
result = message.AddMessage(KEY_USER_USAGE_CONDITIONS, &userUsageConditionsMessage);
result = message.AddMessage(kKeyUserUsageConditions, &userUsageConditionsMessage);
}
if (result == B_OK && shouldFetchPasswordRequirements) {
BMessage passwordRequirementsMessage;
result = passwordRequirements.Archive(&passwordRequirementsMessage);
if (result == B_OK) {
result
= message.AddMessage(KEY_PASSWORD_REQUIREMENTS, &passwordRequirementsMessage);
}
if (result == B_OK)
result = message.AddMessage(kKeyPasswordRequirements, &passwordRequirementsMessage);
}
if (result == B_OK) {
HDDEBUG("successfully completed collection of create account "
@@ -783,10 +781,10 @@ UserLoginWindow::_CreateAccountUserUsageConditionsSetupThread(
status_t result = interface->RetrieveUserUsageConditions(NULL, userUsageConditions);
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 "
"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;
@@ -801,10 +799,11 @@ UserLoginWindow::_CreateAccountPasswordRequirementsSetupThread(
status_t result = interface->RetrievePasswordRequirements(passwordRequirements);
if (result != B_OK) {
AppUtils::NotifySimpleError(B_TRANSLATE("Password requirements download problem"),
B_TRANSLATE("An error has arisen downloading the password "
"requirements required to create a new user. Check the log for "
"details and try again. " ALERT_MSG_LOGS_USER_GUIDE));
AppUtils::NotifySimpleError(
SimpleAlert(B_TRANSLATE("Password requirements download problem"),
B_TRANSLATE("An error has arisen downloading the password requirements required to "
"create a new user. Check the log for details and try "
"again. " ALERT_MSG_LOGS_USER_GUIDE)));
}
return result;
@@ -822,9 +821,9 @@ UserLoginWindow::_CreateAccountCaptchaSetupThread(Captcha& captcha)
// check for transport related errors.
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 "
"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.
@@ -841,9 +840,9 @@ UserLoginWindow::_CreateAccountCaptchaSetupThread(Captcha& captcha)
if (status == B_OK) {
status = _UnpackCaptcha(responsePayload, captcha);
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 "
"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 passwordRequirementsMessage;
if (message->FindMessage(KEY_CAPTCHA_IMAGE, &captchaMessage) == B_OK)
if (message->FindMessage(kKeyCaptchaImage, &captchaMessage) == B_OK)
_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));
if (message->FindMessage(KEY_PASSWORD_REQUIREMENTS, &passwordRequirementsMessage) == B_OK)
if (message->FindMessage(kKeyPasswordRequirements, &passwordRequirementsMessage) == B_OK)
_SetPasswordRequirements(new PasswordRequirements(&passwordRequirementsMessage));
_EnableMutableControls(true);
@@ -1243,6 +1242,9 @@ UserLoginWindow::_CreateAccountThreadEntry(void* data)
void
UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
{
if (detail->LanguageId().IsEmpty())
HDFATAL("the language id was not setup when creating a user");
WebAppInterfaceRef interface = fModel.WebApp();
BMessage responsePayload;
BMessenger messenger(this);
@@ -1263,7 +1265,7 @@ UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
UserCredentials userCredentials(detail->Nickname(), detail->PasswordClear());
userCredentials.Archive(&userCredentialsMessage);
BMessage message(MSG_CREATE_ACCOUNT_SUCCESS);
message.AddMessage(KEY_USER_CREDENTIALS, &userCredentialsMessage);
message.AddMessage(kKeyUserCredentials, &userCredentialsMessage);
messenger.SendMessage(&message);
break;
}
@@ -1274,7 +1276,7 @@ UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
BMessage validationFailuresMessage;
validationFailures.Archive(&validationFailuresMessage);
BMessage message(MSG_CREATE_ACCOUNT_FAILED);
message.AddMessage(KEY_VALIDATION_FAILURES, &validationFailuresMessage);
message.AddMessage(kKeyValidationFailures, &validationFailuresMessage);
messenger.SendMessage(&message);
break;
}
@@ -1290,7 +1292,7 @@ UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
BMessage validationFailuresMessage;
validationFailures.Archive(&validationFailuresMessage);
BMessage message(MSG_CREATE_ACCOUNT_FAILED);
message.AddMessage(KEY_VALIDATION_FAILURES, &validationFailuresMessage);
message.AddMessage(kKeyValidationFailures, &validationFailuresMessage);
messenger.SendMessage(&message);
break;
}
@@ -1300,8 +1302,8 @@ UserLoginWindow::_CreateAccountThread(CreateUserDetail* detail)
break;
}
} else {
AppUtils::NotifySimpleError(B_TRANSLATE("User creation error"),
B_TRANSLATE("It was not possible to create the new user."));
AppUtils::NotifySimpleError(SimpleAlert(B_TRANSLATE("User creation error"),
B_TRANSLATE("It was not possible to create the new user.")));
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 "
"conditions.");
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);
status = B_BAD_DATA;
}
@@ -378,10 +378,10 @@ UserUsageConditionsWindow::_FetchUserUsageConditionsCodeForUserPerform(UserDetai
void
UserUsageConditionsWindow::_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 details and try again. " ALERT_MSG_LOGS_USER_GUIDE));
"conditions. Check the log for details and try again. " ALERT_MSG_LOGS_USER_GUIDE)));
}
+6 -13
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.
*/
@@ -23,20 +23,13 @@
*/
/*static*/ void
AppUtils::NotifySimpleError(const char* title, const char* text,
alert_type type)
AppUtils::NotifySimpleError(const SimpleAlert& alertSimple)
{
BMessage message(MSG_ALERT_SIMPLE_ERROR);
if (title != NULL && strlen(title) != 0)
message.AddString(KEY_ALERT_TITLE, title);
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);
if (alertSimple.Archive(&message) != B_OK)
HDERROR("unable to archive alert");
else
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.
*/
#ifndef APP_UTILS_H
@@ -8,14 +8,13 @@
#include "Alert.h"
#include "Menu.h"
#include "SimpleAlert.h"
class AppUtils {
public:
static void NotifySimpleError(const char* title,
const char* text,
alert_type type = B_INFO_ALERT);
static void NotifySimpleError(const SimpleAlert& simpleAlert);
static status_t MarkItemWithKeyValueInMenuOrFirst(BMenu* menu,
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>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
@@ -12,9 +12,9 @@
#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
// 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.
*/
#include "LanguageMenuUtils.h"
@@ -19,9 +19,6 @@
#include "Logger.h"
static const char* kLanguageIdKey = "id";
/*! This method will add the supplied languages to the menu. It will
add first the popular languages, followed by a separator and then
other less popular languages.
@@ -57,7 +54,8 @@ LanguageMenuUtils::AddLanguagesToMenu(const std::vector<LanguageRef>& languages,
/* static */ void
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)
{
BMessage* message = new BMessage(MSG_LANGUAGE_SELECTED);
message->AddString(kLanguageIdKey, id);
message->AddString(shared_message_keys::kKeyLanguageId, id);
BMenuItem* item = new BMenuItem(name, message);
menu->AddItem(item);
}