1 /*****************************************************************************/ 2 // TranslatorSettings 3 // Written by Michael Wilber, OBOS Translation Kit Team 4 // 5 // TranslatorSettings.cpp 6 // 7 // This class manages (saves/loads/locks/unlocks) the settings 8 // for a Translator. 9 // 10 // 11 // Copyright (c) 2004 OpenBeOS Project 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a 14 // copy of this software and associated documentation files (the "Software"), 15 // to deal in the Software without restriction, including without limitation 16 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 // and/or sell copies of the Software, and to permit persons to whom the 18 // Software is furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included 21 // in all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 // DEALINGS IN THE SOFTWARE. 30 /*****************************************************************************/ 31 32 #include <string.h> 33 #include <File.h> 34 #include <FindDirectory.h> 35 #include <TranslatorFormats.h> 36 // for B_TRANSLATOR_EXT_* 37 #include "TranslatorSettings.h" 38 39 // --------------------------------------------------------------- 40 // Constructor 41 // 42 // Sets the default settings, location for the settings file 43 // and sets the reference count to 1 44 // 45 // Preconditions: 46 // 47 // Parameters: 48 // 49 // Postconditions: 50 // 51 // Returns: 52 // --------------------------------------------------------------- 53 TranslatorSettings::TranslatorSettings(const char *settingsFile, 54 TranSetting *defaults, int32 defCount) 55 : fLock("TranslatorSettings Lock") 56 { 57 if (find_directory(B_USER_SETTINGS_DIRECTORY, &fSettingsPath)) 58 fSettingsPath.SetTo("/tmp"); 59 fSettingsPath.Append(settingsFile); 60 61 fRefCount = 1; 62 63 if (defCount > 0) { 64 fDefaults = defaults; 65 fDefCount = defCount; 66 } else { 67 fDefaults = NULL; 68 fDefCount = 0; 69 } 70 71 // Add Default Settings 72 // (Used when loading from the settings file or from 73 // a BMessage fails) 74 const TranSetting *defs = fDefaults; 75 for (int32 i = 0; i < fDefCount; i++) { 76 switch (defs[i].dataType) { 77 case TRAN_SETTING_BOOL: 78 fSettingsMsg.AddBool(defs[i].name, 79 static_cast<bool>(defs[i].defaultVal)); 80 break; 81 82 case TRAN_SETTING_INT32: 83 fSettingsMsg.AddInt32(defs[i].name, defs[i].defaultVal); 84 break; 85 86 default: 87 // ASSERT here? Erase the bogus setting entry instead? 88 break; 89 } 90 } 91 } 92 93 // --------------------------------------------------------------- 94 // Acquire 95 // 96 // Returns a pointer to the TranslatorSettings and increments 97 // the reference count. 98 // 99 // Preconditions: 100 // 101 // Parameters: 102 // 103 // Postconditions: 104 // 105 // Returns: pointer to this TranslatorSettings object 106 // --------------------------------------------------------------- 107 TranslatorSettings * 108 TranslatorSettings::Acquire() 109 { 110 TranslatorSettings *psettings = NULL; 111 112 fLock.Lock(); 113 fRefCount++; 114 psettings = this; 115 fLock.Unlock(); 116 117 return psettings; 118 } 119 120 // --------------------------------------------------------------- 121 // Release 122 // 123 // Decrements the reference count and deletes the 124 // TranslatorSettings if the reference count is zero. 125 // 126 // Preconditions: 127 // 128 // Parameters: 129 // 130 // Postconditions: 131 // 132 // Returns: pointer to this TranslatorSettings object if 133 // the reference count is greater than zero, returns NULL 134 // if the reference count is zero and the TranslatorSettings 135 // object has been deleted 136 // --------------------------------------------------------------- 137 TranslatorSettings * 138 TranslatorSettings::Release() 139 { 140 TranslatorSettings *psettings = NULL; 141 142 fLock.Lock(); 143 fRefCount--; 144 if (fRefCount > 0) { 145 psettings = this; 146 fLock.Unlock(); 147 } else 148 delete this; 149 // delete this object and 150 // release locks 151 152 return psettings; 153 } 154 155 // --------------------------------------------------------------- 156 // Destructor 157 // 158 // Does nothing! 159 // 160 // Preconditions: 161 // 162 // Parameters: 163 // 164 // Postconditions: 165 // 166 // Returns: 167 // --------------------------------------------------------------- 168 TranslatorSettings::~TranslatorSettings() 169 { 170 } 171 172 // --------------------------------------------------------------- 173 // LoadSettings 174 // 175 // Loads the settings by reading them from the default 176 // settings file. 177 // 178 // Preconditions: 179 // 180 // Parameters: 181 // 182 // Postconditions: 183 // 184 // Returns: B_OK if there were no errors or an error code from 185 // BFile::SetTo() or BMessage::Unflatten() if there were errors 186 // --------------------------------------------------------------- 187 status_t 188 TranslatorSettings::LoadSettings() 189 { 190 status_t result; 191 192 fLock.Lock(); 193 194 // Don't try to open the settings file if there are 195 // no settings that need to be loaded 196 if (fDefCount > 0) { 197 BFile settingsFile; 198 result = settingsFile.SetTo(fSettingsPath.Path(), B_READ_ONLY); 199 if (result == B_OK) { 200 BMessage msg; 201 result = msg.Unflatten(&settingsFile); 202 if (result == B_OK) 203 result = LoadSettings(&msg); 204 } 205 } else 206 result = B_OK; 207 208 fLock.Unlock(); 209 210 return result; 211 } 212 213 // --------------------------------------------------------------- 214 // LoadSettings 215 // 216 // Loads the settings from a BMessage passed to the function. 217 // 218 // Preconditions: 219 // 220 // Parameters: pmsg pointer to BMessage that contains the 221 // settings 222 // 223 // Postconditions: 224 // 225 // Returns: B_BAD_VALUE if pmsg is NULL or invalid options 226 // have been found, B_OK if there were no 227 // errors or an error code from BMessage::FindBool() or 228 // BMessage::ReplaceBool() if there were other errors 229 // --------------------------------------------------------------- 230 status_t 231 TranslatorSettings::LoadSettings(BMessage *pmsg) 232 { 233 if (pmsg == NULL) 234 return B_BAD_VALUE; 235 236 fLock.Lock(); 237 const TranSetting *defaults = fDefaults; 238 for (int32 i = 0; i < fDefCount; i++) { 239 switch (defaults[i].dataType) { 240 case TRAN_SETTING_BOOL: 241 { 242 bool value; 243 if (pmsg->FindBool(defaults[i].name, &value) != B_OK) { 244 if (fSettingsMsg.HasBool(defaults[i].name)) 245 break; 246 else 247 value = static_cast<bool>(defaults[i].defaultVal); 248 } 249 250 fSettingsMsg.ReplaceBool(defaults[i].name, value); 251 break; 252 } 253 254 case TRAN_SETTING_INT32: 255 { 256 int32 value; 257 if (pmsg->FindInt32(defaults[i].name, &value) != B_OK) { 258 if (fSettingsMsg.HasInt32(defaults[i].name)) 259 break; 260 else 261 value = defaults[i].defaultVal; 262 } 263 264 fSettingsMsg.ReplaceInt32(defaults[i].name, value); 265 break; 266 } 267 268 default: 269 // TODO: ASSERT here? Erase the bogus setting entry instead? 270 break; 271 } 272 } 273 274 fLock.Unlock(); 275 return B_OK; 276 } 277 278 // --------------------------------------------------------------- 279 // SaveSettings 280 // 281 // Saves the settings as a flattened BMessage to the default 282 // settings file 283 // 284 // Preconditions: 285 // 286 // Parameters: 287 // 288 // Postconditions: 289 // 290 // Returns: B_OK if no errors or an error code from BFile::SetTo() 291 // or BMessage::Flatten() if there were errors 292 // --------------------------------------------------------------- 293 status_t 294 TranslatorSettings::SaveSettings() 295 { 296 status_t result; 297 298 fLock.Lock(); 299 300 // Only write out settings file if there are 301 // actual settings stored by this object 302 if (fDefCount > 0) { 303 BFile settingsFile; 304 result = settingsFile.SetTo(fSettingsPath.Path(), 305 B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 306 if (result == B_OK) 307 result = fSettingsMsg.Flatten(&settingsFile); 308 } else 309 result = B_OK; 310 311 fLock.Unlock(); 312 313 return result; 314 } 315 316 // --------------------------------------------------------------- 317 // GetConfigurationMessage 318 // 319 // Saves the current settings to the BMessage passed to the 320 // function 321 // 322 // Preconditions: 323 // 324 // Parameters: pmsg pointer to BMessage where the settings 325 // will be stored 326 // 327 // Postconditions: 328 // 329 // Returns: B_OK if there were no errors or an error code from 330 // BMessage::RemoveName() or BMessage::AddBool() if there were 331 // errors 332 // --------------------------------------------------------------- 333 status_t 334 TranslatorSettings::GetConfigurationMessage(BMessage *pmsg) 335 { 336 status_t result = B_BAD_VALUE; 337 338 if (pmsg) { 339 int32 i; 340 for (i = 0; i < fDefCount; i++) { 341 result = pmsg->RemoveName(fDefaults[i].name); 342 if (result != B_OK && result != B_NAME_NOT_FOUND) 343 break; 344 } 345 if (i == fDefCount) { 346 fLock.Lock(); 347 result = B_OK; 348 349 const TranSetting *defs = fDefaults; 350 for (i = 0; i < fDefCount && result >= B_OK; i++) { 351 switch (defs[i].dataType) { 352 case TRAN_SETTING_BOOL: 353 result = pmsg->AddBool(defs[i].name, 354 SetGetBool(defs[i].name)); 355 break; 356 357 case TRAN_SETTING_INT32: 358 result = pmsg->AddInt32(defs[i].name, 359 SetGetInt32(defs[i].name)); 360 break; 361 362 default: 363 // ASSERT here? Erase the bogus setting entry instead? 364 break; 365 } 366 } 367 368 fLock.Unlock(); 369 } 370 } 371 372 return result; 373 } 374 375 // --------------------------------------------------------------- 376 // FindTranSetting 377 // 378 // Returns a pointer to the TranSetting with the given name 379 // 380 // 381 // Preconditions: 382 // 383 // Parameters: name name of the TranSetting to find 384 // 385 // 386 // Postconditions: 387 // 388 // Returns: NULL if the TranSetting cannot be found, or a pointer 389 // to the desired TranSetting if it is found 390 // --------------------------------------------------------------- 391 const TranSetting * 392 TranslatorSettings::FindTranSetting(const char *name) 393 { 394 for (int32 i = 0; i < fDefCount; i++) { 395 if (!strcmp(fDefaults[i].name, name)) 396 return fDefaults + i; 397 } 398 return NULL; 399 } 400 401 // --------------------------------------------------------------- 402 // SetGetBool 403 // 404 // Sets the state of the bool setting identified by the given name 405 // 406 // 407 // Preconditions: 408 // 409 // Parameters: name identifies the setting to set or get 410 // 411 // pbool the new value for the bool, or, if null, 412 // it indicates that the caller wants to Get 413 // rather than Set 414 // 415 // Postconditions: 416 // 417 // Returns: the prior value of the setting 418 // --------------------------------------------------------------- 419 bool 420 TranslatorSettings::SetGetBool(const char *name, bool *pbool) 421 { 422 bool bprevValue; 423 424 fLock.Lock(); 425 426 const TranSetting *def = FindTranSetting(name); 427 if (def) { 428 fSettingsMsg.FindBool(def->name, &bprevValue); 429 if (pbool) 430 fSettingsMsg.ReplaceBool(def->name, *pbool); 431 } else 432 bprevValue = false; 433 434 fLock.Unlock(); 435 436 return bprevValue; 437 } 438 439 // --------------------------------------------------------------- 440 // SetGetInt32 441 // 442 // Sets the state of the int32 setting identified by the given name 443 // 444 // 445 // Preconditions: 446 // 447 // Parameters: name identifies the setting to set or get 448 // 449 // pint32 the new value for the setting, or, if null, 450 // it indicates that the caller wants to Get 451 // rather than Set 452 // 453 // Postconditions: 454 // 455 // Returns: the prior value of the setting 456 // --------------------------------------------------------------- 457 int32 458 TranslatorSettings::SetGetInt32(const char *name, int32 *pint32) 459 { 460 int32 prevValue; 461 462 fLock.Lock(); 463 464 const TranSetting *def = FindTranSetting(name); 465 if (def) { 466 fSettingsMsg.FindInt32(def->name, &prevValue); 467 if (pint32) 468 fSettingsMsg.ReplaceInt32(def->name, *pint32); 469 } else 470 prevValue = 0; 471 472 fLock.Unlock(); 473 474 return prevValue; 475 } 476 477