| 
Zerotorescue@0
 | 
     1 -- You can access this addon's object through: LibStub("AceAddon-3.0"):GetAddon("Inventory")
 | 
| 
Zerotorescue@1
 | 
     2 local addon = LibStub("AceAddon-3.0"):NewAddon("Inventory", "AceEvent-3.0");
 | 
| 
Zerotorescue@1
 | 
     3 
 | 
| 
Zerotorescue@1
 | 
     4 local AceGUI = LibStub("AceGUI-3.0");
 | 
| 
Zerotorescue@0
 | 
     5 
 | 
| 
Zerotorescue@0
 | 
     6 local Media = LibStub("LibSharedMedia-3.0");
 | 
| 
Zerotorescue@0
 | 
     7 Media:Register("sound", "Cartoon FX", [[Sound\Doodad\Goblin_Lottery_Open03.wav]]);
 | 
| 
Zerotorescue@0
 | 
     8 Media:Register("sound", "Cheer", [[Sound\Event Sounds\OgreEventCheerUnique.wav]]);
 | 
| 
Zerotorescue@0
 | 
     9 Media:Register("sound", "Explosion", [[Sound\Doodad\Hellfire_Raid_FX_Explosion05.wav]]);
 | 
| 
Zerotorescue@0
 | 
    10 Media:Register("sound", "Fel Nova", [[Sound\Spells\SeepingGaseous_Fel_Nova.wav]]);
 | 
| 
Zerotorescue@0
 | 
    11 Media:Register("sound", "Fel Portal", [[Sound\Spells\Sunwell_Fel_PortalStand.wav]]);
 | 
| 
Zerotorescue@0
 | 
    12 Media:Register("sound", "Magic Click", [[Sound\interface\MagicClick.wav]]);
 | 
| 
Zerotorescue@0
 | 
    13 Media:Register("sound", "Rubber Ducky", [[Sound\Doodad\Goblin_Lottery_Open01.wav]]);
 | 
| 
Zerotorescue@0
 | 
    14 Media:Register("sound", "Shing!", [[Sound\Doodad\PortcullisActive_Closed.wav]]);
 | 
| 
Zerotorescue@0
 | 
    15 Media:Register("sound", "Simon Chime", [[Sound\Doodad\SimonGame_LargeBlueTree.wav]]);
 | 
| 
Zerotorescue@0
 | 
    16 Media:Register("sound", "Simon Error", [[Sound\Spells\SimonGame_Visual_BadPress.wav]]);
 | 
| 
Zerotorescue@0
 | 
    17 Media:Register("sound", "Simon Start", [[Sound\Spells\SimonGame_Visual_GameStart.wav]]);
 | 
| 
Zerotorescue@0
 | 
    18 Media:Register("sound", "War Drums", [[Sound\Event Sounds\Event_wardrum_ogre.wav]]);
 | 
| 
Zerotorescue@0
 | 
    19 Media:Register("sound", "Wham!", [[Sound\Doodad\PVP_Lordaeron_Door_Open.wav]]);
 | 
| 
Zerotorescue@0
 | 
    20 Media:Register("sound", "Whisper Ping", [[Sound\interface\iTellMessage.wav]]);
 | 
| 
Zerotorescue@0
 | 
    21 Media:Register("sound", "You Will Die!", [[Sound\Creature\CThun\CThunYouWillDIe.wav]]);
 | 
| 
Zerotorescue@0
 | 
    22 
 | 
| 
Zerotorescue@0
 | 
    23 local AceConfigDialog, AceConfigRegistry, AceSerializer;
 | 
| 
Zerotorescue@0
 | 
    24 local groupIdToName = {};
 | 
| 
Zerotorescue@0
 | 
    25 local options = {};
 | 
| 
Zerotorescue@0
 | 
    26 
 | 
| 
Zerotorescue@0
 | 
    27 function addon:OnInitialize()
 | 
| 
Zerotorescue@0
 | 
    28 	self:Debug("OnInitialize");
 | 
| 
Zerotorescue@0
 | 
    29 	
 | 
| 
Zerotorescue@0
 | 
    30 	-- SAVED VARIABLES
 | 
| 
Zerotorescue@0
 | 
    31 	
 | 
| 
Zerotorescue@0
 | 
    32 	local defaults = {
 | 
| 
Zerotorescue@0
 | 
    33 		global = {
 | 
| 
Zerotorescue@0
 | 
    34 			groups = {},
 | 
| 
Zerotorescue@0
 | 
    35 			defaults = {
 | 
| 
Zerotorescue@0
 | 
    36 				minimumStock = 60,
 | 
| 
Zerotorescue@0
 | 
    37 				alertBelowMinimum = true,
 | 
| 
Zerotorescue@0
 | 
    38 				summaryThresholdShow = 10,
 | 
| 
Zerotorescue@0
 | 
    39 				restockTarget = 60,
 | 
| 
Zerotorescue@0
 | 
    40 				minCraftingQueue = 0.05,
 | 
| 
Zerotorescue@0
 | 
    41 				bonusQueue = 0.1,
 | 
| 
Zerotorescue@0
 | 
    42 				priceThreshold = 0,
 | 
| 
Zerotorescue@1
 | 
    43 				hideFromSummaryWhenBelowPriceThreshold = false,
 | 
| 
Zerotorescue@0
 | 
    44 				trackAtCharacters = {},
 | 
| 
Zerotorescue@0
 | 
    45 				colors = {
 | 
| 
Zerotorescue@0
 | 
    46 					red = 0;
 | 
| 
Zerotorescue@0
 | 
    47 					orange = 0.3;
 | 
| 
Zerotorescue@0
 | 
    48 					yellow = 0.6;
 | 
| 
Zerotorescue@0
 | 
    49 					green = 0.95;
 | 
| 
Zerotorescue@0
 | 
    50 				},
 | 
| 
Zerotorescue@0
 | 
    51 			},
 | 
| 
Zerotorescue@0
 | 
    52 		},
 | 
| 
Zerotorescue@0
 | 
    53 		factionrealm = {
 | 
| 
Zerotorescue@0
 | 
    54 			characters = {},
 | 
| 
Zerotorescue@0
 | 
    55 		},
 | 
| 
Zerotorescue@0
 | 
    56 	};
 | 
| 
Zerotorescue@0
 | 
    57 	
 | 
| 
Zerotorescue@0
 | 
    58 	-- Register our saved variables database
 | 
| 
Zerotorescue@0
 | 
    59 	self.db = LibStub("AceDB-3.0"):New("InventoryDB", defaults, true);
 | 
| 
Zerotorescue@0
 | 
    60 	
 | 
| 
Zerotorescue@0
 | 
    61 	-- SLASH COMMANDS
 | 
| 
Zerotorescue@0
 | 
    62 	
 | 
| 
Zerotorescue@0
 | 
    63 	-- Disable the AddonLoader slash commands
 | 
| 
Zerotorescue@0
 | 
    64 	SLASH_INVENTORY1 = nil;
 | 
| 
Zerotorescue@0
 | 
    65 	SLASH_IY1 = nil;
 | 
| 
Zerotorescue@0
 | 
    66 	
 | 
| 
Zerotorescue@0
 | 
    67 	-- Register our own slash commands
 | 
| 
Zerotorescue@0
 | 
    68 	SLASH_INVENTORY1 = "/inventory";
 | 
| 
Zerotorescue@0
 | 
    69 	SLASH_INVENTORY2 = "/iy";
 | 
| 
Zerotorescue@0
 | 
    70 	SlashCmdList["INVENTORY"] = function(msg)
 | 
| 
Zerotorescue@0
 | 
    71 		self:CommandHandler(msg);
 | 
| 
Zerotorescue@0
 | 
    72 	end
 | 
| 
Zerotorescue@0
 | 
    73 	
 | 
| 
Zerotorescue@0
 | 
    74 	-- INTERFACE OPTIONS
 | 
| 
Zerotorescue@0
 | 
    75 	
 | 
| 
Zerotorescue@0
 | 
    76 	 -- Attempt to remove the interface options added by AddonLoader (if enabled)
 | 
| 
Zerotorescue@0
 | 
    77 	if AddonLoader and AddonLoader.RemoveInterfaceOptions then
 | 
| 
Zerotorescue@0
 | 
    78 		AddonLoader:RemoveInterfaceOptions("Inventory");
 | 
| 
Zerotorescue@0
 | 
    79 	end
 | 
| 
Zerotorescue@0
 | 
    80 	
 | 
| 
Zerotorescue@0
 | 
    81 	-- Now create our own options frame
 | 
| 
Zerotorescue@0
 | 
    82 	local frame = CreateFrame("Frame", nil, UIParent);
 | 
| 
Zerotorescue@0
 | 
    83 	frame:Hide();
 | 
| 
Zerotorescue@0
 | 
    84 	frame.name = "Inventory";
 | 
| 
Zerotorescue@0
 | 
    85 	frame:HookScript("OnShow", function(self)
 | 
| 
Zerotorescue@0
 | 
    86 		-- Refresh the frame to instantly show the right options
 | 
| 
Zerotorescue@0
 | 
    87 		InterfaceOptionsFrame_OpenToCategory(self.name)
 | 
| 
Zerotorescue@0
 | 
    88 	end);
 | 
| 
Zerotorescue@0
 | 
    89 	-- And add it to the interface options
 | 
| 
Zerotorescue@0
 | 
    90 	InterfaceOptions_AddCategory(frame);
 | 
| 
Zerotorescue@0
 | 
    91 	
 | 
| 
Zerotorescue@1
 | 
    92 	self:MakeItemLinkButtonWidget();
 | 
| 
Zerotorescue@1
 | 
    93 	self:MakeConfigItemLinkButtonWidget();
 | 
| 
Zerotorescue@0
 | 
    94 	
 | 
| 
Zerotorescue@0
 | 
    95 	-- Remember this character is mine
 | 
| 
Zerotorescue@0
 | 
    96 	local playerName = UnitName("player");
 | 
| 
Zerotorescue@0
 | 
    97 	if not self.db.factionrealm.characters[playerName] then
 | 
| 
Zerotorescue@0
 | 
    98 		self.db.factionrealm.characters[playerName] = true;
 | 
| 
Zerotorescue@0
 | 
    99 		
 | 
| 
Zerotorescue@0
 | 
   100 		-- Default to tracking on all chars, untracking is a convenience, not tracking by default would probably get multiple issue reports.
 | 
| 
Zerotorescue@0
 | 
   101 		self.db.global.defaults.trackAtCharacters[playerName] = true;
 | 
| 
Zerotorescue@0
 | 
   102 	end
 | 
| 
Zerotorescue@0
 | 
   103 end
 | 
| 
Zerotorescue@0
 | 
   104 
 | 
| 
Zerotorescue@1
 | 
   105 local slashArgs = {};
 | 
| 
Zerotorescue@1
 | 
   106 function addon:RegisterSlash(func, ...)
 | 
| 
Zerotorescue@1
 | 
   107 	for _, arg in pairs({ ... }) do
 | 
| 
Zerotorescue@1
 | 
   108 		slashArgs[arg] = func;
 | 
| 
Zerotorescue@1
 | 
   109 	end
 | 
| 
Zerotorescue@1
 | 
   110 end
 | 
| 
Zerotorescue@1
 | 
   111 
 | 
| 
Zerotorescue@1
 | 
   112 function addon:MakeItemLinkButtonWidget()
 | 
| 
Zerotorescue@0
 | 
   113 	--[[
 | 
| 
Zerotorescue@0
 | 
   114 	[ ItemLinkButton ]
 | 
| 
Zerotorescue@1
 | 
   115 	This custom widget has to show an icon with the item link next to it.
 | 
| 
Zerotorescue@1
 | 
   116 	Upon hover it must show the item tooltip.
 | 
| 
Zerotorescue@1
 | 
   117 	Upon click it must execute the function provided through user data.
 | 
| 
Zerotorescue@1
 | 
   118 	
 | 
| 
Zerotorescue@1
 | 
   119 	UserData: itemId, onClickEvent
 | 
| 
Zerotorescue@1
 | 
   120 	
 | 
| 
Zerotorescue@0
 | 
   121 	OnEnter: tooltip show
 | 
| 
Zerotorescue@1
 | 
   122 	OnLeave: tooltip hide
 | 
| 
Zerotorescue@1
 | 
   123 	OnClick: UserData.onClickEvent
 | 
| 
Zerotorescue@0
 | 
   124 	]]
 | 
| 
Zerotorescue@0
 | 
   125 	
 | 
| 
Zerotorescue@0
 | 
   126 	local widgetType = "ItemLinkButton";
 | 
| 
Zerotorescue@0
 | 
   127 	local widgetVersion = 1;
 | 
| 
Zerotorescue@0
 | 
   128 	
 | 
| 
Zerotorescue@1
 | 
   129 	local function Constructor()
 | 
| 
Zerotorescue@1
 | 
   130 	    local widget = AceGUI:Create("InteractiveLabel");
 | 
| 
Zerotorescue@1
 | 
   131 	    widget.type = widgetType;
 | 
| 
Zerotorescue@1
 | 
   132 	    
 | 
| 
Zerotorescue@1
 | 
   133 	    -- We overwrite the OnAcquire as we want to set our callbacks even
 | 
| 
Zerotorescue@1
 | 
   134 	    -- when the widget is re-used from the widget pool
 | 
| 
Zerotorescue@1
 | 
   135 	    widget.originalOnAcquire = widget.OnAcquire;
 | 
| 
Zerotorescue@1
 | 
   136 	    widget.OnAcquire = function(self, ...)
 | 
| 
Zerotorescue@1
 | 
   137 	    
 | 
| 
Zerotorescue@1
 | 
   138 	    
 | 
| 
Zerotorescue@1
 | 
   139 	    	-- We overwrite the setcallback because we don't want anything else 
 | 
| 
Zerotorescue@1
 | 
   140 	    	-- to overwrite our OnEnter, OnLeave and OnClick events
 | 
| 
Zerotorescue@1
 | 
   141 	    	-- which would be done by the AceConfigDialog after a widget gets re-used
 | 
| 
Zerotorescue@1
 | 
   142 		    if not self.originalSetCallBack then
 | 
| 
Zerotorescue@1
 | 
   143 			    self.originalSetCallBack = self.SetCallback;
 | 
| 
Zerotorescue@1
 | 
   144 			    self.SetCallback = function(this, event, func, ...)
 | 
| 
Zerotorescue@1
 | 
   145 			    	if event == "OnEnter" or event == "OnLeave" or event == "OnClick" then
 | 
| 
Zerotorescue@1
 | 
   146 			    		-- Don't allow overwriting of these events
 | 
| 
Zerotorescue@1
 | 
   147 			    		return;
 | 
| 
Zerotorescue@1
 | 
   148 			    	elseif event == "CustomOnEnter" then
 | 
| 
Zerotorescue@1
 | 
   149 			    		return this.originalSetCallBack(this, "OnEnter", func, ...);
 | 
| 
Zerotorescue@1
 | 
   150 			    	elseif event == "CustomOnLeave" then
 | 
| 
Zerotorescue@1
 | 
   151 			    		return this.originalSetCallBack(this, "OnLeave", func, ...);
 | 
| 
Zerotorescue@1
 | 
   152 			    	elseif event == "CustomOnClick" then
 | 
| 
Zerotorescue@1
 | 
   153 			    		return this.originalSetCallBack(this, "OnClick", func, ...);
 | 
| 
Zerotorescue@1
 | 
   154 			    	else
 | 
| 
Zerotorescue@1
 | 
   155 			    		return this.originalSetCallBack(this, event, func, ...);
 | 
| 
Zerotorescue@1
 | 
   156 			    	end
 | 
| 
Zerotorescue@1
 | 
   157 			    end;
 | 
| 
Zerotorescue@1
 | 
   158 		    end
 | 
| 
Zerotorescue@1
 | 
   159 		    
 | 
| 
Zerotorescue@1
 | 
   160 		    
 | 
| 
Zerotorescue@1
 | 
   161 		    -- Set our own events, since we disabled the normal event-names, we'll call them our custom versions
 | 
| 
Zerotorescue@1
 | 
   162 		    self:SetCallback("CustomOnEnter", function(this)
 | 
| 
Zerotorescue@1
 | 
   163 		    	local itemId = this:GetUserData("itemId");
 | 
| 
Zerotorescue@1
 | 
   164 		    	
 | 
| 
Zerotorescue@1
 | 
   165 		    	if itemId then
 | 
| 
Zerotorescue@1
 | 
   166 			    	GameTooltip:SetOwner(this.frame, "ANCHOR_TOPRIGHT");
 | 
| 
Zerotorescue@1
 | 
   167 			    	GameTooltip:SetHyperlink(("item:%d"):format(itemId));
 | 
| 
Zerotorescue@1
 | 
   168 					GameTooltip:Show();
 | 
| 
Zerotorescue@1
 | 
   169 		    	end
 | 
| 
Zerotorescue@1
 | 
   170 		    end);
 | 
| 
Zerotorescue@1
 | 
   171 		    self:SetCallback("CustomOnLeave", function(this)
 | 
| 
Zerotorescue@1
 | 
   172 		    	GameTooltip:Hide();
 | 
| 
Zerotorescue@1
 | 
   173 		    end);
 | 
| 
Zerotorescue@1
 | 
   174 		    self:SetCallback("CustomOnClick", function(this)
 | 
| 
Zerotorescue@1
 | 
   175 		    	if this.OnClick then
 | 
| 
Zerotorescue@1
 | 
   176 		    		this.OnClick(this);
 | 
| 
Zerotorescue@1
 | 
   177 		    	end
 | 
| 
Zerotorescue@1
 | 
   178 		    	
 | 
| 
Zerotorescue@1
 | 
   179 		    	local func = this:GetUserData("exec");
 | 
| 
Zerotorescue@1
 | 
   180 		    	local itemId = this:GetUserData("itemId");
 | 
| 
Zerotorescue@1
 | 
   181 		    	
 | 
| 
Zerotorescue@1
 | 
   182 		    	if func then
 | 
| 
Zerotorescue@1
 | 
   183 		    		-- If this is a config option we will need the group id
 | 
| 
Zerotorescue@1
 | 
   184 		    		local path = this:GetUserData("path");
 | 
| 
Zerotorescue@1
 | 
   185 		    		local groupId = (path and path[2]) or nil;
 | 
| 
Zerotorescue@1
 | 
   186 		    		
 | 
| 
Zerotorescue@1
 | 
   187 		    		func(groupId, itemId);
 | 
| 
Zerotorescue@1
 | 
   188 		    	end
 | 
| 
Zerotorescue@1
 | 
   189 		    end);
 | 
| 
Zerotorescue@1
 | 
   190 		    
 | 
| 
Zerotorescue@1
 | 
   191 		    
 | 
| 
Zerotorescue@1
 | 
   192 		    
 | 
| 
Zerotorescue@1
 | 
   193 		    -- Then also do whatever it wanted to do
 | 
| 
Zerotorescue@1
 | 
   194 		    self.originalOnAcquire(self, ...);
 | 
| 
Zerotorescue@1
 | 
   195 	    end;
 | 
| 
Zerotorescue@1
 | 
   196 	    
 | 
| 
Zerotorescue@1
 | 
   197 	    -- Remember the original SetText as this might get overwritten by the config-widget
 | 
| 
Zerotorescue@1
 | 
   198 	    widget.originalSetText = widget.SetText;
 | 
| 
Zerotorescue@1
 | 
   199 	    
 | 
| 
Zerotorescue@1
 | 
   200 	    widget.SetItemId = function(self, itemId)
 | 
| 
Zerotorescue@1
 | 
   201  		   	self:SetUserData("itemId", itemId);
 | 
| 
Zerotorescue@1
 | 
   202  		   	
 | 
| 
Zerotorescue@1
 | 
   203 	   		-- Put the icon in front of it
 | 
| 
Zerotorescue@1
 | 
   204 			self:SetImage(GetItemIcon(itemId));
 | 
| 
Zerotorescue@0
 | 
   205 			-- Standardize the size
 | 
| 
Zerotorescue@0
 | 
   206 			self:SetImageSize(16, 16);
 | 
| 
Zerotorescue@0
 | 
   207     		
 | 
| 
Zerotorescue@0
 | 
   208 			-- Make readable font
 | 
| 
Zerotorescue@0
 | 
   209     		self:SetFontObject(GameFontHighlight);
 | 
| 
Zerotorescue@0
 | 
   210     		
 | 
| 
Zerotorescue@0
 | 
   211     		-- We don't want to set the itemId as text, but rather the item link, so get that.
 | 
| 
Zerotorescue@1
 | 
   212     		local itemLink = select(2, GetItemInfo(itemId)) or ("Unknown (#%d)"):format(itemId);
 | 
| 
Zerotorescue@0
 | 
   213     		
 | 
| 
Zerotorescue@1
 | 
   214     		self:originalSetText(itemLink);
 | 
| 
Zerotorescue@1
 | 
   215 	    end;
 | 
| 
Zerotorescue@1
 | 
   216 		
 | 
| 
Zerotorescue@1
 | 
   217 		return widget;
 | 
| 
Zerotorescue@0
 | 
   218 	end
 | 
| 
Zerotorescue@1
 | 
   219     
 | 
| 
Zerotorescue@1
 | 
   220 	AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion);
 | 
| 
Zerotorescue@1
 | 
   221 end
 | 
| 
Zerotorescue@1
 | 
   222 
 | 
| 
Zerotorescue@1
 | 
   223 function addon:MakeConfigItemLinkButtonWidget()
 | 
| 
Zerotorescue@1
 | 
   224 	-- Define out custom item link button widget
 | 
| 
Zerotorescue@1
 | 
   225 	-- 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
 | 
   226 	
 | 
| 
Zerotorescue@1
 | 
   227 	local widgetType = "ConfigItemLinkButton";
 | 
| 
Zerotorescue@1
 | 
   228 	local widgetVersion = 1;
 | 
| 
Zerotorescue@0
 | 
   229 	
 | 
| 
Zerotorescue@1
 | 
   230 	-- Empty function for disabling functions
 | 
| 
Zerotorescue@1
 | 
   231 	local function Dummy() end
 | 
| 
Zerotorescue@0
 | 
   232 	
 | 
| 
Zerotorescue@0
 | 
   233 	-- Makes an instance of our ItemLinkButton widget
 | 
| 
Zerotorescue@0
 | 
   234 	local function GetItemLinkButton()
 | 
| 
Zerotorescue@1
 | 
   235 	    local widget = AceGUI:Create("ItemLinkButton");
 | 
| 
Zerotorescue@0
 | 
   236 	    widget.type = widgetType;
 | 
| 
Zerotorescue@0
 | 
   237 	    
 | 
| 
Zerotorescue@0
 | 
   238 	    -- We can only provide custom widgets for input, select and multiselect fields
 | 
| 
Zerotorescue@0
 | 
   239 	    -- Input being the simplest, we use that - however, it provides two parameters: label and text. We only need one, disable the other.
 | 
| 
Zerotorescue@0
 | 
   240 	    widget.SetLabel = Dummy;
 | 
| 
Zerotorescue@0
 | 
   241 	    
 | 
| 
Zerotorescue@1
 | 
   242 	    -- SetText is called when this button is being created and contains the itemId
 | 
| 
Zerotorescue@1
 | 
   243 	    -- Forward that itemId to the ItemLinkButton
 | 
| 
Zerotorescue@1
 | 
   244 	    widget.SetText = function(self, value, ...)
 | 
| 
Zerotorescue@1
 | 
   245 	    	if value and tonumber(value) then
 | 
| 
Zerotorescue@1
 | 
   246 	    		self:SetItemId(tonumber(value));
 | 
| 
Zerotorescue@1
 | 
   247 	    	end
 | 
| 
Zerotorescue@1
 | 
   248 		end;
 | 
| 
Zerotorescue@1
 | 
   249 		
 | 
| 
Zerotorescue@1
 | 
   250 		widget.OnClick = function(self, ...)
 | 
| 
Zerotorescue@1
 | 
   251 			local option = self:GetUserData("option");
 | 
| 
Zerotorescue@1
 | 
   252 	    	
 | 
| 
Zerotorescue@1
 | 
   253 	    	if option and option.set then
 | 
| 
Zerotorescue@1
 | 
   254 				self:SetUserData("exec", option.set);
 | 
| 
Zerotorescue@1
 | 
   255 			end
 | 
| 
Zerotorescue@1
 | 
   256 		end;
 | 
| 
Zerotorescue@0
 | 
   257 	    
 | 
| 
Zerotorescue@0
 | 
   258 	    return widget;
 | 
| 
Zerotorescue@0
 | 
   259 	end
 | 
| 
Zerotorescue@0
 | 
   260     
 | 
| 
Zerotorescue@0
 | 
   261 	AceGUI:RegisterWidgetType(widgetType, GetItemLinkButton, widgetVersion);
 | 
| 
Zerotorescue@0
 | 
   262 end
 | 
| 
Zerotorescue@0
 | 
   263 
 | 
| 
Zerotorescue@0
 | 
   264 function addon:CommandHandler(message)
 | 
| 
Zerotorescue@0
 | 
   265 	local cmd, arg = string.split(" ", (message or ""), 2);
 | 
| 
Zerotorescue@0
 | 
   266 	cmd = string.lower(cmd);
 | 
| 
Zerotorescue@0
 | 
   267 	
 | 
| 
Zerotorescue@0
 | 
   268 	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
 | 
   269 		-- We don't want any other windows open at this time.
 | 
| 
Zerotorescue@9
 | 
   270 		for name, module in self:IterateModules() do
 | 
| 
Zerotorescue@9
 | 
   271 			if module.CloseFrame then
 | 
| 
Zerotorescue@9
 | 
   272 				module:CloseFrame();
 | 
| 
Zerotorescue@9
 | 
   273 			end
 | 
| 
Zerotorescue@9
 | 
   274 		end
 | 
| 
Zerotorescue@9
 | 
   275 		
 | 
| 
Zerotorescue@0
 | 
   276 		self:Show();
 | 
| 
Zerotorescue@0
 | 
   277 	elseif cmd == "d" or cmd == "debug" then
 | 
| 
Zerotorescue@0
 | 
   278 		self.debugChannel = false;
 | 
| 
Zerotorescue@0
 | 
   279 		for i = 1, NUM_CHAT_WINDOWS do
 | 
| 
Zerotorescue@0
 | 
   280 			local name = GetChatWindowInfo(i);
 | 
| 
Zerotorescue@0
 | 
   281 			
 | 
| 
Zerotorescue@0
 | 
   282 			if name:upper() == "DEBUG" then
 | 
| 
Zerotorescue@0
 | 
   283 				self.debugChannel = _G["ChatFrame" .. i];
 | 
| 
Zerotorescue@0
 | 
   284 			
 | 
| 
Zerotorescue@0
 | 
   285 				print("A debug channel already exists, used the old one. (" .. i .. ")");
 | 
| 
Zerotorescue@0
 | 
   286 				return;
 | 
| 
Zerotorescue@0
 | 
   287 			end
 | 
| 
Zerotorescue@0
 | 
   288 		end
 | 
| 
Zerotorescue@0
 | 
   289 		
 | 
| 
Zerotorescue@0
 | 
   290 		if not self.debugChannel then
 | 
| 
Zerotorescue@0
 | 
   291 			-- Create a new debug channel
 | 
| 
Zerotorescue@0
 | 
   292 			local chatFrame = FCF_OpenNewWindow('Debug');
 | 
| 
Zerotorescue@0
 | 
   293 			ChatFrame_RemoveAllMessageGroups(chatFrame);
 | 
| 
Zerotorescue@0
 | 
   294 			self.debugChannel = chatFrame;
 | 
| 
Zerotorescue@0
 | 
   295 			
 | 
| 
Zerotorescue@0
 | 
   296 			print("New debug channel created.");
 | 
| 
Zerotorescue@0
 | 
   297 		end
 | 
| 
Zerotorescue@1
 | 
   298 	elseif slashArgs[cmd] then
 | 
| 
Zerotorescue@1
 | 
   299 		slashArgs[cmd]();
 | 
| 
Zerotorescue@0
 | 
   300 	else
 | 
| 
Zerotorescue@9
 | 
   301 		print("Wrong command, available: /inventory config (or /iy c) and /inventory summary (or /iy s)");
 | 
| 
Zerotorescue@0
 | 
   302 	end
 | 
| 
Zerotorescue@0
 | 
   303 end
 | 
| 
Zerotorescue@0
 | 
   304 
 | 
| 
Zerotorescue@0
 | 
   305 function addon:Load()
 | 
| 
Zerotorescue@0
 | 
   306 	if not AceConfigDialog and not AceConfigRegistry then
 | 
| 
Zerotorescue@0
 | 
   307 		self:FillOptions();
 | 
| 
Zerotorescue@0
 | 
   308 	
 | 
| 
Zerotorescue@0
 | 
   309 		-- Build options dialog
 | 
| 
Zerotorescue@0
 | 
   310 		AceConfigDialog = LibStub("AceConfigDialog-3.0");
 | 
| 
Zerotorescue@0
 | 
   311 		AceConfigRegistry = LibStub("AceConfigRegistry-3.0");
 | 
| 
Zerotorescue@0
 | 
   312 		-- Register options table
 | 
| 
Zerotorescue@0
 | 
   313 		LibStub("AceConfig-3.0"):RegisterOptionsTable("InventoryOptions", options);
 | 
| 
Zerotorescue@0
 | 
   314 		-- Set a nice default size (so that 4 normal sized elements fit next to eachother)
 | 
| 
Zerotorescue@0
 | 
   315 		AceConfigDialog:SetDefaultSize("InventoryOptions", 975, 600);
 | 
| 
Zerotorescue@0
 | 
   316 		
 | 
| 
Zerotorescue@0
 | 
   317 		 -- In case the addon is loaded from another condition, always call the remove interface options
 | 
| 
Zerotorescue@0
 | 
   318 		if AddonLoader and AddonLoader.RemoveInterfaceOptions then
 | 
| 
Zerotorescue@0
 | 
   319 			AddonLoader:RemoveInterfaceOptions("Inventory");
 | 
| 
Zerotorescue@0
 | 
   320 		end
 | 
| 
Zerotorescue@0
 | 
   321 		
 | 
| 
Zerotorescue@0
 | 
   322 		-- Add to the blizzard addons options thing
 | 
| 
Zerotorescue@0
 | 
   323 		--AceConfigDialog:AddToBlizOptions("InventoryOptions");
 | 
| 
Zerotorescue@0
 | 
   324 	end
 | 
| 
Zerotorescue@0
 | 
   325 end
 | 
| 
Zerotorescue@0
 | 
   326 
 | 
| 
Zerotorescue@0
 | 
   327 function addon:Show()
 | 
| 
Zerotorescue@0
 | 
   328 	self:Load();
 | 
| 
Zerotorescue@0
 | 
   329 	
 | 
| 
Zerotorescue@0
 | 
   330 	AceConfigDialog:Open("InventoryOptions");
 | 
| 
Zerotorescue@0
 | 
   331 end
 | 
| 
Zerotorescue@0
 | 
   332 
 | 
| 
Zerotorescue@0
 | 
   333 function addon:FillOptions()
 | 
| 
Zerotorescue@0
 | 
   334 	options = {
 | 
| 
Zerotorescue@0
 | 
   335 		type = "group",	
 | 
| 
Zerotorescue@0
 | 
   336 		name = "Inventory",
 | 
| 
Zerotorescue@0
 | 
   337 		childGroups = "tree",
 | 
| 
Zerotorescue@0
 | 
   338 		args = {
 | 
| 
Zerotorescue@0
 | 
   339 		},
 | 
| 
Zerotorescue@0
 | 
   340 	};
 | 
| 
Zerotorescue@0
 | 
   341 	
 | 
| 
Zerotorescue@0
 | 
   342 	self:FillGeneralOptions();
 | 
| 
Zerotorescue@0
 | 
   343 	
 | 
| 
Zerotorescue@0
 | 
   344 	options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db, true);
 | 
| 
Zerotorescue@0
 | 
   345 	options.args.profiles.order = 200;
 | 
| 
Zerotorescue@0
 | 
   346 	
 | 
| 
Zerotorescue@0
 | 
   347 	self:MakeGroupOptions();
 | 
| 
Zerotorescue@0
 | 
   348 	
 | 
| 
Zerotorescue@0
 | 
   349 	self:FillGroupOptions();
 | 
| 
Zerotorescue@0
 | 
   350 end
 | 
| 
Zerotorescue@0
 | 
   351 
 | 
| 
Zerotorescue@1
 | 
   352 local goldText = "%s%d|cffffd700g|r ";
 | 
| 
Zerotorescue@1
 | 
   353 local silverText = "%s%d|cffc7c7cfs|r ";
 | 
| 
Zerotorescue@1
 | 
   354 local copperText = "%s%d|cffeda55fc|r";
 | 
| 
Zerotorescue@1
 | 
   355 
 | 
| 
Zerotorescue@1
 | 
   356 function addon:ReadableMoney(copper, clean)
 | 
| 
Zerotorescue@1
 | 
   357 	local text = "";
 | 
| 
Zerotorescue@1
 | 
   358 	
 | 
| 
Zerotorescue@1
 | 
   359 	local gold = floor( copper / COPPER_PER_GOLD );
 | 
| 
Zerotorescue@1
 | 
   360 	if gold > 0 then
 | 
| 
Zerotorescue@1
 | 
   361 		text = goldText:format(text, gold);
 | 
| 
Zerotorescue@1
 | 
   362 	end
 | 
| 
Zerotorescue@1
 | 
   363 	
 | 
| 
Zerotorescue@1
 | 
   364 	if not clean or (not gold or gold < 100) then
 | 
| 
Zerotorescue@1
 | 
   365 		local silver = floor( ( copper % COPPER_PER_GOLD ) / COPPER_PER_SILVER );
 | 
| 
Zerotorescue@1
 | 
   366 		if silver > 0 then
 | 
| 
Zerotorescue@1
 | 
   367 			text = silverText:format(text, silver);
 | 
| 
Zerotorescue@1
 | 
   368 		end
 | 
| 
Zerotorescue@1
 | 
   369 		
 | 
| 
Zerotorescue@1
 | 
   370 		if not clean or (not gold or gold < 10) then
 | 
| 
Zerotorescue@1
 | 
   371 			local copper = floor( copper % COPPER_PER_SILVER );
 | 
| 
Zerotorescue@1
 | 
   372 			if copper > 0 or text == "" then
 | 
| 
Zerotorescue@1
 | 
   373 				text = copperText:format(text, copper);
 | 
| 
Zerotorescue@1
 | 
   374 			end
 | 
| 
Zerotorescue@1
 | 
   375 		end
 | 
| 
Zerotorescue@1
 | 
   376 	end
 | 
| 
Zerotorescue@1
 | 
   377 	
 | 
| 
Zerotorescue@1
 | 
   378 	
 | 
| 
Zerotorescue@1
 | 
   379 	return string.trim(text);
 | 
| 
Zerotorescue@1
 | 
   380 end
 | 
| 
Zerotorescue@1
 | 
   381 
 | 
| 
Zerotorescue@1
 | 
   382 function addon:ReadableMoneyToCopper(value)
 | 
| 
Zerotorescue@1
 | 
   383 	-- If a player enters a value it will be filled without color codes
 | 
| 
Zerotorescue@1
 | 
   384 	-- If it is retrieved from the database, it will be colored coded
 | 
| 
Zerotorescue@1
 | 
   385 	-- Thus we look for both
 | 
| 
Zerotorescue@1
 | 
   386 	local gold = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+g|r") or string.match(value, "(%d+)g"));
 | 
| 
Zerotorescue@1
 | 
   387 	local silver = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+s|r") or string.match(value, "(%d+)s"));
 | 
| 
Zerotorescue@1
 | 
   388 	local copper = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+c|r") or string.match(value, "(%d+)c"));
 | 
| 
Zerotorescue@1
 | 
   389 		
 | 
| 
Zerotorescue@1
 | 
   390 	return ( (gold or 0) * COPPER_PER_GOLD ) + ( (silver or 0) * COPPER_PER_SILVER ) + (copper or 0);
 | 
| 
Zerotorescue@1
 | 
   391 end
 | 
| 
Zerotorescue@1
 | 
   392 
 | 
| 
Zerotorescue@1
 | 
   393 function addon:ValidateReadableMoney(info, value)
 | 
| 
Zerotorescue@1
 | 
   394 	-- If a player enters a value it will be filled without color codes
 | 
| 
Zerotorescue@1
 | 
   395 	-- If it is retrieved from the database, it will be colored coded
 | 
| 
Zerotorescue@1
 | 
   396 	-- Thus we look for both
 | 
| 
Zerotorescue@1
 | 
   397 	local gold = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+g|r") or string.match(value, "(%d+)g"));
 | 
| 
Zerotorescue@1
 | 
   398 	local silver = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+s|r") or string.match(value, "(%d+)s"));
 | 
| 
Zerotorescue@1
 | 
   399 	local copper = tonumber(string.match(value, "(%d+)|c[a-fA-F0-9]+c|r") or string.match(value, "(%d+)c"));
 | 
| 
Zerotorescue@1
 | 
   400 	
 | 
| 
Zerotorescue@1
 | 
   401 	if not gold and not silver and not copper then
 | 
| 
Zerotorescue@1
 | 
   402 		return "The provided amount of money is invalid. Please provide the amount of money as #g#s#c, e.g. 591617g24s43c.";
 | 
| 
Zerotorescue@1
 | 
   403 	else
 | 
| 
Zerotorescue@1
 | 
   404 		return true;
 | 
| 
Zerotorescue@1
 | 
   405 	end
 | 
| 
Zerotorescue@1
 | 
   406 end
 | 
| 
Zerotorescue@1
 | 
   407 
 | 
| 
Zerotorescue@0
 | 
   408 function addon:FillGeneralOptions()
 | 
| 
Zerotorescue@0
 | 
   409 	options.args.general = {
 | 
| 
Zerotorescue@0
 | 
   410 		order = 100,
 | 
| 
Zerotorescue@0
 | 
   411 		type = "group",
 | 
| 
Zerotorescue@0
 | 
   412 		name = "General",
 | 
| 
Zerotorescue@0
 | 
   413 		desc = "Change general Inventory settings.",
 | 
| 
Zerotorescue@0
 | 
   414 		args = {
 | 
| 
Zerotorescue@0
 | 
   415 			general = {
 | 
| 
Zerotorescue@0
 | 
   416 				order = 0,
 | 
| 
Zerotorescue@0
 | 
   417 				type = "group",
 | 
| 
Zerotorescue@0
 | 
   418 				inline = true,
 | 
| 
Zerotorescue@0
 | 
   419 				name = "General",
 | 
| 
Zerotorescue@0
 | 
   420 				args = {
 | 
| 
Zerotorescue@0
 | 
   421 					description = {
 | 
| 
Zerotorescue@0
 | 
   422 						order = 0,
 | 
| 
Zerotorescue@0
 | 
   423 						type = "description",
 | 
| 
Zerotorescue@0
 | 
   424 						name = "Change general settings unrelated to groups.",
 | 
| 
Zerotorescue@0
 | 
   425 					},
 | 
| 
Zerotorescue@0
 | 
   426 					header = {
 | 
| 
Zerotorescue@0
 | 
   427 						order = 5,
 | 
| 
Zerotorescue@0
 | 
   428 						type = "header",
 | 
| 
Zerotorescue@0
 | 
   429 						name = "",
 | 
| 
Zerotorescue@0
 | 
   430 					},
 | 
| 
Zerotorescue@0
 | 
   431 					auctionAddon = {
 | 
| 
Zerotorescue@0
 | 
   432 						order = 10,
 | 
| 
Zerotorescue@0
 | 
   433 						type = "select",
 | 
| 
Zerotorescue@0
 | 
   434 						name = "Prefered pricing addon",
 | 
| 
Zerotorescue@0
 | 
   435 						values = {
 | 
| 
Zerotorescue@0
 | 
   436 							Auctioneer = "Auctioneer",
 | 
| 
Zerotorescue@0
 | 
   437 							Auctionator = "Auctionator",
 | 
| 
Zerotorescue@0
 | 
   438 						},
 | 
| 
Zerotorescue@0
 | 
   439 						get = function() end,
 | 
| 
Zerotorescue@0
 | 
   440 						set = function(i, v) end,
 | 
| 
Zerotorescue@0
 | 
   441 					},
 | 
| 
Zerotorescue@0
 | 
   442 					itemCountAddon = {
 | 
| 
Zerotorescue@0
 | 
   443 						order = 20,
 | 
| 
Zerotorescue@0
 | 
   444 						type = "select",
 | 
| 
Zerotorescue@0
 | 
   445 						name = "Prefered item count addon",
 | 
| 
Zerotorescue@0
 | 
   446 						values = {
 | 
| 
Zerotorescue@0
 | 
   447 							Altoholic = "Altoholic",
 | 
| 
Zerotorescue@0
 | 
   448 							DataStore = "DataStore",
 | 
| 
Zerotorescue@0
 | 
   449 							ItemCount = "ItemCount",
 | 
| 
Zerotorescue@0
 | 
   450 						},
 | 
| 
Zerotorescue@0
 | 
   451 						get = function() end,
 | 
| 
Zerotorescue@0
 | 
   452 						set = function(i, v) end,
 | 
| 
Zerotorescue@0
 | 
   453 					},
 | 
| 
Zerotorescue@0
 | 
   454 				},
 | 
| 
Zerotorescue@0
 | 
   455 			},
 | 
| 
Zerotorescue@0
 | 
   456 			minimumStock = {
 | 
| 
Zerotorescue@0
 | 
   457 				order = 10,
 | 
| 
Zerotorescue@0
 | 
   458 				type = "group",
 | 
| 
Zerotorescue@0
 | 
   459 				inline = true,
 | 
| 
Zerotorescue@0
 | 
   460 				name = "Minimum stock",
 | 
| 
Zerotorescue@0
 | 
   461 				args = {
 | 
| 
Zerotorescue@0
 | 
   462 					description = {
 | 
| 
Zerotorescue@0
 | 
   463 						order = 0,
 | 
| 
Zerotorescue@0
 | 
   464 						type = "description",
 | 
| 
Zerotorescue@0
 | 
   465 						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
 | 
   466 					},
 | 
| 
Zerotorescue@0
 | 
   467 					header = {
 | 
| 
Zerotorescue@0
 | 
   468 						order = 5,
 | 
| 
Zerotorescue@0
 | 
   469 						type = "header",
 | 
| 
Zerotorescue@0
 | 
   470 						name = "",
 | 
| 
Zerotorescue@0
 | 
   471 					},
 | 
| 
Zerotorescue@0
 | 
   472 					minimumStock = {
 | 
| 
Zerotorescue@0
 | 
   473 						order = 10,
 | 
| 
Zerotorescue@0
 | 
   474 						type = "range",
 | 
| 
Zerotorescue@0
 | 
   475 						min = 0,
 | 
| 
Zerotorescue@0
 | 
   476 						max = 100000,
 | 
| 
Zerotorescue@0
 | 
   477 						softMax = 1000,
 | 
| 
Zerotorescue@0
 | 
   478 						step = 1,
 | 
| 
Zerotorescue@0
 | 
   479 						name = "Minimum stock",
 | 
| 
Zerotorescue@0
 | 
   480 						desc = "You can manually enter a value between 1.000 and 100.000 in the edit box if the provided range is insufficient.",
 | 
| 
Zerotorescue@0
 | 
   481 						get = function() return self.db.global.defaults.minimumStock; end,
 | 
| 
Zerotorescue@0
 | 
   482 						set = function(i, v) self.db.global.defaults.minimumStock = v; end,
 | 
| 
Zerotorescue@0
 | 
   483 					},
 | 
| 
Zerotorescue@0
 | 
   484 					summaryThresholdShow = {
 | 
| 
Zerotorescue@0
 | 
   485 						order = 20,
 | 
| 
Zerotorescue@0
 | 
   486 						type = "range",
 | 
| 
Zerotorescue@0
 | 
   487 						min = 0,
 | 
| 
Zerotorescue@0
 | 
   488 						max = 100,
 | 
| 
Zerotorescue@0
 | 
   489 						softMax = 10,
 | 
| 
Zerotorescue@0
 | 
   490 						step = 0.05,
 | 
| 
Zerotorescue@0
 | 
   491 						isPercent = true,
 | 
| 
Zerotorescue@0
 | 
   492 						name = "Show in summary when below",
 | 
| 
Zerotorescue@0
 | 
   493 						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
 | 
   494 						get = function() return self.db.global.defaults.summaryThresholdShow; end,
 | 
| 
Zerotorescue@0
 | 
   495 						set = function(i, v) self.db.global.defaults.summaryThresholdShow = v; end,
 | 
| 
Zerotorescue@0
 | 
   496 					},
 | 
| 
Zerotorescue@0
 | 
   497 					alertBelowMinimum = {
 | 
| 
Zerotorescue@0
 | 
   498 						order = 30,
 | 
| 
Zerotorescue@0
 | 
   499 						type = "toggle",
 | 
| 
Zerotorescue@0
 | 
   500 						name = "Alert when below minimum",
 | 
| 
Zerotorescue@0
 | 
   501 						desc = "Show an alert when this item gets below this threshold.",
 | 
| 
Zerotorescue@0
 | 
   502 						get = function() return self.db.global.defaults.alertBelowMinimum; end,
 | 
| 
Zerotorescue@0
 | 
   503 						set = function(i, v) self.db.global.defaults.alertBelowMinimum = v; end,
 | 
| 
Zerotorescue@0
 | 
   504 					},
 | 
| 
Zerotorescue@0
 | 
   505 					trackAtCharacters = {
 | 
| 
Zerotorescue@0
 | 
   506 						order = 40,
 | 
| 
Zerotorescue@0
 | 
   507 						type = "multiselect",
 | 
| 
Zerotorescue@0
 | 
   508 						name = "Track at",
 | 
| 
Zerotorescue@0
 | 
   509 						desc = "Select at which characters this should appear in the summary and generate alerts.",
 | 
| 
Zerotorescue@0
 | 
   510 						values = function()
 | 
| 
Zerotorescue@0
 | 
   511 							local temp = {};
 | 
| 
Zerotorescue@0
 | 
   512 							for charName in pairs(self.db.factionrealm.characters) do
 | 
| 
Zerotorescue@0
 | 
   513 								temp[charName] = charName;
 | 
| 
Zerotorescue@0
 | 
   514 							end
 | 
| 
Zerotorescue@0
 | 
   515 							
 | 
| 
Zerotorescue@0
 | 
   516 							return temp;
 | 
| 
Zerotorescue@0
 | 
   517 						end,
 | 
| 
Zerotorescue@1
 | 
   518 						get = function(i, v) return self.db.global.defaults.trackAtCharacters[v]; end,
 | 
| 
Zerotorescue@0
 | 
   519 						set = function(i, v, e)
 | 
| 
Zerotorescue@0
 | 
   520 							self.db.global.defaults.trackAtCharacters[v] = e or nil;
 | 
| 
Zerotorescue@1
 | 
   521 							
 | 
| 
Zerotorescue@1
 | 
   522 							-- We MUST close this pullout or we can get errors or even game client crashes once we click another group or close the config dialog!
 | 
| 
Zerotorescue@1
 | 
   523 							local count = AceGUI:GetNextWidgetNum("Dropdown-Pullout");
 | 
| 
Zerotorescue@7
 | 
   524 							for i = 1, count do
 | 
| 
Zerotorescue@1
 | 
   525 								if _G['AceGUI30Pullout' .. i] then
 | 
| 
Zerotorescue@1
 | 
   526 									_G['AceGUI30Pullout' .. i]:Hide();
 | 
| 
Zerotorescue@1
 | 
   527 								end
 | 
| 
Zerotorescue@1
 | 
   528 							end
 | 
| 
Zerotorescue@0
 | 
   529 						end,
 | 
| 
Zerotorescue@10
 | 
   530 						confirm = true,
 | 
| 
Zerotorescue@1
 | 
   531 						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
 | 
   532 					},
 | 
| 
Zerotorescue@0
 | 
   533 				},
 | 
| 
Zerotorescue@0
 | 
   534 			},
 | 
| 
Zerotorescue@0
 | 
   535 			refill = {
 | 
| 
Zerotorescue@0
 | 
   536 				order = 20,
 | 
| 
Zerotorescue@0
 | 
   537 				type = "group",
 | 
| 
Zerotorescue@0
 | 
   538 				inline = true,
 | 
| 
Zerotorescue@0
 | 
   539 				name = "Replenishing stock",
 | 
| 
Zerotorescue@0
 | 
   540 				args = {
 | 
| 
Zerotorescue@0
 | 
   541 					description = {
 | 
| 
Zerotorescue@0
 | 
   542 						order = 0,
 | 
| 
Zerotorescue@0
 | 
   543 						type = "description",
 | 
| 
Zerotorescue@0
 | 
   544 						name = function()
 | 
| 
Zerotorescue@0
 | 
   545 							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
 | 
   546 							
 | 
| 
Zerotorescue@0
 | 
   547 							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
 | 
   548 							
 | 
| 
Zerotorescue@0
 | 
   549 							return r;
 | 
| 
Zerotorescue@0
 | 
   550 						end,
 | 
| 
Zerotorescue@0
 | 
   551 					},
 | 
| 
Zerotorescue@0
 | 
   552 					header = {
 | 
| 
Zerotorescue@0
 | 
   553 						order = 5,
 | 
| 
Zerotorescue@0
 | 
   554 						type = "header",
 | 
| 
Zerotorescue@0
 | 
   555 						name = "",
 | 
| 
Zerotorescue@0
 | 
   556 					},
 | 
| 
Zerotorescue@0
 | 
   557 					restockTarget = {
 | 
| 
Zerotorescue@0
 | 
   558 						order = 10,
 | 
| 
Zerotorescue@0
 | 
   559 						type = "range",
 | 
| 
Zerotorescue@0
 | 
   560 						min = 0,
 | 
| 
Zerotorescue@0
 | 
   561 						max = 100000,
 | 
| 
Zerotorescue@0
 | 
   562 						softMax = 1000,
 | 
| 
Zerotorescue@0
 | 
   563 						step = 1,
 | 
| 
Zerotorescue@0
 | 
   564 						name = "Restock target",
 | 
| 
Zerotorescue@0
 | 
   565 						desc = "You can manually enter a value between 1.000 and 100.000 in the edit box if the provided range is insufficient.",
 | 
| 
Zerotorescue@0
 | 
   566 						get = function() return self.db.global.defaults.restockTarget; end,
 | 
| 
Zerotorescue@0
 | 
   567 						set = function(i, v) self.db.global.defaults.restockTarget = v; end,
 | 
| 
Zerotorescue@0
 | 
   568 					},
 | 
| 
Zerotorescue@0
 | 
   569 					minCraftingQueue = {
 | 
| 
Zerotorescue@0
 | 
   570 						order = 20,
 | 
| 
Zerotorescue@0
 | 
   571 						type = "range",
 | 
| 
Zerotorescue@0
 | 
   572 						min = 0,
 | 
| 
Zerotorescue@0
 | 
   573 						max = 1,
 | 
| 
Zerotorescue@0
 | 
   574 						step = 0.01, -- 1%
 | 
| 
Zerotorescue@0
 | 
   575 						isPercent = true,
 | 
| 
Zerotorescue@0
 | 
   576 						name = "Don't queue if I only miss",
 | 
| 
Zerotorescue@0
 | 
   577 						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
 | 
   578 						get = function() return self.db.global.defaults.minCraftingQueue; end,
 | 
| 
Zerotorescue@0
 | 
   579 						set = function(i, v) self.db.global.defaults.minCraftingQueue = v; end,
 | 
| 
Zerotorescue@0
 | 
   580 					},
 | 
| 
Zerotorescue@0
 | 
   581 					bonusQueue = {
 | 
| 
Zerotorescue@0
 | 
   582 						order = 30,
 | 
| 
Zerotorescue@0
 | 
   583 						type = "range",
 | 
| 
Zerotorescue@0
 | 
   584 						min = 0,
 | 
| 
Zerotorescue@0
 | 
   585 						max = 10, -- 1000%
 | 
| 
Zerotorescue@0
 | 
   586 						step = 0.01, -- 1%
 | 
| 
Zerotorescue@0
 | 
   587 						isPercent = true,
 | 
| 
Zerotorescue@0
 | 
   588 						name = "Bonus queue",
 | 
| 
Zerotorescue@1
 | 
   589 						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
 | 
   590 						get = function() return self.db.global.defaults.bonusQueue; end,
 | 
| 
Zerotorescue@0
 | 
   591 						set = function(i, v) self.db.global.defaults.bonusQueue = v; end,
 | 
| 
Zerotorescue@0
 | 
   592 					},
 | 
| 
Zerotorescue@0
 | 
   593 					priceThreshold = {
 | 
| 
Zerotorescue@0
 | 
   594 						order = 40,
 | 
| 
Zerotorescue@0
 | 
   595 						type = "input",
 | 
| 
Zerotorescue@0
 | 
   596 						name = "Price threshold",
 | 
| 
Zerotorescue@1
 | 
   597 						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
 | 
   598 						validate = function(info, value) return self:ValidateReadableMoney(info, value); end,
 | 
| 
Zerotorescue@1
 | 
   599 						get = function() return self:ReadableMoney(self.db.global.defaults.priceThreshold); end,
 | 
| 
Zerotorescue@1
 | 
   600 						set = function(i, v) self.db.global.defaults.priceThreshold = self:ReadableMoneyToCopper(v); end,
 | 
| 
Zerotorescue@0
 | 
   601 					},
 | 
| 
Zerotorescue@1
 | 
   602 					hideFromSummaryWhenBelowPriceThreshold = { -- I wish this var could be a little bit shorter...
 | 
| 
Zerotorescue@0
 | 
   603 						order = 50,
 | 
| 
Zerotorescue@0
 | 
   604 						type = "toggle",
 | 
| 
Zerotorescue@1
 | 
   605 						name = "Hide when below threshold",
 | 
| 
Zerotorescue@0
 | 
   606 						desc = "Hide items from the summary when their value is below the set price threshold.",
 | 
| 
Zerotorescue@1
 | 
   607 						get = function() return self.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold; end,
 | 
| 
Zerotorescue@1
 | 
   608 						set = function(i, v) self.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold = v; end,
 | 
| 
Zerotorescue@0
 | 
   609 					},
 | 
| 
Zerotorescue@0
 | 
   610 				},
 | 
| 
Zerotorescue@0
 | 
   611 			},
 | 
| 
Zerotorescue@0
 | 
   612 			colorCodes = {
 | 
| 
Zerotorescue@0
 | 
   613 				order = 30,
 | 
| 
Zerotorescue@0
 | 
   614 				type = "group",
 | 
| 
Zerotorescue@0
 | 
   615 				inline = true,
 | 
| 
Zerotorescue@0
 | 
   616 				name = "Color codes",
 | 
| 
Zerotorescue@0
 | 
   617 				args = {
 | 
| 
Zerotorescue@0
 | 
   618 					description = {
 | 
| 
Zerotorescue@0
 | 
   619 						order = 0,
 | 
| 
Zerotorescue@0
 | 
   620 						type = "description",
 | 
| 
Zerotorescue@0
 | 
   621 						name = "Change the color code thresholds based on the current stock remaining of the required minimum stock.",
 | 
| 
Zerotorescue@0
 | 
   622 					},
 | 
| 
Zerotorescue@0
 | 
   623 					header = {
 | 
| 
Zerotorescue@0
 | 
   624 						order = 5,
 | 
| 
Zerotorescue@0
 | 
   625 						type = "header",
 | 
| 
Zerotorescue@0
 | 
   626 						name = "",
 | 
| 
Zerotorescue@0
 | 
   627 					},
 | 
| 
Zerotorescue@0
 | 
   628 					green = {
 | 
| 
Zerotorescue@0
 | 
   629 						order = 10,
 | 
| 
Zerotorescue@0
 | 
   630 						type = "range",
 | 
| 
Zerotorescue@0
 | 
   631 						min = 0,
 | 
| 
Zerotorescue@0
 | 
   632 						max = 1,
 | 
| 
Zerotorescue@0
 | 
   633 						step = 0.01,
 | 
| 
Zerotorescue@0
 | 
   634 						isPercent = true,
 | 
| 
Zerotorescue@0
 | 
   635 						name = "|cff00ff00Green|r",
 | 
| 
Zerotorescue@0
 | 
   636 						desc = "Show quantity in green when at least this much of the minimum stock is available.",
 | 
| 
Zerotorescue@0
 | 
   637 						get = function() return self.db.global.defaults.colors.green; end,
 | 
| 
Zerotorescue@0
 | 
   638 						set = function(i, v) self.db.global.defaults.colors.green = v; end,
 | 
| 
Zerotorescue@0
 | 
   639 					},
 | 
| 
Zerotorescue@0
 | 
   640 					yellow = {
 | 
| 
Zerotorescue@0
 | 
   641 						order = 20,
 | 
| 
Zerotorescue@0
 | 
   642 						type = "range",
 | 
| 
Zerotorescue@0
 | 
   643 						min = 0,
 | 
| 
Zerotorescue@0
 | 
   644 						max = 1,
 | 
| 
Zerotorescue@0
 | 
   645 						step = 0.01,
 | 
| 
Zerotorescue@0
 | 
   646 						isPercent = true,
 | 
| 
Zerotorescue@0
 | 
   647 						name = "|cffffff00Yellow|r",
 | 
| 
Zerotorescue@0
 | 
   648 						desc = "Show quantity in yellow when at least this much of the minimum stock is available.",
 | 
| 
Zerotorescue@0
 | 
   649 						get = function() return self.db.global.defaults.colors.yellow; end,
 | 
| 
Zerotorescue@0
 | 
   650 						set = function(i, v) self.db.global.defaults.colors.yellow = v; end,
 | 
| 
Zerotorescue@0
 | 
   651 					},
 | 
| 
Zerotorescue@0
 | 
   652 					orange = {
 | 
| 
Zerotorescue@0
 | 
   653 						order = 30,
 | 
| 
Zerotorescue@0
 | 
   654 						type = "range",
 | 
| 
Zerotorescue@0
 | 
   655 						min = 0,
 | 
| 
Zerotorescue@0
 | 
   656 						max = 1,
 | 
| 
Zerotorescue@0
 | 
   657 						step = 0.01,
 | 
| 
Zerotorescue@0
 | 
   658 						isPercent = true,
 | 
| 
Zerotorescue@0
 | 
   659 						name = "|cffff9933Orange|r",
 | 
| 
Zerotorescue@0
 | 
   660 						desc = "Show quantity in orange when at least this much of the minimum stock is available.",
 | 
| 
Zerotorescue@0
 | 
   661 						get = function() return self.db.global.defaults.colors.orange; end,
 | 
| 
Zerotorescue@0
 | 
   662 						set = function(i, v) self.db.global.defaults.colors.orange = v; end,
 | 
| 
Zerotorescue@0
 | 
   663 					},
 | 
| 
Zerotorescue@0
 | 
   664 					red = {
 | 
| 
Zerotorescue@0
 | 
   665 						order = 40,
 | 
| 
Zerotorescue@0
 | 
   666 						type = "range",
 | 
| 
Zerotorescue@0
 | 
   667 						min = 0,
 | 
| 
Zerotorescue@0
 | 
   668 						max = 1,
 | 
| 
Zerotorescue@0
 | 
   669 						step = 0.01,
 | 
| 
Zerotorescue@0
 | 
   670 						isPercent = true,
 | 
| 
Zerotorescue@0
 | 
   671 						name = "|cffff0000Red|r",
 | 
| 
Zerotorescue@0
 | 
   672 						desc = "Show quantity in red when at least this much of the minimum stock is available.",
 | 
| 
Zerotorescue@0
 | 
   673 						get = function() return self.db.global.defaults.colors.red; end,
 | 
| 
Zerotorescue@0
 | 
   674 						set = function(i, v) self.db.global.defaults.colors.red = v; end,
 | 
| 
Zerotorescue@0
 | 
   675 					},
 | 
| 
Zerotorescue@0
 | 
   676 				},
 | 
| 
Zerotorescue@0
 | 
   677 			},
 | 
| 
Zerotorescue@0
 | 
   678 		},
 | 
| 
Zerotorescue@0
 | 
   679 	};
 | 
| 
Zerotorescue@0
 | 
   680 end
 | 
| 
Zerotorescue@0
 | 
   681 
 | 
| 
Zerotorescue@0
 | 
   682 local count = 0;
 | 
| 
Zerotorescue@0
 | 
   683 local temp = {};
 | 
| 
Zerotorescue@0
 | 
   684 
 | 
| 
Zerotorescue@1
 | 
   685 local function SetOption(info, value, multiSelectEnabled)
 | 
| 
Zerotorescue@0
 | 
   686 	local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
   687 	local optionName = info[#info];
 | 
| 
Zerotorescue@0
 | 
   688 	
 | 
| 
Zerotorescue@0
 | 
   689 	-- No need to store a setting if it's disabled (false)
 | 
| 
Zerotorescue@0
 | 
   690 	if not value and info.arg and not info.arg:find("override") then
 | 
| 
Zerotorescue@0
 | 
   691 		value = nil;
 | 
| 
Zerotorescue@0
 | 
   692 		
 | 
| 
Zerotorescue@0
 | 
   693 		-- If this is an override toggler then also set the related field to nil
 | 
| 
Zerotorescue@0
 | 
   694 		addon.db.global.groups[groupName][info.arg] = nil;
 | 
| 
Zerotorescue@0
 | 
   695 	end
 | 
| 
Zerotorescue@0
 | 
   696 	
 | 
| 
Zerotorescue@1
 | 
   697 	if multiSelectEnabled ~= nil then
 | 
| 
Zerotorescue@1
 | 
   698 		-- 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
 | 
   699 		if not addon.db.global.groups[groupName][optionName] then
 | 
| 
Zerotorescue@1
 | 
   700 			addon.db.global.groups[groupName][optionName] = {};
 | 
| 
Zerotorescue@1
 | 
   701 		end
 | 
| 
Zerotorescue@1
 | 
   702 		
 | 
| 
Zerotorescue@1
 | 
   703 		addon.db.global.groups[groupName][optionName][value] = multiSelectEnabled or nil;
 | 
| 
Zerotorescue@1
 | 
   704 	else
 | 
| 
Zerotorescue@1
 | 
   705 		addon.db.global.groups[groupName][optionName] = value;
 | 
| 
Zerotorescue@1
 | 
   706 	end
 | 
| 
Zerotorescue@0
 | 
   707 end
 | 
| 
Zerotorescue@0
 | 
   708 
 | 
| 
Zerotorescue@1
 | 
   709 function addon:GetOptionByKey(groupName, optionName, noDefault)
 | 
| 
Zerotorescue@0
 | 
   710 	if addon.db.global.groups[groupName][optionName] ~= nil then
 | 
| 
Zerotorescue@0
 | 
   711 		return addon.db.global.groups[groupName][optionName];
 | 
| 
Zerotorescue@0
 | 
   712 	elseif addon.db.global.defaults[optionName] and not noDefault then
 | 
| 
Zerotorescue@0
 | 
   713 		return addon.db.global.defaults[optionName];
 | 
| 
Zerotorescue@0
 | 
   714 	else
 | 
| 
Zerotorescue@0
 | 
   715 		return nil;
 | 
| 
Zerotorescue@0
 | 
   716 	end
 | 
| 
Zerotorescue@0
 | 
   717 end
 | 
| 
Zerotorescue@0
 | 
   718 
 | 
| 
Zerotorescue@0
 | 
   719 local function GetOption(info)
 | 
| 
Zerotorescue@0
 | 
   720 	local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
   721 	local optionName = info[#info];
 | 
| 
Zerotorescue@0
 | 
   722 	
 | 
| 
Zerotorescue@1
 | 
   723 	return addon:GetOptionByKey(groupName, optionName);
 | 
| 
Zerotorescue@1
 | 
   724 end
 | 
| 
Zerotorescue@1
 | 
   725 
 | 
| 
Zerotorescue@1
 | 
   726 local function GetMultiOption(info, value)
 | 
| 
Zerotorescue@1
 | 
   727 	local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@1
 | 
   728 	local optionName = info[#info];
 | 
| 
Zerotorescue@1
 | 
   729 	
 | 
| 
Zerotorescue@1
 | 
   730 	if addon.db.global.groups[groupName][optionName] ~= nil then
 | 
| 
Zerotorescue@1
 | 
   731 		return addon.db.global.groups[groupName][optionName][value];
 | 
| 
Zerotorescue@1
 | 
   732 	elseif addon.db.global.defaults[optionName] then
 | 
| 
Zerotorescue@1
 | 
   733 		return addon.db.global.defaults[optionName][value];
 | 
| 
Zerotorescue@1
 | 
   734 	else
 | 
| 
Zerotorescue@1
 | 
   735 		return nil;
 | 
| 
Zerotorescue@1
 | 
   736 	end
 | 
| 
Zerotorescue@0
 | 
   737 end
 | 
| 
Zerotorescue@0
 | 
   738 
 | 
| 
Zerotorescue@0
 | 
   739 local function GetDisabled(info)
 | 
| 
Zerotorescue@0
 | 
   740 	if not info.arg or not info.arg:find("override") then
 | 
| 
Zerotorescue@0
 | 
   741 		return false;
 | 
| 
Zerotorescue@0
 | 
   742 	end
 | 
| 
Zerotorescue@0
 | 
   743 	
 | 
| 
Zerotorescue@0
 | 
   744 	local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
   745 	local optionName = info[#info];
 | 
| 
Zerotorescue@0
 | 
   746 	
 | 
| 
Zerotorescue@1
 | 
   747 	return (addon:GetOptionByKey(groupName, info.arg, true) == nil);
 | 
| 
Zerotorescue@0
 | 
   748 end
 | 
| 
Zerotorescue@0
 | 
   749 
 | 
| 
Zerotorescue@0
 | 
   750 local function ValidateGroupName(_, value)
 | 
| 
Zerotorescue@0
 | 
   751 	value = string.lower(string.trim(value or ""));
 | 
| 
Zerotorescue@0
 | 
   752 	
 | 
| 
Zerotorescue@0
 | 
   753 	for name, _ in pairs(addon.db.global.groups) do
 | 
| 
Zerotorescue@0
 | 
   754 		if string.lower(name) == value then
 | 
| 
Zerotorescue@0
 | 
   755 			return ("A group named \"%s\" already exists."):format(name);
 | 
| 
Zerotorescue@0
 | 
   756 		end
 | 
| 
Zerotorescue@0
 | 
   757 	end
 | 
| 
Zerotorescue@0
 | 
   758 	
 | 
| 
Zerotorescue@0
 | 
   759 	return true;
 | 
| 
Zerotorescue@0
 | 
   760 end
 | 
| 
Zerotorescue@0
 | 
   761 
 | 
| 
Zerotorescue@0
 | 
   762 local function InGroup(itemId)
 | 
| 
Zerotorescue@0
 | 
   763 	-- Go through all groups to see if this item is already somewhere
 | 
| 
Zerotorescue@0
 | 
   764 	for groupName, values in pairs(addon.db.global.groups) do
 | 
| 
Zerotorescue@0
 | 
   765 		if values.items and values.items[itemId] then
 | 
| 
Zerotorescue@0
 | 
   766 			return groupName;
 | 
| 
Zerotorescue@0
 | 
   767 		end
 | 
| 
Zerotorescue@0
 | 
   768 	end
 | 
| 
Zerotorescue@0
 | 
   769 	
 | 
| 
Zerotorescue@0
 | 
   770 	return;
 | 
| 
Zerotorescue@0
 | 
   771 end
 | 
| 
Zerotorescue@0
 | 
   772 
 | 
| 
Zerotorescue@0
 | 
   773 local function AddToGroup(groupName, itemId)
 | 
| 
Zerotorescue@0
 | 
   774 	if InGroup(itemId) then
 | 
| 
Zerotorescue@0
 | 
   775 		return false;
 | 
| 
Zerotorescue@0
 | 
   776 	end
 | 
| 
Zerotorescue@0
 | 
   777 	
 | 
| 
Zerotorescue@0
 | 
   778 	if not addon.db.global.groups[groupName].items then
 | 
| 
Zerotorescue@0
 | 
   779 		addon.db.global.groups[groupName].items = {};
 | 
| 
Zerotorescue@0
 | 
   780 	end
 | 
| 
Zerotorescue@0
 | 
   781 	
 | 
| 
Zerotorescue@0
 | 
   782 	-- Set this item
 | 
| 
Zerotorescue@0
 | 
   783 	addon.db.global.groups[groupName].items[itemId] = true;
 | 
| 
Zerotorescue@0
 | 
   784 						    	
 | 
| 
Zerotorescue@0
 | 
   785 	-- Now rebuild the list
 | 
| 
Zerotorescue@0
 | 
   786 	AceConfigRegistry:NotifyChange("InventoryOptions");
 | 
| 
Zerotorescue@0
 | 
   787 	
 | 
| 
Zerotorescue@0
 | 
   788 	return true;
 | 
| 
Zerotorescue@0
 | 
   789 end
 | 
| 
Zerotorescue@0
 | 
   790 
 | 
| 
Zerotorescue@0
 | 
   791 local tblAddItemTemplate = {
 | 
| 
Zerotorescue@0
 | 
   792 	order = 0,
 | 
| 
Zerotorescue@0
 | 
   793 	type = "input",
 | 
| 
Zerotorescue@0
 | 
   794 	name = function(info)
 | 
| 
Zerotorescue@0
 | 
   795 		local itemName, _, itemRarity = GetItemInfo(info[#info]);
 | 
| 
Zerotorescue@0
 | 
   796 		return tostring( 7 - (itemRarity or 0) ) .. (itemName or "");
 | 
| 
Zerotorescue@0
 | 
   797 	end,
 | 
| 
Zerotorescue@0
 | 
   798 	get = function(info)
 | 
| 
Zerotorescue@0
 | 
   799 		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
 | 
   800 	end,
 | 
| 
Zerotorescue@1
 | 
   801 	set = function(groupId, itemId)
 | 
| 
Zerotorescue@0
 | 
   802     	-- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info.
 | 
| 
Zerotorescue@0
 | 
   803     	
 | 
| 
Zerotorescue@1
 | 
   804     	if itemId then
 | 
| 
Zerotorescue@1
 | 
   805 	    	local groupName = groupIdToName[groupId];
 | 
| 
Zerotorescue@0
 | 
   806 	    	
 | 
| 
Zerotorescue@1
 | 
   807 	    	if not AddToGroup(groupName, itemId) then
 | 
| 
Zerotorescue@1
 | 
   808 	    		print("|cffff0000Couldn't add the item with itemId (" .. itemId .. ") because it is already in a group.|r");
 | 
| 
Zerotorescue@0
 | 
   809 	    	end
 | 
| 
Zerotorescue@0
 | 
   810     	end
 | 
| 
Zerotorescue@0
 | 
   811 	end,
 | 
| 
Zerotorescue@0
 | 
   812 	width = "double",
 | 
| 
Zerotorescue@1
 | 
   813 	dialogControl = "ConfigItemLinkButton",
 | 
| 
Zerotorescue@0
 | 
   814 };
 | 
| 
Zerotorescue@0
 | 
   815 
 | 
| 
Zerotorescue@0
 | 
   816 local tblRemoveItemTemplate = {
 | 
| 
Zerotorescue@0
 | 
   817 	order = 0,
 | 
| 
Zerotorescue@0
 | 
   818 	type = "input",
 | 
| 
Zerotorescue@0
 | 
   819 	name = function(info)
 | 
| 
Zerotorescue@0
 | 
   820 		local itemName, _, itemRarity = GetItemInfo(info[#info]);
 | 
| 
Zerotorescue@0
 | 
   821 		return tostring( 7 - (itemRarity or 0) ) .. (itemName or "");
 | 
| 
Zerotorescue@0
 | 
   822 	end,
 | 
| 
Zerotorescue@0
 | 
   823 	get = function(info)
 | 
| 
Zerotorescue@0
 | 
   824 		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
 | 
   825 	end,
 | 
| 
Zerotorescue@1
 | 
   826 	set = function(groupId, itemId)
 | 
| 
Zerotorescue@0
 | 
   827     	-- This is NOT a real "set", we pass the widget reference to this function which contains similar, but not the same, info.
 | 
| 
Zerotorescue@0
 | 
   828     	
 | 
| 
Zerotorescue@1
 | 
   829     	if itemId then
 | 
| 
Zerotorescue@1
 | 
   830 	    	local groupName = groupIdToName[groupId];
 | 
| 
Zerotorescue@0
 | 
   831 	    	
 | 
| 
Zerotorescue@0
 | 
   832 	    	-- Unset this item
 | 
| 
Zerotorescue@1
 | 
   833 	    	addon.db.global.groups[groupName].items[itemId] = nil;
 | 
| 
Zerotorescue@0
 | 
   834 	    	
 | 
| 
Zerotorescue@0
 | 
   835 	    	-- Now rebuild the list
 | 
| 
Zerotorescue@0
 | 
   836 	    	AceConfigRegistry:NotifyChange("InventoryOptions");
 | 
| 
Zerotorescue@0
 | 
   837     	end
 | 
| 
Zerotorescue@0
 | 
   838 	end,
 | 
| 
Zerotorescue@0
 | 
   839 	width = "double",
 | 
| 
Zerotorescue@1
 | 
   840 	dialogControl = "ConfigItemLinkButton",
 | 
| 
Zerotorescue@0
 | 
   841 };
 | 
| 
Zerotorescue@0
 | 
   842 
 | 
| 
Zerotorescue@0
 | 
   843 local function UpdateAddItemList(info)
 | 
| 
Zerotorescue@0
 | 
   844 	local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
   845 	
 | 
| 
Zerotorescue@0
 | 
   846 	if not addon.db.global.groups[groupName].items then
 | 
| 
Zerotorescue@0
 | 
   847 		addon.db.global.groups[groupName].items = {};
 | 
| 
Zerotorescue@0
 | 
   848 	end
 | 
| 
Zerotorescue@0
 | 
   849 	
 | 
| 
Zerotorescue@0
 | 
   850 	-- Merge all items from all groups together
 | 
| 
Zerotorescue@0
 | 
   851 	local items = {};
 | 
| 
Zerotorescue@0
 | 
   852 	for groupName, values in pairs(addon.db.global.groups) do
 | 
| 
Zerotorescue@0
 | 
   853 		if values.items then
 | 
| 
Zerotorescue@0
 | 
   854 			for itemId, _ in pairs(values.items) do
 | 
| 
Zerotorescue@0
 | 
   855 				items[itemId] = true;
 | 
| 
Zerotorescue@0
 | 
   856 			end
 | 
| 
Zerotorescue@0
 | 
   857 		end
 | 
| 
Zerotorescue@0
 | 
   858 	end
 | 
| 
Zerotorescue@0
 | 
   859 	
 | 
| 
Zerotorescue@0
 | 
   860 	local ref = options.args.groups.args[info[2]].args.add.args.list.args;
 | 
| 
Zerotorescue@0
 | 
   861 	
 | 
| 
Zerotorescue@0
 | 
   862 	-- Parse bags and show these
 | 
| 
Zerotorescue@0
 | 
   863 	for bagID = 4, 0, -1 do
 | 
| 
Zerotorescue@0
 | 
   864 		for slot = 1, GetContainerNumSlots(bagID) do
 | 
| 
Zerotorescue@0
 | 
   865 			local itemId = addon:GetItemId(GetContainerItemLink(bagID, slot));
 | 
| 
Zerotorescue@0
 | 
   866 			
 | 
| 
Zerotorescue@0
 | 
   867 			if itemId then
 | 
| 
Zerotorescue@0
 | 
   868 				if not items[itemId] then
 | 
| 
Zerotorescue@0
 | 
   869 					-- If this item isn't used in any group yet
 | 
| 
Zerotorescue@0
 | 
   870 					ref[itemId] = tblAddItemTemplate;
 | 
| 
Zerotorescue@0
 | 
   871 				else
 | 
| 
Zerotorescue@0
 | 
   872 					-- It's already used in a group, don't show it
 | 
| 
Zerotorescue@0
 | 
   873 					ref[itemId] = nil;
 | 
| 
Zerotorescue@0
 | 
   874 				end
 | 
| 
Zerotorescue@0
 | 
   875 			end
 | 
| 
Zerotorescue@0
 | 
   876 		end
 | 
| 
Zerotorescue@0
 | 
   877 	end
 | 
| 
Zerotorescue@0
 | 
   878 end
 | 
| 
Zerotorescue@0
 | 
   879 
 | 
| 
Zerotorescue@0
 | 
   880 local function UpdateRemoveItemList(info)
 | 
| 
Zerotorescue@0
 | 
   881 	local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
   882 	
 | 
| 
Zerotorescue@0
 | 
   883 	if not addon.db.global.groups[groupName].items then
 | 
| 
Zerotorescue@0
 | 
   884 		addon.db.global.groups[groupName].items = {};
 | 
| 
Zerotorescue@0
 | 
   885 	end
 | 
| 
Zerotorescue@0
 | 
   886 	
 | 
| 
Zerotorescue@0
 | 
   887 	local ref = options.args.groups.args[info[2]].args.remove.args.list.args;
 | 
| 
Zerotorescue@0
 | 
   888 	
 | 
| 
Zerotorescue@0
 | 
   889 	-- Unset all
 | 
| 
Zerotorescue@0
 | 
   890 	for itemId, _ in pairs(ref) do
 | 
| 
Zerotorescue@0
 | 
   891 		ref[itemId] = nil;
 | 
| 
Zerotorescue@0
 | 
   892 	end
 | 
| 
Zerotorescue@0
 | 
   893 	
 | 
| 
Zerotorescue@0
 | 
   894 	-- Parse items in group and show these
 | 
| 
Zerotorescue@0
 | 
   895 	for itemId, _ in pairs(addon.db.global.groups[groupName].items) do
 | 
| 
Zerotorescue@0
 | 
   896 		ref[itemId] = tblRemoveItemTemplate;
 | 
| 
Zerotorescue@0
 | 
   897 	end
 | 
| 
Zerotorescue@0
 | 
   898 end
 | 
| 
Zerotorescue@0
 | 
   899 
 | 
| 
Zerotorescue@0
 | 
   900 function addon:GetItemId(itemLink)
 | 
| 
Zerotorescue@0
 | 
   901 	itemLink = itemLink and select(3, string.find(itemLink, "|Hitem:([-0-9]+):")); -- if itemLink is nil, it won't execute the second part
 | 
| 
Zerotorescue@0
 | 
   902 	itemLink = itemLink and tonumber(itemLink);
 | 
| 
Zerotorescue@0
 | 
   903 	
 | 
| 
Zerotorescue@0
 | 
   904 	return itemLink;
 | 
| 
Zerotorescue@0
 | 
   905 end
 | 
| 
Zerotorescue@0
 | 
   906 
 | 
| 
Zerotorescue@0
 | 
   907 -- Default group
 | 
| 
Zerotorescue@0
 | 
   908 local defaultGroup = {
 | 
| 
Zerotorescue@0
 | 
   909 	order = 0,
 | 
| 
Zerotorescue@0
 | 
   910 	type = "group",
 | 
| 
Zerotorescue@0
 | 
   911 	childGroups = "tab",
 | 
| 
Zerotorescue@0
 | 
   912 	name = function(info)
 | 
| 
Zerotorescue@0
 | 
   913 		return groupIdToName[info[#info]];
 | 
| 
Zerotorescue@0
 | 
   914 	end,
 | 
| 
Zerotorescue@0
 | 
   915 	args = {
 | 
| 
Zerotorescue@0
 | 
   916 		general = {
 | 
| 
Zerotorescue@0
 | 
   917 			order = 10,
 | 
| 
Zerotorescue@0
 | 
   918 			type = "group",
 | 
| 
Zerotorescue@0
 | 
   919 			name = "Stock settings",
 | 
| 
Zerotorescue@0
 | 
   920 			desc = "Change the stock settings for just this group.",
 | 
| 
Zerotorescue@0
 | 
   921 			args = {
 | 
| 
Zerotorescue@0
 | 
   922 				minimumStock = {
 | 
| 
Zerotorescue@0
 | 
   923 					order = 10,
 | 
| 
Zerotorescue@0
 | 
   924 					type = "group",
 | 
| 
Zerotorescue@0
 | 
   925 					inline = true,
 | 
| 
Zerotorescue@0
 | 
   926 					name = "Minimum stock",
 | 
| 
Zerotorescue@0
 | 
   927 					set = SetOption,
 | 
| 
Zerotorescue@0
 | 
   928 					get = GetOption,
 | 
| 
Zerotorescue@0
 | 
   929 					disabled = GetDisabled,
 | 
| 
Zerotorescue@0
 | 
   930 					args = {
 | 
| 
Zerotorescue@0
 | 
   931 						description = {
 | 
| 
Zerotorescue@0
 | 
   932 							order = 0,
 | 
| 
Zerotorescue@0
 | 
   933 							type = "description",
 | 
| 
Zerotorescue@0
 | 
   934 							name = "Here you can specify the minimum amount of items you wish to keep in stock and related settings for the currently selected group.",
 | 
| 
Zerotorescue@0
 | 
   935 						},
 | 
| 
Zerotorescue@0
 | 
   936 						header = {
 | 
| 
Zerotorescue@0
 | 
   937 							order = 5,
 | 
| 
Zerotorescue@0
 | 
   938 							type = "header",
 | 
| 
Zerotorescue@0
 | 
   939 							name = "",
 | 
| 
Zerotorescue@0
 | 
   940 						},
 | 
| 
Zerotorescue@0
 | 
   941 						overrideMinimumStock = {
 | 
| 
Zerotorescue@0
 | 
   942 							order = 9,
 | 
| 
Zerotorescue@0
 | 
   943 							type = "toggle",
 | 
| 
Zerotorescue@0
 | 
   944 							name = "Override min stock",
 | 
| 
Zerotorescue@0
 | 
   945 							desc = "Allows you to override the minimum stock setting for this group.",
 | 
| 
Zerotorescue@0
 | 
   946 							arg = "minimumStock",
 | 
| 
Zerotorescue@0
 | 
   947 						},
 | 
| 
Zerotorescue@0
 | 
   948 						minimumStock = {
 | 
| 
Zerotorescue@0
 | 
   949 							order = 10,
 | 
| 
Zerotorescue@0
 | 
   950 							type = "range",
 | 
| 
Zerotorescue@0
 | 
   951 							min = 0,
 | 
| 
Zerotorescue@0
 | 
   952 							max = 100000,
 | 
| 
Zerotorescue@0
 | 
   953 							softMax = 1000,
 | 
| 
Zerotorescue@0
 | 
   954 							step = 1,
 | 
| 
Zerotorescue@0
 | 
   955 							name = "Minimum stock",
 | 
| 
Zerotorescue@0
 | 
   956 							desc = "You can manually enter a value between 1.000 and 100.000 in the edit box if the provided range is insufficient.",
 | 
| 
Zerotorescue@0
 | 
   957 							arg = "overrideMinimumStock",
 | 
| 
Zerotorescue@0
 | 
   958 						},
 | 
| 
Zerotorescue@0
 | 
   959 						overrideSummaryThresholdShow = {
 | 
| 
Zerotorescue@0
 | 
   960 							order = 19,
 | 
| 
Zerotorescue@0
 | 
   961 							type = "toggle",
 | 
| 
Zerotorescue@0
 | 
   962 							name = "Override summary showing",
 | 
| 
Zerotorescue@0
 | 
   963 							desc = "Allows you to override when this group should appear in the summary.",
 | 
| 
Zerotorescue@0
 | 
   964 							arg = "summaryThresholdShow",
 | 
| 
Zerotorescue@0
 | 
   965 						},
 | 
| 
Zerotorescue@0
 | 
   966 						summaryThresholdShow = {
 | 
| 
Zerotorescue@0
 | 
   967 							order = 20,
 | 
| 
Zerotorescue@0
 | 
   968 							type = "range",
 | 
| 
Zerotorescue@0
 | 
   969 							min = 0,
 | 
| 
Zerotorescue@0
 | 
   970 							max = 100,
 | 
| 
Zerotorescue@0
 | 
   971 							softMax = 10,
 | 
| 
Zerotorescue@0
 | 
   972 							step = 0.05,
 | 
| 
Zerotorescue@0
 | 
   973 							isPercent = true,
 | 
| 
Zerotorescue@0
 | 
   974 							name = "Show in summary when below",
 | 
| 
Zerotorescue@0
 | 
   975 							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
 | 
   976 							arg = "overrideSummaryThresholdShow",
 | 
| 
Zerotorescue@0
 | 
   977 						},
 | 
| 
Zerotorescue@0
 | 
   978 						overrideAlertBelowMinimum = {
 | 
| 
Zerotorescue@0
 | 
   979 							order = 29,
 | 
| 
Zerotorescue@0
 | 
   980 							type = "toggle",
 | 
| 
Zerotorescue@0
 | 
   981 							name = "Override minimum alert",
 | 
| 
Zerotorescue@0
 | 
   982 							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
 | 
   983 							arg = "alertBelowMinimum",
 | 
| 
Zerotorescue@0
 | 
   984 						},
 | 
| 
Zerotorescue@0
 | 
   985 						alertBelowMinimum = {
 | 
| 
Zerotorescue@0
 | 
   986 							order = 30,
 | 
| 
Zerotorescue@0
 | 
   987 							type = "toggle",
 | 
| 
Zerotorescue@0
 | 
   988 							name = "Alert when below minimum",
 | 
| 
Zerotorescue@0
 | 
   989 							desc = "Show an alert when an item in this group gets below the minimum stock threshold.",
 | 
| 
Zerotorescue@0
 | 
   990 							arg = "overrideAlertBelowMinimum",
 | 
| 
Zerotorescue@0
 | 
   991 						},
 | 
| 
Zerotorescue@1
 | 
   992 						overrideTrackAtCharacters = {
 | 
| 
Zerotorescue@1
 | 
   993 							order = 39,
 | 
| 
Zerotorescue@1
 | 
   994 							type = "toggle",
 | 
| 
Zerotorescue@1
 | 
   995 							name = "Override track at",
 | 
| 
Zerotorescue@1
 | 
   996 							desc = "Allows you to override at which characters items in this group should appear in the summary and generate alerts.",
 | 
| 
Zerotorescue@1
 | 
   997 							arg = "trackAtCharacters",
 | 
| 
Zerotorescue@1
 | 
   998 						},
 | 
| 
Zerotorescue@1
 | 
   999 						trackAtCharacters = {
 | 
| 
Zerotorescue@1
 | 
  1000 							order = 40,
 | 
| 
Zerotorescue@1
 | 
  1001 							type = "multiselect",
 | 
| 
Zerotorescue@1
 | 
  1002 							name = "Track at",
 | 
| 
Zerotorescue@1
 | 
  1003 							desc = "Select at which characters this should appear in the summary and generate alerts.",
 | 
| 
Zerotorescue@1
 | 
  1004 							values = function()
 | 
| 
Zerotorescue@1
 | 
  1005 								local temp = {};
 | 
| 
Zerotorescue@1
 | 
  1006 								for charName in pairs(addon.db.factionrealm.characters) do
 | 
| 
Zerotorescue@1
 | 
  1007 									temp[charName] = charName;
 | 
| 
Zerotorescue@1
 | 
  1008 								end
 | 
| 
Zerotorescue@1
 | 
  1009 								
 | 
| 
Zerotorescue@1
 | 
  1010 								-- We MUST close this pullout or we can get errors or even game client crashes once we click another group or close the config dialog!
 | 
| 
Zerotorescue@1
 | 
  1011 								local count = AceGUI:GetNextWidgetNum("Dropdown-Pullout");
 | 
| 
Zerotorescue@7
 | 
  1012 								for i = 1, count do
 | 
| 
Zerotorescue@1
 | 
  1013 									if _G['AceGUI30Pullout' .. i] then
 | 
| 
Zerotorescue@1
 | 
  1014 										_G['AceGUI30Pullout' .. i]:Hide();
 | 
| 
Zerotorescue@1
 | 
  1015 									end
 | 
| 
Zerotorescue@1
 | 
  1016 								end
 | 
| 
Zerotorescue@1
 | 
  1017 								
 | 
| 
Zerotorescue@1
 | 
  1018 								return temp;
 | 
| 
Zerotorescue@1
 | 
  1019 							end,
 | 
| 
Zerotorescue@1
 | 
  1020 							get = GetMultiOption,
 | 
| 
Zerotorescue@10
 | 
  1021 							confirm = true,
 | 
| 
Zerotorescue@1
 | 
  1022 							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
 | 
  1023 							arg = "overrideTrackAtCharacters",
 | 
| 
Zerotorescue@1
 | 
  1024 						},
 | 
| 
Zerotorescue@0
 | 
  1025 					},
 | 
| 
Zerotorescue@0
 | 
  1026 				},
 | 
| 
Zerotorescue@0
 | 
  1027 				refill = {
 | 
| 
Zerotorescue@0
 | 
  1028 					order = 20,
 | 
| 
Zerotorescue@0
 | 
  1029 					type = "group",
 | 
| 
Zerotorescue@0
 | 
  1030 					inline = true,
 | 
| 
Zerotorescue@0
 | 
  1031 					name = "Replenishing stock",
 | 
| 
Zerotorescue@0
 | 
  1032 					set = SetOption,
 | 
| 
Zerotorescue@0
 | 
  1033 					get = GetOption,
 | 
| 
Zerotorescue@0
 | 
  1034 					disabled = GetDisabled,
 | 
| 
Zerotorescue@0
 | 
  1035 					args = {
 | 
| 
Zerotorescue@0
 | 
  1036 						description = {
 | 
| 
Zerotorescue@0
 | 
  1037 							order = 0,
 | 
| 
Zerotorescue@0
 | 
  1038 							type = "description",
 | 
| 
Zerotorescue@0
 | 
  1039 							name = function(info)
 | 
| 
Zerotorescue@0
 | 
  1040 								local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
  1041 								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
 | 
  1042 								
 | 
| 
Zerotorescue@1
 | 
  1043 								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.";
 | 
| 
Zerotorescue@0
 | 
  1044 								
 | 
| 
Zerotorescue@0
 | 
  1045 								return r;
 | 
| 
Zerotorescue@0
 | 
  1046 							end,
 | 
| 
Zerotorescue@0
 | 
  1047 						},
 | 
| 
Zerotorescue@0
 | 
  1048 						header = {
 | 
| 
Zerotorescue@0
 | 
  1049 							order = 5,
 | 
| 
Zerotorescue@0
 | 
  1050 							type = "header",
 | 
| 
Zerotorescue@0
 | 
  1051 							name = "",
 | 
| 
Zerotorescue@0
 | 
  1052 						},
 | 
| 
Zerotorescue@0
 | 
  1053 						overrideRestockTarget = {
 | 
| 
Zerotorescue@0
 | 
  1054 							order = 9,
 | 
| 
Zerotorescue@0
 | 
  1055 							type = "toggle",
 | 
| 
Zerotorescue@0
 | 
  1056 							name = "Override restock target",
 | 
| 
Zerotorescue@0
 | 
  1057 							desc = "Allows you to override the restock target setting for this group.",
 | 
| 
Zerotorescue@0
 | 
  1058 							arg = "restockTarget",
 | 
| 
Zerotorescue@0
 | 
  1059 						},
 | 
| 
Zerotorescue@0
 | 
  1060 						restockTarget = {
 | 
| 
Zerotorescue@0
 | 
  1061 							order = 10,
 | 
| 
Zerotorescue@0
 | 
  1062 							type = "range",
 | 
| 
Zerotorescue@0
 | 
  1063 							min = 0,
 | 
| 
Zerotorescue@0
 | 
  1064 							max = 100000,
 | 
| 
Zerotorescue@0
 | 
  1065 							softMax = 1000,
 | 
| 
Zerotorescue@0
 | 
  1066 							step = 1,
 | 
| 
Zerotorescue@0
 | 
  1067 							name = "Restock target",
 | 
| 
Zerotorescue@0
 | 
  1068 							desc = "You can manually enter a value between 1.000 and 100.000 in the edit box if the provided range is insufficient.",
 | 
| 
Zerotorescue@0
 | 
  1069 							arg = "overrideRestockTarget",
 | 
| 
Zerotorescue@0
 | 
  1070 						},
 | 
| 
Zerotorescue@0
 | 
  1071 						overrideMinCraftingQueue = {
 | 
| 
Zerotorescue@0
 | 
  1072 							order = 19,
 | 
| 
Zerotorescue@0
 | 
  1073 							type = "toggle",
 | 
| 
Zerotorescue@0
 | 
  1074 							name = "Override min queue",
 | 
| 
Zerotorescue@0
 | 
  1075 							desc = "Allows you to override the minimum craftable items queue setting for this group.",
 | 
| 
Zerotorescue@0
 | 
  1076 							arg = "minCraftingQueue",
 | 
| 
Zerotorescue@0
 | 
  1077 						},
 | 
| 
Zerotorescue@0
 | 
  1078 						minCraftingQueue = {
 | 
| 
Zerotorescue@0
 | 
  1079 							order = 20,
 | 
| 
Zerotorescue@0
 | 
  1080 							type = "range",
 | 
| 
Zerotorescue@0
 | 
  1081 							min = 0,
 | 
| 
Zerotorescue@0
 | 
  1082 							max = 1,
 | 
| 
Zerotorescue@0
 | 
  1083 							step = 0.01,
 | 
| 
Zerotorescue@0
 | 
  1084 							isPercent = true,
 | 
| 
Zerotorescue@0
 | 
  1085 							name = "Don't queue if I only miss",
 | 
| 
Zerotorescue@0
 | 
  1086 							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
 | 
  1087 							arg = "overrideMinCraftingQueue",
 | 
| 
Zerotorescue@0
 | 
  1088 						},
 | 
| 
Zerotorescue@1
 | 
  1089 						overrideBonusQueue = {
 | 
| 
Zerotorescue@1
 | 
  1090 							order = 29,
 | 
| 
Zerotorescue@1
 | 
  1091 							type = "toggle",
 | 
| 
Zerotorescue@1
 | 
  1092 							name = "Override bonus queue",
 | 
| 
Zerotorescue@1
 | 
  1093 							desc = "Allows you to override the bonus craftable items queue setting for this group.",
 | 
| 
Zerotorescue@1
 | 
  1094 							arg = "bonusQueue",
 | 
| 
Zerotorescue@1
 | 
  1095 						},
 | 
| 
Zerotorescue@1
 | 
  1096 						bonusQueue = {
 | 
| 
Zerotorescue@1
 | 
  1097 							order = 30,
 | 
| 
Zerotorescue@1
 | 
  1098 							type = "range",
 | 
| 
Zerotorescue@1
 | 
  1099 							min = 0,
 | 
| 
Zerotorescue@1
 | 
  1100 							max = 10, -- 1000%
 | 
| 
Zerotorescue@1
 | 
  1101 							step = 0.01, -- 1%
 | 
| 
Zerotorescue@1
 | 
  1102 							isPercent = true,
 | 
| 
Zerotorescue@1
 | 
  1103 							name = "Bonus queue",
 | 
| 
Zerotorescue@1
 | 
  1104 							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
 | 
  1105 							arg = "overrideBonusQueue",
 | 
| 
Zerotorescue@1
 | 
  1106 						},
 | 
| 
Zerotorescue@1
 | 
  1107 						overridePriceThreshold = {
 | 
| 
Zerotorescue@1
 | 
  1108 							order = 39,
 | 
| 
Zerotorescue@1
 | 
  1109 							type = "toggle",
 | 
| 
Zerotorescue@1
 | 
  1110 							name = "Override price threshold",
 | 
| 
Zerotorescue@1
 | 
  1111 							desc = "Allows you to override the price threshold setting for this group.",
 | 
| 
Zerotorescue@1
 | 
  1112 							arg = "priceThreshold",
 | 
| 
Zerotorescue@1
 | 
  1113 						},
 | 
| 
Zerotorescue@1
 | 
  1114 						priceThreshold = {
 | 
| 
Zerotorescue@1
 | 
  1115 							order = 40,
 | 
| 
Zerotorescue@1
 | 
  1116 							type = "input",
 | 
| 
Zerotorescue@1
 | 
  1117 							name = "Price threshold",
 | 
| 
Zerotorescue@1
 | 
  1118 							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
 | 
  1119 							validate = function(info, value) return addon:ValidateReadableMoney(info, value); end,
 | 
| 
Zerotorescue@1
 | 
  1120 							get = function(i) return addon:ReadableMoney(GetOption(i)); end,
 | 
| 
Zerotorescue@1
 | 
  1121 							set = function(i, v) SetOption(i, addon:ReadableMoneyToCopper(v)); end,
 | 
| 
Zerotorescue@1
 | 
  1122 							arg = "overridePriceThreshold",
 | 
| 
Zerotorescue@1
 | 
  1123 						},
 | 
| 
Zerotorescue@1
 | 
  1124 						overrideHideFromSummaryWhenBelowPriceThreshold = {
 | 
| 
Zerotorescue@1
 | 
  1125 							order = 49,
 | 
| 
Zerotorescue@1
 | 
  1126 							type = "toggle",
 | 
| 
Zerotorescue@1
 | 
  1127 							name = "Override summary showing",
 | 
| 
Zerotorescue@1
 | 
  1128 							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@1
 | 
  1129 							arg = "hideFromSummaryWhenBelowPriceThreshold",
 | 
| 
Zerotorescue@1
 | 
  1130 						},
 | 
| 
Zerotorescue@1
 | 
  1131 						hideFromSummaryWhenBelowPriceThreshold = { -- I wish this var could be a little bit shorter...
 | 
| 
Zerotorescue@1
 | 
  1132 							order = 50,
 | 
| 
Zerotorescue@1
 | 
  1133 							type = "toggle",
 | 
| 
Zerotorescue@1
 | 
  1134 							name = "Hide when below threshold",
 | 
| 
Zerotorescue@1
 | 
  1135 							desc = "Hide items from the summary when their value is below the set price threshold.",
 | 
| 
Zerotorescue@1
 | 
  1136 							arg = "overrideHideFromSummaryWhenBelowPriceThreshold",
 | 
| 
Zerotorescue@1
 | 
  1137 						},
 | 
| 
Zerotorescue@0
 | 
  1138 					},
 | 
| 
Zerotorescue@0
 | 
  1139 				},
 | 
| 
Zerotorescue@0
 | 
  1140 			},
 | 
| 
Zerotorescue@0
 | 
  1141 		},
 | 
| 
Zerotorescue@0
 | 
  1142 		group = {
 | 
| 
Zerotorescue@0
 | 
  1143 			order = 20,
 | 
| 
Zerotorescue@0
 | 
  1144 			type = "group",
 | 
| 
Zerotorescue@0
 | 
  1145 			name = "Group Management",
 | 
| 
Zerotorescue@0
 | 
  1146 			desc = "Rename, delete or export this group.",
 | 
| 
Zerotorescue@0
 | 
  1147 			args = {
 | 
| 
Zerotorescue@10
 | 
  1148 				actions = {
 | 
| 
Zerotorescue@0
 | 
  1149 					order = 10,
 | 
| 
Zerotorescue@0
 | 
  1150 					type = "group",
 | 
| 
Zerotorescue@10
 | 
  1151 					name = "Actions",
 | 
| 
Zerotorescue@0
 | 
  1152 					inline = true,
 | 
| 
Zerotorescue@0
 | 
  1153 					args = {
 | 
| 
Zerotorescue@0
 | 
  1154 						rename = {
 | 
| 
Zerotorescue@0
 | 
  1155 							order = 10,
 | 
| 
Zerotorescue@0
 | 
  1156 							type = "input",
 | 
| 
Zerotorescue@10
 | 
  1157 							name = "Rename group - New name",
 | 
| 
Zerotorescue@0
 | 
  1158 							desc = "Change the name of this group to something else. You can also use item links here as you wish.",
 | 
| 
Zerotorescue@0
 | 
  1159 							validate = ValidateGroupName,
 | 
| 
Zerotorescue@0
 | 
  1160 							set = function(info, value)
 | 
| 
Zerotorescue@0
 | 
  1161 								local oldGroupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
  1162 								
 | 
| 
Zerotorescue@0
 | 
  1163 								addon.db.global.groups[value] = CopyTable(addon.db.global.groups[oldGroupName]);
 | 
| 
Zerotorescue@0
 | 
  1164 								addon.db.global.groups[oldGroupName] = nil;
 | 
| 
Zerotorescue@0
 | 
  1165 								
 | 
| 
Zerotorescue@0
 | 
  1166 								groupIdToName[info[2]] = value;
 | 
| 
Zerotorescue@0
 | 
  1167 								groupIdToName[value] = true;
 | 
| 
Zerotorescue@0
 | 
  1168 								groupIdToName[oldGroupName] = nil;
 | 
| 
Zerotorescue@0
 | 
  1169 								
 | 
| 
Zerotorescue@0
 | 
  1170 								addon:FillGroupOptions();
 | 
| 
Zerotorescue@0
 | 
  1171 							end,
 | 
| 
Zerotorescue@0
 | 
  1172 							get = function(info)
 | 
| 
Zerotorescue@0
 | 
  1173 								return groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
  1174 							end,
 | 
| 
Zerotorescue@0
 | 
  1175 						},
 | 
| 
Zerotorescue@10
 | 
  1176 						duplicate = {
 | 
| 
Zerotorescue@10
 | 
  1177 							order = 20,
 | 
| 
Zerotorescue@10
 | 
  1178 							type = "input",
 | 
| 
Zerotorescue@10
 | 
  1179 							name = "Duplicate group - New name",
 | 
| 
Zerotorescue@10
 | 
  1180 							desc = "Duplicate this group. You can also use item links here as you wish.\n\nAll item data will be erased.",
 | 
| 
Zerotorescue@10
 | 
  1181 							validate = ValidateGroupName,
 | 
| 
Zerotorescue@10
 | 
  1182 							set = function(info, value)
 | 
| 
Zerotorescue@10
 | 
  1183 								local oldGroupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@10
 | 
  1184 								
 | 
| 
Zerotorescue@10
 | 
  1185 								addon.db.global.groups[value] = CopyTable(addon.db.global.groups[oldGroupName]);
 | 
| 
Zerotorescue@10
 | 
  1186 								
 | 
| 
Zerotorescue@10
 | 
  1187 								-- Reset item data (duplicate items me no want)
 | 
| 
Zerotorescue@10
 | 
  1188 								addon.db.global.groups[value].items = nil;
 | 
| 
Zerotorescue@10
 | 
  1189 								
 | 
| 
Zerotorescue@10
 | 
  1190 								addon:FillGroupOptions();
 | 
| 
Zerotorescue@10
 | 
  1191 							end,
 | 
| 
Zerotorescue@10
 | 
  1192 							get = false,
 | 
| 
Zerotorescue@10
 | 
  1193 						},
 | 
| 
Zerotorescue@0
 | 
  1194 						delete = {
 | 
| 
Zerotorescue@10
 | 
  1195 							order = 30,
 | 
| 
Zerotorescue@0
 | 
  1196 							type = "execute",
 | 
| 
Zerotorescue@0
 | 
  1197 							name = "Delete group",
 | 
| 
Zerotorescue@0
 | 
  1198 							desc = "Delete the currently selected group.",
 | 
| 
Zerotorescue@0
 | 
  1199 							confirm = true,
 | 
| 
Zerotorescue@0
 | 
  1200 							confirmText = "Are you sure you wish to |cffff0000DELETE|r this group? This action is not reversable!",
 | 
| 
Zerotorescue@0
 | 
  1201 							func = function(info)
 | 
| 
Zerotorescue@0
 | 
  1202 								local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
  1203 								
 | 
| 
Zerotorescue@0
 | 
  1204 								addon.db.global.groups[groupName] = nil;
 | 
| 
Zerotorescue@0
 | 
  1205 								
 | 
| 
Zerotorescue@0
 | 
  1206 								addon:FillGroupOptions();
 | 
| 
Zerotorescue@0
 | 
  1207 							end,
 | 
| 
Zerotorescue@0
 | 
  1208 						},
 | 
| 
Zerotorescue@0
 | 
  1209 					},
 | 
| 
Zerotorescue@0
 | 
  1210 				},
 | 
| 
Zerotorescue@0
 | 
  1211 				export = {
 | 
| 
Zerotorescue@10
 | 
  1212 					order = 40,
 | 
| 
Zerotorescue@0
 | 
  1213 					type = "group",
 | 
| 
Zerotorescue@0
 | 
  1214 					name = "Export",
 | 
| 
Zerotorescue@0
 | 
  1215 					inline = true,
 | 
| 
Zerotorescue@0
 | 
  1216 					args = {
 | 
| 
Zerotorescue@0
 | 
  1217 						input = {
 | 
| 
Zerotorescue@0
 | 
  1218 							order = 10,
 | 
| 
Zerotorescue@0
 | 
  1219 							type = "input",
 | 
| 
Zerotorescue@0
 | 
  1220 							multiline = true,
 | 
| 
Zerotorescue@0
 | 
  1221 							name = "Group data",
 | 
| 
Zerotorescue@0
 | 
  1222 							width = "full",
 | 
| 
Zerotorescue@0
 | 
  1223 							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
 | 
  1224 							set = false,
 | 
| 
Zerotorescue@0
 | 
  1225 							get = function(info)
 | 
| 
Zerotorescue@0
 | 
  1226 								local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
  1227 								
 | 
| 
Zerotorescue@0
 | 
  1228 								-- We want to include the group name, so we copy the table then set another value
 | 
| 
Zerotorescue@0
 | 
  1229 								local temp = CopyTable(addon.db.global.groups[groupName]);
 | 
| 
Zerotorescue@0
 | 
  1230 								temp.name = groupName;
 | 
| 
Zerotorescue@9
 | 
  1231 								temp.trackAtCharacters = nil;
 | 
| 
Zerotorescue@9
 | 
  1232 								temp.overrideTrackAtCharacters = nil;
 | 
| 
Zerotorescue@0
 | 
  1233 								
 | 
| 
Zerotorescue@0
 | 
  1234 								if not AceSerializer then
 | 
| 
Zerotorescue@0
 | 
  1235 									AceSerializer = LibStub("AceSerializer-3.0");
 | 
| 
Zerotorescue@0
 | 
  1236 								end
 | 
| 
Zerotorescue@0
 | 
  1237 								
 | 
| 
Zerotorescue@0
 | 
  1238 								return AceSerializer:Serialize(temp);
 | 
| 
Zerotorescue@0
 | 
  1239 							end,
 | 
| 
Zerotorescue@0
 | 
  1240 						},
 | 
| 
Zerotorescue@0
 | 
  1241 					},
 | 
| 
Zerotorescue@0
 | 
  1242 				},
 | 
| 
Zerotorescue@0
 | 
  1243 			},
 | 
| 
Zerotorescue@0
 | 
  1244 		},
 | 
| 
Zerotorescue@0
 | 
  1245 		add = {
 | 
| 
Zerotorescue@0
 | 
  1246 			order = 30,
 | 
| 
Zerotorescue@0
 | 
  1247 			type = "group",
 | 
| 
Zerotorescue@0
 | 
  1248 			name = "Add items",
 | 
| 
Zerotorescue@0
 | 
  1249 			args = {
 | 
| 
Zerotorescue@0
 | 
  1250 				singleAdd = {
 | 
| 
Zerotorescue@0
 | 
  1251 					order = 10,
 | 
| 
Zerotorescue@0
 | 
  1252 					type = "group",
 | 
| 
Zerotorescue@0
 | 
  1253 					inline = true,
 | 
| 
Zerotorescue@0
 | 
  1254 					name = "Add items",
 | 
| 
Zerotorescue@0
 | 
  1255 					args = {
 | 
| 
Zerotorescue@0
 | 
  1256 						help = {
 | 
| 
Zerotorescue@0
 | 
  1257 							order = 10,
 | 
| 
Zerotorescue@0
 | 
  1258 							type = "description",
 | 
| 
Zerotorescue@0
 | 
  1259 							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
 | 
  1260 						},
 | 
| 
Zerotorescue@0
 | 
  1261 						itemLink = {
 | 
| 
Zerotorescue@0
 | 
  1262 							order = 20,
 | 
| 
Zerotorescue@0
 | 
  1263 							type = "input",
 | 
| 
Zerotorescue@0
 | 
  1264 							name = "Single item add (item-link or item-id)",
 | 
| 
Zerotorescue@0
 | 
  1265 							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
 | 
  1266 							validate = function(info, value)
 | 
| 
Zerotorescue@0
 | 
  1267 								-- If the value is empty we'll allow passing to clear the carret
 | 
| 
Zerotorescue@0
 | 
  1268 								if value == "" then return true; end
 | 
| 
Zerotorescue@0
 | 
  1269 								
 | 
| 
Zerotorescue@0
 | 
  1270 								local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
  1271 								
 | 
| 
Zerotorescue@0
 | 
  1272 								local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or ""));
 | 
| 
Zerotorescue@0
 | 
  1273 								
 | 
| 
Zerotorescue@0
 | 
  1274 								if not itemId then
 | 
| 
Zerotorescue@0
 | 
  1275 									return "This is not a valid item link.";
 | 
| 
Zerotorescue@0
 | 
  1276 								elseif InGroup(itemId) then
 | 
| 
Zerotorescue@0
 | 
  1277 									return ("This item is already in the group \"%s\"."):format(InGroup(itemId));
 | 
| 
Zerotorescue@0
 | 
  1278 								end
 | 
| 
Zerotorescue@0
 | 
  1279 								
 | 
| 
Zerotorescue@0
 | 
  1280 								return true;
 | 
| 
Zerotorescue@0
 | 
  1281 							end,
 | 
| 
Zerotorescue@0
 | 
  1282 							set = function(info, value)
 | 
| 
Zerotorescue@0
 | 
  1283 								if value and value ~= "" then
 | 
| 
Zerotorescue@0
 | 
  1284 									local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
  1285 									
 | 
| 
Zerotorescue@0
 | 
  1286 									local itemId = addon:GetItemId(string.trim(value or "")) or tonumber(string.trim(value or ""));
 | 
| 
Zerotorescue@0
 | 
  1287 									
 | 
| 
Zerotorescue@0
 | 
  1288 									AddToGroup(groupName, itemId);
 | 
| 
Zerotorescue@0
 | 
  1289 							    	
 | 
| 
Zerotorescue@0
 | 
  1290 									print(("Added %s"):format(select(2, GetItemInfo(itemId)) or ("Unknown (#%d)"):format(itemId)));
 | 
| 
Zerotorescue@0
 | 
  1291 								end
 | 
| 
Zerotorescue@0
 | 
  1292 							end,
 | 
| 
Zerotorescue@0
 | 
  1293 							get = false,
 | 
| 
Zerotorescue@0
 | 
  1294 						},
 | 
| 
Zerotorescue@0
 | 
  1295 						import = {
 | 
| 
Zerotorescue@0
 | 
  1296 							order = 40,
 | 
| 
Zerotorescue@0
 | 
  1297 							type = "input",
 | 
| 
Zerotorescue@0
 | 
  1298 							name = "Import item data",
 | 
| 
Zerotorescue@0
 | 
  1299 							desc = "Import item data from an exported item data-string. Any items already grouped will be skipped.",
 | 
| 
Zerotorescue@0
 | 
  1300 							set = function(info, value)
 | 
| 
Zerotorescue@0
 | 
  1301 								local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
  1302 								
 | 
| 
Zerotorescue@0
 | 
  1303 								local allItemIds = { string.split(";", value or "") };
 | 
| 
Zerotorescue@0
 | 
  1304 								
 | 
| 
Zerotorescue@0
 | 
  1305 								for _, value in pairs(allItemIds) do
 | 
| 
Zerotorescue@0
 | 
  1306 									local itemId = tonumber(value);
 | 
| 
Zerotorescue@0
 | 
  1307 									
 | 
| 
Zerotorescue@0
 | 
  1308 									if not itemId then
 | 
| 
Zerotorescue@0
 | 
  1309 										print(("\"%s\" is not a number."):format(value));
 | 
| 
Zerotorescue@0
 | 
  1310 									elseif InGroup(itemId) then
 | 
| 
Zerotorescue@0
 | 
  1311 										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
 | 
  1312 									else
 | 
| 
Zerotorescue@0
 | 
  1313 										AddToGroup(groupName, itemId);
 | 
| 
Zerotorescue@0
 | 
  1314 									end
 | 
| 
Zerotorescue@0
 | 
  1315 								end
 | 
| 
Zerotorescue@0
 | 
  1316 							end,
 | 
| 
Zerotorescue@0
 | 
  1317 							get = false,
 | 
| 
Zerotorescue@0
 | 
  1318 						},
 | 
| 
Zerotorescue@0
 | 
  1319 					},
 | 
| 
Zerotorescue@0
 | 
  1320 				},
 | 
| 
Zerotorescue@0
 | 
  1321 				massAdd = {
 | 
| 
Zerotorescue@0
 | 
  1322 					order = 20,
 | 
| 
Zerotorescue@0
 | 
  1323 					type = "group",
 | 
| 
Zerotorescue@0
 | 
  1324 					inline = true,
 | 
| 
Zerotorescue@0
 | 
  1325 					name = "Mass add",
 | 
| 
Zerotorescue@0
 | 
  1326 					args = {
 | 
| 
Zerotorescue@0
 | 
  1327 						help = {
 | 
| 
Zerotorescue@0
 | 
  1328 							order = 10,
 | 
| 
Zerotorescue@0
 | 
  1329 							type = "description",
 | 
| 
Zerotorescue@0
 | 
  1330 							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
 | 
  1331 						},
 | 
| 
Zerotorescue@0
 | 
  1332 						massAdd = {
 | 
| 
Zerotorescue@0
 | 
  1333 							order = 20,
 | 
| 
Zerotorescue@0
 | 
  1334 							type = "input",
 | 
| 
Zerotorescue@0
 | 
  1335 							name = "Add all items matching...",
 | 
| 
Zerotorescue@0
 | 
  1336 							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@0
 | 
  1337 							--set = massAddItems,
 | 
| 
Zerotorescue@0
 | 
  1338 							get = false,
 | 
| 
Zerotorescue@0
 | 
  1339 						},
 | 
| 
Zerotorescue@0
 | 
  1340 					},
 | 
| 
Zerotorescue@0
 | 
  1341 				},
 | 
| 
Zerotorescue@0
 | 
  1342 				list = {
 | 
| 
Zerotorescue@0
 | 
  1343 					order = 30,
 | 
| 
Zerotorescue@0
 | 
  1344 					type = "group",
 | 
| 
Zerotorescue@0
 | 
  1345 					inline = true,
 | 
| 
Zerotorescue@0
 | 
  1346 					name = "Item list",
 | 
| 
Zerotorescue@0
 | 
  1347 					hidden = UpdateAddItemList,
 | 
| 
Zerotorescue@0
 | 
  1348 					args = {
 | 
| 
Zerotorescue@0
 | 
  1349 					
 | 
| 
Zerotorescue@0
 | 
  1350 					},
 | 
| 
Zerotorescue@0
 | 
  1351 				},
 | 
| 
Zerotorescue@0
 | 
  1352 			},
 | 
| 
Zerotorescue@0
 | 
  1353 		},
 | 
| 
Zerotorescue@0
 | 
  1354 		remove = {
 | 
| 
Zerotorescue@0
 | 
  1355 			order = 40,
 | 
| 
Zerotorescue@0
 | 
  1356 			type = "group",
 | 
| 
Zerotorescue@0
 | 
  1357 			name = "Current items",
 | 
| 
Zerotorescue@0
 | 
  1358 			args = {
 | 
| 
Zerotorescue@0
 | 
  1359 				help = {
 | 
| 
Zerotorescue@0
 | 
  1360 					order = 10,
 | 
| 
Zerotorescue@0
 | 
  1361 					type = "group",
 | 
| 
Zerotorescue@0
 | 
  1362 					inline = true,
 | 
| 
Zerotorescue@0
 | 
  1363 					name = "Help",
 | 
| 
Zerotorescue@0
 | 
  1364 					hidden = false,
 | 
| 
Zerotorescue@0
 | 
  1365 					args = {
 | 
| 
Zerotorescue@0
 | 
  1366 						help = {
 | 
| 
Zerotorescue@0
 | 
  1367 							order = 10,
 | 
| 
Zerotorescue@0
 | 
  1368 							type = "description",
 | 
| 
Zerotorescue@0
 | 
  1369 							name = "Click the items you wish to remove from this group.",
 | 
| 
Zerotorescue@0
 | 
  1370 						},
 | 
| 
Zerotorescue@0
 | 
  1371 					},
 | 
| 
Zerotorescue@0
 | 
  1372 				},
 | 
| 
Zerotorescue@0
 | 
  1373 				list = {
 | 
| 
Zerotorescue@0
 | 
  1374 					order = 20,
 | 
| 
Zerotorescue@0
 | 
  1375 					type = "group",
 | 
| 
Zerotorescue@0
 | 
  1376 					inline = true,
 | 
| 
Zerotorescue@0
 | 
  1377 					name = "Item list",
 | 
| 
Zerotorescue@0
 | 
  1378 					hidden = UpdateRemoveItemList,
 | 
| 
Zerotorescue@0
 | 
  1379 					args = {
 | 
| 
Zerotorescue@0
 | 
  1380 					
 | 
| 
Zerotorescue@0
 | 
  1381 					},
 | 
| 
Zerotorescue@0
 | 
  1382 				},
 | 
| 
Zerotorescue@0
 | 
  1383 				export = {
 | 
| 
Zerotorescue@0
 | 
  1384 					order = 30,
 | 
| 
Zerotorescue@0
 | 
  1385 					type = "group",
 | 
| 
Zerotorescue@0
 | 
  1386 					name = "Export",
 | 
| 
Zerotorescue@0
 | 
  1387 					inline = true,
 | 
| 
Zerotorescue@0
 | 
  1388 					args = {
 | 
| 
Zerotorescue@0
 | 
  1389 						input = {
 | 
| 
Zerotorescue@0
 | 
  1390 							order = 10,
 | 
| 
Zerotorescue@0
 | 
  1391 							type = "input",
 | 
| 
Zerotorescue@0
 | 
  1392 							name = "Item data",
 | 
| 
Zerotorescue@0
 | 
  1393 							width = "full",
 | 
| 
Zerotorescue@0
 | 
  1394 							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
 | 
  1395 							set = false,
 | 
| 
Zerotorescue@0
 | 
  1396 							get = function(info)
 | 
| 
Zerotorescue@0
 | 
  1397 								local groupName = groupIdToName[info[2]];
 | 
| 
Zerotorescue@0
 | 
  1398 								
 | 
| 
Zerotorescue@0
 | 
  1399 								local combinedItemIds;
 | 
| 
Zerotorescue@0
 | 
  1400 								-- Parse items in group and show these
 | 
| 
Zerotorescue@0
 | 
  1401 								for itemId, _ in pairs(addon.db.global.groups[groupName].items) do
 | 
| 
Zerotorescue@0
 | 
  1402 									if not combinedItemIds then
 | 
| 
Zerotorescue@0
 | 
  1403 										combinedItemIds = tostring(itemId);
 | 
| 
Zerotorescue@0
 | 
  1404 									else
 | 
| 
Zerotorescue@0
 | 
  1405 										combinedItemIds = combinedItemIds .. (";%d"):format(itemId);
 | 
| 
Zerotorescue@0
 | 
  1406 									end
 | 
| 
Zerotorescue@0
 | 
  1407 								end
 | 
| 
Zerotorescue@0
 | 
  1408 								
 | 
| 
Zerotorescue@0
 | 
  1409 								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
 | 
  1410 							end,
 | 
| 
Zerotorescue@0
 | 
  1411 						},
 | 
| 
Zerotorescue@0
 | 
  1412 					},
 | 
| 
Zerotorescue@0
 | 
  1413 				},
 | 
| 
Zerotorescue@0
 | 
  1414 			},
 | 
| 
Zerotorescue@0
 | 
  1415 		},
 | 
| 
Zerotorescue@0
 | 
  1416 	},
 | 
| 
Zerotorescue@0
 | 
  1417 };
 | 
| 
Zerotorescue@0
 | 
  1418 
 | 
| 
Zerotorescue@0
 | 
  1419 function addon:MakeGroupOptions()
 | 
| 
Zerotorescue@0
 | 
  1420 	options.args.groups = {
 | 
| 
Zerotorescue@0
 | 
  1421 		order = 1100,
 | 
| 
Zerotorescue@0
 | 
  1422 		type = "group",
 | 
| 
Zerotorescue@0
 | 
  1423 		name = "Groups",
 | 
| 
Zerotorescue@0
 | 
  1424 		desc = "Change a group.",
 | 
| 
Zerotorescue@0
 | 
  1425 		args = {
 | 
| 
Zerotorescue@0
 | 
  1426 			create = {
 | 
| 
Zerotorescue@0
 | 
  1427 				order = 10,
 | 
| 
Zerotorescue@0
 | 
  1428 				type = "group",
 | 
| 
Zerotorescue@0
 | 
  1429 				inline = true,
 | 
| 
Zerotorescue@0
 | 
  1430 				name = "Create a brand new group",
 | 
| 
Zerotorescue@0
 | 
  1431 				args = {
 | 
| 
Zerotorescue@0
 | 
  1432 					name = {
 | 
| 
Zerotorescue@0
 | 
  1433 						order = 10,
 | 
| 
Zerotorescue@0
 | 
  1434 						type = "input",
 | 
| 
Zerotorescue@0
 | 
  1435 						name = "Group name",
 | 
| 
Zerotorescue@0
 | 
  1436 						desc = "The name of the group. You can also use item links as you wish.",
 | 
| 
Zerotorescue@0
 | 
  1437 						validate = ValidateGroupName,
 | 
| 
Zerotorescue@0
 | 
  1438 						set = function(_, value)
 | 
| 
Zerotorescue@0
 | 
  1439 							self.db.global.groups[value] = {};
 | 
| 
Zerotorescue@0
 | 
  1440 								
 | 
| 
Zerotorescue@0
 | 
  1441 							addon:FillGroupOptions();
 | 
| 
Zerotorescue@0
 | 
  1442 						end,
 | 
| 
Zerotorescue@0
 | 
  1443 						get = false,
 | 
| 
Zerotorescue@0
 | 
  1444 						width = "double",
 | 
| 
Zerotorescue@0
 | 
  1445 					},
 | 
| 
Zerotorescue@0
 | 
  1446 				},
 | 
| 
Zerotorescue@0
 | 
  1447 			},
 | 
| 
Zerotorescue@0
 | 
  1448 			import = {
 | 
| 
Zerotorescue@0
 | 
  1449 				order = 20,
 | 
| 
Zerotorescue@0
 | 
  1450 				type = "group",
 | 
| 
Zerotorescue@0
 | 
  1451 				inline = true,
 | 
| 
Zerotorescue@0
 | 
  1452 				name = "Import a group",
 | 
| 
Zerotorescue@0
 | 
  1453 				args = {
 | 
| 
Zerotorescue@0
 | 
  1454 					input = {
 | 
| 
Zerotorescue@0
 | 
  1455 						order = 10,
 | 
| 
Zerotorescue@0
 | 
  1456 						type = "input",
 | 
| 
Zerotorescue@0
 | 
  1457 						multiline = true,
 | 
| 
Zerotorescue@0
 | 
  1458 						name = "Group data",
 | 
| 
Zerotorescue@0
 | 
  1459 						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
 | 
  1460 						set = function(info, value)
 | 
| 
Zerotorescue@9
 | 
  1461 							local data = { string.split("\n", value or "") };
 | 
| 
Zerotorescue@0
 | 
  1462 							
 | 
| 
Zerotorescue@9
 | 
  1463 							for _, current in pairs(data) do
 | 
| 
Zerotorescue@0
 | 
  1464 								if not AceSerializer then
 | 
| 
Zerotorescue@0
 | 
  1465 									AceSerializer = LibStub("AceSerializer-3.0");
 | 
| 
Zerotorescue@0
 | 
  1466 								end
 | 
| 
Zerotorescue@0
 | 
  1467 								
 | 
| 
Zerotorescue@0
 | 
  1468 								local result, temp = AceSerializer:Deserialize(current);
 | 
| 
Zerotorescue@0
 | 
  1469 								
 | 
| 
Zerotorescue@0
 | 
  1470 								if not temp.name then
 | 
| 
Zerotorescue@0
 | 
  1471 									print("|cffff0000The provided data is not supported.|r");
 | 
| 
Zerotorescue@10
 | 
  1472 								elseif ValidateGroupName(nil, temp.name) ~= true then
 | 
| 
Zerotorescue@10
 | 
  1473 									print(("|cffff0000Aborting: A group named \"%s\" already exists.|r"):format(temp.name));
 | 
| 
Zerotorescue@0
 | 
  1474 								else
 | 
| 
Zerotorescue@10
 | 
  1475 									local name = temp.name;
 | 
| 
Zerotorescue@0
 | 
  1476 									temp.name = nil;
 | 
| 
Zerotorescue@9
 | 
  1477 									print(("Importing %s..."):format(name));
 | 
| 
Zerotorescue@10
 | 
  1478 									
 | 
| 
Zerotorescue@10
 | 
  1479 									-- Remove items that are already in another group
 | 
| 
Zerotorescue@10
 | 
  1480 									for value, _ in pairs(temp.items) do
 | 
| 
Zerotorescue@10
 | 
  1481 										local itemId = tonumber(itemid);
 | 
| 
Zerotorescue@10
 | 
  1482 										
 | 
| 
Zerotorescue@10
 | 
  1483 										if not itemId then
 | 
| 
Zerotorescue@10
 | 
  1484 											print(("\"%s\" is not a number."):format(value));
 | 
| 
Zerotorescue@10
 | 
  1485 											temp.items[value] = nil;
 | 
| 
Zerotorescue@10
 | 
  1486 										elseif InGroup(itemId) then
 | 
| 
Zerotorescue@10
 | 
  1487 											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
 | 
  1488 											temp.items[value] = nil;
 | 
| 
Zerotorescue@10
 | 
  1489 										else
 | 
| 
Zerotorescue@10
 | 
  1490 											-- Ensure the keys are numeric
 | 
| 
Zerotorescue@10
 | 
  1491 											temp.items[value] = nil;
 | 
| 
Zerotorescue@10
 | 
  1492 											temp.items[itemId] = true;
 | 
| 
Zerotorescue@10
 | 
  1493 										end
 | 
| 
Zerotorescue@10
 | 
  1494 									end
 | 
| 
Zerotorescue@10
 | 
  1495 									
 | 
| 
Zerotorescue@10
 | 
  1496 									-- Ensure this data isn't received (this would be buggy as exports from other accounts won't know what to do with this)
 | 
| 
Zerotorescue@10
 | 
  1497 									temp.trackAtCharacters = nil;
 | 
| 
Zerotorescue@10
 | 
  1498 									temp.overrideTrackAtCharacters = nil;
 | 
| 
Zerotorescue@10
 | 
  1499 									
 | 
| 
Zerotorescue@10
 | 
  1500 									self.db.global.groups[name] = temp;
 | 
| 
Zerotorescue@0
 | 
  1501 								end
 | 
| 
Zerotorescue@0
 | 
  1502 							end
 | 
| 
Zerotorescue@10
 | 
  1503 							
 | 
| 
Zerotorescue@10
 | 
  1504 							self:FillGroupOptions();
 | 
| 
Zerotorescue@0
 | 
  1505 						end,
 | 
| 
Zerotorescue@0
 | 
  1506 						get = false,
 | 
| 
Zerotorescue@0
 | 
  1507 						width = "full",
 | 
| 
Zerotorescue@0
 | 
  1508 					},
 | 
| 
Zerotorescue@0
 | 
  1509 				},
 | 
| 
Zerotorescue@0
 | 
  1510 			},
 | 
| 
Zerotorescue@0
 | 
  1511 		},
 | 
| 
Zerotorescue@0
 | 
  1512 	};
 | 
| 
Zerotorescue@0
 | 
  1513 end
 | 
| 
Zerotorescue@0
 | 
  1514 
 | 
| 
Zerotorescue@0
 | 
  1515 function addon:FillGroupOptions()
 | 
| 
Zerotorescue@0
 | 
  1516 	for id, name in pairs(groupIdToName) do
 | 
| 
Zerotorescue@0
 | 
  1517 		if type(name) == "string" and not self.db.global.groups[name] then
 | 
| 
Zerotorescue@0
 | 
  1518 			options.args.groups.args[id] = nil;
 | 
| 
Zerotorescue@0
 | 
  1519 			groupIdToName[id] = nil;
 | 
| 
Zerotorescue@0
 | 
  1520 			groupIdToName[name] = nil;
 | 
| 
Zerotorescue@0
 | 
  1521 		end
 | 
| 
Zerotorescue@0
 | 
  1522 	end
 | 
| 
Zerotorescue@0
 | 
  1523 	
 | 
| 
Zerotorescue@0
 | 
  1524 	for name, values in pairs(self.db.global.groups) do
 | 
| 
Zerotorescue@0
 | 
  1525 		if not groupIdToName[name] then
 | 
| 
Zerotorescue@0
 | 
  1526 			options.args.groups.args[tostring(count)] = CopyTable(defaultGroup);
 | 
| 
Zerotorescue@0
 | 
  1527 			
 | 
| 
Zerotorescue@0
 | 
  1528 			groupIdToName[tostring(count)] = name;
 | 
| 
Zerotorescue@0
 | 
  1529 			groupIdToName[name] = true;
 | 
| 
Zerotorescue@0
 | 
  1530 			
 | 
| 
Zerotorescue@0
 | 
  1531 			count = ( count + 1 );
 | 
| 
Zerotorescue@0
 | 
  1532 		end
 | 
| 
Zerotorescue@0
 | 
  1533 	end
 | 
| 
Zerotorescue@0
 | 
  1534 end
 | 
| 
Zerotorescue@0
 | 
  1535 
 | 
| 
Zerotorescue@0
 | 
  1536 function addon:GetItemCount(itemId)
 | 
| 
Zerotorescue@0
 | 
  1537 	return Altoholic:GetItemCount(itemId);
 | 
| 
Zerotorescue@0
 | 
  1538 end
 | 
| 
Zerotorescue@0
 | 
  1539 
 | 
| 
Zerotorescue@1
 | 
  1540 function addon:GetAuctionValue(link)
 | 
| 
Zerotorescue@1
 | 
  1541 	if GetAuctionBuyout then
 | 
| 
Zerotorescue@1
 | 
  1542 		-- Auctionator support
 | 
| 
Zerotorescue@1
 | 
  1543 		
 | 
| 
Zerotorescue@1
 | 
  1544 		local lowBuy = GetAuctionBuyout(link);
 | 
| 
Zerotorescue@1
 | 
  1545 		
 | 
| 
Zerotorescue@1
 | 
  1546 		if lowBuy == nil then
 | 
| 
Zerotorescue@1
 | 
  1547 			-- No auctions up at this time
 | 
| 
Zerotorescue@1
 | 
  1548 			return -1;
 | 
| 
Zerotorescue@1
 | 
  1549 		end
 | 
| 
Zerotorescue@1
 | 
  1550 		
 | 
| 
Zerotorescue@1
 | 
  1551 		return lowBuy;
 | 
| 
Zerotorescue@1
 | 
  1552 	elseif AucAdvanced ~= nil and AucAdvanced.Modules.Util.SimpleAuction ~= nil and AucAdvanced.Modules.Util.SimpleAuction.Private.GetItems ~= nil then
 | 
| 
Zerotorescue@1
 | 
  1553 		-- Auctioneer support
 | 
| 
Zerotorescue@1
 | 
  1554 		
 | 
| 
Zerotorescue@1
 | 
  1555 		local imgSeen, _, _, _, _, lowBuy, _, _ = AucAdvanced.Modules.Util.SimpleAuction.Private.GetItems(link);
 | 
| 
Zerotorescue@1
 | 
  1556 		--local imgseen, image, matchBid, matchBuy, lowBid, lowBuy, aveBuy, aSeen 
 | 
| 
Zerotorescue@1
 | 
  1557 		
 | 
| 
Zerotorescue@1
 | 
  1558 		if imgSeen <= 0 then
 | 
| 
Zerotorescue@1
 | 
  1559 			-- No auctions up at this time
 | 
| 
Zerotorescue@1
 | 
  1560 			return -1;
 | 
| 
Zerotorescue@1
 | 
  1561 		end
 | 
| 
Zerotorescue@1
 | 
  1562 	
 | 
| 
Zerotorescue@1
 | 
  1563 		return lowBuy;
 | 
| 
Zerotorescue@1
 | 
  1564 	end
 | 
| 
Zerotorescue@7
 | 
  1565 	
 | 
| 
Zerotorescue@7
 | 
  1566 	return -2;
 | 
| 
Zerotorescue@1
 | 
  1567 end
 | 
| 
Zerotorescue@1
 | 
  1568 
 | 
| 
Zerotorescue@0
 | 
  1569 
 | 
| 
Zerotorescue@0
 | 
  1570 
 | 
| 
Zerotorescue@0
 | 
  1571 
 | 
| 
Zerotorescue@0
 | 
  1572 function addon:Debug(t)
 | 
| 
Zerotorescue@0
 | 
  1573 	if not self.debugChannel and self.debugChannel ~= false then
 | 
| 
Zerotorescue@0
 | 
  1574 		-- 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
 | 
  1575 		self.debugChannel = false;
 | 
| 
Zerotorescue@0
 | 
  1576 		
 | 
| 
Zerotorescue@0
 | 
  1577 		for i = 1, NUM_CHAT_WINDOWS do
 | 
| 
Zerotorescue@0
 | 
  1578 			local name = GetChatWindowInfo(i);
 | 
| 
Zerotorescue@0
 | 
  1579 			
 | 
| 
Zerotorescue@0
 | 
  1580 			if name:upper() == "DEBUG" then
 | 
| 
Zerotorescue@0
 | 
  1581 				self.debugChannel = _G["ChatFrame" .. i];
 | 
| 
Zerotorescue@0
 | 
  1582 			end
 | 
| 
Zerotorescue@0
 | 
  1583 		end
 | 
| 
Zerotorescue@0
 | 
  1584 	end
 | 
| 
Zerotorescue@0
 | 
  1585 	
 | 
| 
Zerotorescue@0
 | 
  1586 	if self.debugChannel then
 | 
| 
Zerotorescue@0
 | 
  1587 		self.debugChannel:AddMessage(t);
 | 
| 
Zerotorescue@0
 | 
  1588 	end
 | 
| 
Zerotorescue@0
 | 
  1589 end
 |