WoWInterface SVN Plink

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /trunk/Plink!/Libs/AceDB-3.0
    from Rev 6 to Rev 7
    Reverse comparison

Rev 6 → Rev 7

AceDB-3.0.lua
1,17 → 1,61
--- AceDB-3.0 allows you to create profiles and smart default values for the SavedVariables of your addon.
--- **AceDB-3.0** manages the SavedVariables of your addon.
-- It offers profile management, smart defaults and namespaces for modules.\\
-- Data can be saved in different data-types, depending on its intended usage.
-- The most common data-type is the `profile` type, which allows the user to choose
-- the active profile, and manage the profiles of all of his characters.\\
-- The following data types are available:
-- * **char** Character-specific data. Every character has its own database.
-- * **realm** Realm-specific data. All of the players characters on the same realm share this database.
-- * **class** Class-specific data. All of the players characters of the same class share this database.
-- * **race** Race-specific data. All of the players characters of the same race share this database.
-- * **faction** Faction-specific data. All of the players characters of the same faction share this database.
-- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database.
-- * **global** Global Data. All characters on the same account share this database.
-- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used.
--
-- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions
-- of the DBObjectLib listed here. \\
-- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note
-- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that,
-- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases.
--
-- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]].
--
-- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs.
--
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample")
--
-- -- declare defaults to be used in the DB
-- local defaults = {
-- profile = {
-- setting = true,
-- }
-- }
--
-- function MyAddon:OnInitialize()
-- -- Assuming the .toc says ## SavedVariables: MyAddonDB
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
-- end
-- @class file
-- @name AceDB-3.0.lua
-- @release $Id: AceDB-3.0.lua 735 2009-02-14 11:10:48Z nevcairiel $
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 10
-- @release $Id: AceDB-3.0.lua 877 2009-11-02 15:56:50Z nevcairiel $
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 19
local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
 
if not AceDB then return end -- No upgrade needed
 
local type = type
local pairs, next = pairs, next
local rawget, rawset = rawget, rawset
local setmetatable = setmetatable
-- Lua APIs
local type, pairs, next, error = type, pairs, next, error
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
 
-- WoW APIs
local _G = _G
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub
 
AceDB.db_registry = AceDB.db_registry or {}
AceDB.frame = AceDB.frame or CreateFrame("Frame")
 
91,6 → 135,9
 
-- Called to remove all defaults in the default table from the database
local function removeDefaults(db, defaults, blocker)
-- remove all metatables from the db, so we don't accidentally create new sub-tables through them
setmetatable(db, nil)
-- loop through the defaults and remove their content
for k,v in pairs(defaults) do
if k == "*" or k == "**" then
if type(v) == "table" then
105,7 → 152,7
db[key] = nil
end
-- if it was specified, only strip ** content, but block values which were set in the key table
elseif k == "**" then
elseif k == "**" then
removeDefaults(value, v, defaults[key])
end
end
131,28 → 178,26
end
end
end
-- remove all metatables from the db
setmetatable(db, nil)
end
 
-- This is called when a table section is first accessed, to set up the defaults
local function initSection(db, section, svstore, key, defaults)
local sv = rawget(db, "sv")
 
 
local tableCreated
if not sv[svstore] then sv[svstore] = {} end
if not sv[svstore][key] then
sv[svstore][key] = {}
tableCreated = true
end
 
 
local tbl = sv[svstore][key]
 
 
if defaults then
copyDefaults(tbl, defaults)
end
rawset(db, section, tbl)
 
 
return tableCreated, tbl
end
 
164,7 → 209,7
if key then
local defaultTbl = rawget(t, "defaults")
local defaults = defaultTbl and defaultTbl[section]
 
 
if section == "profile" then
local new = initSection(t, section, "profiles", key, defaults)
if new then
186,7 → 231,7
initSection(t, section, section, key, defaults)
end
end
 
 
return rawget(t, section)
end
}
218,15 → 263,29
-- Actual database initialization function
local function initdb(sv, defaults, defaultProfile, olddb, parent)
-- Generate the database keys for each section
 
-- Make a container for profile keys
if not sv.profileKeys then sv.profileKeys = {} end
 
-- Try to get the profile selected from the char db
local profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
sv.profileKeys[charKey] = profileKey
 
-- This table contains keys that enable the dynamic creation
 
-- map "true" to our "Default" profile
if defaultProfile == true then defaultProfile = "Default" end
 
local profileKey
if not parent then
-- Make a container for profile keys
if not sv.profileKeys then sv.profileKeys = {} end
 
-- Try to get the profile selected from the char db
profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
 
-- save the selected profile for later
sv.profileKeys[charKey] = profileKey
else
-- Use the profile of the parents DB
profileKey = parent.keys.profile or defaultProfile or charKey
 
-- clear the profileKeys in the DB, namespaces don't need to store them
sv.profileKeys = nil
end
 
-- This table contains keys that enable the dynamic creation
-- of each section of the table. The 'global' and 'profiles'
-- have a key of true, since they are handled in a special case
local keyTbl= {
240,27 → 299,27
["global"] = true,
["profiles"] = true,
}
 
 
validateDefaults(defaults, keyTbl, 1)
 
 
-- This allows us to use this function to reset an entire database
-- Clear out the old database
if olddb then
for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
end
 
 
-- Give this database the metatable so it initializes dynamically
local db = setmetatable(olddb or {}, dbmt)
 
if not rawget(db, "callbacks") then
 
if not rawget(db, "callbacks") then
-- try to load CallbackHandler-1.0 if it loaded after our library
if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
end
 
 
-- Copy methods locally into the database object, to avoid hitting
-- the metatable when calling methods
 
 
if not parent then
for name, func in pairs(DBObjectLib) do
db[name] = func
270,7 → 329,7
db.RegisterDefaults = DBObjectLib.RegisterDefaults
db.ResetProfile = DBObjectLib.ResetProfile
end
 
 
-- Set some properties in the database object
db.profiles = sv.profiles
db.keys = keyTbl
278,10 → 337,10
--db.sv_name = name
db.defaults = defaults
db.parent = parent
 
 
-- store the DB in the registry
AceDB.db_registry[db] = true
 
 
return db
end
 
315,9 → 374,9
if defaults and type(defaults) ~= "table" then
error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
end
 
 
validateDefaults(defaults, self.keys)
 
 
-- Remove any currently set defaults
if self.defaults then
for section,key in pairs(self.keys) do
326,10 → 385,10
end
end
end
 
 
-- Set the DBObject.defaults table
self.defaults = defaults
 
 
-- Copy in any defaults, only touching those sections already created
if defaults then
for section,key in pairs(self.keys) do
347,32 → 406,37
if type(name) ~= "string" then
error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
end
 
 
-- changing to the same profile, dont do anything
if name == self.keys.profile then return end
 
 
local oldProfile = self.profile
local defaults = self.defaults and self.defaults.profile
 
 
-- Callback: OnProfileShutdown, database
self.callbacks:Fire("OnProfileShutdown", self)
 
 
if oldProfile and defaults then
-- Remove the defaults from the old profile
removeDefaults(oldProfile, defaults)
end
 
 
self.profile = nil
self.keys["profile"] = name
self.sv.profileKeys[charKey] = name
 
-- if the storage exists, save the new profile
-- this won't exist on namespaces.
if self.sv.profileKeys then
self.sv.profileKeys[charKey] = name
end
 
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.SetProfile(db, name)
end
end
 
 
-- Callback: OnProfileChanged, database, newProfileKey
self.callbacks:Fire("OnProfileChanged", self, name)
end
393,7 → 457,7
end
 
local curProfile = self.keys.profile
 
 
local i = 0
for profileKey in pairs(self.profiles) do
i = i + 1
406,7 → 470,7
i = i + 1
tbl[i] = curProfile
end
 
 
return tbl, i
end
 
422,24 → 486,24
if type(name) ~= "string" then
error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
end
 
 
if self.keys.profile == name then
error("Cannot delete the active profile in an AceDBObject.", 2)
end
 
 
if not rawget(self.sv.profiles, name) and not silent then
error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
end
 
 
self.sv.profiles[name] = nil
 
 
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.DeleteProfile(db, name, true)
end
end
 
 
-- Callback: OnProfileDeleted, database, profileKey
self.callbacks:Fire("OnProfileDeleted", self, name)
end
452,57 → 516,60
if type(name) ~= "string" then
error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
end
 
 
if name == self.keys.profile then
error("Cannot have the same source and destination profiles.", 2)
end
 
 
if not rawget(self.sv.profiles, name) and not silent then
error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
end
 
 
-- Reset the profile before copying
DBObjectLib.ResetProfile(self)
 
DBObjectLib.ResetProfile(self, nil, true)
 
local profile = self.profile
local source = self.sv.profiles[name]
 
 
copyTable(source, profile)
 
 
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.CopyProfile(db, name, true)
end
end
 
 
-- Callback: OnProfileCopied, database, sourceProfileKey
self.callbacks:Fire("OnProfileCopied", self, name)
end
 
--- Resets the current profile to the default values (if specified).
-- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object
function DBObjectLib:ResetProfile(noChildren)
-- @param noCallbacks if set to true, won't fire the OnProfileReset callback
function DBObjectLib:ResetProfile(noChildren, noCallbacks)
local profile = self.profile
 
 
for k,v in pairs(profile) do
profile[k] = nil
end
 
 
local defaults = self.defaults and self.defaults.profile
if defaults then
copyDefaults(profile, defaults)
end
 
 
-- populate to child namespaces
if self.children and not noChildren then
for _, db in pairs(self.children) do
DBObjectLib.ResetProfile(db)
DBObjectLib.ResetProfile(db, nil, noCallbacks)
end
end
 
 
-- Callback: OnProfileReset, database
self.callbacks:Fire("OnProfileReset", self)
if not noCallbacks then
self.callbacks:Fire("OnProfileReset", self)
end
end
 
--- Resets the entire database, using the string defaultProfile as the new default
512,16 → 579,16
if defaultProfile and type(defaultProfile) ~= "string" then
error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
end
 
 
local sv = self.sv
for k,v in pairs(sv) do
sv[k] = nil
end
 
 
local parent = self.parent
 
 
initdb(sv, self.defaults, defaultProfile, self)
 
 
-- fix the child namespaces
if self.children then
if not sv.namespaces then sv.namespaces = {} end
530,12 → 597,12
initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
end
end
 
-- Callback: OnDatabaseReset, database
 
-- Callback: OnDatabaseReset, database
self.callbacks:Fire("OnDatabaseReset", self)
-- Callback: OnProfileChanged, database, profileKey
self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"])
 
 
return self
end
 
554,51 → 621,81
if self.children and self.children[name] then
error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
end
 
 
local sv = self.sv
if not sv.namespaces then sv.namespaces = {} end
if not sv.namespaces[name] then
sv.namespaces[name] = {}
end
 
 
local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
 
 
if not self.children then self.children = {} end
self.children[name] = newDB
return newDB
end
 
--- Returns an already existing namespace from the database object.
-- @param name The name of the new namespace
-- @param silent if true, the addon is optional, silently return nil if its not found
-- @usage
-- local namespace = self.db:GetNamespace('namespace')
-- @return the namespace object if found
function DBObjectLib:GetNamespace(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2)
end
if not silent and not (self.children and self.children[name]) then
error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2)
end
if not self.children then self.children = {} end
return self.children[name]
end
 
--[[-------------------------------------------------------------------------
AceDB Exposed Methods
---------------------------------------------------------------------------]]
 
--- Creates a new database object that can be used to handle database settings
-- and profiles.
-- @param name The name of variable, or table to use for the database
--- Creates a new database object that can be used to handle database settings and profiles.
-- By default, an empty DB is created, using a character specific profile.
--
-- You can override the default profile used by passing any profile name as the third argument,
-- or by passing //true// as the third argument to use a globally shared profile called "Default".
--
-- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char"
-- will use a profile named "char", and not a character-specific profile.
-- @param tbl The name of variable, or table to use for the database
-- @param defaults A table of database defaults
-- @param defaultProfile The name of the default profile
-- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default.
-- You can also pass //true// to use a shared global profile called "Default".
-- @usage
-- -- Create an empty DB using a character-specific default profile.
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
-- @usage
-- -- Create a DB using defaults and using a shared default profile
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
function AceDB:New(tbl, defaults, defaultProfile)
if type(tbl) == "string" then
local name = tbl
tbl = getglobal(name)
tbl = _G[name]
if not tbl then
tbl = {}
setglobal(name, tbl)
_G[name] = tbl
end
end
 
 
if type(tbl) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
end
 
 
if defaults and type(defaults) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
end
 
if defaultProfile and type(defaultProfile) ~= "string" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string expected.", 2)
 
if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2)
end
 
 
return initdb(tbl, defaults, defaultProfile)
end
 
610,5 → 707,6
end
else
db.RegisterDefaults = DBObjectLib.RegisterDefaults
db.ResetProfile = DBObjectLib.ResetProfile
end
end