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