590 lines
11 KiB
C++
590 lines
11 KiB
C++
/*
|
|
* Copyright 2008-2010, Stephan Aßmus <superstippi@gmx.de>.
|
|
* Copyright 1998, Eric Shepherd.
|
|
* All rights reserved. Distributed under the terms of the Be Sample Code
|
|
* license.
|
|
*/
|
|
|
|
//! Be Newsletter Volume II, Issue 35; September 2, 1998 (Eric Shepherd)
|
|
|
|
#include "SettingsMessage.h"
|
|
|
|
#include <new>
|
|
|
|
#include <Autolock.h>
|
|
#include <Entry.h>
|
|
#include <File.h>
|
|
#include <Messenger.h>
|
|
#include <String.h>
|
|
|
|
|
|
SettingsMessage::SettingsMessage(directory_which directory,
|
|
const char* filename)
|
|
:
|
|
BMessage('pref'),
|
|
fListeners(0)
|
|
{
|
|
fStatus = find_directory(directory, &fPath);
|
|
|
|
if (fStatus == B_OK)
|
|
fStatus = fPath.Append(filename);
|
|
|
|
if (fStatus == B_OK)
|
|
fStatus = Load();
|
|
}
|
|
|
|
|
|
SettingsMessage::~SettingsMessage()
|
|
{
|
|
Save();
|
|
|
|
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
|
|
delete reinterpret_cast<BMessenger*>(fListeners.ItemAtFast(i));
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::InitCheck() const
|
|
{
|
|
return fStatus;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::Load()
|
|
{
|
|
BAutolock _(this);
|
|
|
|
BFile file(fPath.Path(), B_READ_ONLY);
|
|
status_t status = file.InitCheck();
|
|
|
|
if (status == B_OK)
|
|
status = Unflatten(&file);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::Save() const
|
|
{
|
|
BAutolock _(const_cast<SettingsMessage*>(this));
|
|
|
|
BFile file(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
|
status_t status = file.InitCheck();
|
|
|
|
if (status == B_OK)
|
|
status = Flatten(&file);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
bool
|
|
SettingsMessage::AddListener(const BMessenger& listener)
|
|
{
|
|
BAutolock _(this);
|
|
|
|
BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener);
|
|
if (listenerCopy && fListeners.AddItem(listenerCopy))
|
|
return true;
|
|
delete listenerCopy;
|
|
return false;
|
|
}
|
|
|
|
|
|
void
|
|
SettingsMessage::RemoveListener(const BMessenger& listener)
|
|
{
|
|
BAutolock _(this);
|
|
|
|
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
|
|
BMessenger* listenerItem = reinterpret_cast<BMessenger*>(
|
|
fListeners.ItemAtFast(i));
|
|
if (*listenerItem == listener) {
|
|
fListeners.RemoveItem(i);
|
|
delete listenerItem;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, bool value)
|
|
{
|
|
status_t ret = ReplaceBool(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddBool(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, int8 value)
|
|
{
|
|
status_t ret = ReplaceInt8(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddInt8(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, int16 value)
|
|
{
|
|
status_t ret = ReplaceInt16(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddInt16(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, uint16 value)
|
|
{
|
|
status_t ret = ReplaceUInt16(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddUInt16(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, int32 value)
|
|
{
|
|
status_t ret = ReplaceInt32(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddInt32(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, uint32 value)
|
|
{
|
|
status_t ret = ReplaceUInt32(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddUInt32(name, value);
|
|
if (ret == B_BAD_TYPE && HasData(name, B_INT32_TYPE)) {
|
|
// For compatibility with older versions of this class, replace an int32
|
|
RemoveData(name);
|
|
ret = AddUInt32(name, value);
|
|
}
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, int64 value)
|
|
{
|
|
status_t ret = ReplaceInt64(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddInt64(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, uint64 value)
|
|
{
|
|
status_t ret = ReplaceUInt64(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddUInt64(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, float value)
|
|
{
|
|
status_t ret = ReplaceFloat(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddFloat(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, double value)
|
|
{
|
|
status_t ret = ReplaceDouble(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddDouble(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, const char* value)
|
|
{
|
|
status_t ret = ReplaceString(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddString(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, const BString& value)
|
|
{
|
|
status_t ret = ReplaceString(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddString(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, const BPoint& value)
|
|
{
|
|
status_t ret = ReplacePoint(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddPoint(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, const BRect& value)
|
|
{
|
|
status_t ret = ReplaceRect(name, value);
|
|
if (ret != B_OK)
|
|
ret = AddRect(name, value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, const entry_ref& value)
|
|
{
|
|
status_t ret = ReplaceRef(name, &value);
|
|
if (ret != B_OK)
|
|
ret = AddRef(name, &value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, const BMessage& value)
|
|
{
|
|
status_t ret = ReplaceMessage(name, &value);
|
|
if (ret != B_OK)
|
|
ret = AddMessage(name, &value);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, const BFlattenable* value)
|
|
{
|
|
status_t ret = ReplaceFlat(name, const_cast<BFlattenable*>(value));
|
|
if (ret != B_OK)
|
|
ret = AddFlat(name, const_cast<BFlattenable*>(value));
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, type_code type, const void* data,
|
|
ssize_t numBytes)
|
|
{
|
|
status_t ret = ReplaceData(name, type, data, numBytes);
|
|
if (ret != B_OK)
|
|
ret = AddData(name, type, data, numBytes);
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
status_t
|
|
SettingsMessage::SetValue(const char* name, const BFont& value)
|
|
{
|
|
font_family family;
|
|
font_style style;
|
|
value.GetFamilyAndStyle(&family, &style);
|
|
|
|
BMessage fontMessage;
|
|
status_t ret = fontMessage.AddString("family", family);
|
|
if (ret == B_OK)
|
|
ret = fontMessage.AddString("style", style);
|
|
if (ret == B_OK)
|
|
ret = fontMessage.AddFloat("size", value.Size());
|
|
|
|
if (ret == B_OK) {
|
|
if (ReplaceMessage(name, &fontMessage) != B_OK)
|
|
ret = AddMessage(name, &fontMessage);
|
|
}
|
|
if (ret == B_OK)
|
|
_NotifyValueChanged(name);
|
|
return ret;
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
bool
|
|
SettingsMessage::GetValue(const char* name, bool defaultValue) const
|
|
{
|
|
bool value;
|
|
if (FindBool(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
int8
|
|
SettingsMessage::GetValue(const char* name, int8 defaultValue) const
|
|
{
|
|
int8 value;
|
|
if (FindInt8(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
int16
|
|
SettingsMessage::GetValue(const char* name, int16 defaultValue) const
|
|
{
|
|
int16 value;
|
|
if (FindInt16(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
uint16
|
|
SettingsMessage::GetValue(const char* name, uint16 defaultValue) const
|
|
{
|
|
uint16 value;
|
|
if (FindUInt16(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
int32
|
|
SettingsMessage::GetValue(const char* name, int32 defaultValue) const
|
|
{
|
|
int32 value;
|
|
if (FindInt32(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
uint32
|
|
SettingsMessage::GetValue(const char* name, uint32 defaultValue) const
|
|
{
|
|
uint32 value;
|
|
if (FindUInt32(name, &value) == B_OK)
|
|
return value;
|
|
// For compatibility with older versions of this class, also accept an int32
|
|
int32 signedValue;
|
|
if (FindInt32(name, &signedValue) == B_OK && signedValue >= 0)
|
|
return signedValue;
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
int64
|
|
SettingsMessage::GetValue(const char* name, int64 defaultValue) const
|
|
{
|
|
int64 value;
|
|
if (FindInt64(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
uint64
|
|
SettingsMessage::GetValue(const char* name, uint64 defaultValue) const
|
|
{
|
|
uint64 value;
|
|
if (FindUInt64(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
float
|
|
SettingsMessage::GetValue(const char* name, float defaultValue) const
|
|
{
|
|
float value;
|
|
if (FindFloat(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
double
|
|
SettingsMessage::GetValue(const char* name, double defaultValue) const
|
|
{
|
|
double value;
|
|
if (FindDouble(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
BString
|
|
SettingsMessage::GetValue(const char* name, const BString& defaultValue) const
|
|
{
|
|
BString value;
|
|
if (FindString(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
const char*
|
|
SettingsMessage::GetValue(const char* name, const char* defaultValue) const
|
|
{
|
|
const char* value;
|
|
if (FindString(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
BPoint
|
|
SettingsMessage::GetValue(const char *name, BPoint defaultValue) const
|
|
{
|
|
BPoint value;
|
|
if (FindPoint(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
BRect
|
|
SettingsMessage::GetValue(const char* name, BRect defaultValue) const
|
|
{
|
|
BRect value;
|
|
if (FindRect(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
entry_ref
|
|
SettingsMessage::GetValue(const char* name, const entry_ref& defaultValue) const
|
|
{
|
|
entry_ref value;
|
|
if (FindRef(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
BMessage
|
|
SettingsMessage::GetValue(const char* name, const BMessage& defaultValue) const
|
|
{
|
|
BMessage value;
|
|
if (FindMessage(name, &value) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
BFont
|
|
SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const
|
|
{
|
|
BMessage fontMessage;
|
|
if (FindMessage(name, &fontMessage) != B_OK)
|
|
return defaultValue;
|
|
|
|
const char* family;
|
|
const char* style;
|
|
float size;
|
|
if (fontMessage.FindString("family", &family) != B_OK
|
|
|| fontMessage.FindString("style", &style) != B_OK
|
|
|| fontMessage.FindFloat("size", &size) != B_OK) {
|
|
return defaultValue;
|
|
}
|
|
|
|
BFont value;
|
|
if (value.SetFamilyAndStyle(family, style) != B_OK)
|
|
return defaultValue;
|
|
|
|
value.SetSize(size);
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
void*
|
|
SettingsMessage::GetValue(const char* name, type_code type, ssize_t numBytes,
|
|
const void** defaultValue) const
|
|
{
|
|
void* value;
|
|
if (FindData(name, type, (const void**)&value, &numBytes) != B_OK)
|
|
return defaultValue;
|
|
return value;
|
|
}
|
|
|
|
|
|
// #pragma mark - private
|
|
|
|
void
|
|
SettingsMessage::_NotifyValueChanged(const char* name) const
|
|
{
|
|
BMessage message(SETTINGS_VALUE_CHANGED);
|
|
message.AddString("name", name);
|
|
|
|
// Add the value of that name to the notification.
|
|
type_code type;
|
|
if (GetInfo(name, &type) == B_OK) {
|
|
const void* data;
|
|
ssize_t numBytes;
|
|
if (FindData(name, type, &data, &numBytes) == B_OK)
|
|
message.AddData("value", type, data, numBytes);
|
|
}
|
|
|
|
int32 count = fListeners.CountItems();
|
|
for (int32 i = 0; i < count; i++) {
|
|
BMessenger* listener = reinterpret_cast<BMessenger*>(
|
|
fListeners.ItemAtFast(i));
|
|
listener->SendMessage(&message);
|
|
}
|
|
}
|