1/* 2 * Copyright 2008-2010, Stephan A��mus <superstippi@gmx.de>. 3 * Copyright 1998, Eric Shepherd. 4 * All rights reserved. Distributed under the terms of the Be Sample Code 5 * license. 6 */ 7 8//! Be Newsletter Volume II, Issue 35; September 2, 1998 (Eric Shepherd) 9 10#include "SettingsMessage.h" 11 12#include <new> 13 14#include <Autolock.h> 15#include <Entry.h> 16#include <File.h> 17#include <Messenger.h> 18#include <String.h> 19 20 21SettingsMessage::SettingsMessage(directory_which directory, 22 const char* filename) 23 : 24 BMessage('pref'), 25 fListeners(0) 26{ 27 fStatus = find_directory(directory, &fPath); 28 29 if (fStatus == B_OK) 30 fStatus = fPath.Append(filename); 31 32 if (fStatus == B_OK) 33 fStatus = Load(); 34} 35 36 37SettingsMessage::~SettingsMessage() 38{ 39 Save(); 40 41 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) 42 delete reinterpret_cast<BMessenger*>(fListeners.ItemAtFast(i)); 43} 44 45 46status_t 47SettingsMessage::InitCheck() const 48{ 49 return fStatus; 50} 51 52 53status_t 54SettingsMessage::Load() 55{ 56 BAutolock _(this); 57 58 BFile file(fPath.Path(), B_READ_ONLY); 59 status_t status = file.InitCheck(); 60 61 if (status == B_OK) 62 status = Unflatten(&file); 63 64 return status; 65} 66 67 68status_t 69SettingsMessage::Save() const 70{ 71 BAutolock _(const_cast<SettingsMessage*>(this)); 72 73 BFile file(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 74 status_t status = file.InitCheck(); 75 76 if (status == B_OK) 77 status = Flatten(&file); 78 79 return status; 80} 81 82 83bool 84SettingsMessage::AddListener(const BMessenger& listener) 85{ 86 BAutolock _(this); 87 88 BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener); 89 if (listenerCopy && fListeners.AddItem(listenerCopy)) 90 return true; 91 delete listenerCopy; 92 return false; 93} 94 95 96void 97SettingsMessage::RemoveListener(const BMessenger& listener) 98{ 99 BAutolock _(this); 100 101 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) { 102 BMessenger* listenerItem = reinterpret_cast<BMessenger*>( 103 fListeners.ItemAtFast(i)); 104 if (*listenerItem == listener) { 105 fListeners.RemoveItem(i); 106 delete listenerItem; 107 return; 108 } 109 } 110} 111 112 113// #pragma mark - 114 115 116status_t 117SettingsMessage::SetValue(const char* name, bool value) 118{ 119 status_t ret = ReplaceBool(name, value); 120 if (ret != B_OK) 121 ret = AddBool(name, value); 122 if (ret == B_OK) 123 _NotifyValueChanged(name); 124 return ret; 125} 126 127 128status_t 129SettingsMessage::SetValue(const char* name, int8 value) 130{ 131 status_t ret = ReplaceInt8(name, value); 132 if (ret != B_OK) 133 ret = AddInt8(name, value); 134 if (ret == B_OK) 135 _NotifyValueChanged(name); 136 return ret; 137} 138 139 140status_t 141SettingsMessage::SetValue(const char* name, int16 value) 142{ 143 status_t ret = ReplaceInt16(name, value); 144 if (ret != B_OK) 145 ret = AddInt16(name, value); 146 if (ret == B_OK) 147 _NotifyValueChanged(name); 148 return ret; 149} 150 151 152status_t 153SettingsMessage::SetValue(const char* name, uint16 value) 154{ 155 status_t ret = ReplaceUInt16(name, value); 156 if (ret != B_OK) 157 ret = AddUInt16(name, value); 158 if (ret == B_OK) 159 _NotifyValueChanged(name); 160 return ret; 161} 162 163 164status_t 165SettingsMessage::SetValue(const char* name, int32 value) 166{ 167 status_t ret = ReplaceInt32(name, value); 168 if (ret != B_OK) 169 ret = AddInt32(name, value); 170 if (ret == B_OK) 171 _NotifyValueChanged(name); 172 return ret; 173} 174 175 176status_t 177SettingsMessage::SetValue(const char* name, uint32 value) 178{ 179 status_t ret = ReplaceUInt32(name, value); 180 if (ret != B_OK) 181 ret = AddUInt32(name, value); 182 if (ret == B_BAD_TYPE && HasData(name, B_INT32_TYPE)) { 183 // For compatibility with older versions of this class, replace an int32 184 RemoveData(name); 185 ret = AddUInt32(name, value); 186 } 187 if (ret == B_OK) 188 _NotifyValueChanged(name); 189 return ret; 190} 191 192 193status_t 194SettingsMessage::SetValue(const char* name, int64 value) 195{ 196 status_t ret = ReplaceInt64(name, value); 197 if (ret != B_OK) 198 ret = AddInt64(name, value); 199 if (ret == B_OK) 200 _NotifyValueChanged(name); 201 return ret; 202} 203 204 205status_t 206SettingsMessage::SetValue(const char* name, uint64 value) 207{ 208 status_t ret = ReplaceUInt64(name, value); 209 if (ret != B_OK) 210 ret = AddUInt64(name, value); 211 if (ret == B_OK) 212 _NotifyValueChanged(name); 213 return ret; 214} 215 216 217status_t 218SettingsMessage::SetValue(const char* name, float value) 219{ 220 status_t ret = ReplaceFloat(name, value); 221 if (ret != B_OK) 222 ret = AddFloat(name, value); 223 if (ret == B_OK) 224 _NotifyValueChanged(name); 225 return ret; 226} 227 228 229status_t 230SettingsMessage::SetValue(const char* name, double value) 231{ 232 status_t ret = ReplaceDouble(name, value); 233 if (ret != B_OK) 234 ret = AddDouble(name, value); 235 if (ret == B_OK) 236 _NotifyValueChanged(name); 237 return ret; 238} 239 240 241status_t 242SettingsMessage::SetValue(const char* name, const char* value) 243{ 244 status_t ret = ReplaceString(name, value); 245 if (ret != B_OK) 246 ret = AddString(name, value); 247 if (ret == B_OK) 248 _NotifyValueChanged(name); 249 return ret; 250} 251 252 253status_t 254SettingsMessage::SetValue(const char* name, const BString& value) 255{ 256 status_t ret = ReplaceString(name, value); 257 if (ret != B_OK) 258 ret = AddString(name, value); 259 if (ret == B_OK) 260 _NotifyValueChanged(name); 261 return ret; 262} 263 264 265status_t 266SettingsMessage::SetValue(const char* name, const BPoint& value) 267{ 268 status_t ret = ReplacePoint(name, value); 269 if (ret != B_OK) 270 ret = AddPoint(name, value); 271 if (ret == B_OK) 272 _NotifyValueChanged(name); 273 return ret; 274} 275 276 277status_t 278SettingsMessage::SetValue(const char* name, const BRect& value) 279{ 280 status_t ret = ReplaceRect(name, value); 281 if (ret != B_OK) 282 ret = AddRect(name, value); 283 if (ret == B_OK) 284 _NotifyValueChanged(name); 285 return ret; 286} 287 288 289status_t 290SettingsMessage::SetValue(const char* name, const entry_ref& value) 291{ 292 status_t ret = ReplaceRef(name, &value); 293 if (ret != B_OK) 294 ret = AddRef(name, &value); 295 if (ret == B_OK) 296 _NotifyValueChanged(name); 297 return ret; 298} 299 300 301status_t 302SettingsMessage::SetValue(const char* name, const BMessage& value) 303{ 304 status_t ret = ReplaceMessage(name, &value); 305 if (ret != B_OK) 306 ret = AddMessage(name, &value); 307 if (ret == B_OK) 308 _NotifyValueChanged(name); 309 return ret; 310} 311 312 313status_t 314SettingsMessage::SetValue(const char* name, const BFlattenable* value) 315{ 316 status_t ret = ReplaceFlat(name, const_cast<BFlattenable*>(value)); 317 if (ret != B_OK) 318 ret = AddFlat(name, const_cast<BFlattenable*>(value)); 319 if (ret == B_OK) 320 _NotifyValueChanged(name); 321 return ret; 322} 323 324 325status_t 326SettingsMessage::SetValue(const char* name, type_code type, const void* data, 327 ssize_t numBytes) 328{ 329 status_t ret = ReplaceData(name, type, data, numBytes); 330 if (ret != B_OK) 331 ret = AddData(name, type, data, numBytes); 332 if (ret == B_OK) 333 _NotifyValueChanged(name); 334 return ret; 335} 336 337 338status_t 339SettingsMessage::SetValue(const char* name, const BFont& value) 340{ 341 font_family family; 342 font_style style; 343 value.GetFamilyAndStyle(&family, &style); 344 345 BMessage fontMessage; 346 status_t ret = fontMessage.AddString("family", family); 347 if (ret == B_OK) 348 ret = fontMessage.AddString("style", style); 349 if (ret == B_OK) 350 ret = fontMessage.AddFloat("size", value.Size()); 351 352 if (ret == B_OK) { 353 if (ReplaceMessage(name, &fontMessage) != B_OK) 354 ret = AddMessage(name, &fontMessage); 355 } 356 if (ret == B_OK) 357 _NotifyValueChanged(name); 358 return ret; 359} 360 361 362// #pragma mark - 363 364 365bool 366SettingsMessage::GetValue(const char* name, bool defaultValue) const 367{ 368 bool value; 369 if (FindBool(name, &value) != B_OK) 370 return defaultValue; 371 return value; 372} 373 374 375int8 376SettingsMessage::GetValue(const char* name, int8 defaultValue) const 377{ 378 int8 value; 379 if (FindInt8(name, &value) != B_OK) 380 return defaultValue; 381 return value; 382} 383 384 385int16 386SettingsMessage::GetValue(const char* name, int16 defaultValue) const 387{ 388 int16 value; 389 if (FindInt16(name, &value) != B_OK) 390 return defaultValue; 391 return value; 392} 393 394 395uint16 396SettingsMessage::GetValue(const char* name, uint16 defaultValue) const 397{ 398 uint16 value; 399 if (FindUInt16(name, &value) != B_OK) 400 return defaultValue; 401 return value; 402} 403 404 405int32 406SettingsMessage::GetValue(const char* name, int32 defaultValue) const 407{ 408 int32 value; 409 if (FindInt32(name, &value) != B_OK) 410 return defaultValue; 411 return value; 412} 413 414 415uint32 416SettingsMessage::GetValue(const char* name, uint32 defaultValue) const 417{ 418 uint32 value; 419 if (FindUInt32(name, &value) == B_OK) 420 return value; 421 // For compatibility with older versions of this class, also accept an int32 422 int32 signedValue; 423 if (FindInt32(name, &signedValue) == B_OK && signedValue >= 0) 424 return signedValue; 425 return defaultValue; 426} 427 428 429int64 430SettingsMessage::GetValue(const char* name, int64 defaultValue) const 431{ 432 int64 value; 433 if (FindInt64(name, &value) != B_OK) 434 return defaultValue; 435 return value; 436} 437 438 439uint64 440SettingsMessage::GetValue(const char* name, uint64 defaultValue) const 441{ 442 uint64 value; 443 if (FindUInt64(name, &value) != B_OK) 444 return defaultValue; 445 return value; 446} 447 448 449float 450SettingsMessage::GetValue(const char* name, float defaultValue) const 451{ 452 float value; 453 if (FindFloat(name, &value) != B_OK) 454 return defaultValue; 455 return value; 456} 457 458 459double 460SettingsMessage::GetValue(const char* name, double defaultValue) const 461{ 462 double value; 463 if (FindDouble(name, &value) != B_OK) 464 return defaultValue; 465 return value; 466} 467 468 469BString 470SettingsMessage::GetValue(const char* name, const BString& defaultValue) const 471{ 472 BString value; 473 if (FindString(name, &value) != B_OK) 474 return defaultValue; 475 return value; 476} 477 478 479const char* 480SettingsMessage::GetValue(const char* name, const char* defaultValue) const 481{ 482 const char* value; 483 if (FindString(name, &value) != B_OK) 484 return defaultValue; 485 return value; 486} 487 488 489BPoint 490SettingsMessage::GetValue(const char *name, BPoint defaultValue) const 491{ 492 BPoint value; 493 if (FindPoint(name, &value) != B_OK) 494 return defaultValue; 495 return value; 496} 497 498 499BRect 500SettingsMessage::GetValue(const char* name, BRect defaultValue) const 501{ 502 BRect value; 503 if (FindRect(name, &value) != B_OK) 504 return defaultValue; 505 return value; 506} 507 508 509entry_ref 510SettingsMessage::GetValue(const char* name, const entry_ref& defaultValue) const 511{ 512 entry_ref value; 513 if (FindRef(name, &value) != B_OK) 514 return defaultValue; 515 return value; 516} 517 518 519BMessage 520SettingsMessage::GetValue(const char* name, const BMessage& defaultValue) const 521{ 522 BMessage value; 523 if (FindMessage(name, &value) != B_OK) 524 return defaultValue; 525 return value; 526} 527 528 529BFont 530SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const 531{ 532 BMessage fontMessage; 533 if (FindMessage(name, &fontMessage) != B_OK) 534 return defaultValue; 535 536 const char* family; 537 const char* style; 538 float size; 539 if (fontMessage.FindString("family", &family) != B_OK 540 || fontMessage.FindString("style", &style) != B_OK 541 || fontMessage.FindFloat("size", &size) != B_OK) { 542 return defaultValue; 543 } 544 545 BFont value; 546 if (value.SetFamilyAndStyle(family, style) != B_OK) 547 return defaultValue; 548 549 value.SetSize(size); 550 551 return value; 552} 553 554 555void* 556SettingsMessage::GetValue(const char* name, type_code type, ssize_t numBytes, 557 const void** defaultValue) const 558{ 559 void* value; 560 if (FindData(name, type, (const void**)&value, &numBytes) != B_OK) 561 return defaultValue; 562 return value; 563} 564 565 566// #pragma mark - private 567 568void 569SettingsMessage::_NotifyValueChanged(const char* name) const 570{ 571 BMessage message(SETTINGS_VALUE_CHANGED); 572 message.AddString("name", name); 573 574 // Add the value of that name to the notification. 575 type_code type; 576 if (GetInfo(name, &type) == B_OK) { 577 const void* data; 578 ssize_t numBytes; 579 if (FindData(name, type, &data, &numBytes) == B_OK) 580 message.AddData("value", type, data, numBytes); 581 } 582 583 int32 count = fListeners.CountItems(); 584 for (int32 i = 0; i < count; i++) { 585 BMessenger* listener = reinterpret_cast<BMessenger*>( 586 fListeners.ItemAtFast(i)); 587 listener->SendMessage(&message); 588 } 589} 590