xref: /haiku/src/kits/shared/SettingsMessage.cpp (revision a5061ecec55353a5f394759473f1fd6df04890da)
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