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