1/* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "SettingsManager.h" 8 9#include <new> 10 11#include <Directory.h> 12#include <File.h> 13#include <FindDirectory.h> 14 15#include <AutoDeleter.h> 16#include <AutoLocker.h> 17 18#include "TeamSettings.h" 19 20 21static const char* const kSettingsDirPath = "Debugger"; 22static const char* const kGlobalSettingsName = "Global"; 23static const int32 kMaxRecentTeamSettings = 10; 24 25 26SettingsManager::SettingsManager() 27 : 28 fLock("settings manager"), 29 fRecentTeamSettings(kMaxRecentTeamSettings, true) 30{ 31} 32 33 34SettingsManager::~SettingsManager() 35{ 36 _Unset(); 37} 38 39 40status_t 41SettingsManager::Init() 42{ 43 // check the lock 44 status_t error = fLock.InitCheck(); 45 if (error != B_OK) 46 return error; 47 48 // get and create our settings directory 49 if (find_directory(B_USER_SETTINGS_DIRECTORY, &fSettingsPath, true) == B_OK 50 && fSettingsPath.Append(kSettingsDirPath) == B_OK 51 && create_directory(fSettingsPath.Path(), 0700) == B_OK 52 && fSettingsPath.Append(kGlobalSettingsName) == B_OK) { 53 // load the settings 54 _LoadSettings(); 55 } else { 56 // something went wrong -- clear the path 57 fSettingsPath.Unset(); 58 } 59 60 return B_OK; 61} 62 63 64status_t 65SettingsManager::LoadTeamSettings(const char* teamName, TeamSettings& settings) 66{ 67 AutoLocker<BLocker> locker(fLock); 68 69 int32 index = _TeamSettingsIndex(teamName); 70 if (index < 0) 71 return B_ENTRY_NOT_FOUND; 72 73 try { 74 settings = *fRecentTeamSettings.ItemAt(index); 75 return B_OK; 76 } catch (std::bad_alloc) { 77 return B_NO_MEMORY; 78 } 79} 80 81 82status_t 83SettingsManager::SaveTeamSettings(const TeamSettings& _settings) 84{ 85 AutoLocker<BLocker> locker(fLock); 86 87 TeamSettings* settings; 88 int32 index = _TeamSettingsIndex(_settings.TeamName()); 89 if (index >= 0) { 90 settings = fRecentTeamSettings.RemoveItemAt(index); 91 } else { 92 settings = new(std::nothrow) TeamSettings; 93 if (settings == NULL) 94 return B_NO_MEMORY; 95 96 // enforce recent limit 97 while (fRecentTeamSettings.CountItems() >= kMaxRecentTeamSettings) 98 delete fRecentTeamSettings.RemoveItemAt(0); 99 100 } 101 ObjectDeleter<TeamSettings> settingsDeleter(settings); 102 103 try { 104 *settings = _settings; 105 if (!fRecentTeamSettings.AddItem(settings)) 106 return B_NO_MEMORY; 107 settingsDeleter.Detach(); 108 109 return _SaveSettings(); 110 } catch (std::bad_alloc) { 111 return B_NO_MEMORY; 112 } 113} 114 115 116void 117SettingsManager::_Unset() 118{ 119 fRecentTeamSettings.MakeEmpty(); 120} 121 122 123status_t 124SettingsManager::_LoadSettings() 125{ 126 _Unset(); 127 128 if (fSettingsPath.Path() == NULL) 129 return B_ENTRY_NOT_FOUND; 130 131 // read the settings file 132 BFile file; 133 status_t error = file.SetTo(fSettingsPath.Path(), B_READ_ONLY); 134 if (error != B_OK) 135 return error; 136 137 BMessage archive; 138 error = archive.Unflatten(&file); 139 if (error != B_OK) 140 return error; 141 142 // unarchive the recent team settings 143 BMessage childArchive; 144 for (int32 i = 0; archive.FindMessage("teamSettings", i, &childArchive) 145 == B_OK; i++) { 146 TeamSettings* settings = new(std::nothrow) TeamSettings; 147 if (settings == NULL) 148 return B_NO_MEMORY; 149 150 error = settings->SetTo(childArchive); 151 if (error != B_OK) { 152 delete settings; 153 continue; 154 } 155 156 if (!fRecentTeamSettings.AddItem(settings)) { 157 delete settings; 158 return B_NO_MEMORY; 159 } 160 } 161 162 return B_OK; 163} 164 165 166status_t 167SettingsManager::_SaveSettings() 168{ 169 if (fSettingsPath.Path() == NULL) 170 return B_ENTRY_NOT_FOUND; 171 172 // archive the recent team settings 173 BMessage archive; 174 for (int32 i = 0; TeamSettings* settings = fRecentTeamSettings.ItemAt(i); 175 i++) { 176 BMessage childArchive; 177 status_t error = settings->WriteTo(childArchive); 178 if (error != B_OK) 179 return error; 180 181 error = archive.AddMessage("teamSettings", &childArchive); 182 if (error != B_OK) 183 return error; 184 } 185 186 // open the settings file 187 BFile file; 188 status_t error = file.SetTo(fSettingsPath.Path(), 189 B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 190 if (error != B_OK) 191 return error; 192 193 return archive.Flatten(&file); 194} 195 196 197int32 198SettingsManager::_TeamSettingsIndex(const char* teamName) const 199{ 200 for (int32 i = 0; TeamSettings* settings = fRecentTeamSettings.ItemAt(i); 201 i++) { 202 if (settings->TeamName() == teamName) 203 return i; 204 } 205 206 return -1; 207} 208