annotate Libs/AceDB-3.0/AceDB-3.0.lua @ 3:c6f0976069c7

Default value for the welcome / bye notification is now set to false The mailframe checkbox now primarily toggles the mail opening, however if you hold shift you can still disable the entire addon Now properly removes QuickAuction?s mail count Now tracks when a mail lost all attachments rather than it being deleted in order to continue processing the next item (mail sent by players containing text should now work properly). This should also be good for a nice speed increase. Added a variable called ?busy? to the MailOpener object indicating whether or not Mail Opener is currently working. Other addons (or macros) can retrieve it with ?LibStub("AceAddon-3.0"):GetAddon("MailOpener").busy? A mail refresh from the Postal service should no longer occur while mail is being opened but will happen instantly afterwards. Postal?s module toggling will now be handled by Postal itself. Added a short summary to the top of all modules for other developers. The time remaining until next mail box refresh should be displayed for as long as Mail Opener can be sure.
author Zerotorescue
date Tue, 07 Sep 2010 17:46:27 +0200
parents 823e33465b6e
children
rev   line source
Zerotorescue@0 1 --- **AceDB-3.0** manages the SavedVariables of your addon.
Zerotorescue@0 2 -- It offers profile management, smart defaults and namespaces for modules.\\
Zerotorescue@0 3 -- Data can be saved in different data-types, depending on its intended usage.
Zerotorescue@0 4 -- The most common data-type is the `profile` type, which allows the user to choose
Zerotorescue@0 5 -- the active profile, and manage the profiles of all of his characters.\\
Zerotorescue@0 6 -- The following data types are available:
Zerotorescue@0 7 -- * **char** Character-specific data. Every character has its own database.
Zerotorescue@0 8 -- * **realm** Realm-specific data. All of the players characters on the same realm share this database.
Zerotorescue@0 9 -- * **class** Class-specific data. All of the players characters of the same class share this database.
Zerotorescue@0 10 -- * **race** Race-specific data. All of the players characters of the same race share this database.
Zerotorescue@0 11 -- * **faction** Faction-specific data. All of the players characters of the same faction share this database.
Zerotorescue@0 12 -- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database.
Zerotorescue@0 13 -- * **global** Global Data. All characters on the same account share this database.
Zerotorescue@0 14 -- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used.
Zerotorescue@0 15 --
Zerotorescue@0 16 -- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions
Zerotorescue@0 17 -- of the DBObjectLib listed here. \\
Zerotorescue@0 18 -- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note
Zerotorescue@0 19 -- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that,
Zerotorescue@0 20 -- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases.
Zerotorescue@0 21 --
Zerotorescue@0 22 -- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]].
Zerotorescue@0 23 --
Zerotorescue@0 24 -- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs.
Zerotorescue@0 25 --
Zerotorescue@0 26 -- @usage
Zerotorescue@0 27 -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample")
Zerotorescue@0 28 --
Zerotorescue@0 29 -- -- declare defaults to be used in the DB
Zerotorescue@0 30 -- local defaults = {
Zerotorescue@0 31 -- profile = {
Zerotorescue@0 32 -- setting = true,
Zerotorescue@0 33 -- }
Zerotorescue@0 34 -- }
Zerotorescue@0 35 --
Zerotorescue@0 36 -- function MyAddon:OnInitialize()
Zerotorescue@0 37 -- -- Assuming the .toc says ## SavedVariables: MyAddonDB
Zerotorescue@0 38 -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
Zerotorescue@0 39 -- end
Zerotorescue@0 40 -- @class file
Zerotorescue@0 41 -- @name AceDB-3.0.lua
Zerotorescue@0 42 -- @release $Id: AceDB-3.0.lua 940 2010-06-19 08:01:47Z nevcairiel $
Zerotorescue@0 43 local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 21
Zerotorescue@0 44 local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
Zerotorescue@0 45
Zerotorescue@0 46 if not AceDB then return end -- No upgrade needed
Zerotorescue@0 47
Zerotorescue@0 48 -- Lua APIs
Zerotorescue@0 49 local type, pairs, next, error = type, pairs, next, error
Zerotorescue@0 50 local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
Zerotorescue@0 51
Zerotorescue@0 52 -- WoW APIs
Zerotorescue@0 53 local _G = _G
Zerotorescue@0 54
Zerotorescue@0 55 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
Zerotorescue@0 56 -- List them here for Mikk's FindGlobals script
Zerotorescue@0 57 -- GLOBALS: LibStub
Zerotorescue@0 58
Zerotorescue@0 59 AceDB.db_registry = AceDB.db_registry or {}
Zerotorescue@0 60 AceDB.frame = AceDB.frame or CreateFrame("Frame")
Zerotorescue@0 61
Zerotorescue@0 62 local CallbackHandler
Zerotorescue@0 63 local CallbackDummy = { Fire = function() end }
Zerotorescue@0 64
Zerotorescue@0 65 local DBObjectLib = {}
Zerotorescue@0 66
Zerotorescue@0 67 --[[-------------------------------------------------------------------------
Zerotorescue@0 68 AceDB Utility Functions
Zerotorescue@0 69 ---------------------------------------------------------------------------]]
Zerotorescue@0 70
Zerotorescue@0 71 -- Simple shallow copy for copying defaults
Zerotorescue@0 72 local function copyTable(src, dest)
Zerotorescue@0 73 if type(dest) ~= "table" then dest = {} end
Zerotorescue@0 74 if type(src) == "table" then
Zerotorescue@0 75 for k,v in pairs(src) do
Zerotorescue@0 76 if type(v) == "table" then
Zerotorescue@0 77 -- try to index the key first so that the metatable creates the defaults, if set, and use that table
Zerotorescue@0 78 v = copyTable(v, dest[k])
Zerotorescue@0 79 end
Zerotorescue@0 80 dest[k] = v
Zerotorescue@0 81 end
Zerotorescue@0 82 end
Zerotorescue@0 83 return dest
Zerotorescue@0 84 end
Zerotorescue@0 85
Zerotorescue@0 86 -- Called to add defaults to a section of the database
Zerotorescue@0 87 --
Zerotorescue@0 88 -- When a ["*"] default section is indexed with a new key, a table is returned
Zerotorescue@0 89 -- and set in the host table. These tables must be cleaned up by removeDefaults
Zerotorescue@0 90 -- in order to ensure we don't write empty default tables.
Zerotorescue@0 91 local function copyDefaults(dest, src)
Zerotorescue@0 92 -- this happens if some value in the SV overwrites our default value with a non-table
Zerotorescue@0 93 --if type(dest) ~= "table" then return end
Zerotorescue@0 94 for k, v in pairs(src) do
Zerotorescue@0 95 if k == "*" or k == "**" then
Zerotorescue@0 96 if type(v) == "table" then
Zerotorescue@0 97 -- This is a metatable used for table defaults
Zerotorescue@0 98 local mt = {
Zerotorescue@0 99 -- This handles the lookup and creation of new subtables
Zerotorescue@0 100 __index = function(t,k)
Zerotorescue@0 101 if k == nil then return nil end
Zerotorescue@0 102 local tbl = {}
Zerotorescue@0 103 copyDefaults(tbl, v)
Zerotorescue@0 104 rawset(t, k, tbl)
Zerotorescue@0 105 return tbl
Zerotorescue@0 106 end,
Zerotorescue@0 107 }
Zerotorescue@0 108 setmetatable(dest, mt)
Zerotorescue@0 109 -- handle already existing tables in the SV
Zerotorescue@0 110 for dk, dv in pairs(dest) do
Zerotorescue@0 111 if not rawget(src, dk) and type(dv) == "table" then
Zerotorescue@0 112 copyDefaults(dv, v)
Zerotorescue@0 113 end
Zerotorescue@0 114 end
Zerotorescue@0 115 else
Zerotorescue@0 116 -- Values are not tables, so this is just a simple return
Zerotorescue@0 117 local mt = {__index = function(t,k) return k~=nil and v or nil end}
Zerotorescue@0 118 setmetatable(dest, mt)
Zerotorescue@0 119 end
Zerotorescue@0 120 elseif type(v) == "table" then
Zerotorescue@0 121 if not rawget(dest, k) then rawset(dest, k, {}) end
Zerotorescue@0 122 if type(dest[k]) == "table" then
Zerotorescue@0 123 copyDefaults(dest[k], v)
Zerotorescue@0 124 if src['**'] then
Zerotorescue@0 125 copyDefaults(dest[k], src['**'])
Zerotorescue@0 126 end
Zerotorescue@0 127 end
Zerotorescue@0 128 else
Zerotorescue@0 129 if rawget(dest, k) == nil then
Zerotorescue@0 130 rawset(dest, k, v)
Zerotorescue@0 131 end
Zerotorescue@0 132 end
Zerotorescue@0 133 end
Zerotorescue@0 134 end
Zerotorescue@0 135
Zerotorescue@0 136 -- Called to remove all defaults in the default table from the database
Zerotorescue@0 137 local function removeDefaults(db, defaults, blocker)
Zerotorescue@0 138 -- remove all metatables from the db, so we don't accidentally create new sub-tables through them
Zerotorescue@0 139 setmetatable(db, nil)
Zerotorescue@0 140 -- loop through the defaults and remove their content
Zerotorescue@0 141 for k,v in pairs(defaults) do
Zerotorescue@0 142 if k == "*" or k == "**" then
Zerotorescue@0 143 if type(v) == "table" then
Zerotorescue@0 144 -- Loop through all the actual k,v pairs and remove
Zerotorescue@0 145 for key, value in pairs(db) do
Zerotorescue@0 146 if type(value) == "table" then
Zerotorescue@0 147 -- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables
Zerotorescue@0 148 if defaults[key] == nil and (not blocker or blocker[key] == nil) then
Zerotorescue@0 149 removeDefaults(value, v)
Zerotorescue@0 150 -- if the table is empty afterwards, remove it
Zerotorescue@0 151 if next(value) == nil then
Zerotorescue@0 152 db[key] = nil
Zerotorescue@0 153 end
Zerotorescue@0 154 -- if it was specified, only strip ** content, but block values which were set in the key table
Zerotorescue@0 155 elseif k == "**" then
Zerotorescue@0 156 removeDefaults(value, v, defaults[key])
Zerotorescue@0 157 end
Zerotorescue@0 158 end
Zerotorescue@0 159 end
Zerotorescue@0 160 elseif k == "*" then
Zerotorescue@0 161 -- check for non-table default
Zerotorescue@0 162 for key, value in pairs(db) do
Zerotorescue@0 163 if defaults[key] == nil and v == value then
Zerotorescue@0 164 db[key] = nil
Zerotorescue@0 165 end
Zerotorescue@0 166 end
Zerotorescue@0 167 end
Zerotorescue@0 168 elseif type(v) == "table" and type(db[k]) == "table" then
Zerotorescue@0 169 -- if a blocker was set, dive into it, to allow multi-level defaults
Zerotorescue@0 170 removeDefaults(db[k], v, blocker and blocker[k])
Zerotorescue@0 171 if next(db[k]) == nil then
Zerotorescue@0 172 db[k] = nil
Zerotorescue@0 173 end
Zerotorescue@0 174 else
Zerotorescue@0 175 -- check if the current value matches the default, and that its not blocked by another defaults table
Zerotorescue@0 176 if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then
Zerotorescue@0 177 db[k] = nil
Zerotorescue@0 178 end
Zerotorescue@0 179 end
Zerotorescue@0 180 end
Zerotorescue@0 181 end
Zerotorescue@0 182
Zerotorescue@0 183 -- This is called when a table section is first accessed, to set up the defaults
Zerotorescue@0 184 local function initSection(db, section, svstore, key, defaults)
Zerotorescue@0 185 local sv = rawget(db, "sv")
Zerotorescue@0 186
Zerotorescue@0 187 local tableCreated
Zerotorescue@0 188 if not sv[svstore] then sv[svstore] = {} end
Zerotorescue@0 189 if not sv[svstore][key] then
Zerotorescue@0 190 sv[svstore][key] = {}
Zerotorescue@0 191 tableCreated = true
Zerotorescue@0 192 end
Zerotorescue@0 193
Zerotorescue@0 194 local tbl = sv[svstore][key]
Zerotorescue@0 195
Zerotorescue@0 196 if defaults then
Zerotorescue@0 197 copyDefaults(tbl, defaults)
Zerotorescue@0 198 end
Zerotorescue@0 199 rawset(db, section, tbl)
Zerotorescue@0 200
Zerotorescue@0 201 return tableCreated, tbl
Zerotorescue@0 202 end
Zerotorescue@0 203
Zerotorescue@0 204 -- Metatable to handle the dynamic creation of sections and copying of sections.
Zerotorescue@0 205 local dbmt = {
Zerotorescue@0 206 __index = function(t, section)
Zerotorescue@0 207 local keys = rawget(t, "keys")
Zerotorescue@0 208 local key = keys[section]
Zerotorescue@0 209 if key then
Zerotorescue@0 210 local defaultTbl = rawget(t, "defaults")
Zerotorescue@0 211 local defaults = defaultTbl and defaultTbl[section]
Zerotorescue@0 212
Zerotorescue@0 213 if section == "profile" then
Zerotorescue@0 214 local new = initSection(t, section, "profiles", key, defaults)
Zerotorescue@0 215 if new then
Zerotorescue@0 216 -- Callback: OnNewProfile, database, newProfileKey
Zerotorescue@0 217 t.callbacks:Fire("OnNewProfile", t, key)
Zerotorescue@0 218 end
Zerotorescue@0 219 elseif section == "profiles" then
Zerotorescue@0 220 local sv = rawget(t, "sv")
Zerotorescue@0 221 if not sv.profiles then sv.profiles = {} end
Zerotorescue@0 222 rawset(t, "profiles", sv.profiles)
Zerotorescue@0 223 elseif section == "global" then
Zerotorescue@0 224 local sv = rawget(t, "sv")
Zerotorescue@0 225 if not sv.global then sv.global = {} end
Zerotorescue@0 226 if defaults then
Zerotorescue@0 227 copyDefaults(sv.global, defaults)
Zerotorescue@0 228 end
Zerotorescue@0 229 rawset(t, section, sv.global)
Zerotorescue@0 230 else
Zerotorescue@0 231 initSection(t, section, section, key, defaults)
Zerotorescue@0 232 end
Zerotorescue@0 233 end
Zerotorescue@0 234
Zerotorescue@0 235 return rawget(t, section)
Zerotorescue@0 236 end
Zerotorescue@0 237 }
Zerotorescue@0 238
Zerotorescue@0 239 local function validateDefaults(defaults, keyTbl, offset)
Zerotorescue@0 240 if not defaults then return end
Zerotorescue@0 241 offset = offset or 0
Zerotorescue@0 242 for k in pairs(defaults) do
Zerotorescue@0 243 if not keyTbl[k] or k == "profiles" then
Zerotorescue@0 244 error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset)
Zerotorescue@0 245 end
Zerotorescue@0 246 end
Zerotorescue@0 247 end
Zerotorescue@0 248
Zerotorescue@0 249 local preserve_keys = {
Zerotorescue@0 250 ["callbacks"] = true,
Zerotorescue@0 251 ["RegisterCallback"] = true,
Zerotorescue@0 252 ["UnregisterCallback"] = true,
Zerotorescue@0 253 ["UnregisterAllCallbacks"] = true,
Zerotorescue@0 254 ["children"] = true,
Zerotorescue@0 255 }
Zerotorescue@0 256
Zerotorescue@0 257 local realmKey = GetRealmName()
Zerotorescue@0 258 local charKey = UnitName("player") .. " - " .. realmKey
Zerotorescue@0 259 local _, classKey = UnitClass("player")
Zerotorescue@0 260 local _, raceKey = UnitRace("player")
Zerotorescue@0 261 local factionKey = UnitFactionGroup("player")
Zerotorescue@0 262 local factionrealmKey = factionKey .. " - " .. realmKey
Zerotorescue@0 263 -- Actual database initialization function
Zerotorescue@0 264 local function initdb(sv, defaults, defaultProfile, olddb, parent)
Zerotorescue@0 265 -- Generate the database keys for each section
Zerotorescue@0 266
Zerotorescue@0 267 -- map "true" to our "Default" profile
Zerotorescue@0 268 if defaultProfile == true then defaultProfile = "Default" end
Zerotorescue@0 269
Zerotorescue@0 270 local profileKey
Zerotorescue@0 271 if not parent then
Zerotorescue@0 272 -- Make a container for profile keys
Zerotorescue@0 273 if not sv.profileKeys then sv.profileKeys = {} end
Zerotorescue@0 274
Zerotorescue@0 275 -- Try to get the profile selected from the char db
Zerotorescue@0 276 profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
Zerotorescue@0 277
Zerotorescue@0 278 -- save the selected profile for later
Zerotorescue@0 279 sv.profileKeys[charKey] = profileKey
Zerotorescue@0 280 else
Zerotorescue@0 281 -- Use the profile of the parents DB
Zerotorescue@0 282 profileKey = parent.keys.profile or defaultProfile or charKey
Zerotorescue@0 283
Zerotorescue@0 284 -- clear the profileKeys in the DB, namespaces don't need to store them
Zerotorescue@0 285 sv.profileKeys = nil
Zerotorescue@0 286 end
Zerotorescue@0 287
Zerotorescue@0 288 -- This table contains keys that enable the dynamic creation
Zerotorescue@0 289 -- of each section of the table. The 'global' and 'profiles'
Zerotorescue@0 290 -- have a key of true, since they are handled in a special case
Zerotorescue@0 291 local keyTbl= {
Zerotorescue@0 292 ["char"] = charKey,
Zerotorescue@0 293 ["realm"] = realmKey,
Zerotorescue@0 294 ["class"] = classKey,
Zerotorescue@0 295 ["race"] = raceKey,
Zerotorescue@0 296 ["faction"] = factionKey,
Zerotorescue@0 297 ["factionrealm"] = factionrealmKey,
Zerotorescue@0 298 ["profile"] = profileKey,
Zerotorescue@0 299 ["global"] = true,
Zerotorescue@0 300 ["profiles"] = true,
Zerotorescue@0 301 }
Zerotorescue@0 302
Zerotorescue@0 303 validateDefaults(defaults, keyTbl, 1)
Zerotorescue@0 304
Zerotorescue@0 305 -- This allows us to use this function to reset an entire database
Zerotorescue@0 306 -- Clear out the old database
Zerotorescue@0 307 if olddb then
Zerotorescue@0 308 for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
Zerotorescue@0 309 end
Zerotorescue@0 310
Zerotorescue@0 311 -- Give this database the metatable so it initializes dynamically
Zerotorescue@0 312 local db = setmetatable(olddb or {}, dbmt)
Zerotorescue@0 313
Zerotorescue@0 314 if not rawget(db, "callbacks") then
Zerotorescue@0 315 -- try to load CallbackHandler-1.0 if it loaded after our library
Zerotorescue@0 316 if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
Zerotorescue@0 317 db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
Zerotorescue@0 318 end
Zerotorescue@0 319
Zerotorescue@0 320 -- Copy methods locally into the database object, to avoid hitting
Zerotorescue@0 321 -- the metatable when calling methods
Zerotorescue@0 322
Zerotorescue@0 323 if not parent then
Zerotorescue@0 324 for name, func in pairs(DBObjectLib) do
Zerotorescue@0 325 db[name] = func
Zerotorescue@0 326 end
Zerotorescue@0 327 else
Zerotorescue@0 328 -- hack this one in
Zerotorescue@0 329 db.RegisterDefaults = DBObjectLib.RegisterDefaults
Zerotorescue@0 330 db.ResetProfile = DBObjectLib.ResetProfile
Zerotorescue@0 331 end
Zerotorescue@0 332
Zerotorescue@0 333 -- Set some properties in the database object
Zerotorescue@0 334 db.profiles = sv.profiles
Zerotorescue@0 335 db.keys = keyTbl
Zerotorescue@0 336 db.sv = sv
Zerotorescue@0 337 --db.sv_name = name
Zerotorescue@0 338 db.defaults = defaults
Zerotorescue@0 339 db.parent = parent
Zerotorescue@0 340
Zerotorescue@0 341 -- store the DB in the registry
Zerotorescue@0 342 AceDB.db_registry[db] = true
Zerotorescue@0 343
Zerotorescue@0 344 return db
Zerotorescue@0 345 end
Zerotorescue@0 346
Zerotorescue@0 347 -- handle PLAYER_LOGOUT
Zerotorescue@0 348 -- strip all defaults from all databases
Zerotorescue@0 349 -- and cleans up empty sections
Zerotorescue@0 350 local function logoutHandler(frame, event)
Zerotorescue@0 351 if event == "PLAYER_LOGOUT" then
Zerotorescue@0 352 for db in pairs(AceDB.db_registry) do
Zerotorescue@0 353 db.callbacks:Fire("OnDatabaseShutdown", db)
Zerotorescue@0 354 db:RegisterDefaults(nil)
Zerotorescue@0 355
Zerotorescue@0 356 -- cleanup sections that are empty without defaults
Zerotorescue@0 357 local sv = rawget(db, "sv")
Zerotorescue@0 358 for section in pairs(db.keys) do
Zerotorescue@0 359 if rawget(sv, section) then
Zerotorescue@0 360 -- global is special, all other sections have sub-entrys
Zerotorescue@0 361 -- also don't delete empty profiles on main dbs, only on namespaces
Zerotorescue@0 362 if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then
Zerotorescue@0 363 for key in pairs(sv[section]) do
Zerotorescue@0 364 if not next(sv[section][key]) then
Zerotorescue@0 365 sv[section][key] = nil
Zerotorescue@0 366 end
Zerotorescue@0 367 end
Zerotorescue@0 368 end
Zerotorescue@0 369 if not next(sv[section]) then
Zerotorescue@0 370 sv[section] = nil
Zerotorescue@0 371 end
Zerotorescue@0 372 end
Zerotorescue@0 373 end
Zerotorescue@0 374 end
Zerotorescue@0 375 end
Zerotorescue@0 376 end
Zerotorescue@0 377
Zerotorescue@0 378 AceDB.frame:RegisterEvent("PLAYER_LOGOUT")
Zerotorescue@0 379 AceDB.frame:SetScript("OnEvent", logoutHandler)
Zerotorescue@0 380
Zerotorescue@0 381
Zerotorescue@0 382 --[[-------------------------------------------------------------------------
Zerotorescue@0 383 AceDB Object Method Definitions
Zerotorescue@0 384 ---------------------------------------------------------------------------]]
Zerotorescue@0 385
Zerotorescue@0 386 --- Sets the defaults table for the given database object by clearing any
Zerotorescue@0 387 -- that are currently set, and then setting the new defaults.
Zerotorescue@0 388 -- @param defaults A table of defaults for this database
Zerotorescue@0 389 function DBObjectLib:RegisterDefaults(defaults)
Zerotorescue@0 390 if defaults and type(defaults) ~= "table" then
Zerotorescue@0 391 error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
Zerotorescue@0 392 end
Zerotorescue@0 393
Zerotorescue@0 394 validateDefaults(defaults, self.keys)
Zerotorescue@0 395
Zerotorescue@0 396 -- Remove any currently set defaults
Zerotorescue@0 397 if self.defaults then
Zerotorescue@0 398 for section,key in pairs(self.keys) do
Zerotorescue@0 399 if self.defaults[section] and rawget(self, section) then
Zerotorescue@0 400 removeDefaults(self[section], self.defaults[section])
Zerotorescue@0 401 end
Zerotorescue@0 402 end
Zerotorescue@0 403 end
Zerotorescue@0 404
Zerotorescue@0 405 -- Set the DBObject.defaults table
Zerotorescue@0 406 self.defaults = defaults
Zerotorescue@0 407
Zerotorescue@0 408 -- Copy in any defaults, only touching those sections already created
Zerotorescue@0 409 if defaults then
Zerotorescue@0 410 for section,key in pairs(self.keys) do
Zerotorescue@0 411 if defaults[section] and rawget(self, section) then
Zerotorescue@0 412 copyDefaults(self[section], defaults[section])
Zerotorescue@0 413 end
Zerotorescue@0 414 end
Zerotorescue@0 415 end
Zerotorescue@0 416 end
Zerotorescue@0 417
Zerotorescue@0 418 --- Changes the profile of the database and all of it's namespaces to the
Zerotorescue@0 419 -- supplied named profile
Zerotorescue@0 420 -- @param name The name of the profile to set as the current profile
Zerotorescue@0 421 function DBObjectLib:SetProfile(name)
Zerotorescue@0 422 if type(name) ~= "string" then
Zerotorescue@0 423 error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
Zerotorescue@0 424 end
Zerotorescue@0 425
Zerotorescue@0 426 -- changing to the same profile, dont do anything
Zerotorescue@0 427 if name == self.keys.profile then return end
Zerotorescue@0 428
Zerotorescue@0 429 local oldProfile = self.profile
Zerotorescue@0 430 local defaults = self.defaults and self.defaults.profile
Zerotorescue@0 431
Zerotorescue@0 432 -- Callback: OnProfileShutdown, database
Zerotorescue@0 433 self.callbacks:Fire("OnProfileShutdown", self)
Zerotorescue@0 434
Zerotorescue@0 435 if oldProfile and defaults then
Zerotorescue@0 436 -- Remove the defaults from the old profile
Zerotorescue@0 437 removeDefaults(oldProfile, defaults)
Zerotorescue@0 438 end
Zerotorescue@0 439
Zerotorescue@0 440 self.profile = nil
Zerotorescue@0 441 self.keys["profile"] = name
Zerotorescue@0 442
Zerotorescue@0 443 -- if the storage exists, save the new profile
Zerotorescue@0 444 -- this won't exist on namespaces.
Zerotorescue@0 445 if self.sv.profileKeys then
Zerotorescue@0 446 self.sv.profileKeys[charKey] = name
Zerotorescue@0 447 end
Zerotorescue@0 448
Zerotorescue@0 449 -- populate to child namespaces
Zerotorescue@0 450 if self.children then
Zerotorescue@0 451 for _, db in pairs(self.children) do
Zerotorescue@0 452 DBObjectLib.SetProfile(db, name)
Zerotorescue@0 453 end
Zerotorescue@0 454 end
Zerotorescue@0 455
Zerotorescue@0 456 -- Callback: OnProfileChanged, database, newProfileKey
Zerotorescue@0 457 self.callbacks:Fire("OnProfileChanged", self, name)
Zerotorescue@0 458 end
Zerotorescue@0 459
Zerotorescue@0 460 --- Returns a table with the names of the existing profiles in the database.
Zerotorescue@0 461 -- You can optionally supply a table to re-use for this purpose.
Zerotorescue@0 462 -- @param tbl A table to store the profile names in (optional)
Zerotorescue@0 463 function DBObjectLib:GetProfiles(tbl)
Zerotorescue@0 464 if tbl and type(tbl) ~= "table" then
Zerotorescue@0 465 error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2)
Zerotorescue@0 466 end
Zerotorescue@0 467
Zerotorescue@0 468 -- Clear the container table
Zerotorescue@0 469 if tbl then
Zerotorescue@0 470 for k,v in pairs(tbl) do tbl[k] = nil end
Zerotorescue@0 471 else
Zerotorescue@0 472 tbl = {}
Zerotorescue@0 473 end
Zerotorescue@0 474
Zerotorescue@0 475 local curProfile = self.keys.profile
Zerotorescue@0 476
Zerotorescue@0 477 local i = 0
Zerotorescue@0 478 for profileKey in pairs(self.profiles) do
Zerotorescue@0 479 i = i + 1
Zerotorescue@0 480 tbl[i] = profileKey
Zerotorescue@0 481 if curProfile and profileKey == curProfile then curProfile = nil end
Zerotorescue@0 482 end
Zerotorescue@0 483
Zerotorescue@0 484 -- Add the current profile, if it hasn't been created yet
Zerotorescue@0 485 if curProfile then
Zerotorescue@0 486 i = i + 1
Zerotorescue@0 487 tbl[i] = curProfile
Zerotorescue@0 488 end
Zerotorescue@0 489
Zerotorescue@0 490 return tbl, i
Zerotorescue@0 491 end
Zerotorescue@0 492
Zerotorescue@0 493 --- Returns the current profile name used by the database
Zerotorescue@0 494 function DBObjectLib:GetCurrentProfile()
Zerotorescue@0 495 return self.keys.profile
Zerotorescue@0 496 end
Zerotorescue@0 497
Zerotorescue@0 498 --- Deletes a named profile. This profile must not be the active profile.
Zerotorescue@0 499 -- @param name The name of the profile to be deleted
Zerotorescue@0 500 -- @param silent If true, do not raise an error when the profile does not exist
Zerotorescue@0 501 function DBObjectLib:DeleteProfile(name, silent)
Zerotorescue@0 502 if type(name) ~= "string" then
Zerotorescue@0 503 error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
Zerotorescue@0 504 end
Zerotorescue@0 505
Zerotorescue@0 506 if self.keys.profile == name then
Zerotorescue@0 507 error("Cannot delete the active profile in an AceDBObject.", 2)
Zerotorescue@0 508 end
Zerotorescue@0 509
Zerotorescue@0 510 if not rawget(self.profiles, name) and not silent then
Zerotorescue@0 511 error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
Zerotorescue@0 512 end
Zerotorescue@0 513
Zerotorescue@0 514 self.profiles[name] = nil
Zerotorescue@0 515
Zerotorescue@0 516 -- populate to child namespaces
Zerotorescue@0 517 if self.children then
Zerotorescue@0 518 for _, db in pairs(self.children) do
Zerotorescue@0 519 DBObjectLib.DeleteProfile(db, name, true)
Zerotorescue@0 520 end
Zerotorescue@0 521 end
Zerotorescue@0 522
Zerotorescue@0 523 -- Callback: OnProfileDeleted, database, profileKey
Zerotorescue@0 524 self.callbacks:Fire("OnProfileDeleted", self, name)
Zerotorescue@0 525 end
Zerotorescue@0 526
Zerotorescue@0 527 --- Copies a named profile into the current profile, overwriting any conflicting
Zerotorescue@0 528 -- settings.
Zerotorescue@0 529 -- @param name The name of the profile to be copied into the current profile
Zerotorescue@0 530 -- @param silent If true, do not raise an error when the profile does not exist
Zerotorescue@0 531 function DBObjectLib:CopyProfile(name, silent)
Zerotorescue@0 532 if type(name) ~= "string" then
Zerotorescue@0 533 error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
Zerotorescue@0 534 end
Zerotorescue@0 535
Zerotorescue@0 536 if name == self.keys.profile then
Zerotorescue@0 537 error("Cannot have the same source and destination profiles.", 2)
Zerotorescue@0 538 end
Zerotorescue@0 539
Zerotorescue@0 540 if not rawget(self.profiles, name) and not silent then
Zerotorescue@0 541 error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
Zerotorescue@0 542 end
Zerotorescue@0 543
Zerotorescue@0 544 -- Reset the profile before copying
Zerotorescue@0 545 DBObjectLib.ResetProfile(self, nil, true)
Zerotorescue@0 546
Zerotorescue@0 547 local profile = self.profile
Zerotorescue@0 548 local source = self.profiles[name]
Zerotorescue@0 549
Zerotorescue@0 550 copyTable(source, profile)
Zerotorescue@0 551
Zerotorescue@0 552 -- populate to child namespaces
Zerotorescue@0 553 if self.children then
Zerotorescue@0 554 for _, db in pairs(self.children) do
Zerotorescue@0 555 DBObjectLib.CopyProfile(db, name, true)
Zerotorescue@0 556 end
Zerotorescue@0 557 end
Zerotorescue@0 558
Zerotorescue@0 559 -- Callback: OnProfileCopied, database, sourceProfileKey
Zerotorescue@0 560 self.callbacks:Fire("OnProfileCopied", self, name)
Zerotorescue@0 561 end
Zerotorescue@0 562
Zerotorescue@0 563 --- Resets the current profile to the default values (if specified).
Zerotorescue@0 564 -- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object
Zerotorescue@0 565 -- @param noCallbacks if set to true, won't fire the OnProfileReset callback
Zerotorescue@0 566 function DBObjectLib:ResetProfile(noChildren, noCallbacks)
Zerotorescue@0 567 local profile = self.profile
Zerotorescue@0 568
Zerotorescue@0 569 for k,v in pairs(profile) do
Zerotorescue@0 570 profile[k] = nil
Zerotorescue@0 571 end
Zerotorescue@0 572
Zerotorescue@0 573 local defaults = self.defaults and self.defaults.profile
Zerotorescue@0 574 if defaults then
Zerotorescue@0 575 copyDefaults(profile, defaults)
Zerotorescue@0 576 end
Zerotorescue@0 577
Zerotorescue@0 578 -- populate to child namespaces
Zerotorescue@0 579 if self.children and not noChildren then
Zerotorescue@0 580 for _, db in pairs(self.children) do
Zerotorescue@0 581 DBObjectLib.ResetProfile(db, nil, noCallbacks)
Zerotorescue@0 582 end
Zerotorescue@0 583 end
Zerotorescue@0 584
Zerotorescue@0 585 -- Callback: OnProfileReset, database
Zerotorescue@0 586 if not noCallbacks then
Zerotorescue@0 587 self.callbacks:Fire("OnProfileReset", self)
Zerotorescue@0 588 end
Zerotorescue@0 589 end
Zerotorescue@0 590
Zerotorescue@0 591 --- Resets the entire database, using the string defaultProfile as the new default
Zerotorescue@0 592 -- profile.
Zerotorescue@0 593 -- @param defaultProfile The profile name to use as the default
Zerotorescue@0 594 function DBObjectLib:ResetDB(defaultProfile)
Zerotorescue@0 595 if defaultProfile and type(defaultProfile) ~= "string" then
Zerotorescue@0 596 error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
Zerotorescue@0 597 end
Zerotorescue@0 598
Zerotorescue@0 599 local sv = self.sv
Zerotorescue@0 600 for k,v in pairs(sv) do
Zerotorescue@0 601 sv[k] = nil
Zerotorescue@0 602 end
Zerotorescue@0 603
Zerotorescue@0 604 local parent = self.parent
Zerotorescue@0 605
Zerotorescue@0 606 initdb(sv, self.defaults, defaultProfile, self)
Zerotorescue@0 607
Zerotorescue@0 608 -- fix the child namespaces
Zerotorescue@0 609 if self.children then
Zerotorescue@0 610 if not sv.namespaces then sv.namespaces = {} end
Zerotorescue@0 611 for name, db in pairs(self.children) do
Zerotorescue@0 612 if not sv.namespaces[name] then sv.namespaces[name] = {} end
Zerotorescue@0 613 initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
Zerotorescue@0 614 end
Zerotorescue@0 615 end
Zerotorescue@0 616
Zerotorescue@0 617 -- Callback: OnDatabaseReset, database
Zerotorescue@0 618 self.callbacks:Fire("OnDatabaseReset", self)
Zerotorescue@0 619 -- Callback: OnProfileChanged, database, profileKey
Zerotorescue@0 620 self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"])
Zerotorescue@0 621
Zerotorescue@0 622 return self
Zerotorescue@0 623 end
Zerotorescue@0 624
Zerotorescue@0 625 --- Creates a new database namespace, directly tied to the database. This
Zerotorescue@0 626 -- is a full scale database in it's own rights other than the fact that
Zerotorescue@0 627 -- it cannot control its profile individually
Zerotorescue@0 628 -- @param name The name of the new namespace
Zerotorescue@0 629 -- @param defaults A table of values to use as defaults
Zerotorescue@0 630 function DBObjectLib:RegisterNamespace(name, defaults)
Zerotorescue@0 631 if type(name) ~= "string" then
Zerotorescue@0 632 error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2)
Zerotorescue@0 633 end
Zerotorescue@0 634 if defaults and type(defaults) ~= "table" then
Zerotorescue@0 635 error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2)
Zerotorescue@0 636 end
Zerotorescue@0 637 if self.children and self.children[name] then
Zerotorescue@0 638 error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
Zerotorescue@0 639 end
Zerotorescue@0 640
Zerotorescue@0 641 local sv = self.sv
Zerotorescue@0 642 if not sv.namespaces then sv.namespaces = {} end
Zerotorescue@0 643 if not sv.namespaces[name] then
Zerotorescue@0 644 sv.namespaces[name] = {}
Zerotorescue@0 645 end
Zerotorescue@0 646
Zerotorescue@0 647 local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
Zerotorescue@0 648
Zerotorescue@0 649 if not self.children then self.children = {} end
Zerotorescue@0 650 self.children[name] = newDB
Zerotorescue@0 651 return newDB
Zerotorescue@0 652 end
Zerotorescue@0 653
Zerotorescue@0 654 --- Returns an already existing namespace from the database object.
Zerotorescue@0 655 -- @param name The name of the new namespace
Zerotorescue@0 656 -- @param silent if true, the addon is optional, silently return nil if its not found
Zerotorescue@0 657 -- @usage
Zerotorescue@0 658 -- local namespace = self.db:GetNamespace('namespace')
Zerotorescue@0 659 -- @return the namespace object if found
Zerotorescue@0 660 function DBObjectLib:GetNamespace(name, silent)
Zerotorescue@0 661 if type(name) ~= "string" then
Zerotorescue@0 662 error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2)
Zerotorescue@0 663 end
Zerotorescue@0 664 if not silent and not (self.children and self.children[name]) then
Zerotorescue@0 665 error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2)
Zerotorescue@0 666 end
Zerotorescue@0 667 if not self.children then self.children = {} end
Zerotorescue@0 668 return self.children[name]
Zerotorescue@0 669 end
Zerotorescue@0 670
Zerotorescue@0 671 --[[-------------------------------------------------------------------------
Zerotorescue@0 672 AceDB Exposed Methods
Zerotorescue@0 673 ---------------------------------------------------------------------------]]
Zerotorescue@0 674
Zerotorescue@0 675 --- Creates a new database object that can be used to handle database settings and profiles.
Zerotorescue@0 676 -- By default, an empty DB is created, using a character specific profile.
Zerotorescue@0 677 --
Zerotorescue@0 678 -- You can override the default profile used by passing any profile name as the third argument,
Zerotorescue@0 679 -- or by passing //true// as the third argument to use a globally shared profile called "Default".
Zerotorescue@0 680 --
Zerotorescue@0 681 -- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char"
Zerotorescue@0 682 -- will use a profile named "char", and not a character-specific profile.
Zerotorescue@0 683 -- @param tbl The name of variable, or table to use for the database
Zerotorescue@0 684 -- @param defaults A table of database defaults
Zerotorescue@0 685 -- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default.
Zerotorescue@0 686 -- You can also pass //true// to use a shared global profile called "Default".
Zerotorescue@0 687 -- @usage
Zerotorescue@0 688 -- -- Create an empty DB using a character-specific default profile.
Zerotorescue@0 689 -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
Zerotorescue@0 690 -- @usage
Zerotorescue@0 691 -- -- Create a DB using defaults and using a shared default profile
Zerotorescue@0 692 -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
Zerotorescue@0 693 function AceDB:New(tbl, defaults, defaultProfile)
Zerotorescue@0 694 if type(tbl) == "string" then
Zerotorescue@0 695 local name = tbl
Zerotorescue@0 696 tbl = _G[name]
Zerotorescue@0 697 if not tbl then
Zerotorescue@0 698 tbl = {}
Zerotorescue@0 699 _G[name] = tbl
Zerotorescue@0 700 end
Zerotorescue@0 701 end
Zerotorescue@0 702
Zerotorescue@0 703 if type(tbl) ~= "table" then
Zerotorescue@0 704 error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
Zerotorescue@0 705 end
Zerotorescue@0 706
Zerotorescue@0 707 if defaults and type(defaults) ~= "table" then
Zerotorescue@0 708 error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
Zerotorescue@0 709 end
Zerotorescue@0 710
Zerotorescue@0 711 if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then
Zerotorescue@0 712 error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2)
Zerotorescue@0 713 end
Zerotorescue@0 714
Zerotorescue@0 715 return initdb(tbl, defaults, defaultProfile)
Zerotorescue@0 716 end
Zerotorescue@0 717
Zerotorescue@0 718 -- upgrade existing databases
Zerotorescue@0 719 for db in pairs(AceDB.db_registry) do
Zerotorescue@0 720 if not db.parent then
Zerotorescue@0 721 for name,func in pairs(DBObjectLib) do
Zerotorescue@0 722 db[name] = func
Zerotorescue@0 723 end
Zerotorescue@0 724 else
Zerotorescue@0 725 db.RegisterDefaults = DBObjectLib.RegisterDefaults
Zerotorescue@0 726 db.ResetProfile = DBObjectLib.ResetProfile
Zerotorescue@0 727 end
Zerotorescue@0 728 end