flickerstreak@28: --[[ $Id: AceDB-3.0.lua 63886 2008-03-08 12:43:31Z nevcairiel $ ]] flickerstreak@28: local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 5 flickerstreak@28: local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR) flickerstreak@28: flickerstreak@28: if not AceDB then return end -- No upgrade needed flickerstreak@28: flickerstreak@28: local type = type flickerstreak@28: local pairs, next = pairs, next flickerstreak@28: local rawget, rawset = rawget, rawset flickerstreak@28: local setmetatable = setmetatable flickerstreak@28: flickerstreak@28: AceDB.db_registry = AceDB.db_registry or {} flickerstreak@28: AceDB.frame = AceDB.frame or CreateFrame("Frame") flickerstreak@28: flickerstreak@28: local CallbackHandler flickerstreak@28: local CallbackDummy = { Fire = function() end } flickerstreak@28: flickerstreak@28: local DBObjectLib = {} flickerstreak@28: flickerstreak@28: --[[------------------------------------------------------------------------- flickerstreak@28: AceDB Utility Functions flickerstreak@28: ---------------------------------------------------------------------------]] flickerstreak@28: flickerstreak@28: -- Simple shallow copy for copying defaults flickerstreak@28: local function copyTable(src, dest) flickerstreak@28: if type(dest) ~= "table" then dest = {} end flickerstreak@28: if type(src) == "table" then flickerstreak@28: for k,v in pairs(src) do flickerstreak@28: if type(v) == "table" then flickerstreak@28: -- try to index the key first so that the metatable creates the defaults, if set, and use that table flickerstreak@28: v = copyTable(v, dest[k]) flickerstreak@28: end flickerstreak@28: dest[k] = v flickerstreak@28: end flickerstreak@28: end flickerstreak@28: return dest flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Called to add defaults to a section of the database flickerstreak@28: -- flickerstreak@28: -- When a ["*"] default section is indexed with a new key, a table is returned flickerstreak@28: -- and set in the host table. These tables must be cleaned up by removeDefaults flickerstreak@28: -- in order to ensure we don't write empty default tables. flickerstreak@28: local function copyDefaults(dest, src) flickerstreak@28: -- this happens if some value in the SV overwrites our default value with a non-table flickerstreak@28: --if type(dest) ~= "table" then return end flickerstreak@28: for k, v in pairs(src) do flickerstreak@28: if k == "*" or k == "**" then flickerstreak@28: if type(v) == "table" then flickerstreak@28: -- This is a metatable used for table defaults flickerstreak@28: local mt = { flickerstreak@28: -- This handles the lookup and creation of new subtables flickerstreak@28: __index = function(t,k) flickerstreak@28: if k == nil then return nil end flickerstreak@28: local tbl = {} flickerstreak@28: copyDefaults(tbl, v) flickerstreak@28: rawset(t, k, tbl) flickerstreak@28: return tbl flickerstreak@28: end, flickerstreak@28: } flickerstreak@28: setmetatable(dest, mt) flickerstreak@28: -- handle already existing tables in the SV flickerstreak@28: for dk, dv in pairs(dest) do flickerstreak@28: if not rawget(src, dk) and type(dv) == "table" then flickerstreak@28: copyDefaults(dv, v) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: else flickerstreak@28: -- Values are not tables, so this is just a simple return flickerstreak@28: local mt = {__index = function(t,k) return k~=nil and v or nil end} flickerstreak@28: setmetatable(dest, mt) flickerstreak@28: end flickerstreak@28: elseif type(v) == "table" then flickerstreak@28: if not rawget(dest, k) then rawset(dest, k, {}) end flickerstreak@28: if type(dest[k]) == "table" then flickerstreak@28: copyDefaults(dest[k], v) flickerstreak@28: if src['**'] then flickerstreak@28: copyDefaults(dest[k], src['**']) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: else flickerstreak@28: if rawget(dest, k) == nil then flickerstreak@28: rawset(dest, k, v) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Called to remove all defaults in the default table from the database flickerstreak@28: local function removeDefaults(db, defaults, blocker) flickerstreak@28: for k,v in pairs(defaults) do flickerstreak@28: if k == "*" or k == "**" then flickerstreak@28: if type(v) == "table" then flickerstreak@28: -- Loop through all the actual k,v pairs and remove flickerstreak@28: for key, value in pairs(db) do flickerstreak@28: if type(value) == "table" then flickerstreak@28: -- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables flickerstreak@28: if defaults[key] == nil then flickerstreak@28: removeDefaults(value, v) flickerstreak@28: -- if the table is empty afterwards, remove it flickerstreak@28: if not next(value) then flickerstreak@28: db[key] = nil flickerstreak@28: end flickerstreak@28: -- if it was specified, only strip ** content, but block values which were set in the key table flickerstreak@28: elseif k == "**" then flickerstreak@28: removeDefaults(value, v, defaults[key]) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: elseif k == "*" then flickerstreak@28: -- check for non-table default flickerstreak@28: for key, value in pairs(db) do flickerstreak@28: if defaults[key] == nil and v == value then flickerstreak@28: db[key] = nil flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: elseif type(v) == "table" and type(db[k]) == "table" then flickerstreak@28: -- if a blocker was set, dive into it, to allow multi-level defaults flickerstreak@28: removeDefaults(db[k], v, blocker and blocker[k]) flickerstreak@28: if not next(db[k]) then flickerstreak@28: db[k] = nil flickerstreak@28: end flickerstreak@28: else flickerstreak@28: -- check if the current value matches the default, and that its not blocked by another defaults table flickerstreak@28: if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then flickerstreak@28: db[k] = nil flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: -- remove all metatables from the db flickerstreak@28: setmetatable(db, nil) flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- This is called when a table section is first accessed, to set up the defaults flickerstreak@28: local function initSection(db, section, svstore, key, defaults) flickerstreak@28: local sv = rawget(db, "sv") flickerstreak@28: flickerstreak@28: local tableCreated flickerstreak@28: if not sv[svstore] then sv[svstore] = {} end flickerstreak@28: if not sv[svstore][key] then flickerstreak@28: sv[svstore][key] = {} flickerstreak@28: tableCreated = true flickerstreak@28: end flickerstreak@28: flickerstreak@28: local tbl = sv[svstore][key] flickerstreak@28: flickerstreak@28: if defaults then flickerstreak@28: copyDefaults(tbl, defaults) flickerstreak@28: end flickerstreak@28: rawset(db, section, tbl) flickerstreak@28: flickerstreak@28: return tableCreated, tbl flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Metatable to handle the dynamic creation of sections and copying of sections. flickerstreak@28: local dbmt = { flickerstreak@28: __index = function(t, section) flickerstreak@28: local keys = rawget(t, "keys") flickerstreak@28: local key = keys[section] flickerstreak@28: if key then flickerstreak@28: local defaultTbl = rawget(t, "defaults") flickerstreak@28: local defaults = defaultTbl and defaultTbl[section] flickerstreak@28: flickerstreak@28: if section == "profile" then flickerstreak@28: local new = initSection(t, section, "profiles", key, defaults) flickerstreak@28: if new then flickerstreak@28: -- Callback: OnNewProfile, database, newProfileKey flickerstreak@28: t.callbacks:Fire("OnNewProfile", t, key) flickerstreak@28: end flickerstreak@28: elseif section == "profiles" then flickerstreak@28: local sv = rawget(t, "sv") flickerstreak@28: if not sv.profiles then sv.profiles = {} end flickerstreak@28: rawset(t, "profiles", sv.profiles) flickerstreak@28: elseif section == "global" then flickerstreak@28: local sv = rawget(t, "sv") flickerstreak@28: if not sv.global then sv.global = {} end flickerstreak@28: if defaults then flickerstreak@28: copyDefaults(sv.global, defaults) flickerstreak@28: end flickerstreak@28: rawset(t, section, sv.global) flickerstreak@28: else flickerstreak@28: initSection(t, section, section, key, defaults) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: return rawget(t, section) flickerstreak@28: end flickerstreak@28: } flickerstreak@28: flickerstreak@28: local function validateDefaults(defaults, keyTbl, offset) flickerstreak@28: if not defaults then return end flickerstreak@28: offset = offset or 0 flickerstreak@28: for k in pairs(defaults) do flickerstreak@28: if not keyTbl[k] or k == "profiles" then flickerstreak@28: error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: local preserve_keys = { flickerstreak@28: ["callbacks"] = true, flickerstreak@28: ["RegisterCallback"] = true, flickerstreak@28: ["UnregisterCallback"] = true, flickerstreak@28: ["UnregisterAllCallbacks"] = true, flickerstreak@28: ["children"] = true, flickerstreak@28: } flickerstreak@28: flickerstreak@28: local realmKey = GetRealmName() flickerstreak@28: local charKey = UnitName("player") .. " - " .. realmKey flickerstreak@28: local _, classKey = UnitClass("player") flickerstreak@28: local _, raceKey = UnitRace("player") flickerstreak@28: local factionKey = UnitFactionGroup("player") flickerstreak@28: local factionrealmKey = factionKey .. " - " .. realmKey flickerstreak@28: -- Actual database initialization function flickerstreak@28: local function initdb(sv, defaults, defaultProfile, olddb, parent) flickerstreak@28: -- Generate the database keys for each section flickerstreak@28: flickerstreak@28: -- Make a container for profile keys flickerstreak@28: if not sv.profileKeys then sv.profileKeys = {} end flickerstreak@28: flickerstreak@28: -- Try to get the profile selected from the char db flickerstreak@28: local profileKey = sv.profileKeys[charKey] or defaultProfile or charKey flickerstreak@28: sv.profileKeys[charKey] = profileKey flickerstreak@28: flickerstreak@28: -- This table contains keys that enable the dynamic creation flickerstreak@28: -- of each section of the table. The 'global' and 'profiles' flickerstreak@28: -- have a key of true, since they are handled in a special case flickerstreak@28: local keyTbl= { flickerstreak@28: ["char"] = charKey, flickerstreak@28: ["realm"] = realmKey, flickerstreak@28: ["class"] = classKey, flickerstreak@28: ["race"] = raceKey, flickerstreak@28: ["faction"] = factionKey, flickerstreak@28: ["factionrealm"] = factionrealmKey, flickerstreak@28: ["profile"] = profileKey, flickerstreak@28: ["global"] = true, flickerstreak@28: ["profiles"] = true, flickerstreak@28: } flickerstreak@28: flickerstreak@28: validateDefaults(defaults, keyTbl, 1) flickerstreak@28: flickerstreak@28: -- This allows us to use this function to reset an entire database flickerstreak@28: -- Clear out the old database flickerstreak@28: if olddb then flickerstreak@28: for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Give this database the metatable so it initializes dynamically flickerstreak@28: local db = setmetatable(olddb or {}, dbmt) flickerstreak@28: flickerstreak@28: if not rawget(db, "callbacks") then flickerstreak@28: -- try to load CallbackHandler-1.0 if it loaded after our library flickerstreak@28: if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end flickerstreak@28: db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Copy methods locally into the database object, to avoid hitting flickerstreak@28: -- the metatable when calling methods flickerstreak@28: flickerstreak@28: if not parent then flickerstreak@28: for name, func in pairs(DBObjectLib) do flickerstreak@28: db[name] = func flickerstreak@28: end flickerstreak@28: else flickerstreak@28: -- hack this one in flickerstreak@28: db.RegisterDefaults = DBObjectLib.RegisterDefaults flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Set some properties in the database object flickerstreak@28: db.profiles = sv.profiles flickerstreak@28: db.keys = keyTbl flickerstreak@28: db.sv = sv flickerstreak@28: --db.sv_name = name flickerstreak@28: db.defaults = defaults flickerstreak@28: db.parent = parent flickerstreak@28: flickerstreak@28: -- store the DB in the registry flickerstreak@28: AceDB.db_registry[db] = true flickerstreak@28: flickerstreak@28: return db flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- handle PLAYER_LOGOUT flickerstreak@28: -- strip all defaults from all databases flickerstreak@28: local function logoutHandler(frame, event) flickerstreak@28: if event == "PLAYER_LOGOUT" then flickerstreak@28: for db in pairs(AceDB.db_registry) do flickerstreak@28: db.callbacks:Fire("OnDatabaseShutdown", db) flickerstreak@28: for section, key in pairs(db.keys) do flickerstreak@28: if db.defaults and db.defaults[section] and rawget(db, section) then flickerstreak@28: removeDefaults(db[section], db.defaults[section]) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: AceDB.frame:RegisterEvent("PLAYER_LOGOUT") flickerstreak@28: AceDB.frame:SetScript("OnEvent", logoutHandler) flickerstreak@28: flickerstreak@28: flickerstreak@28: --[[------------------------------------------------------------------------- flickerstreak@28: AceDB Object Method Definitions flickerstreak@28: ---------------------------------------------------------------------------]] flickerstreak@28: flickerstreak@28: -- DBObject:RegisterDefaults(defaults) flickerstreak@28: -- defaults (table) - A table of defaults for this database flickerstreak@28: -- flickerstreak@28: -- Sets the defaults table for the given database object by clearing any flickerstreak@28: -- that are currently set, and then setting the new defaults. flickerstreak@28: function DBObjectLib:RegisterDefaults(defaults) flickerstreak@28: if defaults and type(defaults) ~= "table" then flickerstreak@28: error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: validateDefaults(defaults, self.keys) flickerstreak@28: flickerstreak@28: -- Remove any currently set defaults flickerstreak@28: if self.defaults then flickerstreak@28: for section,key in pairs(self.keys) do flickerstreak@28: if self.defaults[section] and rawget(self, section) then flickerstreak@28: removeDefaults(self[section], self.defaults[section]) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Set the DBObject.defaults table flickerstreak@28: self.defaults = defaults flickerstreak@28: flickerstreak@28: -- Copy in any defaults, only touching those sections already created flickerstreak@28: if defaults then flickerstreak@28: for section,key in pairs(self.keys) do flickerstreak@28: if defaults[section] and rawget(self, section) then flickerstreak@28: copyDefaults(self[section], defaults[section]) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- DBObject:SetProfile(name) flickerstreak@28: -- name (string) - The name of the profile to set as the current profile flickerstreak@28: -- flickerstreak@28: -- Changes the profile of the database and all of it's namespaces to the flickerstreak@28: -- supplied named profile flickerstreak@28: function DBObjectLib:SetProfile(name) flickerstreak@28: if type(name) ~= "string" then flickerstreak@28: error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- changing to the same profile, dont do anything flickerstreak@28: if name == self.keys.profile then return end flickerstreak@28: flickerstreak@28: local oldProfile = self.profile flickerstreak@28: local defaults = self.defaults and self.defaults.profile flickerstreak@28: flickerstreak@28: if oldProfile and defaults then flickerstreak@28: -- Remove the defaults from the old profile flickerstreak@28: removeDefaults(oldProfile, defaults) flickerstreak@28: end flickerstreak@28: flickerstreak@28: self.profile = nil flickerstreak@28: self.keys["profile"] = name flickerstreak@28: self.sv.profileKeys[charKey] = name flickerstreak@28: flickerstreak@28: -- Callback: OnProfileChanged, database, newProfileKey flickerstreak@28: self.callbacks:Fire("OnProfileChanged", self, name) flickerstreak@28: flickerstreak@28: -- populate to child namespaces flickerstreak@28: if self.children then flickerstreak@28: for _, db in pairs(self.children) do flickerstreak@28: DBObjectLib.SetProfile(db, name) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- DBObject:GetProfiles(tbl) flickerstreak@28: -- tbl (table) - A table to store the profile names in (optional) flickerstreak@28: -- flickerstreak@28: -- Returns a table with the names of the existing profiles in the database. flickerstreak@28: -- You can optionally supply a table to re-use for this purpose. flickerstreak@28: function DBObjectLib:GetProfiles(tbl) flickerstreak@28: if tbl and type(tbl) ~= "table" then flickerstreak@28: error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Clear the container table flickerstreak@28: if tbl then flickerstreak@28: for k,v in pairs(tbl) do tbl[k] = nil end flickerstreak@28: else flickerstreak@28: tbl = {} flickerstreak@28: end flickerstreak@28: flickerstreak@28: local curProfile = self.keys.profile flickerstreak@28: flickerstreak@28: local i = 0 flickerstreak@28: for profileKey in pairs(self.profiles) do flickerstreak@28: i = i + 1 flickerstreak@28: tbl[i] = profileKey flickerstreak@28: if curProfile and profileKey == curProfile then curProfile = nil end flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Add the current profile, if it hasn't been created yet flickerstreak@28: if curProfile then flickerstreak@28: i = i + 1 flickerstreak@28: tbl[i] = curProfile flickerstreak@28: end flickerstreak@28: flickerstreak@28: return tbl, i flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- DBObject:GetCurrentProfile() flickerstreak@28: -- flickerstreak@28: -- Returns the current profile name used by the database flickerstreak@28: function DBObjectLib:GetCurrentProfile() flickerstreak@28: return self.keys.profile flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- DBObject:DeleteProfile(name) flickerstreak@28: -- name (string) - The name of the profile to be deleted flickerstreak@28: -- flickerstreak@28: -- Deletes a named profile. This profile must not be the active profile. flickerstreak@28: function DBObjectLib:DeleteProfile(name, silent) flickerstreak@28: if type(name) ~= "string" then flickerstreak@28: error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: if self.keys.profile == name then flickerstreak@28: error("Cannot delete the active profile in an AceDBObject.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: if not rawget(self.sv.profiles, name) and not silent then flickerstreak@28: error("Cannot delete profile '" .. name .. "'. It does not exist.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: self.sv.profiles[name] = nil flickerstreak@28: -- Callback: OnProfileDeleted, database, profileKey flickerstreak@28: self.callbacks:Fire("OnProfileDeleted", self, name) flickerstreak@28: flickerstreak@28: -- populate to child namespaces flickerstreak@28: if self.children then flickerstreak@28: for _, db in pairs(self.children) do flickerstreak@28: DBObjectLib.DeleteProfile(db, name, true) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- DBObject:CopyProfile(name) flickerstreak@28: -- name (string) - The name of the profile to be copied into the current profile flickerstreak@28: -- flickerstreak@28: -- Copies a named profile into the current profile, overwriting any conflicting flickerstreak@28: -- settings. flickerstreak@28: function DBObjectLib:CopyProfile(name, silent) flickerstreak@28: if type(name) ~= "string" then flickerstreak@28: error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: if name == self.keys.profile then flickerstreak@28: error("Cannot have the same source and destination profiles.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: if not rawget(self.sv.profiles, name) and not silent then flickerstreak@28: error("Cannot copy profile '" .. name .. "'. It does not exist.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Reset the profile before copying flickerstreak@28: DBObjectLib.ResetProfile(self) flickerstreak@28: flickerstreak@28: local profile = self.profile flickerstreak@28: local source = self.sv.profiles[name] flickerstreak@28: flickerstreak@28: copyTable(source, profile) flickerstreak@28: flickerstreak@28: -- Callback: OnProfileCopied, database, sourceProfileKey flickerstreak@28: self.callbacks:Fire("OnProfileCopied", self, name) flickerstreak@28: flickerstreak@28: -- populate to child namespaces flickerstreak@28: if self.children then flickerstreak@28: for _, db in pairs(self.children) do flickerstreak@28: DBObjectLib.CopyProfile(db, name, true) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- DBObject:ResetProfile() flickerstreak@28: -- flickerstreak@28: -- Resets the current profile flickerstreak@28: function DBObjectLib:ResetProfile() flickerstreak@28: local profile = self.profile flickerstreak@28: flickerstreak@28: for k,v in pairs(profile) do flickerstreak@28: profile[k] = nil flickerstreak@28: end flickerstreak@28: flickerstreak@28: local defaults = self.defaults and self.defaults.profile flickerstreak@28: if defaults then flickerstreak@28: copyDefaults(profile, defaults) flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- Callback: OnProfileReset, database flickerstreak@28: self.callbacks:Fire("OnProfileReset", self) flickerstreak@28: flickerstreak@28: -- populate to child namespaces flickerstreak@28: if self.children then flickerstreak@28: for _, db in pairs(self.children) do flickerstreak@28: DBObjectLib.ResetProfile(db) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- DBObject:ResetDB(defaultProfile) flickerstreak@28: -- defaultProfile (string) - The profile name to use as the default flickerstreak@28: -- flickerstreak@28: -- Resets the entire database, using the string defaultProfile as the default flickerstreak@28: -- profile. flickerstreak@28: function DBObjectLib:ResetDB(defaultProfile) flickerstreak@28: if defaultProfile and type(defaultProfile) ~= "string" then flickerstreak@28: error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: local sv = self.sv flickerstreak@28: for k,v in pairs(sv) do flickerstreak@28: sv[k] = nil flickerstreak@28: end flickerstreak@28: flickerstreak@28: local parent = self.parent flickerstreak@28: flickerstreak@28: initdb(sv, self.defaults, defaultProfile, self) flickerstreak@28: flickerstreak@28: -- Callback: OnDatabaseReset, database flickerstreak@28: self.callbacks:Fire("OnDatabaseReset", self) flickerstreak@28: -- Callback: OnProfileChanged, database, profileKey flickerstreak@28: self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"]) flickerstreak@28: flickerstreak@28: -- fix the child namespaces flickerstreak@28: if self.children then flickerstreak@28: if not sv.namespaces then sv.namespaces = {} end flickerstreak@28: for name, db in pairs(self.children) do flickerstreak@28: if not sv.namespaces[name] then sv.namespaces[name] = {} end flickerstreak@28: initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: return self flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- DBObject:RegisterNamespace(name [, defaults]) flickerstreak@28: -- name (string) - The name of the new namespace flickerstreak@28: -- defaults (table) - A table of values to use as defaults flickerstreak@28: -- flickerstreak@28: -- Creates a new database namespace, directly tied to the database. This flickerstreak@28: -- is a full scale database in it's own rights other than the fact that flickerstreak@28: -- it cannot control its profile individually flickerstreak@28: function DBObjectLib:RegisterNamespace(name, defaults) flickerstreak@28: if type(name) ~= "string" then flickerstreak@28: error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2) flickerstreak@28: end flickerstreak@28: if defaults and type(defaults) ~= "table" then flickerstreak@28: error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2) flickerstreak@28: end flickerstreak@28: if self.children and self.children[name] then flickerstreak@28: error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: local sv = self.sv flickerstreak@28: if not sv.namespaces then sv.namespaces = {} end flickerstreak@28: if not sv.namespaces[name] then flickerstreak@28: sv.namespaces[name] = {} flickerstreak@28: end flickerstreak@28: flickerstreak@28: local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self) flickerstreak@28: flickerstreak@28: if not self.children then self.children = {} end flickerstreak@28: self.children[name] = newDB flickerstreak@28: return newDB flickerstreak@28: end flickerstreak@28: flickerstreak@28: --[[------------------------------------------------------------------------- flickerstreak@28: AceDB Exposed Methods flickerstreak@28: ---------------------------------------------------------------------------]] flickerstreak@28: flickerstreak@28: -- AceDB:New(name, defaults, defaultProfile) flickerstreak@28: -- name (table or string) - The name of variable, or table to use for the database flickerstreak@28: -- defaults (table) - A table of database defaults flickerstreak@28: -- defaultProfile (string) - The name of the default profile flickerstreak@28: -- flickerstreak@28: -- Creates a new database object that can be used to handle database settings flickerstreak@28: -- and profiles. flickerstreak@28: function AceDB:New(tbl, defaults, defaultProfile) flickerstreak@28: if type(tbl) == "string" then flickerstreak@28: local name = tbl flickerstreak@28: tbl = getglobal(name) flickerstreak@28: if not tbl then flickerstreak@28: tbl = {} flickerstreak@28: setglobal(name, tbl) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: if type(tbl) ~= "table" then flickerstreak@28: error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: if defaults and type(defaults) ~= "table" then flickerstreak@28: error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: if defaultProfile and type(defaultProfile) ~= "string" then flickerstreak@28: error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string expected.", 2) flickerstreak@28: end flickerstreak@28: flickerstreak@28: return initdb(tbl, defaults, defaultProfile) flickerstreak@28: end flickerstreak@28: flickerstreak@28: -- upgrade existing databases flickerstreak@28: for db in pairs(AceDB.db_registry) do flickerstreak@28: if not db.parent then flickerstreak@28: for name,func in pairs(DBObjectLib) do flickerstreak@28: db[name] = func flickerstreak@28: end flickerstreak@28: else flickerstreak@28: db.RegisterDefaults = DBObjectLib.RegisterDefaults flickerstreak@28: end flickerstreak@28: end