|
>@5
|
1 --- **LibModuleDBShare-1.0**\\
|
|
>@5
|
2 -- A description will eventually be here.
|
|
>@5
|
3 --
|
|
>@5
|
4 -- @usage
|
|
>@5
|
5 -- Also coming soon.
|
|
>@5
|
6 -- @class file
|
|
>@5
|
7 -- @name LibModuleDBShare-1.0.lua
|
|
>@3
|
8 local MAJOR, MINOR = "LibModuleDBShare-1.0", 1
|
|
>@3
|
9 local LibModuleDBShare, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
|
|
>@3
|
10
|
|
>@4
|
11 if not LibModuleDBShare then return end -- No upgrade needed
|
|
>@4
|
12
|
|
andrewtknoll@29
|
13 -- Lua functions
|
|
andrewtknoll@26
|
14 local error, type, pairs, time = error, type, pairs, time;
|
|
andrewtknoll@15
|
15
|
|
andrewtknoll@29
|
16 -- Blizzard functions
|
|
andrewtknoll@29
|
17 local GetActiveSpecGroup = GetActiveSpecGroup;
|
|
andrewtknoll@29
|
18
|
|
andrewtknoll@17
|
19 -- Required Libraries
|
|
@12
|
20 local AceDB = LibStub("AceDB-3.0");
|
|
andrewtknoll@17
|
21 local AceDBOptions = LibStub("AceDBOptions-3.0");
|
|
andrewtknoll@17
|
22 local AceConfigRegistry = LibStub("AceConfigRegistry-3.0");
|
|
andrewtknoll@17
|
23 local AceConfigDialog = LibStub("AceConfigDialog-3.0");
|
|
@12
|
24
|
|
andrewtknoll@28
|
25 -- Optional Libraries
|
|
andrewtknoll@28
|
26 local LibDualSpec = LibStub("LibDualSpec-1.0", true);
|
|
andrewtknoll@28
|
27
|
|
>@4
|
28 LibModuleDBShare.groups = LibModuleDBShare.groups or {};
|
|
>@4
|
29
|
|
>@5
|
30 local DBGroup = {};
|
|
>@5
|
31
|
|
>@5
|
32 --- Creates a new DB group.
|
|
>@5
|
33 -- @param groupName The name of the new DB group.
|
|
andrewtknoll@21
|
34 -- @param groupDescription A description of the group to be shown in the root options panel.
|
|
andrewtknoll@21
|
35 -- @param initialDB The first DB to add to the group.
|
|
andrewtknoll@28
|
36 -- @param usesDualSpec True if this group should use LibDualSpec, false otherwise.
|
|
>@5
|
37 -- @usage
|
|
>@5
|
38 -- local myAddonDBGroup = LibStub("LibModuleDBShare-1.0"):NewGroup("MyAddonGroupName", true)
|
|
>@5
|
39 -- @return the new DB group object
|
|
andrewtknoll@21
|
40 function LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec)
|
|
andrewtknoll@21
|
41 -- verify parameters
|
|
andrewtknoll@26
|
42 if type(groupName) ~= "string" then
|
|
andrewtknoll@26
|
43 error("Usage: LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'groupName' must be a string.", 2);
|
|
andrewtknoll@26
|
44 elseif type(groupDescription) ~= "string" then
|
|
andrewtknoll@26
|
45 error("Usage: LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'groupDescription' must be a string.", 2);
|
|
andrewtknoll@26
|
46 elseif type(LibModuleDBShare.groups[groupName]) ~= "nil" then
|
|
andrewtknoll@26
|
47 error("LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): group '"..groupName.."' already exists.", 2);
|
|
andrewtknoll@27
|
48 elseif type(initialDB) ~= "table" or not AceDB.db_registry[initialDB] then
|
|
andrewtknoll@27
|
49 error("LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'initalDB' must be an AceDB-3.0 database.", 2);
|
|
andrewtknoll@28
|
50 elseif type(usesDualSpec) ~= "boolean" and type(usesDualSpec) ~= "nil" then
|
|
andrewtknoll@28
|
51 error("LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'usesDualSpec' must be a boolean or nil.", 2);
|
|
andrewtknoll@28
|
52 elseif usesDualSpec and not LibDualSpec then
|
|
andrewtknoll@28
|
53 error("LibModuleDBShare:NewGroup(groupName, groupDescription, initialDB, usesDualSpec): 'usesDualSpec' cannot be true without LibDualSpec-1.0 installed.", 2);
|
|
andrewtknoll@26
|
54 end
|
|
andrewtknoll@21
|
55 -- create group
|
|
@12
|
56 local group = {}
|
|
@12
|
57 group.name = groupName;
|
|
andrewtknoll@21
|
58 group.members = {};
|
|
andrewtknoll@21
|
59 -- create root option panel for group
|
|
andrewtknoll@17
|
60 group.rootOptionsTable = {
|
|
andrewtknoll@17
|
61 type = "group",
|
|
andrewtknoll@17
|
62 name = groupName,
|
|
andrewtknoll@17
|
63 args = {
|
|
andrewtknoll@17
|
64 text = {
|
|
andrewtknoll@17
|
65 type = "description",
|
|
andrewtknoll@21
|
66 name = groupDescription,
|
|
andrewtknoll@17
|
67 },
|
|
andrewtknoll@17
|
68 },
|
|
andrewtknoll@17
|
69 };
|
|
andrewtknoll@17
|
70 AceConfigRegistry:RegisterOptionsTable(groupName, group.rootOptionsTable);
|
|
andrewtknoll@17
|
71 AceConfigDialog:AddToBlizOptions(groupName);
|
|
andrewtknoll@21
|
72 -- create sync DB and profile options page
|
|
@12
|
73 group.syncDBTable = {};
|
|
andrewtknoll@21
|
74 group.syncDB = AceDB:New(group.syncDBTable, nil, initialDB:GetCurrentProfile());
|
|
andrewtknoll@17
|
75 group.profileOptionsTable = AceDBOptions:GetOptionsTable(group.syncDB, false);
|
|
andrewtknoll@28
|
76 if usesDualSpec then
|
|
andrewtknoll@29
|
77 group.usesDualSpec = true;
|
|
andrewtknoll@28
|
78 LibDualSpec:EnhanceDatabase(group.syncDB, groupName);
|
|
andrewtknoll@28
|
79 LibDualSpec:EnhanceOptions(group.profileOptionsTable, group.syncDB);
|
|
andrewtknoll@29
|
80 else
|
|
andrewtknoll@29
|
81 group.usesDualSpec = false;
|
|
andrewtknoll@28
|
82 end
|
|
andrewtknoll@17
|
83 AceConfigRegistry:RegisterOptionsTable(groupName.."Profiles", group.profileOptionsTable);
|
|
andrewtknoll@18
|
84 AceConfigDialog:AddToBlizOptions(groupName.."Profiles", group.profileOptionsTable.name, groupName);
|
|
andrewtknoll@21
|
85 -- add all profiles from initialDB to syncDB
|
|
andrewtknoll@21
|
86 for i, profile in pairs(initialDB:GetProfiles()) do
|
|
andrewtknoll@21
|
87 group.syncDB:SetProfile(profile);
|
|
andrewtknoll@21
|
88 end
|
|
andrewtknoll@28
|
89 -- load profile info from initialDB
|
|
andrewtknoll@21
|
90 group.syncDB:SetProfile(initialDB:GetCurrentProfile());
|
|
andrewtknoll@27
|
91 group.members[initialDB] = initialDB:GetNamespace(MAJOR, true) or initialDB:RegisterNamespace(MAJOR);
|
|
andrewtknoll@29
|
92 local storedData = group.members[initialDB].char;
|
|
andrewtknoll@29
|
93 if type(storedData.logoutTimestamp) == "number" then
|
|
andrewtknoll@29
|
94 group.profileTimestamp = storedData.logoutTimestamp;
|
|
andrewtknoll@22
|
95 else
|
|
andrewtknoll@22
|
96 group.profileTimestamp = 0;
|
|
andrewtknoll@22
|
97 end
|
|
andrewtknoll@29
|
98 if usesDualSpec and storedData.altProfile then
|
|
andrewtknoll@29
|
99 group.syncDB:SetDualSpecProfile(storedData.altProfile);
|
|
andrewtknoll@29
|
100 group.syncDB:SetDualSpecEnabled(storedData.dualSpecEnabled);
|
|
andrewtknoll@29
|
101 if storedData.dualSpecEnabled and storedData.activeSpecGroup ~= GetActiveSpecGroup() then
|
|
andrewtknoll@29
|
102 group.syncDB:SetDualSpecProfile(group.syncDB:GetCurrentProfile());
|
|
andrewtknoll@29
|
103 group.syncDB:SetProfile(storedData.altProfile);
|
|
andrewtknoll@29
|
104 initialDB:SetProfile(storedData.altProfile);
|
|
andrewtknoll@29
|
105 end
|
|
andrewtknoll@28
|
106 end
|
|
andrewtknoll@21
|
107 -- add methods and callbacks
|
|
@12
|
108 for k, v in pairs(DBGroup) do
|
|
@12
|
109 group[k] = v;
|
|
@12
|
110 end
|
|
andrewtknoll@19
|
111 group.syncDB.RegisterCallback(group, "OnProfileChanged", "OnProfileChanged");
|
|
andrewtknoll@19
|
112 group.syncDB.RegisterCallback(group, "OnProfileDeleted", "OnProfileDeleted");
|
|
andrewtknoll@19
|
113 group.syncDB.RegisterCallback(group, "OnProfileCopied", "OnProfileCopied");
|
|
andrewtknoll@19
|
114 group.syncDB.RegisterCallback(group, "OnProfileReset", "OnProfileReset");
|
|
andrewtknoll@28
|
115 group.syncDB.RegisterCallback(group, "OnDatabaseShutdown", "OnSyncShutdown");
|
|
andrewtknoll@28
|
116 initialDB.RegisterCallback(group, "OnDatabaseShutdown", "OnMemberShutdown");
|
|
andrewtknoll@20
|
117 group.squelchCallbacks = false;
|
|
andrewtknoll@19
|
118 LibModuleDBShare.groups[groupName] = group;
|
|
@12
|
119 return group;
|
|
>@4
|
120 end
|
|
>@4
|
121
|
|
>@5
|
122 --- Retrieves an existing DB group.
|
|
>@5
|
123 -- @param groupName The name of the DB group to retrieve.
|
|
>@5
|
124 -- @usage
|
|
>@5
|
125 -- local myAddonDBGroup = LibStub("LibModuleDBShare-1.0"):GetGroup("MyAddonGroupName")
|
|
>@5
|
126 -- @return the DB group object, or nil if not found
|
|
>@5
|
127 function LibModuleDBShare:GetGroup(groupName)
|
|
andrewtknoll@27
|
128 if type(groupName) ~= "string" then
|
|
andrewtknoll@27
|
129 error("Usage: LibModuleDBShare:GetGroup(groupName): 'groupName' must be a string.", 2);
|
|
andrewtknoll@27
|
130 end
|
|
@12
|
131 return LibModuleDBShare.groups[groupName];
|
|
>@4
|
132 end
|
|
>@5
|
133
|
|
>@5
|
134 --- Adds a database to the group.
|
|
andrewtknoll@22
|
135 -- @param newDB The database to add.
|
|
>@5
|
136 -- @usage
|
|
>@5
|
137 -- myAddonDBGroup:AddDB(MyAddon.db)
|
|
andrewtknoll@22
|
138 function DBGroup:AddDB(newDB)
|
|
andrewtknoll@22
|
139 -- verify parameters
|
|
andrewtknoll@26
|
140 if type(newDB) ~= "table" or not AceDB.db_registry[newDB] then
|
|
andrewtknoll@26
|
141 error("Usage: DBGroup:AddDB(newDB): 'newDB' must be a table.", 2);
|
|
andrewtknoll@26
|
142 elseif type(self.members[newDB]) ~= "nil" then
|
|
andrewtknoll@26
|
143 error("DBGroup:AddDB(newDB): 'newDB' is already a member of DBGroup.", 2);
|
|
andrewtknoll@26
|
144 end
|
|
andrewtknoll@22
|
145 -- record current profile
|
|
andrewtknoll@20
|
146 local syncProfile = self.syncDB:GetCurrentProfile();
|
|
andrewtknoll@22
|
147 -- add new profiles to syncDB
|
|
andrewtknoll@20
|
148 self.squelchCallbacks = true;
|
|
andrewtknoll@22
|
149 for i, profile in pairs(newDB:GetProfiles()) do
|
|
andrewtknoll@20
|
150 self.syncDB:SetProfile(profile);
|
|
andrewtknoll@20
|
151 end
|
|
andrewtknoll@22
|
152 -- set current profile based on timestamps
|
|
andrewtknoll@27
|
153 local namespace = newDB:GetNamespace(MAJOR, true) or newDB:RegisterNamespace(MAJOR);
|
|
andrewtknoll@29
|
154 local storedData = namespace.char;
|
|
andrewtknoll@29
|
155 if type(storedData.logoutTimestamp) == "number" and storedData.logoutTimestamp > self.profileTimestamp then
|
|
andrewtknoll@22
|
156 self.squelchCallbacks = false;
|
|
andrewtknoll@22
|
157 self.syncDB:SetProfile(newDB:GetCurrentProfile());
|
|
andrewtknoll@29
|
158 self.profileTimestamp = storedData.logoutTimestamp;
|
|
andrewtknoll@29
|
159 if self.usesDualSpec and storedData.altProfile then
|
|
andrewtknoll@29
|
160 self.syncDB:SetDualSpecProfile(storedData.altProfile);
|
|
andrewtknoll@29
|
161 self.syncDB:SetDualSpecEnabled(storedData.dualSpecEnabled);
|
|
andrewtknoll@29
|
162 if storedData.dualSpecEnabled and storedData.activeSpecGroup ~= GetActiveSpecGroup() then
|
|
andrewtknoll@29
|
163 self.syncDB:SetDualSpecProfile(self.syncDB:GetCurrentProfile());
|
|
andrewtknoll@29
|
164 self.syncDB:SetProfile(storedData.altProfile);
|
|
andrewtknoll@29
|
165 newDB:SetProfile(storedData.altProfile);
|
|
andrewtknoll@29
|
166 end
|
|
andrewtknoll@28
|
167 end
|
|
andrewtknoll@20
|
168 else
|
|
andrewtknoll@20
|
169 self.syncDB:SetProfile(syncProfile);
|
|
andrewtknoll@22
|
170 newDB:SetProfile(syncProfile);
|
|
andrewtknoll@22
|
171 self.squelchCallbacks = false;
|
|
andrewtknoll@20
|
172 end
|
|
andrewtknoll@22
|
173 -- add to members list
|
|
andrewtknoll@27
|
174 self.members[newDB] = namespace;
|
|
andrewtknoll@28
|
175 newDB.RegisterCallback(self, "OnDatabaseShutdown", "OnMemberShutdown");
|
|
>@5
|
176 end
|
|
andrewtknoll@18
|
177
|
|
andrewtknoll@19
|
178 -- callback handlers (new profiles are handled by OnProfileChanged)
|
|
andrewtknoll@19
|
179
|
|
andrewtknoll@24
|
180 function DBGroup:OnProfileChanged(callback, syncDB, profile)
|
|
andrewtknoll@24
|
181 if not self.squelchCallbacks then
|
|
andrewtknoll@24
|
182 for db, _ in pairs(self.members) do
|
|
andrewtknoll@25
|
183 db:SetProfile(profile);
|
|
andrewtknoll@24
|
184 end
|
|
andrewtknoll@24
|
185 end
|
|
andrewtknoll@18
|
186 end
|
|
andrewtknoll@18
|
187
|
|
andrewtknoll@24
|
188 function DBGroup:OnProfileDeleted(callback, syncDB, profile)
|
|
andrewtknoll@24
|
189 for db, _ in pairs(self.members) do
|
|
andrewtknoll@24
|
190 db:DeleteProfile(profile, true);
|
|
andrewtknoll@24
|
191 end
|
|
andrewtknoll@18
|
192 end
|
|
andrewtknoll@18
|
193
|
|
andrewtknoll@24
|
194 function DBGroup:OnProfileCopied(callback, syncDB, profile)
|
|
andrewtknoll@24
|
195 for db, _ in pairs(self.members) do
|
|
andrewtknoll@24
|
196 db:CopyProfile(profile, true);
|
|
andrewtknoll@24
|
197 end
|
|
andrewtknoll@18
|
198 end
|
|
andrewtknoll@18
|
199
|
|
andrewtknoll@24
|
200 function DBGroup:OnProfileReset(callback, syncDB)
|
|
andrewtknoll@24
|
201 for db, _ in pairs(self.members) do
|
|
andrewtknoll@24
|
202 db:ResetProfile(false, false);
|
|
andrewtknoll@24
|
203 end
|
|
andrewtknoll@18
|
204 end
|
|
andrewtknoll@23
|
205
|
|
andrewtknoll@29
|
206 local altProfile = nil;
|
|
andrewtknoll@29
|
207 local dualSpecEnabled = nil;
|
|
andrewtknoll@29
|
208 local activeSpecGroup = nil;
|
|
andrewtknoll@28
|
209
|
|
andrewtknoll@28
|
210 function DBGroup:OnSyncShutdown(callback, syncDB)
|
|
andrewtknoll@29
|
211 if self.usesDualSpec and not altProfile then
|
|
andrewtknoll@29
|
212 altProfile = syncDB:GetDualSpecProfile();
|
|
andrewtknoll@29
|
213 dualSpecEnabled = syncDB:IsDualSpecEnabled();
|
|
andrewtknoll@29
|
214 activeSpecGroup = GetActiveSpecGroup();
|
|
andrewtknoll@28
|
215 end
|
|
andrewtknoll@28
|
216 end
|
|
andrewtknoll@28
|
217
|
|
andrewtknoll@24
|
218 local timestamp = nil;
|
|
andrewtknoll@24
|
219
|
|
andrewtknoll@28
|
220 function DBGroup:OnMemberShutdown(callback, db)
|
|
andrewtknoll@27
|
221 if not timestamp then -- ensure uniform timestamps to minimize
|
|
andrewtknoll@27
|
222 timestamp = time(); -- calls to SetProfile in NewGroup
|
|
andrewtknoll@24
|
223 end
|
|
andrewtknoll@29
|
224 if self.usesDualSpec then
|
|
andrewtknoll@29
|
225 if not altProfile then
|
|
andrewtknoll@29
|
226 altProfile = self.syncDB:GetDualSpecProfile();
|
|
andrewtknoll@29
|
227 dualSpecEnabled = self.syncDB:IsDualSpecEnabled();
|
|
andrewtknoll@29
|
228 activeSpecGroup = GetActiveSpecGroup();
|
|
andrewtknoll@29
|
229 end
|
|
andrewtknoll@29
|
230 self.members[db].char.logoutTimestamp = timestamp;
|
|
andrewtknoll@29
|
231 self.members[db].char.altProfile = altProfile;
|
|
andrewtknoll@29
|
232 self.members[db].char.dualSpecEnabled = dualSpecEnabled;
|
|
andrewtknoll@29
|
233 self.members[db].char.activeSpecGroup = activeSpecGroup;
|
|
andrewtknoll@28
|
234 end
|
|
andrewtknoll@23
|
235 end
|