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 21 SettingsMessage::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 37 SettingsMessage::~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 46 status_t 47 SettingsMessage::InitCheck() const 48 { 49 return fStatus; 50 } 51 52 53 status_t 54 SettingsMessage::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 68 status_t 69 SettingsMessage::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 83 bool 84 SettingsMessage::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 96 void 97 SettingsMessage::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 116 status_t 117 SettingsMessage::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 128 status_t 129 SettingsMessage::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 140 status_t 141 SettingsMessage::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 152 status_t 153 SettingsMessage::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 164 status_t 165 SettingsMessage::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 176 status_t 177 SettingsMessage::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 193 status_t 194 SettingsMessage::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 205 status_t 206 SettingsMessage::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 217 status_t 218 SettingsMessage::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 229 status_t 230 SettingsMessage::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 241 status_t 242 SettingsMessage::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 253 status_t 254 SettingsMessage::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 265 status_t 266 SettingsMessage::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 277 status_t 278 SettingsMessage::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 289 status_t 290 SettingsMessage::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 301 status_t 302 SettingsMessage::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 313 status_t 314 SettingsMessage::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 325 status_t 326 SettingsMessage::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 338 status_t 339 SettingsMessage::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 365 bool 366 SettingsMessage::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 375 int8 376 SettingsMessage::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 385 int16 386 SettingsMessage::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 395 uint16 396 SettingsMessage::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 405 int32 406 SettingsMessage::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 415 uint32 416 SettingsMessage::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 429 int64 430 SettingsMessage::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 439 uint64 440 SettingsMessage::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 449 float 450 SettingsMessage::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 459 double 460 SettingsMessage::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 469 BString 470 SettingsMessage::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 479 const char* 480 SettingsMessage::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 489 BPoint 490 SettingsMessage::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 499 BRect 500 SettingsMessage::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 509 entry_ref 510 SettingsMessage::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 519 BMessage 520 SettingsMessage::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 529 BFont 530 SettingsMessage::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 555 void* 556 SettingsMessage::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 568 void 569 SettingsMessage::_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