| Zerotorescue@11 | 1 -- You can access this addon's object through: LibStub("AceAddon-3.0"):GetAddon("Inventorium") | 
| Zerotorescue@17 | 2 local addon = select(2, ...); | 
| Zerotorescue@17 | 3 addon = LibStub("AceAddon-3.0"):NewAddon(addon, "Inventorium", "AceEvent-3.0"); | 
| Zerotorescue@1 | 4 | 
| Zerotorescue@1 | 5 local AceGUI = LibStub("AceGUI-3.0"); | 
| Zerotorescue@0 | 6 | 
| Zerotorescue@0 | 7 local AceConfigDialog, AceConfigRegistry, AceSerializer; | 
| Zerotorescue@30 | 8 local groupIdToName, groupIsVirtual, options = {}, {}, {}; | 
| Zerotorescue@13 | 9 local includeTradeSkillItems = 500; | 
| Zerotorescue@13 | 10 | 
| Zerotorescue@13 | 11 --  All modules must be able to retrieve our supported addons database, thus keep it public | 
| Zerotorescue@13 | 12 addon.supportedAddons = {}; | 
| Zerotorescue@13 | 13 addon.supportedAddons.auctionPricing = {}; | 
| Zerotorescue@13 | 14 addon.supportedAddons.itemCount = {}; | 
| Zerotorescue@13 | 15 addon.supportedAddons.crafting = {}; | 
| Zerotorescue@0 | 16 | 
| Zerotorescue@0 | 17 function addon:OnInitialize() | 
| Zerotorescue@0 | 18 	self:Debug("OnInitialize"); | 
| Zerotorescue@0 | 19 | 
| Zerotorescue@0 | 20 	-- SAVED VARIABLES | 
| Zerotorescue@0 | 21 | 
| Zerotorescue@0 | 22 	local defaults = { | 
| Zerotorescue@0 | 23 		global = { | 
| Zerotorescue@0 | 24 			groups = {}, | 
| Zerotorescue@0 | 25 			defaults = { | 
| Zerotorescue@13 | 26 				auctionPricingAddon = "Auctioneer", | 
| Zerotorescue@13 | 27 				itemCountAddon = "Altoholic", | 
| Zerotorescue@13 | 28 				craftingAddon = "AdvancedTradeSkillWindow", | 
| Zerotorescue@0 | 29 				minimumStock = 60, | 
| Zerotorescue@0 | 30 				alertBelowMinimum = true, | 
| Zerotorescue@0 | 31 				summaryThresholdShow = 10, | 
| Zerotorescue@0 | 32 				restockTarget = 60, | 
| Zerotorescue@0 | 33 				minCraftingQueue = 0.05, | 
| Zerotorescue@0 | 34 				bonusQueue = 0.1, | 
| Zerotorescue@0 | 35 				priceThreshold = 0, | 
| Zerotorescue@13 | 36 				summaryHidePriceThreshold = false, | 
| Zerotorescue@0 | 37 				trackAtCharacters = {}, | 
| Zerotorescue@31 | 38 				localItemData = { | 
| Zerotorescue@31 | 39 					["Bag"] = true, | 
| Zerotorescue@31 | 40 					["Auction House"] = true, | 
| Zerotorescue@31 | 41 				}, | 
| Zerotorescue@13 | 42 				summary = { | 
| Zerotorescue@13 | 43 					speed = 5, | 
| Zerotorescue@13 | 44 					width = 650, | 
| Zerotorescue@13 | 45 					height = 600, | 
| Zerotorescue@13 | 46 				}, | 
| Zerotorescue@0 | 47 				colors = { | 
| Zerotorescue@17 | 48 					red = 0, | 
| Zerotorescue@17 | 49 					orange = 0.3, | 
| Zerotorescue@17 | 50 					yellow = 0.6, | 
| Zerotorescue@17 | 51 					green = 0.95, | 
| Zerotorescue@0 | 52 				}, | 
| Zerotorescue@0 | 53 			}, | 
| Zerotorescue@0 | 54 		}, | 
| Zerotorescue@0 | 55 		factionrealm = { | 
| Zerotorescue@0 | 56 			characters = {}, | 
| Zerotorescue@0 | 57 		}, | 
| Zerotorescue@0 | 58 	}; | 
| Zerotorescue@0 | 59 | 
| Zerotorescue@0 | 60 	-- Register our saved variables database | 
| Zerotorescue@11 | 61 	self.db = LibStub("AceDB-3.0"):New("InventoriumDB", defaults, true); | 
| Zerotorescue@0 | 62 | 
| Zerotorescue@0 | 63 	-- SLASH COMMANDS | 
| Zerotorescue@0 | 64 | 
| Zerotorescue@0 | 65 	-- Disable the AddonLoader slash commands | 
| Zerotorescue@11 | 66 	SLASH_INVENTORIUM1 = nil; | 
| Zerotorescue@0 | 67 	SLASH_IY1 = nil; | 
| Zerotorescue@0 | 68 | 
| Zerotorescue@0 | 69 	-- Register our own slash commands | 
| Zerotorescue@11 | 70 	SLASH_INVENTORIUM1 = "/inventorium"; | 
| Zerotorescue@11 | 71 	SLASH_INVENTORIUM2 = "/im"; | 
| Zerotorescue@11 | 72 	SlashCmdList["INVENTORIUM"] = function(msg) | 
| Zerotorescue@0 | 73 		self:CommandHandler(msg); | 
| Zerotorescue@0 | 74 	end | 
| Zerotorescue@0 | 75 | 
| Zerotorescue@0 | 76 	-- INTERFACE OPTIONS | 
| Zerotorescue@0 | 77 | 
| Zerotorescue@0 | 78 	 -- Attempt to remove the interface options added by AddonLoader (if enabled) | 
| Zerotorescue@0 | 79 	if AddonLoader and AddonLoader.RemoveInterfaceOptions then | 
| Zerotorescue@11 | 80 		AddonLoader:RemoveInterfaceOptions("Inventorium"); | 
| Zerotorescue@0 | 81 	end | 
| Zerotorescue@0 | 82 | 
| Zerotorescue@0 | 83 	-- Now create our own options frame | 
| Zerotorescue@0 | 84 	local frame = CreateFrame("Frame", nil, UIParent); | 
| Zerotorescue@0 | 85 	frame:Hide(); | 
| Zerotorescue@11 | 86 	frame.name = "Inventorium"; | 
| Zerotorescue@0 | 87 	frame:HookScript("OnShow", function(self) | 
| Zerotorescue@0 | 88 		-- Refresh the frame to instantly show the right options | 
| Zerotorescue@0 | 89 		InterfaceOptionsFrame_OpenToCategory(self.name) | 
| Zerotorescue@0 | 90 	end); | 
| Zerotorescue@0 | 91 	-- And add it to the interface options | 
| Zerotorescue@0 | 92 	InterfaceOptions_AddCategory(frame); | 
| Zerotorescue@0 | 93 | 
| Zerotorescue@1 | 94 	self:MakeItemLinkButtonWidget(); | 
| Zerotorescue@1 | 95 	self:MakeConfigItemLinkButtonWidget(); | 
| Zerotorescue@0 | 96 | 
| Zerotorescue@0 | 97 	-- Remember this character is mine | 
| Zerotorescue@0 | 98 	local playerName = UnitName("player"); | 
| Zerotorescue@0 | 99 	if not self.db.factionrealm.characters[playerName] then | 
| Zerotorescue@0 | 100 		self.db.factionrealm.characters[playerName] = true; | 
| Zerotorescue@0 | 101 | 
| Zerotorescue@0 | 102 		-- Default to tracking on all chars, untracking is a convenience, not tracking by default would probably get multiple issue reports. | 
| Zerotorescue@0 | 103 		self.db.global.defaults.trackAtCharacters[playerName] = true; | 
| Zerotorescue@0 | 104 	end | 
| Zerotorescue@23 | 105 | 
| Zerotorescue@23 | 106 	self:PremadeGroupsCheck(); | 
| Zerotorescue@0 | 107 end | 
| Zerotorescue@0 | 108 | 
| Zerotorescue@24 | 109 local function InGroup(itemId) | 
| Zerotorescue@24 | 110 	-- Go through all groups to see if this item is already somewhere | 
| Zerotorescue@24 | 111 	for groupName, values in pairs(addon.db.global.groups) do | 
| Zerotorescue@24 | 112 		if values.items and values.items[itemId] then | 
| Zerotorescue@24 | 113 			return groupName; | 
| Zerotorescue@24 | 114 		end | 
| Zerotorescue@24 | 115 	end | 
| Zerotorescue@24 | 116 | 
| Zerotorescue@24 | 117 	return; | 
| Zerotorescue@24 | 118 end | 
| Zerotorescue@24 | 119 | 
| Zerotorescue@23 | 120 function addon:PremadeGroupsCheck(updateGroupName, updateKey, accept) | 
| Zerotorescue@23 | 121 	-- Compare the current premade groups with those used, notify about changes | 
| Zerotorescue@23 | 122 	if addon.defaultGroups then | 
| Zerotorescue@23 | 123 		for key, groupInfo in pairs(addon.defaultGroups) do | 
| Zerotorescue@23 | 124 			-- Go through all default groups | 
| Zerotorescue@23 | 125 | 
| Zerotorescue@23 | 126 			for groupName, values in pairs(addon.db.global.groups) do | 
| Zerotorescue@23 | 127 				-- Go through all groups to find those with this premade group | 
| Zerotorescue@23 | 128 | 
| Zerotorescue@23 | 129 				if values.premadeGroups and values.premadeGroups[key] and values.premadeGroups[key] < groupInfo.version then | 
| Zerotorescue@23 | 130 					-- Outdated group | 
| Zerotorescue@23 | 131 | 
| Zerotorescue@23 | 132 					if updateGroupName and updateKey then | 
| Zerotorescue@23 | 133 						-- This function was called after pressing yes or no in a confirm box | 
| Zerotorescue@23 | 134 | 
| Zerotorescue@23 | 135 						if accept then | 
| Zerotorescue@23 | 136 							-- Yes was clicked | 
| Zerotorescue@23 | 137 | 
| Zerotorescue@23 | 138 							for itemId, version in pairs(groupInfo.items) do | 
| Zerotorescue@23 | 139 								-- Go through all items in this premade group | 
| Zerotorescue@23 | 140 | 
| Zerotorescue@23 | 141 								if version > values.premadeGroups[key] then | 
| Zerotorescue@23 | 142 									-- This item was added in a more recent version than this group: Add item | 
| Zerotorescue@23 | 143 | 
| Zerotorescue@23 | 144 									if InGroup(itemId) then | 
| Zerotorescue@23 | 145 										print(("Skipping %s (#%d) as it is already in the group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId))); | 
| Zerotorescue@23 | 146 									elseif AddToGroup(groupName, itemId) then | 
| Zerotorescue@23 | 147 										print(("Added %s (#%d) found in the premade group |cfffed000%s|r to the group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId))); | 
| Zerotorescue@23 | 148 									end | 
| Zerotorescue@23 | 149 								end | 
| Zerotorescue@23 | 150 							end | 
| Zerotorescue@23 | 151 | 
| Zerotorescue@23 | 152 							-- Remember the new version | 
| Zerotorescue@23 | 153 							values.premadeGroups[key] = groupInfo.version; | 
| Zerotorescue@23 | 154 						else | 
| Zerotorescue@23 | 155 							-- No was clicked | 
| Zerotorescue@23 | 156 | 
| Zerotorescue@23 | 157 							-- Let user know what was not added | 
| Zerotorescue@23 | 158 							for itemId, version in pairs(groupInfo.items) do | 
| Zerotorescue@23 | 159 								-- Go through all items in this premade group | 
| Zerotorescue@23 | 160 | 
| Zerotorescue@23 | 161 								if version > values.premadeGroups[key] then | 
| Zerotorescue@23 | 162 									-- This item was added in a more recent version than this group: don't add (since we clicked no), but announce it | 
| Zerotorescue@23 | 163 | 
| Zerotorescue@23 | 164 									print(("Skipping %s (#%d) found in the premade group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId))); | 
| Zerotorescue@23 | 165 								end | 
| Zerotorescue@23 | 166 							end | 
| Zerotorescue@23 | 167 | 
| Zerotorescue@23 | 168 							-- Remember the new version | 
| Zerotorescue@23 | 169 							values.premadeGroups[key] = groupInfo.version; | 
| Zerotorescue@23 | 170 						end | 
| Zerotorescue@23 | 171 					else | 
| Zerotorescue@23 | 172 						StaticPopupDialogs["InventoriumConfirmUpdatePremadeGroup"] = { | 
| Zerotorescue@23 | 173 							text = "The premade group |cfffed000%s|r used in the group |cfffed000%s|r has been changed. Do you wish to copy these changes?", | 
| Zerotorescue@23 | 174 							button1 = YES, | 
| Zerotorescue@23 | 175 							button2 = NO, | 
| Zerotorescue@23 | 176 							OnAccept = function(self) | 
| Zerotorescue@23 | 177 								addon:PremadeGroupsCheck(groupName, key, true); | 
| Zerotorescue@23 | 178 							end, | 
| Zerotorescue@23 | 179 							OnCancel = function(self, _, reason) | 
| Zerotorescue@23 | 180 								if reason == "clicked" then | 
| Zerotorescue@23 | 181 									addon:PremadeGroupsCheck(groupName, key, false); | 
| Zerotorescue@23 | 182 								end | 
| Zerotorescue@23 | 183 							end, | 
| Zerotorescue@23 | 184 							timeout = 0, | 
| Zerotorescue@23 | 185 							whileDead = 1, | 
| Zerotorescue@23 | 186 							hideOnEscape = 1, | 
| Zerotorescue@23 | 187 						}; | 
| Zerotorescue@23 | 188 						StaticPopup_Show("InventoriumConfirmUpdatePremadeGroup", key, groupName); | 
| Zerotorescue@23 | 189 | 
| Zerotorescue@23 | 190 						return; | 
| Zerotorescue@23 | 191 					end | 
| Zerotorescue@23 | 192 				end | 
| Zerotorescue@23 | 193 			end | 
| Zerotorescue@23 | 194 		end | 
| Zerotorescue@23 | 195 	end | 
| Zerotorescue@23 | 196 end | 
| Zerotorescue@23 | 197 | 
| Zerotorescue@23 | 198 | 
| Zerotorescue@1 | 199 local slashArgs = {}; | 
| Zerotorescue@1 | 200 function addon:RegisterSlash(func, ...) | 
| Zerotorescue@1 | 201 	for _, arg in pairs({ ... }) do | 
| Zerotorescue@1 | 202 		slashArgs[arg] = func; | 
| Zerotorescue@1 | 203 	end | 
| Zerotorescue@1 | 204 end | 
| Zerotorescue@1 | 205 | 
| Zerotorescue@1 | 206 function addon:MakeItemLinkButtonWidget() | 
| Zerotorescue@0 | 207 	--[[ | 
| Zerotorescue@0 | 208 	[ ItemLinkButton ] | 
| Zerotorescue@1 | 209 	This custom widget has to show an icon with the item link next to it. | 
| Zerotorescue@1 | 210 	Upon hover it must show the item tooltip. | 
| Zerotorescue@1 | 211 	Upon click it must execute the function provided through user data. | 
| Zerotorescue@1 | 212 | 
| Zerotorescue@1 | 213 	UserData: itemId, onClickEvent | 
| Zerotorescue@1 | 214 | 
| Zerotorescue@0 | 215 	OnEnter: tooltip show | 
| Zerotorescue@1 | 216 	OnLeave: tooltip hide | 
| Zerotorescue@1 | 217 	OnClick: UserData.onClickEvent | 
| Zerotorescue@0 | 218 	]] | 
| Zerotorescue@0 | 219 | 
| Zerotorescue@0 | 220 	local widgetType = "ItemLinkButton"; | 
| Zerotorescue@0 | 221 	local widgetVersion = 1; | 
| Zerotorescue@0 | 222 | 
| Zerotorescue@1 | 223 	local function Constructor() | 
| Zerotorescue@1 | 224 	    local widget = AceGUI:Create("InteractiveLabel"); | 
| Zerotorescue@1 | 225 	    widget.type = widgetType; | 
| Zerotorescue@1 | 226 | 
| Zerotorescue@1 | 227 	    -- We overwrite the OnAcquire as we want to set our callbacks even | 
| Zerotorescue@1 | 228 	    -- when the widget is re-used from the widget pool | 
| Zerotorescue@1 | 229 	    widget.originalOnAcquire = widget.OnAcquire; | 
| Zerotorescue@1 | 230 	    widget.OnAcquire = function(self, ...) | 
| Zerotorescue@1 | 231 | 
| Zerotorescue@1 | 232 | 
| Zerotorescue@1 | 233 	    	-- We overwrite the setcallback because we don't want anything else | 
| Zerotorescue@1 | 234 	    	-- to overwrite our OnEnter, OnLeave and OnClick events | 
| Zerotorescue@1 | 235 	    	-- which would be done by the AceConfigDialog after a widget gets re-used | 
| Zerotorescue@1 | 236 		    if not self.originalSetCallBack then | 
| Zerotorescue@1 | 237 			    self.originalSetCallBack = self.SetCallback; | 
| Zerotorescue@1 | 238 			    self.SetCallback = function(this, event, func, ...) | 
| Zerotorescue@1 | 239 			    	if event == "OnEnter" or event == "OnLeave" or event == "OnClick" then | 
| Zerotorescue@1 | 240 			    		-- Don't allow overwriting of these events | 
| Zerotorescue@1 | 241 			    		return; | 
| Zerotorescue@1 | 242 			    	elseif event == "CustomOnEnter" then | 
| Zerotorescue@1 | 243 			    		return this.originalSetCallBack(this, "OnEnter", func, ...); | 
| Zerotorescue@1 | 244 			    	elseif event == "CustomOnLeave" then | 
| Zerotorescue@1 | 245 			    		return this.originalSetCallBack(this, "OnLeave", func, ...); | 
| Zerotorescue@1 | 246 			    	elseif event == "CustomOnClick" then | 
| Zerotorescue@1 | 247 			    		return this.originalSetCallBack(this, "OnClick", func, ...); | 
| Zerotorescue@1 | 248 			    	else | 
| Zerotorescue@1 | 249 			    		return this.originalSetCallBack(this, event, func, ...); | 
| Zerotorescue@1 | 250 			    	end | 
| Zerotorescue@1 | 251 			    end; | 
| Zerotorescue@1 | 252 		    end | 
| Zerotorescue@1 | 253 | 
| Zerotorescue@1 | 254 | 
| Zerotorescue@1 | 255 		    -- Set our own events, since we disabled the normal event-names, we'll call them our custom versions | 
| Zerotorescue@1 | 256 		    self:SetCallback("CustomOnEnter", function(this) | 
| Zerotorescue@1 | 257 		    	local itemId = this:GetUserData("itemId"); | 
| Zerotorescue@1 | 258 | 
| Zerotorescue@1 | 259 		    	if itemId then | 
| Zerotorescue@1 | 260 			    	GameTooltip:SetOwner(this.frame, "ANCHOR_TOPRIGHT"); | 
| Zerotorescue@1 | 261 			    	GameTooltip:SetHyperlink(("item:%d"):format(itemId)); | 
| Zerotorescue@1 | 262 					GameTooltip:Show(); | 
| Zerotorescue@1 | 263 		    	end | 
| Zerotorescue@1 | 264 		    end); | 
| Zerotorescue@1 | 265 		    self:SetCallback("CustomOnLeave", function(this) | 
| Zerotorescue@1 | 266 		    	GameTooltip:Hide(); | 
| Zerotorescue@1 | 267 		    end); | 
| Zerotorescue@23 | 268 		    self:SetCallback("CustomOnClick", function(this, ...) | 
| Zerotorescue@23 | 269 		    	-- Below is used in child widgets to prepare for onclick | 
| Zerotorescue@1 | 270 		    	if this.OnClick then | 
| Zerotorescue@23 | 271 		    		this.OnClick(this, ...); | 
| Zerotorescue@1 | 272 		    	end | 
| Zerotorescue@1 | 273 | 
| Zerotorescue@1 | 274 		    	local func = this:GetUserData("exec"); | 
| Zerotorescue@1 | 275 		    	local itemId = this:GetUserData("itemId"); | 
| Zerotorescue@1 | 276 | 
| Zerotorescue@1 | 277 		    	if func then | 
| Zerotorescue@1 | 278 		    		-- If this is a config option we will need the group id | 
| Zerotorescue@1 | 279 		    		local path = this:GetUserData("path"); | 
| Zerotorescue@1 | 280 		    		local groupId = (path and path[2]) or nil; | 
| Zerotorescue@1 | 281 | 
| Zerotorescue@23 | 282 		    		func(groupId, itemId, ...); | 
| Zerotorescue@1 | 283 		    	end | 
| Zerotorescue@1 | 284 		    end); | 
| Zerotorescue@1 | 285 | 
| Zerotorescue@1 | 286 | 
| Zerotorescue@1 | 287 | 
| Zerotorescue@1 | 288 		    -- Then also do whatever it wanted to do | 
| Zerotorescue@1 | 289 		    self.originalOnAcquire(self, ...); | 
| Zerotorescue@1 | 290 	    end; | 
| Zerotorescue@1 | 291 | 
| Zerotorescue@1 | 292 	    -- Remember the original SetText as this might get overwritten by the config-widget | 
| Zerotorescue@1 | 293 	    widget.originalSetText = widget.SetText; | 
| Zerotorescue@1 | 294 | 
| Zerotorescue@1 | 295 	    widget.SetItemId = function(self, itemId) | 
| Zerotorescue@1 | 296  		   	self:SetUserData("itemId", itemId); | 
| Zerotorescue@1 | 297 | 
| Zerotorescue@1 | 298 	   		-- Put the icon in front of it | 
| Zerotorescue@1 | 299 			self:SetImage(GetItemIcon(itemId)); | 
| Zerotorescue@0 | 300 			-- Standardize the size | 
| Zerotorescue@0 | 301 			self:SetImageSize(16, 16); | 
| Zerotorescue@0 | 302 | 
| Zerotorescue@0 | 303 			-- Make readable font | 
| Zerotorescue@0 | 304     		self:SetFontObject(GameFontHighlight); | 
| Zerotorescue@0 | 305 | 
| Zerotorescue@0 | 306     		-- We don't want to set the itemId as text, but rather the item link, so get that. | 
| Zerotorescue@1 | 307     		local itemLink = select(2, GetItemInfo(itemId)) or ("Unknown (#%d)"):format(itemId); | 
| Zerotorescue@0 | 308 | 
| Zerotorescue@1 | 309     		self:originalSetText(itemLink); | 
| Zerotorescue@1 | 310 	    end; | 
| Zerotorescue@1 | 311 | 
| Zerotorescue@1 | 312 		return widget; | 
| Zerotorescue@0 | 313 	end | 
| Zerotorescue@1 | 314 | 
| Zerotorescue@1 | 315 	AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion); | 
| Zerotorescue@1 | 316 end | 
| Zerotorescue@1 | 317 | 
| Zerotorescue@1 | 318 function addon:MakeConfigItemLinkButtonWidget() | 
| Zerotorescue@1 | 319 	-- Define out custom item link button widget | 
| Zerotorescue@1 | 320 	-- This will be called as if it's an input element, we overwrite some of the related functions which are called for default input fields | 
| Zerotorescue@0 | 321 | 
| Zerotorescue@1 | 322 	local widgetType = "ConfigItemLinkButton"; | 
| Zerotorescue@1 | 323 	local widgetVersion = 1; | 
| Zerotorescue@0 | 324 | 
| Zerotorescue@1 | 325 	-- Empty function for disabling functions | 
| Zerotorescue@1 | 326 	local function Dummy() end | 
| Zerotorescue@0 | 327 | 
| Zerotorescue@0 | 328 	-- Makes an instance of our ItemLinkButton widget | 
| Zerotorescue@0 | 329 	local function GetItemLinkButton() | 
| Zerotorescue@1 | 330 	    local widget = AceGUI:Create("ItemLinkButton"); | 
| Zerotorescue@0 | 331 	    widget.type = widgetType; | 
| Zerotorescue@0 | 332 | 
| Zerotorescue@0 | 333 	    -- We can only provide custom widgets for input, select and multiselect fields | 
| Zerotorescue@0 | 334 	    -- Input being the simplest, we use that - however, it provides two parameters: label and text. We only need one, disable the other. | 
| Zerotorescue@0 | 335 	    widget.SetLabel = Dummy; | 
| Zerotorescue@0 | 336 | 
| Zerotorescue@1 | 337 	    -- SetText is called when this button is being created and contains the itemId | 
| Zerotorescue@1 | 338 	    -- Forward that itemId to the ItemLinkButton | 
| Zerotorescue@1 | 339 	    widget.SetText = function(self, value, ...) | 
| Zerotorescue@1 | 340 	    	if value and tonumber(value) then | 
| Zerotorescue@1 | 341 	    		self:SetItemId(tonumber(value)); | 
| Zerotorescue@1 | 342 	    	end | 
| Zerotorescue@1 | 343 		end; | 
| Zerotorescue@1 | 344 | 
| Zerotorescue@1 | 345 		widget.OnClick = function(self, ...) | 
| Zerotorescue@1 | 346 			local option = self:GetUserData("option"); | 
| Zerotorescue@1 | 347 | 
| Zerotorescue@1 | 348 	    	if option and option.set then | 
| Zerotorescue@1 | 349 				self:SetUserData("exec", option.set); | 
| Zerotorescue@1 | 350 			end | 
| Zerotorescue@1 | 351 		end; | 
| Zerotorescue@0 | 352 | 
| Zerotorescue@0 | 353 	    return widget; | 
| Zerotorescue@0 | 354 	end | 
| Zerotorescue@0 | 355 | 
| Zerotorescue@0 | 356 	AceGUI:RegisterWidgetType(widgetType, GetItemLinkButton, widgetVersion); | 
| Zerotorescue@0 | 357 end | 
| Zerotorescue@0 | 358 | 
| Zerotorescue@0 | 359 function addon:CommandHandler(message) | 
| Zerotorescue@0 | 360 	local cmd, arg = string.split(" ", (message or ""), 2); | 
| Zerotorescue@0 | 361 	cmd = string.lower(cmd); | 
| Zerotorescue@0 | 362 | 
| Zerotorescue@0 | 363 	if cmd == "c" or cmd == "config" or cmd == "conf" or cmd == "option" or cmd == "options" or cmd == "opt" or cmd == "setting" or cmd == "settings" then | 
| Zerotorescue@9 | 364 		-- We don't want any other windows open at this time. | 
| Zerotorescue@9 | 365 		for name, module in self:IterateModules() do | 
| Zerotorescue@9 | 366 			if module.CloseFrame then | 
| Zerotorescue@9 | 367 				module:CloseFrame(); | 
| Zerotorescue@9 | 368 			end | 
| Zerotorescue@9 | 369 		end | 
| Zerotorescue@9 | 370 | 
| Zerotorescue@0 | 371 		self:Show(); | 
| Zerotorescue@0 | 372 	elseif cmd == "d" or cmd == "debug" then | 
| Zerotorescue@0 | 373 		self.debugChannel = false; | 
| Zerotorescue@0 | 374 		for i = 1, NUM_CHAT_WINDOWS do | 
| Zerotorescue@0 | 375 			local name = GetChatWindowInfo(i); | 
| Zerotorescue@0 | 376 | 
| Zerotorescue@0 | 377 			if name:upper() == "DEBUG" then | 
| Zerotorescue@0 | 378 				self.debugChannel = _G["ChatFrame" .. i]; | 
| Zerotorescue@0 | 379 | 
| Zerotorescue@0 | 380 				print("A debug channel already exists, used the old one. (" .. i .. ")"); | 
| Zerotorescue@0 | 381 				return; | 
| Zerotorescue@0 | 382 			end | 
| Zerotorescue@0 | 383 		end | 
| Zerotorescue@0 | 384 | 
| Zerotorescue@0 | 385 		if not self.debugChannel then | 
| Zerotorescue@0 | 386 			-- Create a new debug channel | 
| Zerotorescue@0 | 387 			local chatFrame = FCF_OpenNewWindow('Debug'); | 
| Zerotorescue@0 | 388 			ChatFrame_RemoveAllMessageGroups(chatFrame); | 
| Zerotorescue@0 | 389 			self.debugChannel = chatFrame; | 
| Zerotorescue@0 | 390 | 
| Zerotorescue@0 | 391 			print("New debug channel created."); | 
| Zerotorescue@0 | 392 		end | 
| Zerotorescue@1 | 393 	elseif slashArgs[cmd] then | 
| Zerotorescue@1 | 394 		slashArgs[cmd](); | 
| Zerotorescue@0 | 395 	else | 
| Zerotorescue@11 | 396 		print("Wrong command, available: /inventorium config (or /im c) and /inventorium summary (or /im s)"); | 
| Zerotorescue@0 | 397 	end | 
| Zerotorescue@0 | 398 end | 
| Zerotorescue@0 | 399 | 
| Zerotorescue@0 | 400 function addon:Load() | 
| Zerotorescue@0 | 401 	if not AceConfigDialog and not AceConfigRegistry then | 
| Zerotorescue@0 | 402 		self:FillOptions(); | 
| Zerotorescue@0 | 403 | 
| Zerotorescue@0 | 404 		-- Build options dialog | 
| Zerotorescue@0 | 405 		AceConfigDialog = LibStub("AceConfigDialog-3.0"); | 
| Zerotorescue@0 | 406 		AceConfigRegistry = LibStub("AceConfigRegistry-3.0"); | 
| Zerotorescue@0 | 407 		-- Register options table | 
| Zerotorescue@11 | 408 		LibStub("AceConfig-3.0"):RegisterOptionsTable("InventoriumOptions", options); | 
| Zerotorescue@0 | 409 		-- Set a nice default size (so that 4 normal sized elements fit next to eachother) | 
| Zerotorescue@11 | 410 		AceConfigDialog:SetDefaultSize("InventoriumOptions", 975, 600); | 
| Zerotorescue@0 | 411 | 
| Zerotorescue@0 | 412 		 -- In case the addon is loaded from another condition, always call the remove interface options | 
| Zerotorescue@0 | 413 		if AddonLoader and AddonLoader.RemoveInterfaceOptions then | 
| Zerotorescue@11 | 414 			AddonLoader:RemoveInterfaceOptions("Inventorium"); | 
| Zerotorescue@0 | 415 		end | 
| Zerotorescue@0 | 416 | 
| Zerotorescue@0 | 417 		-- Add to the blizzard addons options thing | 
| Zerotorescue@11 | 418 		--AceConfigDialog:AddToBlizOptions("InventoriumOptions"); | 
| Zerotorescue@0 | 419 	end | 
| Zerotorescue@0 | 420 end | 
| Zerotorescue@0 | 421 | 
| Zerotorescue@0 | 422 function addon:Show() | 
| Zerotorescue@0 | 423 	self:Load(); | 
| Zerotorescue@0 | 424 | 
| Zerotorescue@11 | 425 	AceConfigDialog:Open("InventoriumOptions"); | 
| Zerotorescue@0 | 426 end | 
| Zerotorescue@0 | 427 | 
| Zerotorescue@0 | 428 function addon:FillOptions() | 
| Zerotorescue@0 | 429 	options = { | 
| Zerotorescue@0 | 430 		type = "group", | 
| Zerotorescue@11 | 431 		name = "Inventorium", | 
| Zerotorescue@0 | 432 		childGroups = "tree", | 
| Zerotorescue@0 | 433 		args = { | 
| Zerotorescue@0 | 434 		}, | 
| Zerotorescue@0 | 435 	}; | 
| Zerotorescue@0 | 436 | 
| Zerotorescue@0 | 437 	self:FillGeneralOptions(); | 
| Zerotorescue@0 | 438 | 
| Zerotorescue@0 | 439 	options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db, true); | 
| Zerotorescue@0 | 440 	options.args.profiles.order = 200; | 
| Zerotorescue@0 | 441 | 
| Zerotorescue@0 | 442 	self:MakeGroupOptions(); | 
| Zerotorescue@0 | 443 | 
| Zerotorescue@0 | 444 	self:FillGroupOptions(); | 
| Zerotorescue@0 | 445 end | 
| Zerotorescue@0 | 446 | 
| Zerotorescue@1 | 447 local goldText = "%s%d|cffffd700g|r "; | 
| Zerotorescue@1 | 448 local silverText = "%s%d|cffc7c7cfs|r "; | 
| Zerotorescue@1 | 449 local copperText = "%s%d|cffeda55fc|r"; | 
| Zerotorescue@1 | 450 | 
| Zerotorescue@1 | 451 function addon:ReadableMoney(copper, clean) | 
| Zerotorescue@1 | 452 	local text = ""; | 
| Zerotorescue@1 | 453 | 
| Zerotorescue@1 | 454 	local gold = floor( copper / COPPER_PER_GOLD ); | 
| Zerotorescue@1 | 455 	if gold > 0 then | 
| Zerotorescue@1 | 456 		text = goldText:format(text, gold); | 
| Zerotorescue@1 | 457 	end | 
| Zerotorescue@1 | 458 | 
| Zerotorescue@13 | 459 	if not clean or (not gold or gold < 10) then | 
| Zerotorescue@1 | 460 		local silver = floor( ( copper % COPPER_PER_GOLD ) / COPPER_PER_SILVER ); | 
| Zerotorescue@1 | 461 		if silver > 0 then | 
| Zerotorescue@1 | 462 			text = silverText:format(text, silver); | 
| Zerotorescue@1 | 463 		end | 
| Zerotorescue@1 | 464 | 
| Zerotorescue@13 | 465 		if not clean or (not gold or gold < 1) then | 
| Zerotorescue@1 | 466 			local copper = floor( copper % COPPER_PER_SILVER ); | 
| Zerotorescue@1 | 467 			if copper > 0 or text == "" then | 
| Zerotorescue@1 | 468 				text = copperText:format(text, copper); | 
| Zerotorescue@1 | 469 			end | 
| Zerotorescue@1 | 470 		end | 
| Zerotorescue@1 | 471 	end | 
| Zerotorescue@1 | 472 | 
| Zerotorescue@1 | 473 | 
| Zerotorescue@1 | 474 	return string.trim(text); | 
| Zerotorescue@1 | 475 end | 
| Zerotorescue@1 | 476 | 
| Zerotorescue@1 | 477 function addon:ReadableMoneyToCopper(value) | 
| Zerotorescue@1 | 478 	-- If a player enters a value it will be filled without color codes | 
| Zerotorescue@1 | 479 	-- If it is retrieved from the database, it will be colored coded | 
| Zerotorescue@1 | 480 	-- Thus we look for both | 
| Zerotorescue@1 | 481 	local gold = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+g|r") or string.match(value, "(%d+)g")); | 
| Zerotorescue@1 | 482 	local silver = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+s|r") or string.match(value, "(%d+)s")); | 
| Zerotorescue@1 | 483 	local copper = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+c|r") or string.match(value, "(%d+)c")); | 
| Zerotorescue@1 | 484 | 
| Zerotorescue@1 | 485 	return ( (gold or 0) * COPPER_PER_GOLD ) + ( (silver or 0) * COPPER_PER_SILVER ) + (copper or 0); | 
| Zerotorescue@1 | 486 end | 
| Zerotorescue@1 | 487 | 
| Zerotorescue@1 | 488 function addon:ValidateReadableMoney(info, value) | 
| Zerotorescue@1 | 489 	-- If a player enters a value it will be filled without color codes | 
| Zerotorescue@1 | 490 	-- If it is retrieved from the database, it will be colored coded | 
| Zerotorescue@1 | 491 	-- Thus we look for both | 
| Zerotorescue@1 | 492 	local gold = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+g|r") or string.match(value, "(%d+)g")); | 
| Zerotorescue@1 | 493 	local silver = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+s|r") or string.match(value, "(%d+)s")); | 
| Zerotorescue@1 | 494 	local copper = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+c|r") or string.match(value, "(%d+)c")); | 
| Zerotorescue@1 | 495 | 
| Zerotorescue@1 | 496 	if not gold and not silver and not copper then | 
| Zerotorescue@1 | 497 		return "The provided amount of money is invalid. Please provide the amount of money as #g#s#c, e.g. 591617g24s43c."; | 
| Zerotorescue@1 | 498 	else | 
| Zerotorescue@1 | 499 		return true; | 
| Zerotorescue@1 | 500 	end | 
| Zerotorescue@1 | 501 end | 
| Zerotorescue@1 | 502 | 
| Zerotorescue@0 | 503 function addon:FillGeneralOptions() | 
| Zerotorescue@0 | 504 	options.args.general = { | 
| Zerotorescue@0 | 505 		order = 100, | 
| Zerotorescue@0 | 506 		type = "group", | 
| Zerotorescue@0 | 507 		name = "General", | 
| Zerotorescue@11 | 508 		desc = "Change general Inventorium settings.", | 
| Zerotorescue@0 | 509 		args = { | 
| Zerotorescue@31 | 510 			info = { | 
| Zerotorescue@31 | 511 				order = 1, | 
| Zerotorescue@31 | 512 				type = "group", | 
| Zerotorescue@31 | 513 				inline = true, | 
| Zerotorescue@31 | 514 				name = "BETA Information", | 
| Zerotorescue@31 | 515 				args = { | 
| Zerotorescue@31 | 516 					description = { | 
| Zerotorescue@31 | 517 						order = 5, | 
| Zerotorescue@31 | 518 						type = "description", | 
| Zerotorescue@31 | 519 						name = "Please note that all multi-select |cfffed000dropdown|r boxes were turned into multi-select |cfffed000toggle|r boxes. I do not intend to keep it this way, however it can not yet be reverted due to a major bug in one of the libraries used by Inventorium. The layout of this config may look terribly organized in it's current state.\n\n" .. | 
| Zerotorescue@31 | 520 								"Since this is a beta some functionality might not be implemented yet while the options are available (usually - but not always - tagged as \"NYI\"). These options are used to indicate a feature is on the way and will be implemented before Inventorium is tagged as a release.\n\n" .. | 
| Zerotorescue@31 | 521 								"Please request things you want and report anything that's clunky, weird, vague or otherwise buggy at |cfffed000the Inventorium development addon page|r. You can find this by searching for \"|cfffed000Inventorium|r\" at |cfffed000CurseForge.com|r.\n\n" .. | 
| Zerotorescue@31 | 522 								"Tutorials for Inventorium will be created after the first stable release. If you require any help before that you can always contact me in the |cfffed000#JMTC|r IRC channel at |cfffed000QuakeNet.org|r. You may also report issues and request things there if you wish.\n\n" .. | 
| Zerotorescue@31 | 523 								"You might notice the summary window currently gets very slow when refreshed once you get over 100-200 items in the list, this is a known issue and will be fixed in version 1.1 (which is after the initial release).", | 
| Zerotorescue@31 | 524 					}, | 
| Zerotorescue@31 | 525 				}, | 
| Zerotorescue@31 | 526 			}, | 
| Zerotorescue@0 | 527 			general = { | 
| Zerotorescue@31 | 528 				order = 1, | 
| Zerotorescue@0 | 529 				type = "group", | 
| Zerotorescue@0 | 530 				inline = true, | 
| Zerotorescue@0 | 531 				name = "General", | 
| Zerotorescue@0 | 532 				args = { | 
| Zerotorescue@0 | 533 					description = { | 
| Zerotorescue@0 | 534 						order = 0, | 
| Zerotorescue@0 | 535 						type = "description", | 
| Zerotorescue@23 | 536 						name = "Here you can set general settings. The settings entered here will be used when you choose not to override the settings within an individual group.", | 
| Zerotorescue@0 | 537 					}, | 
| Zerotorescue@0 | 538 					header = { | 
| Zerotorescue@0 | 539 						order = 5, | 
| Zerotorescue@0 | 540 						type = "header", | 
| Zerotorescue@0 | 541 						name = "", | 
| Zerotorescue@0 | 542 					}, | 
| Zerotorescue@13 | 543 					auctionPricingAddon = { | 
| Zerotorescue@0 | 544 						order = 10, | 
| Zerotorescue@0 | 545 						type = "select", | 
| Zerotorescue@0 | 546 						name = "Prefered pricing addon", | 
| Zerotorescue@13 | 547 						desc = "Select the addon you prefer data to be retrieved from. A random supported addon will be used if the selected addon can not be found.", | 
| Zerotorescue@13 | 548 						values = function() | 
| Zerotorescue@13 | 549 							local temp = {}; | 
| Zerotorescue@13 | 550 							for name, value in pairs(self.supportedAddons.auctionPricing) do | 
| Zerotorescue@13 | 551 								temp[name] = name; | 
| Zerotorescue@13 | 552 							end | 
| Zerotorescue@13 | 553 | 
| Zerotorescue@13 | 554 							return temp; | 
| Zerotorescue@13 | 555 						end, | 
| Zerotorescue@13 | 556 						get = function() return self.db.global.defaults.auctionPricingAddon; end, | 
| Zerotorescue@13 | 557 						set = function(i, v) self.db.global.defaults.auctionPricingAddon = v; end, | 
| Zerotorescue@0 | 558 					}, | 
| Zerotorescue@0 | 559 					itemCountAddon = { | 
| Zerotorescue@0 | 560 						order = 20, | 
| Zerotorescue@0 | 561 						type = "select", | 
| Zerotorescue@0 | 562 						name = "Prefered item count addon", | 
| Zerotorescue@13 | 563 						desc = "Select the addon you prefer data to be retrieved from. A random supported addon will be used if the selected addon can not be found.", | 
| Zerotorescue@13 | 564 						values = function() | 
| Zerotorescue@13 | 565 							local temp = {}; | 
| Zerotorescue@13 | 566 							for name, value in pairs(self.supportedAddons.itemCount) do | 
| Zerotorescue@13 | 567 								temp[name] = name; | 
| Zerotorescue@13 | 568 							end | 
| Zerotorescue@13 | 569 | 
| Zerotorescue@13 | 570 							return temp; | 
| Zerotorescue@13 | 571 						end, | 
| Zerotorescue@13 | 572 						get = function() return self.db.global.defaults.itemCountAddon; end, | 
| Zerotorescue@13 | 573 						set = function(i, v) self.db.global.defaults.itemCountAddon = v; end, | 
| Zerotorescue@13 | 574 					}, | 
| Zerotorescue@13 | 575 					craftingAddon = { | 
| Zerotorescue@23 | 576 						order = 30, | 
| Zerotorescue@13 | 577 						type = "select", | 
| Zerotorescue@13 | 578 						name = "Prefered crafting addon", | 
| Zerotorescue@13 | 579 						desc = "Select the addon you prefer data to be queued into. A random supported addon will be used if the selected addon can not be found.", | 
| Zerotorescue@13 | 580 						values = function() | 
| Zerotorescue@13 | 581 							local temp = {}; | 
| Zerotorescue@13 | 582 							for name, value in pairs(self.supportedAddons.crafting) do | 
| Zerotorescue@13 | 583 								temp[name] = name; | 
| Zerotorescue@13 | 584 							end | 
| Zerotorescue@13 | 585 | 
| Zerotorescue@13 | 586 							return temp; | 
| Zerotorescue@13 | 587 						end, | 
| Zerotorescue@13 | 588 						get = function() return self.db.global.defaults.craftingAddon; end, | 
| Zerotorescue@13 | 589 						set = function(i, v) self.db.global.defaults.craftingAddon = v; end, | 
| Zerotorescue@0 | 590 					}, | 
| Zerotorescue@23 | 591 					localItemData = { | 
| Zerotorescue@23 | 592 						order = 40, | 
| Zerotorescue@23 | 593 						type = "multiselect", | 
| Zerotorescue@31 | 594 						name = "Include in local item data", | 
| Zerotorescue@23 | 595 						desc = "Select which data should be included in the local item data.", | 
| Zerotorescue@23 | 596 						values = { | 
| Zerotorescue@23 | 597 							["Bag"] = "Bag", | 
| Zerotorescue@23 | 598 							["Bank"] = "Bank", | 
| Zerotorescue@23 | 599 							["Auction House"] = "Auction House", | 
| Zerotorescue@23 | 600 							["Mailbox"] = "Mailbox", | 
| Zerotorescue@23 | 601 						}, | 
| Zerotorescue@23 | 602 						get = function(i, v) return self.db.global.defaults.localItemData and self.db.global.defaults.localItemData[v]; end, | 
| Zerotorescue@23 | 603 						set = function(i, v, e) self.db.global.defaults.localItemData[v] = e or nil; end, | 
| Zerotorescue@23 | 604 						--dialogControl = "Dropdown", -- this is not standard, normal multiselect control gives us a list of all chars with toggle-boxes. UGLY! We want a multiselect-box instead. | 
| Zerotorescue@23 | 605 					}, | 
| Zerotorescue@0 | 606 				}, | 
| Zerotorescue@0 | 607 			}, | 
| Zerotorescue@0 | 608 			minimumStock = { | 
| Zerotorescue@0 | 609 				order = 10, | 
| Zerotorescue@0 | 610 				type = "group", | 
| Zerotorescue@0 | 611 				inline = true, | 
| Zerotorescue@0 | 612 				name = "Minimum stock", | 
| Zerotorescue@0 | 613 				args = { | 
| Zerotorescue@0 | 614 					description = { | 
| Zerotorescue@0 | 615 						order = 0, | 
| Zerotorescue@0 | 616 						type = "description", | 
| Zerotorescue@0 | 617 						name = "Here you can specify the default minimum amount of items you wish to keep in stock and related settings. The settings entered here will be used when you choose not to override the settings within an individual group.", | 
| Zerotorescue@0 | 618 					}, | 
| Zerotorescue@0 | 619 					header = { | 
| Zerotorescue@0 | 620 						order = 5, | 
| Zerotorescue@0 | 621 						type = "header", | 
| Zerotorescue@0 | 622 						name = "", | 
| Zerotorescue@0 | 623 					}, | 
| Zerotorescue@0 | 624 					minimumStock = { | 
| Zerotorescue@0 | 625 						order = 10, | 
| Zerotorescue@0 | 626 						type = "range", | 
| Zerotorescue@0 | 627 						min = 0, | 
| Zerotorescue@0 | 628 						max = 100000, | 
| Zerotorescue@17 | 629 						softMax = 100, | 
| Zerotorescue@0 | 630 						step = 1, | 
| Zerotorescue@0 | 631 						name = "Minimum stock", | 
| Zerotorescue@17 | 632 						desc = "You can manually enter a value between 100 and 100.000 in the text box below if the provided range is insufficient.", | 
| Zerotorescue@0 | 633 						get = function() return self.db.global.defaults.minimumStock; end, | 
| Zerotorescue@0 | 634 						set = function(i, v) self.db.global.defaults.minimumStock = v; end, | 
| Zerotorescue@0 | 635 					}, | 
| Zerotorescue@0 | 636 					summaryThresholdShow = { | 
| Zerotorescue@0 | 637 						order = 20, | 
| Zerotorescue@0 | 638 						type = "range", | 
| Zerotorescue@0 | 639 						min = 0, | 
| Zerotorescue@0 | 640 						max = 100, | 
| Zerotorescue@0 | 641 						softMax = 10, | 
| Zerotorescue@0 | 642 						step = 0.05, | 
| Zerotorescue@0 | 643 						isPercent = true, | 
| Zerotorescue@0 | 644 						name = "Show in summary when below", | 
| Zerotorescue@0 | 645 						desc = "Show items in the summary when below this percentage of the minimum stock.\n\nYou can manually enter a value between 1.000% and 10.000% in the edit box if the provided range is insufficient.", | 
| Zerotorescue@0 | 646 						get = function() return self.db.global.defaults.summaryThresholdShow; end, | 
| Zerotorescue@0 | 647 						set = function(i, v) self.db.global.defaults.summaryThresholdShow = v; end, | 
| Zerotorescue@0 | 648 					}, | 
| Zerotorescue@0 | 649 					alertBelowMinimum = { | 
| Zerotorescue@0 | 650 						order = 30, | 
| Zerotorescue@0 | 651 						type = "toggle", | 
| Zerotorescue@30 | 652 						name = "NYI | Alert when below minimum", | 
| Zerotorescue@0 | 653 						desc = "Show an alert when this item gets below this threshold.", | 
| Zerotorescue@0 | 654 						get = function() return self.db.global.defaults.alertBelowMinimum; end, | 
| Zerotorescue@0 | 655 						set = function(i, v) self.db.global.defaults.alertBelowMinimum = v; end, | 
| Zerotorescue@0 | 656 					}, | 
| Zerotorescue@0 | 657 					trackAtCharacters = { | 
| Zerotorescue@0 | 658 						order = 40, | 
| Zerotorescue@0 | 659 						type = "multiselect", | 
| Zerotorescue@0 | 660 						name = "Track at", | 
| Zerotorescue@0 | 661 						desc = "Select at which characters this should appear in the summary and generate alerts.", | 
| Zerotorescue@0 | 662 						values = function() | 
| Zerotorescue@0 | 663 							local temp = {}; | 
| Zerotorescue@0 | 664 							for charName in pairs(self.db.factionrealm.characters) do | 
| Zerotorescue@0 | 665 								temp[charName] = charName; | 
| Zerotorescue@0 | 666 							end | 
| Zerotorescue@0 | 667 | 
| Zerotorescue@0 | 668 							return temp; | 
| Zerotorescue@0 | 669 						end, | 
| Zerotorescue@1 | 670 						get = function(i, v) return self.db.global.defaults.trackAtCharacters[v]; end, | 
| Zerotorescue@23 | 671 						set = function(i, v, e) self.db.global.defaults.trackAtCharacters[v] = e or nil; end, | 
| Zerotorescue@13 | 672 						--dialogControl = "Dropdown", -- this is not standard, normal multiselect control gives us a list of all chars with toggle-boxes. UGLY! We want a multiselect-box instead. | 
| Zerotorescue@0 | 673 					}, | 
| Zerotorescue@0 | 674 				}, | 
| Zerotorescue@0 | 675 			}, | 
| Zerotorescue@0 | 676 			refill = { | 
| Zerotorescue@0 | 677 				order = 20, | 
| Zerotorescue@0 | 678 				type = "group", | 
| Zerotorescue@0 | 679 				inline = true, | 
| Zerotorescue@0 | 680 				name = "Replenishing stock", | 
| Zerotorescue@0 | 681 				args = { | 
| Zerotorescue@0 | 682 					description = { | 
| Zerotorescue@0 | 683 						order = 0, | 
| Zerotorescue@0 | 684 						type = "description", | 
| Zerotorescue@0 | 685 						name = function() | 
| Zerotorescue@0 | 686 							local r = "Here you can specify the default amount of items to which you wish to restock when you are collecting new items. This may be higher than the minimum stock. The settings entered here will be used when you choose not to override the settings within an individual group.\n\n"; | 
| Zerotorescue@0 | 687 | 
| Zerotorescue@0 | 688 							r = r .. "When restocking the target amount is |cfffed000" .. self.db.global.defaults.restockTarget .. "|r of every item. Not queueing craftable items when only missing |cfffed000" .. floor( self.db.global.defaults.minCraftingQueue * self.db.global.defaults.restockTarget ) .. "|r (|cfffed000" .. ( self.db.global.defaults.minCraftingQueue * 100 ) .. "%|r) of the restock target."; | 
| Zerotorescue@0 | 689 | 
| Zerotorescue@0 | 690 							return r; | 
| Zerotorescue@0 | 691 						end, | 
| Zerotorescue@0 | 692 					}, | 
| Zerotorescue@0 | 693 					header = { | 
| Zerotorescue@0 | 694 						order = 5, | 
| Zerotorescue@0 | 695 						type = "header", | 
| Zerotorescue@0 | 696 						name = "", | 
| Zerotorescue@0 | 697 					}, | 
| Zerotorescue@0 | 698 					restockTarget = { | 
| Zerotorescue@0 | 699 						order = 10, | 
| Zerotorescue@0 | 700 						type = "range", | 
| Zerotorescue@0 | 701 						min = 0, | 
| Zerotorescue@0 | 702 						max = 100000, | 
| Zerotorescue@30 | 703 						softMax = 100, | 
| Zerotorescue@0 | 704 						step = 1, | 
| Zerotorescue@0 | 705 						name = "Restock target", | 
| Zerotorescue@30 | 706 						desc = "You can manually enter a value between 100 and 100.000 in the edit box if the provided range is insufficient.", | 
| Zerotorescue@0 | 707 						get = function() return self.db.global.defaults.restockTarget; end, | 
| Zerotorescue@0 | 708 						set = function(i, v) self.db.global.defaults.restockTarget = v; end, | 
| Zerotorescue@0 | 709 					}, | 
| Zerotorescue@0 | 710 					minCraftingQueue = { | 
| Zerotorescue@0 | 711 						order = 20, | 
| Zerotorescue@0 | 712 						type = "range", | 
| Zerotorescue@0 | 713 						min = 0, | 
| Zerotorescue@0 | 714 						max = 1, | 
| Zerotorescue@0 | 715 						step = 0.01, -- 1% | 
| Zerotorescue@0 | 716 						isPercent = true, | 
| Zerotorescue@0 | 717 						name = "Don't queue if I only miss", | 
| Zerotorescue@0 | 718 						desc = "Don't add a craftable item to the queue if I only miss this much or less of the restock target.\n\nExample: if your restock target is set to 60 and this is set to 5%, an item won't be queued unless you are missing more than 3 of it.", | 
| Zerotorescue@0 | 719 						get = function() return self.db.global.defaults.minCraftingQueue; end, | 
| Zerotorescue@0 | 720 						set = function(i, v) self.db.global.defaults.minCraftingQueue = v; end, | 
| Zerotorescue@0 | 721 					}, | 
| Zerotorescue@0 | 722 					bonusQueue = { | 
| Zerotorescue@0 | 723 						order = 30, | 
| Zerotorescue@0 | 724 						type = "range", | 
| Zerotorescue@0 | 725 						min = 0, | 
| Zerotorescue@0 | 726 						max = 10, -- 1000% | 
| Zerotorescue@0 | 727 						step = 0.01, -- 1% | 
| Zerotorescue@0 | 728 						isPercent = true, | 
| Zerotorescue@0 | 729 						name = "Bonus queue", | 
| Zerotorescue@1 | 730 						desc = "Get additional items when there are none left.\n\nExample: if your restock target is set to 60 and this is set to 10%, you will get 66 items instead of just 60 if you end up with none left while queueing.", | 
| Zerotorescue@0 | 731 						get = function() return self.db.global.defaults.bonusQueue; end, | 
| Zerotorescue@0 | 732 						set = function(i, v) self.db.global.defaults.bonusQueue = v; end, | 
| Zerotorescue@0 | 733 					}, | 
| Zerotorescue@0 | 734 					priceThreshold = { | 
| Zerotorescue@0 | 735 						order = 40, | 
| Zerotorescue@0 | 736 						type = "input", | 
| Zerotorescue@0 | 737 						name = "Price threshold", | 
| Zerotorescue@1 | 738 						desc = "Only queue craftable items when they are worth at least this much according to your auction house addon.\n\nSet to 0 to ignore auction prices.", | 
| Zerotorescue@1 | 739 						validate = function(info, value) return self:ValidateReadableMoney(info, value); end, | 
| Zerotorescue@1 | 740 						get = function() return self:ReadableMoney(self.db.global.defaults.priceThreshold); end, | 
| Zerotorescue@1 | 741 						set = function(i, v) self.db.global.defaults.priceThreshold = self:ReadableMoneyToCopper(v); end, | 
| Zerotorescue@0 | 742 					}, | 
| Zerotorescue@13 | 743 					summaryHidePriceThreshold = { | 
| Zerotorescue@0 | 744 						order = 50, | 
| Zerotorescue@0 | 745 						type = "toggle", | 
| Zerotorescue@1 | 746 						name = "Hide when below threshold", | 
| Zerotorescue@0 | 747 						desc = "Hide items from the summary when their value is below the set price threshold.", | 
| Zerotorescue@13 | 748 						get = function() return self.db.global.defaults.summaryHidePriceThreshold; end, | 
| Zerotorescue@13 | 749 						set = function(i, v) self.db.global.defaults.summaryHidePriceThreshold = v; end, | 
| Zerotorescue@0 | 750 					}, | 
| Zerotorescue@23 | 751 					alwaysGetAuctionValue = { | 
| Zerotorescue@23 | 752 						order = 60, | 
| Zerotorescue@23 | 753 						type = "toggle", | 
| Zerotorescue@23 | 754 						name = "Always show auction value", | 
| Zerotorescue@31 | 755 						desc = "Always cache and show the auction value of items, even if the price threshold is set to 0|cffeda55fc|r.", | 
| Zerotorescue@23 | 756 						get = function() return self.db.global.defaults.alwaysGetAuctionValue; end, | 
| Zerotorescue@23 | 757 						set = function(i, v) self.db.global.defaults.alwaysGetAuctionValue = v; end, | 
| Zerotorescue@23 | 758 					}, | 
| Zerotorescue@0 | 759 				}, | 
| Zerotorescue@0 | 760 			}, | 
| Zerotorescue@0 | 761 			colorCodes = { | 
| Zerotorescue@0 | 762 				order = 30, | 
| Zerotorescue@0 | 763 				type = "group", | 
| Zerotorescue@0 | 764 				inline = true, | 
| Zerotorescue@0 | 765 				name = "Color codes", | 
| Zerotorescue@0 | 766 				args = { | 
| Zerotorescue@0 | 767 					description = { | 
| Zerotorescue@0 | 768 						order = 0, | 
| Zerotorescue@0 | 769 						type = "description", | 
| Zerotorescue@0 | 770 						name = "Change the color code thresholds based on the current stock remaining of the required minimum stock.", | 
| Zerotorescue@0 | 771 					}, | 
| Zerotorescue@0 | 772 					header = { | 
| Zerotorescue@0 | 773 						order = 5, | 
| Zerotorescue@0 | 774 						type = "header", | 
| Zerotorescue@0 | 775 						name = "", | 
| Zerotorescue@0 | 776 					}, | 
| Zerotorescue@0 | 777 					green = { | 
| Zerotorescue@0 | 778 						order = 10, | 
| Zerotorescue@0 | 779 						type = "range", | 
| Zerotorescue@0 | 780 						min = 0, | 
| Zerotorescue@0 | 781 						max = 1, | 
| Zerotorescue@0 | 782 						step = 0.01, | 
| Zerotorescue@0 | 783 						isPercent = true, | 
| Zerotorescue@0 | 784 						name = "|cff00ff00Green|r", | 
| Zerotorescue@0 | 785 						desc = "Show quantity in green when at least this much of the minimum stock is available.", | 
| Zerotorescue@0 | 786 						get = function() return self.db.global.defaults.colors.green; end, | 
| Zerotorescue@0 | 787 						set = function(i, v) self.db.global.defaults.colors.green = v; end, | 
| Zerotorescue@0 | 788 					}, | 
| Zerotorescue@0 | 789 					yellow = { | 
| Zerotorescue@0 | 790 						order = 20, | 
| Zerotorescue@0 | 791 						type = "range", | 
| Zerotorescue@0 | 792 						min = 0, | 
| Zerotorescue@0 | 793 						max = 1, | 
| Zerotorescue@0 | 794 						step = 0.01, | 
| Zerotorescue@0 | 795 						isPercent = true, | 
| Zerotorescue@0 | 796 						name = "|cffffff00Yellow|r", | 
| Zerotorescue@0 | 797 						desc = "Show quantity in yellow when at least this much of the minimum stock is available.", | 
| Zerotorescue@0 | 798 						get = function() return self.db.global.defaults.colors.yellow; end, | 
| Zerotorescue@0 | 799 						set = function(i, v) self.db.global.defaults.colors.yellow = v; end, | 
| Zerotorescue@0 | 800 					}, | 
| Zerotorescue@0 | 801 					orange = { | 
| Zerotorescue@0 | 802 						order = 30, | 
| Zerotorescue@0 | 803 						type = "range", | 
| Zerotorescue@0 | 804 						min = 0, | 
| Zerotorescue@0 | 805 						max = 1, | 
| Zerotorescue@0 | 806 						step = 0.01, | 
| Zerotorescue@0 | 807 						isPercent = true, | 
| Zerotorescue@0 | 808 						name = "|cffff9933Orange|r", | 
| Zerotorescue@0 | 809 						desc = "Show quantity in orange when at least this much of the minimum stock is available.", | 
| Zerotorescue@0 | 810 						get = function() return self.db.global.defaults.colors.orange; end, | 
| Zerotorescue@0 | 811 						set = function(i, v) self.db.global.defaults.colors.orange = v; end, | 
| Zerotorescue@0 | 812 					}, | 
| Zerotorescue@0 | 813 					red = { | 
| Zerotorescue@0 | 814 						order = 40, | 
| Zerotorescue@0 | 815 						type = "range", | 
| Zerotorescue@0 | 816 						min = 0, | 
| Zerotorescue@0 | 817 						max = 1, | 
| Zerotorescue@0 | 818 						step = 0.01, | 
| Zerotorescue@0 | 819 						isPercent = true, | 
| Zerotorescue@0 | 820 						name = "|cffff0000Red|r", | 
| Zerotorescue@0 | 821 						desc = "Show quantity in red when at least this much of the minimum stock is available.", | 
| Zerotorescue@0 | 822 						get = function() return self.db.global.defaults.colors.red; end, | 
| Zerotorescue@0 | 823 						set = function(i, v) self.db.global.defaults.colors.red = v; end, | 
| Zerotorescue@0 | 824 					}, | 
| Zerotorescue@0 | 825 				}, | 
| Zerotorescue@0 | 826 			}, | 
| Zerotorescue@0 | 827 		}, | 
| Zerotorescue@0 | 828 	}; | 
| Zerotorescue@0 | 829 end | 
| Zerotorescue@0 | 830 | 
| Zerotorescue@0 | 831 local count = 0; | 
| Zerotorescue@0 | 832 local temp = {}; | 
| Zerotorescue@0 | 833 | 
| Zerotorescue@1 | 834 local function SetOption(info, value, multiSelectEnabled) | 
| Zerotorescue@0 | 835 	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 836 	local optionName = info[#info]; | 
| Zerotorescue@0 | 837 | 
| Zerotorescue@23 | 838 	-- Special treatment for override toggle boxes | 
| Zerotorescue@31 | 839 	if optionName:find("override") then | 
| Zerotorescue@23 | 840 		if not value and info.arg then | 
| Zerotorescue@23 | 841 			-- If this override was disabled and a saved variable name was provided, set it to nil rather than false | 
| Zerotorescue@23 | 842 | 
| Zerotorescue@23 | 843 			value = nil; | 
| Zerotorescue@23 | 844 | 
| Zerotorescue@23 | 845 			-- If this is an override toggler then also set the related field to nil | 
| Zerotorescue@23 | 846 			addon.db.global.groups[groupName][info.arg] = nil; | 
| Zerotorescue@23 | 847 		elseif value and info.arg then | 
| Zerotorescue@23 | 848 			-- If this override is now enabled, we need to copy the default into this field (unless it is not nil (which is supposed to be impossible), in which case we'll use the already selected value) | 
| Zerotorescue@23 | 849 | 
| Zerotorescue@23 | 850 			addon.db.global.groups[groupName][info.arg] = addon:GetOptionByKey(groupName, info.arg); | 
| Zerotorescue@23 | 851 		end | 
| Zerotorescue@0 | 852 	end | 
| Zerotorescue@0 | 853 | 
| Zerotorescue@1 | 854 	if multiSelectEnabled ~= nil then | 
| Zerotorescue@1 | 855 		-- The saved vars for a multiselect will always be an array, it may not yet exist in which case it must be created. | 
| Zerotorescue@1 | 856 		if not addon.db.global.groups[groupName][optionName] then | 
| Zerotorescue@1 | 857 			addon.db.global.groups[groupName][optionName] = {}; | 
| Zerotorescue@1 | 858 		end | 
| Zerotorescue@1 | 859 | 
| Zerotorescue@1 | 860 		addon.db.global.groups[groupName][optionName][value] = multiSelectEnabled or nil; | 
| Zerotorescue@1 | 861 	else | 
| Zerotorescue@1 | 862 		addon.db.global.groups[groupName][optionName] = value; | 
| Zerotorescue@1 | 863 	end | 
| Zerotorescue@0 | 864 end | 
| Zerotorescue@0 | 865 | 
| Zerotorescue@1 | 866 function addon:GetOptionByKey(groupName, optionName, noDefault) | 
| Zerotorescue@23 | 867 	if groupName and self.db.global.groups[groupName] and self.db.global.groups[groupName][optionName] ~= nil then | 
| Zerotorescue@31 | 868 		-- If this option exists within the settings of this group | 
| Zerotorescue@31 | 869 | 
| Zerotorescue@23 | 870 		return self.db.global.groups[groupName][optionName]; | 
| Zerotorescue@31 | 871 	elseif groupName and self.db.global.groups[groupName] and self.db.global.groups[groupName].virtualGroup ~= "" and not noDefault then | 
| Zerotorescue@31 | 872 		-- If a virtual group was selected | 
| Zerotorescue@31 | 873 | 
| Zerotorescue@31 | 874 		return self:GetOptionByKey(self.db.global.groups[groupName].virtualGroup, optionName, noDefault); | 
| Zerotorescue@23 | 875 	elseif self.db.global.defaults[optionName] and not noDefault then | 
| Zerotorescue@23 | 876 		return self.db.global.defaults[optionName]; | 
| Zerotorescue@0 | 877 	else | 
| Zerotorescue@0 | 878 		return nil; | 
| Zerotorescue@0 | 879 	end | 
| Zerotorescue@0 | 880 end | 
| Zerotorescue@0 | 881 | 
| Zerotorescue@0 | 882 local function GetOption(info) | 
| Zerotorescue@0 | 883 	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 884 	local optionName = info[#info]; | 
| Zerotorescue@0 | 885 | 
| Zerotorescue@31 | 886 	local noDefault; | 
| Zerotorescue@31 | 887 | 
| Zerotorescue@31 | 888 	if optionName:find("override") then | 
| Zerotorescue@31 | 889 		noDefault = true; | 
| Zerotorescue@31 | 890 	end | 
| Zerotorescue@31 | 891 | 
| Zerotorescue@31 | 892 	return addon:GetOptionByKey(groupName, optionName, noDefault); | 
| Zerotorescue@1 | 893 end | 
| Zerotorescue@1 | 894 | 
| Zerotorescue@1 | 895 local function GetMultiOption(info, value) | 
| Zerotorescue@1 | 896 	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@1 | 897 	local optionName = info[#info]; | 
| Zerotorescue@1 | 898 | 
| Zerotorescue@1 | 899 	if addon.db.global.groups[groupName][optionName] ~= nil then | 
| Zerotorescue@1 | 900 		return addon.db.global.groups[groupName][optionName][value]; | 
| Zerotorescue@1 | 901 	elseif addon.db.global.defaults[optionName] then | 
| Zerotorescue@1 | 902 		return addon.db.global.defaults[optionName][value]; | 
| Zerotorescue@1 | 903 	else | 
| Zerotorescue@1 | 904 		return nil; | 
| Zerotorescue@1 | 905 	end | 
| Zerotorescue@0 | 906 end | 
| Zerotorescue@0 | 907 | 
| Zerotorescue@0 | 908 local function GetDisabled(info) | 
| Zerotorescue@31 | 909 	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@31 | 910 	local optionName = info[#info]; | 
| Zerotorescue@31 | 911 | 
| Zerotorescue@31 | 912 	if optionName:find("override") then | 
| Zerotorescue@0 | 913 		return false; | 
| Zerotorescue@0 | 914 	end | 
| Zerotorescue@0 | 915 | 
| Zerotorescue@1 | 916 	return (addon:GetOptionByKey(groupName, info.arg, true) == nil); | 
| Zerotorescue@0 | 917 end | 
| Zerotorescue@0 | 918 | 
| Zerotorescue@0 | 919 local function ValidateGroupName(_, value) | 
| Zerotorescue@0 | 920 	value = string.lower(string.trim(value or "")); | 
| Zerotorescue@0 | 921 | 
| Zerotorescue@0 | 922 	for name, _ in pairs(addon.db.global.groups) do | 
| Zerotorescue@0 | 923 		if string.lower(name) == value then | 
| Zerotorescue@0 | 924 			return ("A group named \"%s\" already exists."):format(name); | 
| Zerotorescue@0 | 925 		end | 
| Zerotorescue@0 | 926 	end | 
| Zerotorescue@0 | 927 | 
| Zerotorescue@0 | 928 	return true; | 
| Zerotorescue@0 | 929 end | 
| Zerotorescue@0 | 930 | 
| Zerotorescue@0 | 931 local function AddToGroup(groupName, itemId) | 
| Zerotorescue@0 | 932 	if InGroup(itemId) then | 
| Zerotorescue@0 | 933 		return false; | 
| Zerotorescue@0 | 934 	end | 
| Zerotorescue@0 | 935 | 
| Zerotorescue@0 | 936 	if not addon.db.global.groups[groupName].items then | 
| Zerotorescue@0 | 937 		addon.db.global.groups[groupName].items = {}; | 
| Zerotorescue@0 | 938 	end | 
| Zerotorescue@0 | 939 | 
| Zerotorescue@0 | 940 	-- Set this item | 
| Zerotorescue@0 | 941 	addon.db.global.groups[groupName].items[itemId] = true; | 
| Zerotorescue@0 | 942 | 
| Zerotorescue@0 | 943 	-- Now rebuild the list | 
| Zerotorescue@11 | 944 	AceConfigRegistry:NotifyChange("InventoriumOptions"); | 
| Zerotorescue@0 | 945 | 
| Zerotorescue@0 | 946 	return true; | 
| Zerotorescue@0 | 947 end | 
| Zerotorescue@0 | 948 | 
| Zerotorescue@0 | 949 local tblAddItemTemplate = { | 
| Zerotorescue@0 | 950 	order = 0, | 
| Zerotorescue@0 | 951 	type = "input", | 
| Zerotorescue@0 | 952 	name = function(info) | 
| Zerotorescue@0 | 953 		local itemName, _, itemRarity = GetItemInfo(info[#info]); | 
| Zerotorescue@0 | 954 		return tostring( 7 - (itemRarity or 0) ) .. (itemName or ""); | 
| Zerotorescue@0 | 955 	end, | 
| Zerotorescue@0 | 956 	get = function(info) | 
| Zerotorescue@0 | 957 		return tostring(info[#info]); -- Ace is going to be anal about this if it's a numeric value, so we transmute it into a string here then back to a number on the other side | 
| Zerotorescue@0 | 958 	end, | 
| Zerotorescue@1 | 959 	set = function(groupId, itemId) | 
| Zerotorescue@0 | 960     	-- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info. | 
| Zerotorescue@0 | 961 | 
| Zerotorescue@1 | 962     	if itemId then | 
| Zerotorescue@1 | 963 	    	local groupName = groupIdToName[groupId]; | 
| Zerotorescue@0 | 964 | 
| Zerotorescue@1 | 965 	    	if not AddToGroup(groupName, itemId) then | 
| Zerotorescue@1 | 966 	    		print("|cffff0000Couldn't add the item with itemId (" .. itemId .. ") because it is already in a group.|r"); | 
| Zerotorescue@0 | 967 	    	end | 
| Zerotorescue@0 | 968     	end | 
| Zerotorescue@0 | 969 	end, | 
| Zerotorescue@0 | 970 	width = "double", | 
| Zerotorescue@1 | 971 	dialogControl = "ConfigItemLinkButton", | 
| Zerotorescue@0 | 972 }; | 
| Zerotorescue@0 | 973 | 
| Zerotorescue@0 | 974 local tblRemoveItemTemplate = { | 
| Zerotorescue@0 | 975 	order = 0, | 
| Zerotorescue@0 | 976 	type = "input", | 
| Zerotorescue@0 | 977 	name = function(info) | 
| Zerotorescue@0 | 978 		local itemName, _, itemRarity = GetItemInfo(info[#info]); | 
| Zerotorescue@0 | 979 		return tostring( 7 - (itemRarity or 0) ) .. (itemName or ""); | 
| Zerotorescue@0 | 980 	end, | 
| Zerotorescue@0 | 981 	get = function(info) | 
| Zerotorescue@0 | 982 		return tostring(info[#info]); -- Ace is going to be anal about this if it's a numeric value, so we transmute it into a string here then back to a number on the other side | 
| Zerotorescue@0 | 983 	end, | 
| Zerotorescue@1 | 984 	set = function(groupId, itemId) | 
| Zerotorescue@0 | 985     	-- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info. | 
| Zerotorescue@0 | 986 | 
| Zerotorescue@1 | 987     	if itemId then | 
| Zerotorescue@1 | 988 	    	local groupName = groupIdToName[groupId]; | 
| Zerotorescue@0 | 989 | 
| Zerotorescue@0 | 990 	    	-- Unset this item | 
| Zerotorescue@1 | 991 	    	addon.db.global.groups[groupName].items[itemId] = nil; | 
| Zerotorescue@0 | 992 | 
| Zerotorescue@0 | 993 	    	-- Now rebuild the list | 
| Zerotorescue@11 | 994 	    	AceConfigRegistry:NotifyChange("InventoriumOptions"); | 
| Zerotorescue@0 | 995     	end | 
| Zerotorescue@0 | 996 	end, | 
| Zerotorescue@0 | 997 	width = "double", | 
| Zerotorescue@1 | 998 	dialogControl = "ConfigItemLinkButton", | 
| Zerotorescue@0 | 999 }; | 
| Zerotorescue@0 | 1000 | 
| Zerotorescue@0 | 1001 local function UpdateAddItemList(info) | 
| Zerotorescue@0 | 1002 	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1003 | 
| Zerotorescue@0 | 1004 	if not addon.db.global.groups[groupName].items then | 
| Zerotorescue@0 | 1005 		addon.db.global.groups[groupName].items = {}; | 
| Zerotorescue@0 | 1006 	end | 
| Zerotorescue@0 | 1007 | 
| Zerotorescue@0 | 1008 	-- Merge all items from all groups together | 
| Zerotorescue@0 | 1009 	local items = {}; | 
| Zerotorescue@0 | 1010 	for groupName, values in pairs(addon.db.global.groups) do | 
| Zerotorescue@0 | 1011 		if values.items then | 
| Zerotorescue@0 | 1012 			for itemId, _ in pairs(values.items) do | 
| Zerotorescue@0 | 1013 				items[itemId] = true; | 
| Zerotorescue@0 | 1014 			end | 
| Zerotorescue@0 | 1015 		end | 
| Zerotorescue@0 | 1016 	end | 
| Zerotorescue@0 | 1017 | 
| Zerotorescue@0 | 1018 	local ref = options.args.groups.args[info[2]].args.add.args.list.args; | 
| Zerotorescue@0 | 1019 | 
| Zerotorescue@13 | 1020 	-- Remaking the list, so out with the old, in with the new | 
| Zerotorescue@13 | 1021 	table.wipe(ref); | 
| Zerotorescue@13 | 1022 | 
| Zerotorescue@0 | 1023 	-- Parse bags and show these | 
| Zerotorescue@0 | 1024 	for bagID = 4, 0, -1 do | 
| Zerotorescue@0 | 1025 		for slot = 1, GetContainerNumSlots(bagID) do | 
| Zerotorescue@0 | 1026 			local itemId = addon:GetItemId(GetContainerItemLink(bagID, slot)); | 
| Zerotorescue@0 | 1027 | 
| Zerotorescue@0 | 1028 			if itemId then | 
| Zerotorescue@0 | 1029 				if not items[itemId] then | 
| Zerotorescue@0 | 1030 					-- If this item isn't used in any group yet | 
| Zerotorescue@0 | 1031 					ref[itemId] = tblAddItemTemplate; | 
| Zerotorescue@0 | 1032 				else | 
| Zerotorescue@0 | 1033 					-- It's already used in a group, don't show it | 
| Zerotorescue@0 | 1034 					ref[itemId] = nil; | 
| Zerotorescue@0 | 1035 				end | 
| Zerotorescue@0 | 1036 			end | 
| Zerotorescue@0 | 1037 		end | 
| Zerotorescue@0 | 1038 	end | 
| Zerotorescue@13 | 1039 | 
| Zerotorescue@13 | 1040 	if includeTradeSkillItems ~= 500 then | 
| Zerotorescue@13 | 1041 		-- Include tradeskill items | 
| Zerotorescue@13 | 1042 | 
| Zerotorescue@13 | 1043 		-- Go through all trade skills for the profession | 
| Zerotorescue@13 | 1044 		for i = 1, GetNumTradeSkills() do | 
| Zerotorescue@13 | 1045 			-- Try to retrieve the itemlink, this will be nil if current item is a group instead | 
| Zerotorescue@13 | 1046 			local itemLink = GetTradeSkillItemLink(i); | 
| Zerotorescue@13 | 1047 | 
| Zerotorescue@13 | 1048 			if itemLink then | 
| Zerotorescue@13 | 1049 				local itemId = addon:GetItemId(itemLink); | 
| Zerotorescue@13 | 1050 				if not itemId then | 
| Zerotorescue@13 | 1051 					-- If this isn't an item, it can only be an enchant instead | 
| Zerotorescue@13 | 1052 					itemId = tonumber(itemLink:match("|Henchant:([-0-9]+)|h")); | 
| Zerotorescue@13 | 1053 | 
| Zerotorescue@17 | 1054 					itemId = addon.scrollIds[itemId]; -- change enchantIds into scrollIds | 
| Zerotorescue@13 | 1055 				end | 
| Zerotorescue@13 | 1056 | 
| Zerotorescue@17 | 1057 				if itemId then | 
| Zerotorescue@17 | 1058 					local itemLevel = select(4, GetItemInfo(itemId)) or 0; | 
| Zerotorescue@17 | 1059 | 
| Zerotorescue@17 | 1060 					if includeTradeSkillItems == 0 or itemLevel >= includeTradeSkillItems then | 
| Zerotorescue@17 | 1061 						if not items[itemId] then | 
| Zerotorescue@17 | 1062 							-- If this item isn't used in any group yet | 
| Zerotorescue@17 | 1063 							ref[itemId] = tblAddItemTemplate; | 
| Zerotorescue@17 | 1064 						else | 
| Zerotorescue@17 | 1065 							-- It's already used in a group, don't show it | 
| Zerotorescue@17 | 1066 							ref[itemId] = nil; | 
| Zerotorescue@17 | 1067 						end | 
| Zerotorescue@13 | 1068 					end | 
| Zerotorescue@17 | 1069 				else | 
| Zerotorescue@17 | 1070 					addon:Debug("|cffff0000ERROR|r: Couldn't find proper item id for " .. itemLink); | 
| Zerotorescue@13 | 1071 				end | 
| Zerotorescue@13 | 1072 			end | 
| Zerotorescue@13 | 1073 		end | 
| Zerotorescue@13 | 1074 	end | 
| Zerotorescue@0 | 1075 end | 
| Zerotorescue@0 | 1076 | 
| Zerotorescue@0 | 1077 local function UpdateRemoveItemList(info) | 
| Zerotorescue@0 | 1078 	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1079 | 
| Zerotorescue@0 | 1080 	if not addon.db.global.groups[groupName].items then | 
| Zerotorescue@0 | 1081 		addon.db.global.groups[groupName].items = {}; | 
| Zerotorescue@0 | 1082 	end | 
| Zerotorescue@0 | 1083 | 
| Zerotorescue@0 | 1084 	local ref = options.args.groups.args[info[2]].args.remove.args.list.args; | 
| Zerotorescue@0 | 1085 | 
| Zerotorescue@0 | 1086 	-- Unset all | 
| Zerotorescue@0 | 1087 	for itemId, _ in pairs(ref) do | 
| Zerotorescue@0 | 1088 		ref[itemId] = nil; | 
| Zerotorescue@0 | 1089 	end | 
| Zerotorescue@0 | 1090 | 
| Zerotorescue@0 | 1091 	-- Parse items in group and show these | 
| Zerotorescue@0 | 1092 	for itemId, _ in pairs(addon.db.global.groups[groupName].items) do | 
| Zerotorescue@0 | 1093 		ref[itemId] = tblRemoveItemTemplate; | 
| Zerotorescue@0 | 1094 	end | 
| Zerotorescue@0 | 1095 end | 
| Zerotorescue@0 | 1096 | 
| Zerotorescue@0 | 1097 function addon:GetItemId(itemLink) | 
| Zerotorescue@13 | 1098 	itemLink = itemLink and itemLink:match("|Hitem:([-0-9]+):"); -- if itemLink is nil, it won't execute the second part | 
| Zerotorescue@0 | 1099 	itemLink = itemLink and tonumber(itemLink); | 
| Zerotorescue@0 | 1100 | 
| Zerotorescue@0 | 1101 	return itemLink; | 
| Zerotorescue@0 | 1102 end | 
| Zerotorescue@0 | 1103 | 
| Zerotorescue@0 | 1104 -- Default group | 
| Zerotorescue@0 | 1105 local defaultGroup = { | 
| Zerotorescue@0 | 1106 	order = 0, | 
| Zerotorescue@0 | 1107 	type = "group", | 
| Zerotorescue@0 | 1108 	childGroups = "tab", | 
| Zerotorescue@0 | 1109 	name = function(info) | 
| Zerotorescue@30 | 1110 		local groupId = info[#info]; | 
| Zerotorescue@30 | 1111 		if groupIsVirtual[groupId] then | 
| Zerotorescue@30 | 1112 			return ("%s  |cfffed000Virtual|r"):format(groupIdToName[groupId]); | 
| Zerotorescue@30 | 1113 		else | 
| Zerotorescue@30 | 1114 			return groupIdToName[groupId]; | 
| Zerotorescue@30 | 1115 		end | 
| Zerotorescue@30 | 1116 	end, | 
| Zerotorescue@30 | 1117 	desc = function(info) | 
| Zerotorescue@30 | 1118 		local groupId = info[#info]; | 
| Zerotorescue@30 | 1119 		if groupIsVirtual[groupId] then | 
| Zerotorescue@30 | 1120 			return "This is a virtual group, you can use it to override the defaults for other groups."; | 
| Zerotorescue@30 | 1121 		end | 
| Zerotorescue@0 | 1122 	end, | 
| Zerotorescue@0 | 1123 	args = { | 
| Zerotorescue@0 | 1124 		general = { | 
| Zerotorescue@0 | 1125 			order = 10, | 
| Zerotorescue@0 | 1126 			type = "group", | 
| Zerotorescue@23 | 1127 			name = "General", | 
| Zerotorescue@23 | 1128 			desc = "Change the general settings for just this group.", | 
| Zerotorescue@0 | 1129 			args = { | 
| Zerotorescue@23 | 1130 				general = { | 
| Zerotorescue@23 | 1131 					order = 0, | 
| Zerotorescue@23 | 1132 					type = "group", | 
| Zerotorescue@23 | 1133 					inline = true, | 
| Zerotorescue@23 | 1134 					name = "General", | 
| Zerotorescue@23 | 1135 					set = SetOption, | 
| Zerotorescue@23 | 1136 					get = GetOption, | 
| Zerotorescue@23 | 1137 					disabled = GetDisabled, | 
| Zerotorescue@23 | 1138 					args = { | 
| Zerotorescue@23 | 1139 						description = { | 
| Zerotorescue@23 | 1140 							order = 0, | 
| Zerotorescue@23 | 1141 							type = "description", | 
| Zerotorescue@23 | 1142 							name = "Here you can set general settings for the currently selected group. If you do not wish to override a setting, the default setting specified in the general group will be used.", | 
| Zerotorescue@23 | 1143 						}, | 
| Zerotorescue@23 | 1144 						header = { | 
| Zerotorescue@23 | 1145 							order = 5, | 
| Zerotorescue@23 | 1146 							type = "header", | 
| Zerotorescue@23 | 1147 							name = "", | 
| Zerotorescue@23 | 1148 						}, | 
| Zerotorescue@23 | 1149 						overrideAuctionPricingAddon = { | 
| Zerotorescue@23 | 1150 							order = 9, | 
| Zerotorescue@23 | 1151 							type = "toggle", | 
| Zerotorescue@23 | 1152 							name = "Override pricing addon", | 
| Zerotorescue@23 | 1153 							desc = "Allows you to override the pricing addon setting for this group.", | 
| Zerotorescue@23 | 1154 							arg = "auctionPricingAddon", | 
| Zerotorescue@23 | 1155 						}, | 
| Zerotorescue@23 | 1156 						auctionPricingAddon = { | 
| Zerotorescue@23 | 1157 							order = 10, | 
| Zerotorescue@23 | 1158 							type = "select", | 
| Zerotorescue@23 | 1159 							name = "Prefered pricing addon", | 
| Zerotorescue@23 | 1160 							desc = "Select the addon you prefer data for this group to be retrieved from. A random supported addon will be used if the selected addon can not be found.", | 
| Zerotorescue@23 | 1161 							values = function() | 
| Zerotorescue@23 | 1162 								local temp = {}; | 
| Zerotorescue@23 | 1163 								for name, value in pairs(addon.supportedAddons.auctionPricing) do | 
| Zerotorescue@23 | 1164 									temp[name] = name; | 
| Zerotorescue@23 | 1165 								end | 
| Zerotorescue@23 | 1166 | 
| Zerotorescue@23 | 1167 								return temp; | 
| Zerotorescue@23 | 1168 							end, | 
| Zerotorescue@23 | 1169 							arg = "overrideAuctionPricingAddon", | 
| Zerotorescue@23 | 1170 						}, | 
| Zerotorescue@23 | 1171 						overrideItemCountAddon = { | 
| Zerotorescue@23 | 1172 							order = 19, | 
| Zerotorescue@23 | 1173 							type = "toggle", | 
| Zerotorescue@23 | 1174 							name = "Override item count addon", | 
| Zerotorescue@23 | 1175 							desc = "Allows you to override the item count addon setting for this group.", | 
| Zerotorescue@23 | 1176 							arg = "itemCountAddon", | 
| Zerotorescue@23 | 1177 						}, | 
| Zerotorescue@23 | 1178 						itemCountAddon = { | 
| Zerotorescue@23 | 1179 							order = 20, | 
| Zerotorescue@23 | 1180 							type = "select", | 
| Zerotorescue@23 | 1181 							name = "Prefered item count addon", | 
| Zerotorescue@23 | 1182 							desc = "Select the addon you prefer data for this group to be retrieved from. A random supported addon will be used if the selected addon can not be found.", | 
| Zerotorescue@23 | 1183 							values = function() | 
| Zerotorescue@23 | 1184 								local temp = {}; | 
| Zerotorescue@23 | 1185 								for name, value in pairs(addon.supportedAddons.itemCount) do | 
| Zerotorescue@23 | 1186 									temp[name] = name; | 
| Zerotorescue@23 | 1187 								end | 
| Zerotorescue@23 | 1188 | 
| Zerotorescue@23 | 1189 								return temp; | 
| Zerotorescue@23 | 1190 							end, | 
| Zerotorescue@23 | 1191 							arg = "overrideItemCountAddon", | 
| Zerotorescue@23 | 1192 						}, | 
| Zerotorescue@23 | 1193 						overrideCraftingAddon = { | 
| Zerotorescue@23 | 1194 							order = 29, | 
| Zerotorescue@23 | 1195 							type = "toggle", | 
| Zerotorescue@23 | 1196 							name = "Override crafting addon", | 
| Zerotorescue@23 | 1197 							desc = "Allows you to override the crafting addon setting for this group.", | 
| Zerotorescue@23 | 1198 							arg = "craftingAddon", | 
| Zerotorescue@23 | 1199 						}, | 
| Zerotorescue@23 | 1200 						craftingAddon = { | 
| Zerotorescue@23 | 1201 							order = 30, | 
| Zerotorescue@23 | 1202 							type = "select", | 
| Zerotorescue@23 | 1203 							name = "Prefered crafting addon", | 
| Zerotorescue@23 | 1204 							desc = "Select the addon you prefer data from this group to be queued into. A random supported addon will be used if the selected addon can not be found.", | 
| Zerotorescue@23 | 1205 							values = function() | 
| Zerotorescue@23 | 1206 								local temp = {}; | 
| Zerotorescue@23 | 1207 								for name, value in pairs(addon.supportedAddons.crafting) do | 
| Zerotorescue@23 | 1208 									temp[name] = name; | 
| Zerotorescue@23 | 1209 								end | 
| Zerotorescue@23 | 1210 | 
| Zerotorescue@23 | 1211 								return temp; | 
| Zerotorescue@23 | 1212 							end, | 
| Zerotorescue@23 | 1213 							arg = "overrideCraftingAddon", | 
| Zerotorescue@23 | 1214 						}, | 
| Zerotorescue@31 | 1215 						overrideLocalItemData = { | 
| Zerotorescue@31 | 1216 							order = 39, | 
| Zerotorescue@31 | 1217 							type = "toggle", | 
| Zerotorescue@31 | 1218 							name = "Override local item data", | 
| Zerotorescue@31 | 1219 							desc = "Allows you to override the local item data setting for this group.", | 
| Zerotorescue@31 | 1220 							arg = "localItemData", | 
| Zerotorescue@31 | 1221 						}, | 
| Zerotorescue@31 | 1222 						localItemData = { | 
| Zerotorescue@31 | 1223 							order = 40, | 
| Zerotorescue@31 | 1224 							type = "multiselect", | 
| Zerotorescue@31 | 1225 							name = "Include in local item data", | 
| Zerotorescue@31 | 1226 							desc = "Select which data should be included in the local item data.", | 
| Zerotorescue@31 | 1227 							values = { | 
| Zerotorescue@31 | 1228 								["Bag"] = "Bag", | 
| Zerotorescue@31 | 1229 								["Bank"] = "Bank", | 
| Zerotorescue@31 | 1230 								["Auction House"] = "Auction House", | 
| Zerotorescue@31 | 1231 								["Mailbox"] = "Mailbox", | 
| Zerotorescue@31 | 1232 							}, | 
| Zerotorescue@31 | 1233 							get = GetMultiOption, | 
| Zerotorescue@31 | 1234 							--dialogControl = "Dropdown", -- this is not standard, normal multiselect control gives us a list of all chars with toggle-boxes. UGLY! We want a multiselect-box instead. | 
| Zerotorescue@31 | 1235 							arg = "overrideLocalItemData", | 
| Zerotorescue@31 | 1236 						}, | 
| Zerotorescue@30 | 1237 						virtualGroup = { | 
| Zerotorescue@31 | 1238 							order = 50, | 
| Zerotorescue@30 | 1239 							type = "select", | 
| Zerotorescue@30 | 1240 							name = "Use virtual group settings", | 
| Zerotorescue@30 | 1241 							desc = "Use the settings from a virtual group before using the general defaults.\n\n|cffff9933This is an advanced option, you will probably not need it unless you manage a lot of groups.|r\n\n|cfffed000Off|r: Use the overridden options in this group and then the defaults.\n\n|cfffed000On|r: Use the overridden options in this group, then the ones in the selected virtual group and then the defaults.", | 
| Zerotorescue@31 | 1242 							values = function(info) | 
| Zerotorescue@31 | 1243 								local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@31 | 1244 | 
| Zerotorescue@30 | 1245 								local temp = {}; | 
| Zerotorescue@30 | 1246 | 
| Zerotorescue@30 | 1247 								temp[""] = ""; | 
| Zerotorescue@31 | 1248 								for name, values in pairs(addon.db.global.groups) do | 
| Zerotorescue@31 | 1249 									if values.isVirtual and name ~= groupName then | 
| Zerotorescue@31 | 1250 										temp[name] = name; | 
| Zerotorescue@31 | 1251 									end | 
| Zerotorescue@31 | 1252 								end | 
| Zerotorescue@30 | 1253 | 
| Zerotorescue@30 | 1254 								return temp; | 
| Zerotorescue@30 | 1255 							end, | 
| Zerotorescue@31 | 1256 							set = function(info, value) | 
| Zerotorescue@31 | 1257 								local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@31 | 1258 								local optionName = info[#info]; | 
| Zerotorescue@31 | 1259 | 
| Zerotorescue@31 | 1260 								addon.db.global.groups[groupName][optionName] = value ~= "" and value; | 
| Zerotorescue@31 | 1261 							end, | 
| Zerotorescue@30 | 1262 						}, | 
| Zerotorescue@23 | 1263 					}, | 
| Zerotorescue@23 | 1264 				}, | 
| Zerotorescue@0 | 1265 				minimumStock = { | 
| Zerotorescue@0 | 1266 					order = 10, | 
| Zerotorescue@0 | 1267 					type = "group", | 
| Zerotorescue@0 | 1268 					inline = true, | 
| Zerotorescue@0 | 1269 					name = "Minimum stock", | 
| Zerotorescue@0 | 1270 					set = SetOption, | 
| Zerotorescue@0 | 1271 					get = GetOption, | 
| Zerotorescue@0 | 1272 					disabled = GetDisabled, | 
| Zerotorescue@0 | 1273 					args = { | 
| Zerotorescue@0 | 1274 						description = { | 
| Zerotorescue@0 | 1275 							order = 0, | 
| Zerotorescue@0 | 1276 							type = "description", | 
| Zerotorescue@31 | 1277 							name = "Here you can specify the minimum amount of items you wish to keep in stock and related settings for the currently selected group. Please note the values entered here do not affect the queued quantities, you must set settings for that in the area below.", | 
| Zerotorescue@0 | 1278 						}, | 
| Zerotorescue@0 | 1279 						header = { | 
| Zerotorescue@0 | 1280 							order = 5, | 
| Zerotorescue@0 | 1281 							type = "header", | 
| Zerotorescue@0 | 1282 							name = "", | 
| Zerotorescue@0 | 1283 						}, | 
| Zerotorescue@0 | 1284 						overrideMinimumStock = { | 
| Zerotorescue@0 | 1285 							order = 9, | 
| Zerotorescue@0 | 1286 							type = "toggle", | 
| Zerotorescue@0 | 1287 							name = "Override min stock", | 
| Zerotorescue@0 | 1288 							desc = "Allows you to override the minimum stock setting for this group.", | 
| Zerotorescue@0 | 1289 							arg = "minimumStock", | 
| Zerotorescue@0 | 1290 						}, | 
| Zerotorescue@0 | 1291 						minimumStock = { | 
| Zerotorescue@0 | 1292 							order = 10, | 
| Zerotorescue@0 | 1293 							type = "range", | 
| Zerotorescue@0 | 1294 							min = 0, | 
| Zerotorescue@0 | 1295 							max = 100000, | 
| Zerotorescue@17 | 1296 							softMax = 100, | 
| Zerotorescue@0 | 1297 							step = 1, | 
| Zerotorescue@0 | 1298 							name = "Minimum stock", | 
| Zerotorescue@17 | 1299 							desc = "You can manually enter a value between 100 and 100.000 in the text box below if the provided range is insufficient.", | 
| Zerotorescue@0 | 1300 							arg = "overrideMinimumStock", | 
| Zerotorescue@0 | 1301 						}, | 
| Zerotorescue@0 | 1302 						overrideSummaryThresholdShow = { | 
| Zerotorescue@0 | 1303 							order = 19, | 
| Zerotorescue@0 | 1304 							type = "toggle", | 
| Zerotorescue@0 | 1305 							name = "Override summary showing", | 
| Zerotorescue@0 | 1306 							desc = "Allows you to override when this group should appear in the summary.", | 
| Zerotorescue@0 | 1307 							arg = "summaryThresholdShow", | 
| Zerotorescue@0 | 1308 						}, | 
| Zerotorescue@0 | 1309 						summaryThresholdShow = { | 
| Zerotorescue@0 | 1310 							order = 20, | 
| Zerotorescue@0 | 1311 							type = "range", | 
| Zerotorescue@0 | 1312 							min = 0, | 
| Zerotorescue@0 | 1313 							max = 100, | 
| Zerotorescue@0 | 1314 							softMax = 10, | 
| Zerotorescue@0 | 1315 							step = 0.05, | 
| Zerotorescue@0 | 1316 							isPercent = true, | 
| Zerotorescue@0 | 1317 							name = "Show in summary when below", | 
| Zerotorescue@0 | 1318 							desc = "Show items in the summary when below the specified percentage of the minimum stock.\n\nYou can manually enter a value between 1.000% and 10.000% in the edit box if the provided range is insufficient.", | 
| Zerotorescue@0 | 1319 							arg = "overrideSummaryThresholdShow", | 
| Zerotorescue@0 | 1320 						}, | 
| Zerotorescue@0 | 1321 						overrideAlertBelowMinimum = { | 
| Zerotorescue@0 | 1322 							order = 29, | 
| Zerotorescue@0 | 1323 							type = "toggle", | 
| Zerotorescue@0 | 1324 							name = "Override minimum alert", | 
| Zerotorescue@0 | 1325 							desc = "Allows you to override wether an alert should be shown when an item in this group gets below the minimum stock threshold.", | 
| Zerotorescue@0 | 1326 							arg = "alertBelowMinimum", | 
| Zerotorescue@0 | 1327 						}, | 
| Zerotorescue@0 | 1328 						alertBelowMinimum = { | 
| Zerotorescue@0 | 1329 							order = 30, | 
| Zerotorescue@0 | 1330 							type = "toggle", | 
| Zerotorescue@30 | 1331 							name = "NYI | Alert when below minimum", | 
| Zerotorescue@0 | 1332 							desc = "Show an alert when an item in this group gets below the minimum stock threshold.", | 
| Zerotorescue@0 | 1333 							arg = "overrideAlertBelowMinimum", | 
| Zerotorescue@0 | 1334 						}, | 
| Zerotorescue@1 | 1335 						overrideTrackAtCharacters = { | 
| Zerotorescue@1 | 1336 							order = 39, | 
| Zerotorescue@1 | 1337 							type = "toggle", | 
| Zerotorescue@1 | 1338 							name = "Override track at", | 
| Zerotorescue@1 | 1339 							desc = "Allows you to override at which characters items in this group should appear in the summary and generate alerts.", | 
| Zerotorescue@1 | 1340 							arg = "trackAtCharacters", | 
| Zerotorescue@1 | 1341 						}, | 
| Zerotorescue@1 | 1342 						trackAtCharacters = { | 
| Zerotorescue@1 | 1343 							order = 40, | 
| Zerotorescue@1 | 1344 							type = "multiselect", | 
| Zerotorescue@1 | 1345 							name = "Track at", | 
| Zerotorescue@1 | 1346 							desc = "Select at which characters this should appear in the summary and generate alerts.", | 
| Zerotorescue@1 | 1347 							values = function() | 
| Zerotorescue@1 | 1348 								local temp = {}; | 
| Zerotorescue@1 | 1349 								for charName in pairs(addon.db.factionrealm.characters) do | 
| Zerotorescue@1 | 1350 									temp[charName] = charName; | 
| Zerotorescue@1 | 1351 								end | 
| Zerotorescue@1 | 1352 | 
| Zerotorescue@1 | 1353 								return temp; | 
| Zerotorescue@1 | 1354 							end, | 
| Zerotorescue@1 | 1355 							get = GetMultiOption, | 
| Zerotorescue@13 | 1356 							--dialogControl = "Dropdown", -- this is not standard, normal multiselect control gives us a list of all chars with toggle-boxes. UGLY! We want a multiselect-box instead. | 
| Zerotorescue@1 | 1357 							arg = "overrideTrackAtCharacters", | 
| Zerotorescue@1 | 1358 						}, | 
| Zerotorescue@0 | 1359 					}, | 
| Zerotorescue@0 | 1360 				}, | 
| Zerotorescue@0 | 1361 				refill = { | 
| Zerotorescue@0 | 1362 					order = 20, | 
| Zerotorescue@0 | 1363 					type = "group", | 
| Zerotorescue@0 | 1364 					inline = true, | 
| Zerotorescue@0 | 1365 					name = "Replenishing stock", | 
| Zerotorescue@0 | 1366 					set = SetOption, | 
| Zerotorescue@0 | 1367 					get = GetOption, | 
| Zerotorescue@0 | 1368 					disabled = GetDisabled, | 
| Zerotorescue@0 | 1369 					args = { | 
| Zerotorescue@0 | 1370 						description = { | 
| Zerotorescue@0 | 1371 							order = 0, | 
| Zerotorescue@0 | 1372 							type = "description", | 
| Zerotorescue@0 | 1373 							name = function(info) | 
| Zerotorescue@0 | 1374 								local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1375 								local r = "Here you can specify the amount of items to which you wish to restock when you are collecting new items for the currently selected group. This may be higher than the minimum stock.\n\n"; | 
| Zerotorescue@0 | 1376 | 
| Zerotorescue@31 | 1377 								r = r .. "When restocking the target amount is |cfffed000" .. addon:GetOptionByKey(groupName, "restockTarget") .. "|r of every item. Not queueing craftable items when only missing |cfffed000" .. floor( addon:GetOptionByKey(groupName, "minCraftingQueue") * addon:GetOptionByKey(groupName, "restockTarget") ) .. "|r (|cfffed000" .. ( addon:GetOptionByKey(groupName, "minCraftingQueue") * 100 ) .. "%|r) of the restock target and making |cfffed000" .. floor( ( addon:GetOptionByKey(groupName, "bonusQueue") * addon:GetOptionByKey(groupName, "restockTarget") ) + .5 ) .. "|r (|cfffed000" .. ( addon:GetOptionByKey(groupName, "bonusQueue") * 100 ) .. "%|r) extra items when you completely ran out. "; | 
| Zerotorescue@31 | 1378 | 
| Zerotorescue@31 | 1379 								if addon:GetOptionByKey(groupName, "priceThreshold") == 0 then | 
| Zerotorescue@31 | 1380 									r = r .. "Queueing items at |cfffed000any|r auction value."; | 
| Zerotorescue@31 | 1381 								else | 
| Zerotorescue@31 | 1382 									r = r .. "Queueing items worth |cfffed000" .. addon:ReadableMoney(addon:GetOptionByKey(groupName, "priceThreshold")) .. "|r or more."; | 
| Zerotorescue@31 | 1383 								end | 
| Zerotorescue@0 | 1384 | 
| Zerotorescue@0 | 1385 								return r; | 
| Zerotorescue@0 | 1386 							end, | 
| Zerotorescue@0 | 1387 						}, | 
| Zerotorescue@0 | 1388 						header = { | 
| Zerotorescue@0 | 1389 							order = 5, | 
| Zerotorescue@0 | 1390 							type = "header", | 
| Zerotorescue@0 | 1391 							name = "", | 
| Zerotorescue@0 | 1392 						}, | 
| Zerotorescue@0 | 1393 						overrideRestockTarget = { | 
| Zerotorescue@0 | 1394 							order = 9, | 
| Zerotorescue@0 | 1395 							type = "toggle", | 
| Zerotorescue@0 | 1396 							name = "Override restock target", | 
| Zerotorescue@0 | 1397 							desc = "Allows you to override the restock target setting for this group.", | 
| Zerotorescue@0 | 1398 							arg = "restockTarget", | 
| Zerotorescue@0 | 1399 						}, | 
| Zerotorescue@0 | 1400 						restockTarget = { | 
| Zerotorescue@0 | 1401 							order = 10, | 
| Zerotorescue@0 | 1402 							type = "range", | 
| Zerotorescue@0 | 1403 							min = 0, | 
| Zerotorescue@0 | 1404 							max = 100000, | 
| Zerotorescue@30 | 1405 							softMax = 100, | 
| Zerotorescue@0 | 1406 							step = 1, | 
| Zerotorescue@0 | 1407 							name = "Restock target", | 
| Zerotorescue@30 | 1408 							desc = "You can manually enter a value between 100 and 100.000 in the edit box if the provided range is insufficient.", | 
| Zerotorescue@0 | 1409 							arg = "overrideRestockTarget", | 
| Zerotorescue@0 | 1410 						}, | 
| Zerotorescue@0 | 1411 						overrideMinCraftingQueue = { | 
| Zerotorescue@0 | 1412 							order = 19, | 
| Zerotorescue@0 | 1413 							type = "toggle", | 
| Zerotorescue@0 | 1414 							name = "Override min queue", | 
| Zerotorescue@0 | 1415 							desc = "Allows you to override the minimum craftable items queue setting for this group.", | 
| Zerotorescue@0 | 1416 							arg = "minCraftingQueue", | 
| Zerotorescue@0 | 1417 						}, | 
| Zerotorescue@0 | 1418 						minCraftingQueue = { | 
| Zerotorescue@0 | 1419 							order = 20, | 
| Zerotorescue@0 | 1420 							type = "range", | 
| Zerotorescue@0 | 1421 							min = 0, | 
| Zerotorescue@0 | 1422 							max = 1, | 
| Zerotorescue@0 | 1423 							step = 0.01, | 
| Zerotorescue@0 | 1424 							isPercent = true, | 
| Zerotorescue@0 | 1425 							name = "Don't queue if I only miss", | 
| Zerotorescue@0 | 1426 							desc = "Don't add a craftable item to the queue if I only miss this much or less of the restock target.\n\nExample: if your restock target is set to 60 and this is set to 5%, an item won't be queued unless you are missing more than 3 of it.", | 
| Zerotorescue@0 | 1427 							arg = "overrideMinCraftingQueue", | 
| Zerotorescue@0 | 1428 						}, | 
| Zerotorescue@1 | 1429 						overrideBonusQueue = { | 
| Zerotorescue@1 | 1430 							order = 29, | 
| Zerotorescue@1 | 1431 							type = "toggle", | 
| Zerotorescue@1 | 1432 							name = "Override bonus queue", | 
| Zerotorescue@1 | 1433 							desc = "Allows you to override the bonus craftable items queue setting for this group.", | 
| Zerotorescue@1 | 1434 							arg = "bonusQueue", | 
| Zerotorescue@1 | 1435 						}, | 
| Zerotorescue@1 | 1436 						bonusQueue = { | 
| Zerotorescue@1 | 1437 							order = 30, | 
| Zerotorescue@1 | 1438 							type = "range", | 
| Zerotorescue@1 | 1439 							min = 0, | 
| Zerotorescue@1 | 1440 							max = 10, -- 1000% | 
| Zerotorescue@1 | 1441 							step = 0.01, -- 1% | 
| Zerotorescue@1 | 1442 							isPercent = true, | 
| Zerotorescue@1 | 1443 							name = "Bonus queue", | 
| Zerotorescue@1 | 1444 							desc = "Get additional items when there are none left.\n\nExample: if your restock target is set to 60 and this is set to 10%, you will get 66 items instead of just 60 if you end up with none left while queueing.", | 
| Zerotorescue@1 | 1445 							arg = "overrideBonusQueue", | 
| Zerotorescue@1 | 1446 						}, | 
| Zerotorescue@1 | 1447 						overridePriceThreshold = { | 
| Zerotorescue@1 | 1448 							order = 39, | 
| Zerotorescue@1 | 1449 							type = "toggle", | 
| Zerotorescue@1 | 1450 							name = "Override price threshold", | 
| Zerotorescue@1 | 1451 							desc = "Allows you to override the price threshold setting for this group.", | 
| Zerotorescue@1 | 1452 							arg = "priceThreshold", | 
| Zerotorescue@1 | 1453 						}, | 
| Zerotorescue@1 | 1454 						priceThreshold = { | 
| Zerotorescue@1 | 1455 							order = 40, | 
| Zerotorescue@1 | 1456 							type = "input", | 
| Zerotorescue@1 | 1457 							name = "Price threshold", | 
| Zerotorescue@1 | 1458 							desc = "Only queue craftable items when they are worth at least this much according to your auction house addon.\n\nSet to 0 to ignore auction prices.", | 
| Zerotorescue@1 | 1459 							validate = function(info, value) return addon:ValidateReadableMoney(info, value); end, | 
| Zerotorescue@1 | 1460 							get = function(i) return addon:ReadableMoney(GetOption(i)); end, | 
| Zerotorescue@1 | 1461 							set = function(i, v) SetOption(i, addon:ReadableMoneyToCopper(v)); end, | 
| Zerotorescue@1 | 1462 							arg = "overridePriceThreshold", | 
| Zerotorescue@1 | 1463 						}, | 
| Zerotorescue@13 | 1464 						overrideSummaryHidePriceThreshold = { | 
| Zerotorescue@1 | 1465 							order = 49, | 
| Zerotorescue@1 | 1466 							type = "toggle", | 
| Zerotorescue@1 | 1467 							name = "Override summary showing", | 
| Zerotorescue@1 | 1468 							desc = "Allows you to override if items in this group should be hidden from the summary while their value is below the price threshold.", | 
| Zerotorescue@13 | 1469 							arg = "summaryHidePriceThreshold", | 
| Zerotorescue@1 | 1470 						}, | 
| Zerotorescue@13 | 1471 						summaryHidePriceThreshold = { | 
| Zerotorescue@1 | 1472 							order = 50, | 
| Zerotorescue@1 | 1473 							type = "toggle", | 
| Zerotorescue@1 | 1474 							name = "Hide when below threshold", | 
| Zerotorescue@1 | 1475 							desc = "Hide items from the summary when their value is below the set price threshold.", | 
| Zerotorescue@13 | 1476 							arg = "overrideSummaryHidePriceThreshold", | 
| Zerotorescue@1 | 1477 						}, | 
| Zerotorescue@23 | 1478 						overrideAlwaysGetAuctionValue = { | 
| Zerotorescue@23 | 1479 							order = 59, | 
| Zerotorescue@23 | 1480 							type = "toggle", | 
| Zerotorescue@23 | 1481 							name = "Override auction value showing", | 
| Zerotorescue@31 | 1482 							desc = "Allows you to override if the auction value of items in this group should be cached and displayed even when the price threshold is set to 0|cffeda55fc|r.", | 
| Zerotorescue@23 | 1483 							arg = "alwaysGetAuctionValue", | 
| Zerotorescue@23 | 1484 						}, | 
| Zerotorescue@23 | 1485 						alwaysGetAuctionValue = { | 
| Zerotorescue@23 | 1486 							order = 60, | 
| Zerotorescue@23 | 1487 							type = "toggle", | 
| Zerotorescue@23 | 1488 							name = "Always show auction value", | 
| Zerotorescue@31 | 1489 							desc = "Always cache and show the auction value of items in this group, even if the price threshold is set to 0|cffeda55fc|r.", | 
| Zerotorescue@23 | 1490 							arg = "overrideAlwaysGetAuctionValue", | 
| Zerotorescue@23 | 1491 						}, | 
| Zerotorescue@0 | 1492 					}, | 
| Zerotorescue@0 | 1493 				}, | 
| Zerotorescue@0 | 1494 			}, | 
| Zerotorescue@0 | 1495 		}, | 
| Zerotorescue@0 | 1496 		group = { | 
| Zerotorescue@0 | 1497 			order = 20, | 
| Zerotorescue@0 | 1498 			type = "group", | 
| Zerotorescue@23 | 1499 			name = "Management", | 
| Zerotorescue@23 | 1500 			desc = "Rename, delete, duplicate or export this group.", | 
| Zerotorescue@0 | 1501 			args = { | 
| Zerotorescue@10 | 1502 				actions = { | 
| Zerotorescue@0 | 1503 					order = 10, | 
| Zerotorescue@0 | 1504 					type = "group", | 
| Zerotorescue@10 | 1505 					name = "Actions", | 
| Zerotorescue@0 | 1506 					inline = true, | 
| Zerotorescue@0 | 1507 					args = { | 
| Zerotorescue@0 | 1508 						rename = { | 
| Zerotorescue@0 | 1509 							order = 10, | 
| Zerotorescue@0 | 1510 							type = "input", | 
| Zerotorescue@10 | 1511 							name = "Rename group - New name", | 
| Zerotorescue@0 | 1512 							desc = "Change the name of this group to something else. You can also use item links here as you wish.", | 
| Zerotorescue@0 | 1513 							validate = ValidateGroupName, | 
| Zerotorescue@0 | 1514 							set = function(info, value) | 
| Zerotorescue@0 | 1515 								local oldGroupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1516 | 
| Zerotorescue@0 | 1517 								addon.db.global.groups[value] = CopyTable(addon.db.global.groups[oldGroupName]); | 
| Zerotorescue@0 | 1518 								addon.db.global.groups[oldGroupName] = nil; | 
| Zerotorescue@0 | 1519 | 
| Zerotorescue@0 | 1520 								groupIdToName[info[2]] = value; | 
| Zerotorescue@0 | 1521 								groupIdToName[value] = true; | 
| Zerotorescue@0 | 1522 								groupIdToName[oldGroupName] = nil; | 
| Zerotorescue@0 | 1523 | 
| Zerotorescue@0 | 1524 								addon:FillGroupOptions(); | 
| Zerotorescue@0 | 1525 							end, | 
| Zerotorescue@0 | 1526 							get = function(info) | 
| Zerotorescue@0 | 1527 								return groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1528 							end, | 
| Zerotorescue@0 | 1529 						}, | 
| Zerotorescue@10 | 1530 						duplicate = { | 
| Zerotorescue@10 | 1531 							order = 20, | 
| Zerotorescue@10 | 1532 							type = "input", | 
| Zerotorescue@10 | 1533 							name = "Duplicate group - New name", | 
| Zerotorescue@10 | 1534 							desc = "Duplicate this group. You can also use item links here as you wish.\n\nAll item data will be erased.", | 
| Zerotorescue@10 | 1535 							validate = ValidateGroupName, | 
| Zerotorescue@10 | 1536 							set = function(info, value) | 
| Zerotorescue@10 | 1537 								local oldGroupName = groupIdToName[info[2]]; | 
| Zerotorescue@10 | 1538 | 
| Zerotorescue@10 | 1539 								addon.db.global.groups[value] = CopyTable(addon.db.global.groups[oldGroupName]); | 
| Zerotorescue@10 | 1540 | 
| Zerotorescue@10 | 1541 								-- Reset item data (duplicate items me no want) | 
| Zerotorescue@10 | 1542 								addon.db.global.groups[value].items = nil; | 
| Zerotorescue@10 | 1543 | 
| Zerotorescue@10 | 1544 								addon:FillGroupOptions(); | 
| Zerotorescue@10 | 1545 							end, | 
| Zerotorescue@10 | 1546 							get = false, | 
| Zerotorescue@10 | 1547 						}, | 
| Zerotorescue@0 | 1548 						delete = { | 
| Zerotorescue@10 | 1549 							order = 30, | 
| Zerotorescue@0 | 1550 							type = "execute", | 
| Zerotorescue@0 | 1551 							name = "Delete group", | 
| Zerotorescue@0 | 1552 							desc = "Delete the currently selected group.", | 
| Zerotorescue@0 | 1553 							confirm = true, | 
| Zerotorescue@0 | 1554 							confirmText = "Are you sure you wish to |cffff0000DELETE|r this group? This action is not reversable!", | 
| Zerotorescue@0 | 1555 							func = function(info) | 
| Zerotorescue@0 | 1556 								local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1557 | 
| Zerotorescue@0 | 1558 								addon.db.global.groups[groupName] = nil; | 
| Zerotorescue@0 | 1559 | 
| Zerotorescue@0 | 1560 								addon:FillGroupOptions(); | 
| Zerotorescue@0 | 1561 							end, | 
| Zerotorescue@0 | 1562 						}, | 
| Zerotorescue@0 | 1563 					}, | 
| Zerotorescue@0 | 1564 				}, | 
| Zerotorescue@0 | 1565 				export = { | 
| Zerotorescue@10 | 1566 					order = 40, | 
| Zerotorescue@0 | 1567 					type = "group", | 
| Zerotorescue@0 | 1568 					name = "Export", | 
| Zerotorescue@0 | 1569 					inline = true, | 
| Zerotorescue@0 | 1570 					args = { | 
| Zerotorescue@0 | 1571 						input = { | 
| Zerotorescue@0 | 1572 							order = 10, | 
| Zerotorescue@0 | 1573 							type = "input", | 
| Zerotorescue@0 | 1574 							multiline = true, | 
| Zerotorescue@0 | 1575 							name = "Group data", | 
| Zerotorescue@0 | 1576 							width = "full", | 
| Zerotorescue@0 | 1577 							desc = "Export the group data for the currently selected group. Press CTRL-A to select all and CTRL-C to copy the text.", | 
| Zerotorescue@0 | 1578 							set = false, | 
| Zerotorescue@0 | 1579 							get = function(info) | 
| Zerotorescue@0 | 1580 								local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1581 | 
| Zerotorescue@0 | 1582 								-- We want to include the group name, so we copy the table then set another value | 
| Zerotorescue@0 | 1583 								local temp = CopyTable(addon.db.global.groups[groupName]); | 
| Zerotorescue@0 | 1584 								temp.name = groupName; | 
| Zerotorescue@9 | 1585 								temp.trackAtCharacters = nil; | 
| Zerotorescue@9 | 1586 								temp.overrideTrackAtCharacters = nil; | 
| Zerotorescue@0 | 1587 | 
| Zerotorescue@0 | 1588 								if not AceSerializer then | 
| Zerotorescue@0 | 1589 									AceSerializer = LibStub("AceSerializer-3.0"); | 
| Zerotorescue@0 | 1590 								end | 
| Zerotorescue@0 | 1591 | 
| Zerotorescue@0 | 1592 								return AceSerializer:Serialize(temp); | 
| Zerotorescue@0 | 1593 							end, | 
| Zerotorescue@0 | 1594 						}, | 
| Zerotorescue@0 | 1595 					}, | 
| Zerotorescue@0 | 1596 				}, | 
| Zerotorescue@0 | 1597 			}, | 
| Zerotorescue@0 | 1598 		}, | 
| Zerotorescue@0 | 1599 		add = { | 
| Zerotorescue@0 | 1600 			order = 30, | 
| Zerotorescue@0 | 1601 			type = "group", | 
| Zerotorescue@0 | 1602 			name = "Add items", | 
| Zerotorescue@23 | 1603 			desc = "Add new items to this group.", | 
| Zerotorescue@31 | 1604 			hidden = function(info) return groupIsVirtual[info[2]]; end, | 
| Zerotorescue@0 | 1605 			args = { | 
| Zerotorescue@0 | 1606 				singleAdd = { | 
| Zerotorescue@0 | 1607 					order = 10, | 
| Zerotorescue@0 | 1608 					type = "group", | 
| Zerotorescue@0 | 1609 					inline = true, | 
| Zerotorescue@0 | 1610 					name = "Add items", | 
| Zerotorescue@0 | 1611 					args = { | 
| Zerotorescue@0 | 1612 						help = { | 
| Zerotorescue@0 | 1613 							order = 10, | 
| Zerotorescue@0 | 1614 							type = "description", | 
| Zerotorescue@0 | 1615 							name = "You can add a single item to this group at a time by pasting the item-id or an item-link in the field to the left or you can also import multiple items at once by pasting exported item data in the field to the right. Scroll further down to add items based on your inventory contents.", | 
| Zerotorescue@0 | 1616 						}, | 
| Zerotorescue@0 | 1617 						itemLink = { | 
| Zerotorescue@0 | 1618 							order = 20, | 
| Zerotorescue@0 | 1619 							type = "input", | 
| Zerotorescue@0 | 1620 							name = "Single item add (item-link or item-id)", | 
| Zerotorescue@0 | 1621 							desc = "Shift-click an item-link or enter an item-id to add the related item to this group. You can only add one item link or item id at a time.", | 
| Zerotorescue@0 | 1622 							validate = function(info, value) | 
| Zerotorescue@0 | 1623 								-- If the value is empty we'll allow passing to clear the carret | 
| Zerotorescue@0 | 1624 								if value == "" then return true; end | 
| Zerotorescue@0 | 1625 | 
| Zerotorescue@0 | 1626 								local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1627 | 
| Zerotorescue@0 | 1628 								local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or "")); | 
| Zerotorescue@0 | 1629 | 
| Zerotorescue@0 | 1630 								if not itemId then | 
| Zerotorescue@0 | 1631 									return "This is not a valid item link."; | 
| Zerotorescue@0 | 1632 								elseif InGroup(itemId) then | 
| Zerotorescue@0 | 1633 									return ("This item is already in the group \"%s\"."):format(InGroup(itemId)); | 
| Zerotorescue@0 | 1634 								end | 
| Zerotorescue@0 | 1635 | 
| Zerotorescue@0 | 1636 								return true; | 
| Zerotorescue@0 | 1637 							end, | 
| Zerotorescue@0 | 1638 							set = function(info, value) | 
| Zerotorescue@0 | 1639 								if value and value ~= "" then | 
| Zerotorescue@0 | 1640 									local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1641 | 
| Zerotorescue@0 | 1642 									local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or "")); | 
| Zerotorescue@0 | 1643 | 
| Zerotorescue@0 | 1644 									AddToGroup(groupName, itemId); | 
| Zerotorescue@0 | 1645 | 
| Zerotorescue@0 | 1646 									print(("Added %s"):format(select(2, GetItemInfo(itemId)) or ("Unknown (#%d)"):format(itemId))); | 
| Zerotorescue@0 | 1647 								end | 
| Zerotorescue@0 | 1648 							end, | 
| Zerotorescue@0 | 1649 							get = false, | 
| Zerotorescue@0 | 1650 						}, | 
| Zerotorescue@17 | 1651 						importItemData = { | 
| Zerotorescue@17 | 1652 							order = 30, | 
| Zerotorescue@0 | 1653 							type = "input", | 
| Zerotorescue@0 | 1654 							name = "Import item data", | 
| Zerotorescue@0 | 1655 							desc = "Import item data from an exported item data-string. Any items already grouped will be skipped.", | 
| Zerotorescue@0 | 1656 							set = function(info, value) | 
| Zerotorescue@0 | 1657 								local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1658 | 
| Zerotorescue@0 | 1659 								local allItemIds = { string.split(";", value or "") }; | 
| Zerotorescue@0 | 1660 | 
| Zerotorescue@0 | 1661 								for _, value in pairs(allItemIds) do | 
| Zerotorescue@0 | 1662 									local itemId = tonumber(value); | 
| Zerotorescue@0 | 1663 | 
| Zerotorescue@0 | 1664 									if not itemId then | 
| Zerotorescue@0 | 1665 										print(("\"%s\" is not a number."):format(value)); | 
| Zerotorescue@0 | 1666 									elseif InGroup(itemId) then | 
| Zerotorescue@0 | 1667 										print(("Skipping %s (#%d) as it is already in the group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId))); | 
| Zerotorescue@0 | 1668 									else | 
| Zerotorescue@0 | 1669 										AddToGroup(groupName, itemId); | 
| Zerotorescue@0 | 1670 									end | 
| Zerotorescue@0 | 1671 								end | 
| Zerotorescue@0 | 1672 							end, | 
| Zerotorescue@0 | 1673 							get = false, | 
| Zerotorescue@0 | 1674 						}, | 
| Zerotorescue@17 | 1675 						importPremadeData = { | 
| Zerotorescue@17 | 1676 							order = 40, | 
| Zerotorescue@17 | 1677 							type = "select", | 
| Zerotorescue@17 | 1678 							name = "Import premade data", | 
| Zerotorescue@17 | 1679 							desc = "Import item data from a premade item-group. Any items already grouped will be skipped.", | 
| Zerotorescue@17 | 1680 							values = function() | 
| Zerotorescue@17 | 1681 								local temp = {}; | 
| Zerotorescue@17 | 1682 								for key, group in pairs(addon.defaultGroups) do | 
| Zerotorescue@17 | 1683 									temp[key] = key; | 
| Zerotorescue@17 | 1684 								end | 
| Zerotorescue@17 | 1685 | 
| Zerotorescue@17 | 1686 								return temp; | 
| Zerotorescue@17 | 1687 							end, | 
| Zerotorescue@17 | 1688 							set = function(info, value) | 
| Zerotorescue@17 | 1689 								local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@17 | 1690 | 
| Zerotorescue@17 | 1691 								print(("Importing items from the premade group \"|cfffed000%s|r\"."):format(value)); | 
| Zerotorescue@17 | 1692 | 
| Zerotorescue@17 | 1693 								-- Remember we imported this group and it's version so if it is ever changed, people can be notified | 
| Zerotorescue@17 | 1694 								if not addon.db.global.groups[groupName].premadeGroups then | 
| Zerotorescue@17 | 1695 									addon.db.global.groups[groupName].premadeGroups = {}; | 
| Zerotorescue@17 | 1696 								end | 
| Zerotorescue@17 | 1697 								addon.db.global.groups[groupName].premadeGroups[value] = addon.defaultGroups[value].version; | 
| Zerotorescue@17 | 1698 | 
| Zerotorescue@17 | 1699 								for itemId, _ in pairs(addon.defaultGroups[value].items) do | 
| Zerotorescue@17 | 1700 									itemId = itemId and tonumber(itemId); | 
| Zerotorescue@17 | 1701 | 
| Zerotorescue@17 | 1702 									if not itemId then | 
| Zerotorescue@17 | 1703 										print(("\"|cfffed000%s|r\" is not a number."):format(value)); | 
| Zerotorescue@17 | 1704 									elseif InGroup(itemId) then | 
| Zerotorescue@17 | 1705 										print(("Skipping |cfffed000%s|r (#%d) as it is already in the group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId))); | 
| Zerotorescue@17 | 1706 									else | 
| Zerotorescue@17 | 1707 										AddToGroup(groupName, itemId); | 
| Zerotorescue@17 | 1708 									end | 
| Zerotorescue@17 | 1709 								end | 
| Zerotorescue@17 | 1710 							end, | 
| Zerotorescue@17 | 1711 							get = false, | 
| Zerotorescue@17 | 1712 						}, | 
| Zerotorescue@0 | 1713 					}, | 
| Zerotorescue@0 | 1714 				}, | 
| Zerotorescue@0 | 1715 				massAdd = { | 
| Zerotorescue@0 | 1716 					order = 20, | 
| Zerotorescue@0 | 1717 					type = "group", | 
| Zerotorescue@0 | 1718 					inline = true, | 
| Zerotorescue@0 | 1719 					name = "Mass add", | 
| Zerotorescue@0 | 1720 					args = { | 
| Zerotorescue@0 | 1721 						help = { | 
| Zerotorescue@0 | 1722 							order = 10, | 
| Zerotorescue@0 | 1723 							type = "description", | 
| Zerotorescue@0 | 1724 							name = "Click the items you wish to add to this group or add multiple of these items at once by providing a name filter in the field below.", | 
| Zerotorescue@0 | 1725 						}, | 
| Zerotorescue@0 | 1726 						massAdd = { | 
| Zerotorescue@0 | 1727 							order = 20, | 
| Zerotorescue@0 | 1728 							type = "input", | 
| Zerotorescue@0 | 1729 							name = "Add all items matching...", | 
| Zerotorescue@0 | 1730 							desc = "Add every item in your inventory matching the name entered in this field. If you enter \"Glyph\" as a filter, any items in your inventory containing this in their name will be added to this group.", | 
| Zerotorescue@13 | 1731 							set = function(info, value) | 
| Zerotorescue@17 | 1732 						    	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@17 | 1733 | 
| Zerotorescue@13 | 1734 								if not value then return; end | 
| Zerotorescue@13 | 1735 | 
| Zerotorescue@13 | 1736 								value = value:lower(); | 
| Zerotorescue@13 | 1737 | 
| Zerotorescue@13 | 1738 								local ref = options.args.groups.args[info[2]].args.add.args.list.args; | 
| Zerotorescue@13 | 1739 | 
| Zerotorescue@13 | 1740 								for itemId, test in pairs(ref) do | 
| Zerotorescue@13 | 1741 									if test then | 
| Zerotorescue@13 | 1742 										local itemName = GetItemInfo(itemId); | 
| Zerotorescue@13 | 1743 | 
| Zerotorescue@13 | 1744 										if itemName:lower():find(value) then | 
| Zerotorescue@13 | 1745 									    	if not AddToGroup(groupName, itemId) then | 
| Zerotorescue@13 | 1746 									    		print("|cffff0000Couldn't add the item with itemId (" .. itemId .. ") because it is already in a group.|r"); | 
| Zerotorescue@13 | 1747 									    	end | 
| Zerotorescue@13 | 1748 										end | 
| Zerotorescue@13 | 1749 									end | 
| Zerotorescue@13 | 1750 								end | 
| Zerotorescue@13 | 1751 							end, | 
| Zerotorescue@0 | 1752 							get = false, | 
| Zerotorescue@0 | 1753 						}, | 
| Zerotorescue@13 | 1754 						minItemLevel = { | 
| Zerotorescue@13 | 1755 							order = 40, | 
| Zerotorescue@13 | 1756 							type = "select", | 
| Zerotorescue@13 | 1757 							values = function() | 
| Zerotorescue@13 | 1758 								local temp = {}; | 
| Zerotorescue@13 | 1759 | 
| Zerotorescue@13 | 1760 								temp[0] = "Include everything"; | 
| Zerotorescue@13 | 1761 | 
| Zerotorescue@13 | 1762 								local itemLevelTemplate = "Itemlevel >= %d"; | 
| Zerotorescue@13 | 1763 | 
| Zerotorescue@13 | 1764 								for i = 1, 49 do | 
| Zerotorescue@13 | 1765 									temp[( i * 10 )] = itemLevelTemplate:format(( i * 10 )); | 
| Zerotorescue@13 | 1766 								end | 
| Zerotorescue@13 | 1767 | 
| Zerotorescue@13 | 1768 								temp[500] = "Include nothing"; | 
| Zerotorescue@13 | 1769 | 
| Zerotorescue@13 | 1770 								return temp; | 
| Zerotorescue@13 | 1771 							end, | 
| Zerotorescue@13 | 1772 							name = "Include tradeskill items", | 
| Zerotorescue@13 | 1773 							desc = "Include all items above this item level from the currently opened tradeskill window in the below item list.\n\nSetting this very low this might considerably slow down this config window.\n\nSet to 500 to disable showing of items completely.", | 
| Zerotorescue@13 | 1774 							set = function(i, v) includeTradeSkillItems = v; end, | 
| Zerotorescue@13 | 1775 							get = function() return includeTradeSkillItems; end, | 
| Zerotorescue@13 | 1776 							disabled = function() | 
| Zerotorescue@13 | 1777 								if GetTradeSkillLine() == "UNKNOWN" then | 
| Zerotorescue@13 | 1778 									includeTradeSkillItems = 500; | 
| Zerotorescue@13 | 1779 									return true; -- disabled | 
| Zerotorescue@13 | 1780 								else | 
| Zerotorescue@13 | 1781 									return false; | 
| Zerotorescue@13 | 1782 								end | 
| Zerotorescue@13 | 1783 							end, | 
| Zerotorescue@13 | 1784 						}, | 
| Zerotorescue@0 | 1785 					}, | 
| Zerotorescue@0 | 1786 				}, | 
| Zerotorescue@0 | 1787 				list = { | 
| Zerotorescue@0 | 1788 					order = 30, | 
| Zerotorescue@0 | 1789 					type = "group", | 
| Zerotorescue@0 | 1790 					inline = true, | 
| Zerotorescue@0 | 1791 					name = "Item list", | 
| Zerotorescue@0 | 1792 					hidden = UpdateAddItemList, | 
| Zerotorescue@0 | 1793 					args = { | 
| Zerotorescue@0 | 1794 | 
| Zerotorescue@0 | 1795 					}, | 
| Zerotorescue@0 | 1796 				}, | 
| Zerotorescue@0 | 1797 			}, | 
| Zerotorescue@0 | 1798 		}, | 
| Zerotorescue@0 | 1799 		remove = { | 
| Zerotorescue@0 | 1800 			order = 40, | 
| Zerotorescue@0 | 1801 			type = "group", | 
| Zerotorescue@0 | 1802 			name = "Current items", | 
| Zerotorescue@23 | 1803 			desc = "View, export or remove items from this group.", | 
| Zerotorescue@31 | 1804 			hidden = function(info) return groupIsVirtual[info[2]]; end, | 
| Zerotorescue@0 | 1805 			args = { | 
| Zerotorescue@0 | 1806 				help = { | 
| Zerotorescue@0 | 1807 					order = 10, | 
| Zerotorescue@0 | 1808 					type = "group", | 
| Zerotorescue@0 | 1809 					inline = true, | 
| Zerotorescue@0 | 1810 					name = "Help", | 
| Zerotorescue@0 | 1811 					hidden = false, | 
| Zerotorescue@0 | 1812 					args = { | 
| Zerotorescue@0 | 1813 						help = { | 
| Zerotorescue@0 | 1814 							order = 10, | 
| Zerotorescue@0 | 1815 							type = "description", | 
| Zerotorescue@0 | 1816 							name = "Click the items you wish to remove from this group.", | 
| Zerotorescue@0 | 1817 						}, | 
| Zerotorescue@17 | 1818 						massRemove = { | 
| Zerotorescue@17 | 1819 							order = 20, | 
| Zerotorescue@17 | 1820 							type = "input", | 
| Zerotorescue@17 | 1821 							name = "Remove all items matching...", | 
| Zerotorescue@17 | 1822 							desc = "Remove every item in this group matching the name entered in this field. If you enter \"Glyph\" as a filter, any items in this group containing this in their name will be removed from this group.", | 
| Zerotorescue@17 | 1823 							set = function(info, value) | 
| Zerotorescue@17 | 1824 						    	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@17 | 1825 | 
| Zerotorescue@17 | 1826 								if not value then return; end | 
| Zerotorescue@17 | 1827 | 
| Zerotorescue@17 | 1828 								value = value:lower(); | 
| Zerotorescue@17 | 1829 | 
| Zerotorescue@17 | 1830 								local ref = options.args.groups.args[info[2]].args.remove.args.list.args; | 
| Zerotorescue@17 | 1831 | 
| Zerotorescue@17 | 1832 								for itemId, test in pairs(ref) do | 
| Zerotorescue@17 | 1833 									if test then | 
| Zerotorescue@17 | 1834 										local itemName = GetItemInfo(itemId); | 
| Zerotorescue@17 | 1835 | 
| Zerotorescue@17 | 1836 										if itemName:lower():find(value) then | 
| Zerotorescue@17 | 1837 									    	-- Unset this item | 
| Zerotorescue@17 | 1838 									    	addon.db.global.groups[groupName].items[itemId] = nil; | 
| Zerotorescue@17 | 1839 										end | 
| Zerotorescue@17 | 1840 									end | 
| Zerotorescue@17 | 1841 								end | 
| Zerotorescue@17 | 1842 							end, | 
| Zerotorescue@17 | 1843 							get = false, | 
| Zerotorescue@17 | 1844 						}, | 
| Zerotorescue@17 | 1845 						premadeGroups = { | 
| Zerotorescue@17 | 1846 							order = 30, | 
| Zerotorescue@17 | 1847 							type = "select", | 
| Zerotorescue@17 | 1848 							name = "Imported premade groups", | 
| Zerotorescue@23 | 1849 							desc = "This is a list of all premade groups that were imported into this group. You will be notified when any of these premade groups have changed and you will be able to import these changes.\n\nSelect a group to stop reminding you of changes to the premade group (the item list will be unaffected). Doing so will require you to manually update this when new items are added to the game.", | 
| Zerotorescue@17 | 1850 							values = function(info) | 
| Zerotorescue@17 | 1851 						    	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@17 | 1852 | 
| Zerotorescue@17 | 1853 						    	local temp = {}; | 
| Zerotorescue@17 | 1854 						    	if addon.db.global.groups[groupName].premadeGroups then | 
| Zerotorescue@17 | 1855 							    	for name, version in pairs(addon.db.global.groups[groupName].premadeGroups) do | 
| Zerotorescue@17 | 1856 							    		temp[name] = name; | 
| Zerotorescue@17 | 1857 							    	end | 
| Zerotorescue@17 | 1858 						    	end | 
| Zerotorescue@17 | 1859 | 
| Zerotorescue@17 | 1860 						    	return temp; | 
| Zerotorescue@17 | 1861 							end, | 
| Zerotorescue@17 | 1862 							set = function(info, value) | 
| Zerotorescue@17 | 1863 								-- Remove premade group from this group | 
| Zerotorescue@17 | 1864 						    	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@17 | 1865 | 
| Zerotorescue@17 | 1866 						    	addon.db.global.groups[groupName].premadeGroups[value] = nil; | 
| Zerotorescue@17 | 1867 | 
| Zerotorescue@17 | 1868 						    	print(("No longer notifying you about changes made to the premade group named \"|cfffed000%s|r\"."):format(value)); | 
| Zerotorescue@17 | 1869 							end, | 
| Zerotorescue@17 | 1870 							get = false, | 
| Zerotorescue@17 | 1871 							disabled = function(info) | 
| Zerotorescue@17 | 1872 						    	local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@17 | 1873 | 
| Zerotorescue@17 | 1874 								return (not addon.db.global.groups[groupName].premadeGroups); | 
| Zerotorescue@17 | 1875 							end, | 
| Zerotorescue@17 | 1876 						}, | 
| Zerotorescue@0 | 1877 					}, | 
| Zerotorescue@0 | 1878 				}, | 
| Zerotorescue@0 | 1879 				list = { | 
| Zerotorescue@0 | 1880 					order = 20, | 
| Zerotorescue@0 | 1881 					type = "group", | 
| Zerotorescue@0 | 1882 					inline = true, | 
| Zerotorescue@0 | 1883 					name = "Item list", | 
| Zerotorescue@0 | 1884 					hidden = UpdateRemoveItemList, | 
| Zerotorescue@0 | 1885 					args = { | 
| Zerotorescue@0 | 1886 | 
| Zerotorescue@0 | 1887 					}, | 
| Zerotorescue@0 | 1888 				}, | 
| Zerotorescue@0 | 1889 				export = { | 
| Zerotorescue@0 | 1890 					order = 30, | 
| Zerotorescue@0 | 1891 					type = "group", | 
| Zerotorescue@0 | 1892 					name = "Export", | 
| Zerotorescue@0 | 1893 					inline = true, | 
| Zerotorescue@0 | 1894 					args = { | 
| Zerotorescue@0 | 1895 						input = { | 
| Zerotorescue@0 | 1896 							order = 10, | 
| Zerotorescue@0 | 1897 							type = "input", | 
| Zerotorescue@0 | 1898 							name = "Item data", | 
| Zerotorescue@0 | 1899 							width = "full", | 
| Zerotorescue@0 | 1900 							desc = "Export the item data for the currently selected group. Press CTRL-A to select all and CTRL-C to copy the text.", | 
| Zerotorescue@0 | 1901 							set = false, | 
| Zerotorescue@0 | 1902 							get = function(info) | 
| Zerotorescue@0 | 1903 								local groupName = groupIdToName[info[2]]; | 
| Zerotorescue@0 | 1904 | 
| Zerotorescue@0 | 1905 								local combinedItemIds; | 
| Zerotorescue@0 | 1906 								-- Parse items in group and show these | 
| Zerotorescue@0 | 1907 								for itemId, _ in pairs(addon.db.global.groups[groupName].items) do | 
| Zerotorescue@0 | 1908 									if not combinedItemIds then | 
| Zerotorescue@0 | 1909 										combinedItemIds = tostring(itemId); | 
| Zerotorescue@0 | 1910 									else | 
| Zerotorescue@0 | 1911 										combinedItemIds = combinedItemIds .. (";%d"):format(itemId); | 
| Zerotorescue@0 | 1912 									end | 
| Zerotorescue@0 | 1913 								end | 
| Zerotorescue@0 | 1914 | 
| Zerotorescue@0 | 1915 								return combinedItemIds; -- We don't serialize this because we actually DO want people to be able to manually modify it - besides, parsing it isn't going to be hard | 
| Zerotorescue@0 | 1916 							end, | 
| Zerotorescue@0 | 1917 						}, | 
| Zerotorescue@0 | 1918 					}, | 
| Zerotorescue@0 | 1919 				}, | 
| Zerotorescue@0 | 1920 			}, | 
| Zerotorescue@0 | 1921 		}, | 
| Zerotorescue@0 | 1922 	}, | 
| Zerotorescue@0 | 1923 }; | 
| Zerotorescue@0 | 1924 | 
| Zerotorescue@30 | 1925 local currentGroupType = "Normal"; | 
| Zerotorescue@0 | 1926 function addon:MakeGroupOptions() | 
| Zerotorescue@0 | 1927 	options.args.groups = { | 
| Zerotorescue@0 | 1928 		order = 1100, | 
| Zerotorescue@0 | 1929 		type = "group", | 
| Zerotorescue@0 | 1930 		name = "Groups", | 
| Zerotorescue@0 | 1931 		desc = "Change a group.", | 
| Zerotorescue@0 | 1932 		args = { | 
| Zerotorescue@0 | 1933 			create = { | 
| Zerotorescue@0 | 1934 				order = 10, | 
| Zerotorescue@0 | 1935 				type = "group", | 
| Zerotorescue@0 | 1936 				inline = true, | 
| Zerotorescue@0 | 1937 				name = "Create a brand new group", | 
| Zerotorescue@0 | 1938 				args = { | 
| Zerotorescue@0 | 1939 					name = { | 
| Zerotorescue@0 | 1940 						order = 10, | 
| Zerotorescue@0 | 1941 						type = "input", | 
| Zerotorescue@0 | 1942 						name = "Group name", | 
| Zerotorescue@0 | 1943 						desc = "The name of the group. You can also use item links as you wish.", | 
| Zerotorescue@0 | 1944 						validate = ValidateGroupName, | 
| Zerotorescue@0 | 1945 						set = function(_, value) | 
| Zerotorescue@0 | 1946 							self.db.global.groups[value] = {}; | 
| Zerotorescue@30 | 1947 							if currentGroupType == "Virtual" then | 
| Zerotorescue@30 | 1948 								self.db.global.groups[value].isVirtual = true; | 
| Zerotorescue@30 | 1949 							end | 
| Zerotorescue@30 | 1950 | 
| Zerotorescue@0 | 1951 							addon:FillGroupOptions(); | 
| Zerotorescue@0 | 1952 						end, | 
| Zerotorescue@0 | 1953 						get = false, | 
| Zerotorescue@0 | 1954 						width = "double", | 
| Zerotorescue@0 | 1955 					}, | 
| Zerotorescue@30 | 1956 					type = { | 
| Zerotorescue@30 | 1957 						order = 20, | 
| Zerotorescue@30 | 1958 						type = "select", | 
| Zerotorescue@30 | 1959 						name = "Type (advanced)", | 
| Zerotorescue@30 | 1960 						desc = "The type of the new group. This can not be changed at a later time.\n\n|cffff9933This is an advanced option, you will probably not need it unless you manage a lot of groups.|r\n\n|cfffed000Normal|r: A normal group with complete functionality.\n\n|cfffed000Virtual|r: A virtual group which you can use to override the defaults for a set of groups. You can not add items to virtual groups.", | 
| Zerotorescue@30 | 1961 						values = { | 
| Zerotorescue@30 | 1962 							["Normal"] = "Normal", | 
| Zerotorescue@30 | 1963 							["Virtual"] = "Virtual", | 
| Zerotorescue@30 | 1964 						}, | 
| Zerotorescue@30 | 1965 						set = function(_, value) currentGroupType = value; end, | 
| Zerotorescue@30 | 1966 						get = function() return currentGroupType; end, | 
| Zerotorescue@30 | 1967 					}, | 
| Zerotorescue@0 | 1968 				}, | 
| Zerotorescue@0 | 1969 			}, | 
| Zerotorescue@0 | 1970 			import = { | 
| Zerotorescue@0 | 1971 				order = 20, | 
| Zerotorescue@0 | 1972 				type = "group", | 
| Zerotorescue@0 | 1973 				inline = true, | 
| Zerotorescue@0 | 1974 				name = "Import a group", | 
| Zerotorescue@0 | 1975 				args = { | 
| Zerotorescue@0 | 1976 					input = { | 
| Zerotorescue@0 | 1977 						order = 10, | 
| Zerotorescue@0 | 1978 						type = "input", | 
| Zerotorescue@0 | 1979 						multiline = true, | 
| Zerotorescue@0 | 1980 						name = "Group data", | 
| Zerotorescue@0 | 1981 						desc = "Paste the group data as provided by a group export. If you are trying to import multiple groups at the same time, make sure to use newlines to seperate them.", | 
| Zerotorescue@0 | 1982 						set = function(info, value) | 
| Zerotorescue@9 | 1983 							local data = { string.split("\n", value or "") }; | 
| Zerotorescue@0 | 1984 | 
| Zerotorescue@9 | 1985 							for _, current in pairs(data) do | 
| Zerotorescue@0 | 1986 								if not AceSerializer then | 
| Zerotorescue@0 | 1987 									AceSerializer = LibStub("AceSerializer-3.0"); | 
| Zerotorescue@0 | 1988 								end | 
| Zerotorescue@0 | 1989 | 
| Zerotorescue@0 | 1990 								local result, temp = AceSerializer:Deserialize(current); | 
| Zerotorescue@0 | 1991 | 
| Zerotorescue@0 | 1992 								if not temp.name then | 
| Zerotorescue@0 | 1993 									print("|cffff0000The provided data is not supported.|r"); | 
| Zerotorescue@10 | 1994 								elseif ValidateGroupName(nil, temp.name) ~= true then | 
| Zerotorescue@10 | 1995 									print(("|cffff0000Aborting: A group named \"%s\" already exists.|r"):format(temp.name)); | 
| Zerotorescue@0 | 1996 								else | 
| Zerotorescue@10 | 1997 									local name = temp.name; | 
| Zerotorescue@0 | 1998 									temp.name = nil; | 
| Zerotorescue@9 | 1999 									print(("Importing %s..."):format(name)); | 
| Zerotorescue@10 | 2000 | 
| Zerotorescue@10 | 2001 									-- Remove items that are already in another group | 
| Zerotorescue@10 | 2002 									for value, _ in pairs(temp.items) do | 
| Zerotorescue@17 | 2003 										local itemId = tonumber(value); | 
| Zerotorescue@10 | 2004 | 
| Zerotorescue@10 | 2005 										if not itemId then | 
| Zerotorescue@10 | 2006 											print(("\"%s\" is not a number."):format(value)); | 
| Zerotorescue@10 | 2007 											temp.items[value] = nil; | 
| Zerotorescue@10 | 2008 										elseif InGroup(itemId) then | 
| Zerotorescue@10 | 2009 											print(("Skipping %s (#%d) as it is already in the group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId))); | 
| Zerotorescue@10 | 2010 											temp.items[value] = nil; | 
| Zerotorescue@10 | 2011 										else | 
| Zerotorescue@10 | 2012 											-- Ensure the keys are numeric | 
| Zerotorescue@10 | 2013 											temp.items[value] = nil; | 
| Zerotorescue@10 | 2014 											temp.items[itemId] = true; | 
| Zerotorescue@10 | 2015 										end | 
| Zerotorescue@10 | 2016 									end | 
| Zerotorescue@10 | 2017 | 
| Zerotorescue@23 | 2018 									-- Ensure this data isn't received (this would be silly/buggy as exports from other accounts - with different characters - won't know what to do with this) | 
| Zerotorescue@10 | 2019 									temp.trackAtCharacters = nil; | 
| Zerotorescue@10 | 2020 									temp.overrideTrackAtCharacters = nil; | 
| Zerotorescue@10 | 2021 | 
| Zerotorescue@10 | 2022 									self.db.global.groups[name] = temp; | 
| Zerotorescue@0 | 2023 								end | 
| Zerotorescue@0 | 2024 							end | 
| Zerotorescue@10 | 2025 | 
| Zerotorescue@10 | 2026 							self:FillGroupOptions(); | 
| Zerotorescue@0 | 2027 						end, | 
| Zerotorescue@0 | 2028 						get = false, | 
| Zerotorescue@0 | 2029 						width = "full", | 
| Zerotorescue@0 | 2030 					}, | 
| Zerotorescue@0 | 2031 				}, | 
| Zerotorescue@0 | 2032 			}, | 
| Zerotorescue@0 | 2033 		}, | 
| Zerotorescue@0 | 2034 	}; | 
| Zerotorescue@0 | 2035 end | 
| Zerotorescue@0 | 2036 | 
| Zerotorescue@0 | 2037 function addon:FillGroupOptions() | 
| Zerotorescue@0 | 2038 	for id, name in pairs(groupIdToName) do | 
| Zerotorescue@0 | 2039 		if type(name) == "string" and not self.db.global.groups[name] then | 
| Zerotorescue@0 | 2040 			options.args.groups.args[id] = nil; | 
| Zerotorescue@0 | 2041 			groupIdToName[id] = nil; | 
| Zerotorescue@0 | 2042 			groupIdToName[name] = nil; | 
| Zerotorescue@30 | 2043 			groupIsVirtual[id] = nil; | 
| Zerotorescue@0 | 2044 		end | 
| Zerotorescue@0 | 2045 	end | 
| Zerotorescue@0 | 2046 | 
| Zerotorescue@0 | 2047 	for name, values in pairs(self.db.global.groups) do | 
| Zerotorescue@0 | 2048 		if not groupIdToName[name] then | 
| Zerotorescue@23 | 2049 			options.args.groups.args[tostring(count)] = defaultGroup; | 
| Zerotorescue@0 | 2050 | 
| Zerotorescue@0 | 2051 			groupIdToName[tostring(count)] = name; | 
| Zerotorescue@0 | 2052 			groupIdToName[name] = true; | 
| Zerotorescue@30 | 2053 			if values.isVirtual then | 
| Zerotorescue@30 | 2054 				groupIsVirtual[tostring(count)] = true; | 
| Zerotorescue@30 | 2055 			end | 
| Zerotorescue@0 | 2056 | 
| Zerotorescue@0 | 2057 			count = ( count + 1 ); | 
| Zerotorescue@0 | 2058 		end | 
| Zerotorescue@0 | 2059 	end | 
| Zerotorescue@0 | 2060 end | 
| Zerotorescue@0 | 2061 | 
| Zerotorescue@13 | 2062 | 
| Zerotorescue@13 | 2063 | 
| Zerotorescue@13 | 2064 -- General functions used addon-wide | 
| Zerotorescue@13 | 2065 | 
| Zerotorescue@23 | 2066 function addon:GetItemCount(itemId, group) | 
| Zerotorescue@13 | 2067 	itemId = tonumber(itemId); | 
| Zerotorescue@13 | 2068 | 
| Zerotorescue@13 | 2069 	if not itemId then return; end | 
| Zerotorescue@13 | 2070 | 
| Zerotorescue@23 | 2071 	local selectedExternalAddon = self:GetOptionByKey(group, "itemCountAddon"); | 
| Zerotorescue@23 | 2072 | 
| Zerotorescue@23 | 2073 	if self.supportedAddons.itemCount[selectedExternalAddon] and self.supportedAddons.itemCount[selectedExternalAddon].IsEnabled() then | 
| Zerotorescue@13 | 2074 		-- Try to use the default item count addon | 
| Zerotorescue@13 | 2075 | 
| Zerotorescue@23 | 2076 		return self.supportedAddons.itemCount[selectedExternalAddon].GetTotalCount(itemId); | 
| Zerotorescue@13 | 2077 	else | 
| Zerotorescue@13 | 2078 		-- Default not available, get the first one then | 
| Zerotorescue@13 | 2079 | 
| Zerotorescue@13 | 2080 		for name, value in pairs(self.supportedAddons.itemCount) do | 
| Zerotorescue@13 | 2081 			if value.IsEnabled() then | 
| Zerotorescue@17 | 2082 				return value.GetTotalCount(itemId); | 
| Zerotorescue@13 | 2083 			end | 
| Zerotorescue@13 | 2084 		end | 
| Zerotorescue@13 | 2085 	end | 
| Zerotorescue@13 | 2086 | 
| Zerotorescue@13 | 2087 	return -1; | 
| Zerotorescue@0 | 2088 end | 
| Zerotorescue@0 | 2089 | 
| Zerotorescue@23 | 2090 function addon:GetAuctionValue(itemLink, group) | 
| Zerotorescue@23 | 2091 	if not itemLink then return -5; end | 
| Zerotorescue@13 | 2092 | 
| Zerotorescue@23 | 2093 	local selectedExternalAddon = self:GetOptionByKey(group, "auctionPricingAddon"); | 
| Zerotorescue@23 | 2094 | 
| Zerotorescue@23 | 2095 	if self.supportedAddons.auctionPricing[selectedExternalAddon] and self.supportedAddons.auctionPricing[selectedExternalAddon].IsEnabled() then | 
| Zerotorescue@13 | 2096 		-- Try to use the default auction pricing addon | 
| Zerotorescue@1 | 2097 | 
| Zerotorescue@23 | 2098 		return self.supportedAddons.auctionPricing[selectedExternalAddon].GetValue(itemLink); | 
| Zerotorescue@13 | 2099 	else | 
| Zerotorescue@13 | 2100 		-- Default not available, get the first one then | 
| Zerotorescue@1 | 2101 | 
| Zerotorescue@13 | 2102 		for name, value in pairs(self.supportedAddons.auctionPricing) do | 
| Zerotorescue@13 | 2103 			if value.IsEnabled() then | 
| Zerotorescue@13 | 2104 				return value.GetValue(itemLink); | 
| Zerotorescue@13 | 2105 			end | 
| Zerotorescue@1 | 2106 		end | 
| Zerotorescue@1 | 2107 	end | 
| Zerotorescue@7 | 2108 | 
| Zerotorescue@7 | 2109 	return -2; | 
| Zerotorescue@1 | 2110 end | 
| Zerotorescue@1 | 2111 | 
| Zerotorescue@0 | 2112 | 
| Zerotorescue@0 | 2113 | 
| Zerotorescue@13 | 2114 -- Public | 
| Zerotorescue@13 | 2115 | 
| Zerotorescue@13 | 2116 function IMRegisterPricingAddon(name, get, enabled) | 
| Zerotorescue@13 | 2117 	addon.supportedAddons.auctionPricing[name] = { | 
| Zerotorescue@13 | 2118 		GetValue = get, | 
| Zerotorescue@13 | 2119 		IsEnabled = enabled, | 
| Zerotorescue@13 | 2120 	}; | 
| Zerotorescue@13 | 2121 end | 
| Zerotorescue@13 | 2122 | 
| Zerotorescue@17 | 2123 function IMRegisterItemCountAddon(name, getTotal, getCharacter, enabled) | 
| Zerotorescue@13 | 2124 	addon.supportedAddons.itemCount[name] = { | 
| Zerotorescue@17 | 2125 		GetTotalCount = getTotal, | 
| Zerotorescue@17 | 2126 		GetCharacterCount = getCharacter, | 
| Zerotorescue@13 | 2127 		IsEnabled = enabled, | 
| Zerotorescue@13 | 2128 	}; | 
| Zerotorescue@13 | 2129 end | 
| Zerotorescue@13 | 2130 | 
| Zerotorescue@13 | 2131 function IMRegisterCraftingAddon(name, queue, enabled) | 
| Zerotorescue@13 | 2132 	addon.supportedAddons.crafting[name] = { | 
| Zerotorescue@13 | 2133 		Queue = queue, | 
| Zerotorescue@13 | 2134 		IsEnabled = enabled, | 
| Zerotorescue@13 | 2135 	}; | 
| Zerotorescue@13 | 2136 end | 
| Zerotorescue@13 | 2137 | 
| Zerotorescue@13 | 2138 | 
| Zerotorescue@13 | 2139 | 
| Zerotorescue@13 | 2140 -- Debug | 
| Zerotorescue@0 | 2141 | 
| Zerotorescue@0 | 2142 function addon:Debug(t) | 
| Zerotorescue@0 | 2143 	if not self.debugChannel and self.debugChannel ~= false then | 
| Zerotorescue@0 | 2144 		-- We want to check just once, so if you add a debug channel later just do a /reload (registering an event for this is wasted resources) | 
| Zerotorescue@0 | 2145 		self.debugChannel = false; | 
| Zerotorescue@0 | 2146 | 
| Zerotorescue@0 | 2147 		for i = 1, NUM_CHAT_WINDOWS do | 
| Zerotorescue@0 | 2148 			local name = GetChatWindowInfo(i); | 
| Zerotorescue@0 | 2149 | 
| Zerotorescue@0 | 2150 			if name:upper() == "DEBUG" then | 
| Zerotorescue@0 | 2151 				self.debugChannel = _G["ChatFrame" .. i]; | 
| Zerotorescue@0 | 2152 			end | 
| Zerotorescue@0 | 2153 		end | 
| Zerotorescue@0 | 2154 	end | 
| Zerotorescue@0 | 2155 | 
| Zerotorescue@0 | 2156 	if self.debugChannel then | 
| Zerotorescue@0 | 2157 		self.debugChannel:AddMessage(t); | 
| Zerotorescue@0 | 2158 	end | 
| Zerotorescue@0 | 2159 end |