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