Mercurial > wow > inventory
changeset 10:c4d0e5d47e10
Ok, please don?t crash again you silly Ace3 multiselect dropdown box. I know you?re itchy, but there?s nothing I can do for you.
Cleaned up group management layout, added a duplicate group button.
Track at character data is erased when exporting/importing groups.
Duplicate items are erased when importing groups.
Bug fixes and speed increases in Summary.
Added a button to refresh the cache.
Added a slider to increase caching speed.
Auction value will no longer be cached if the threshold was set to 0.
author | Zerotorescue |
---|---|
date | Tue, 12 Oct 2010 02:08:37 +0200 |
parents | 3bac0bdd59e2 |
children | 10a2244f7ff0 |
files | Core.lua Inventorium.toc Inventory.toc Summary.lua |
diffstat | 4 files changed, 198 insertions(+), 99 deletions(-) [+] |
line wrap: on
line diff
--- a/Core.lua Sun Oct 10 04:37:21 2010 +0200 +++ b/Core.lua Tue Oct 12 02:08:37 2010 +0200 @@ -527,6 +527,7 @@ end end end, + confirm = true, 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. }, }, @@ -1017,6 +1018,7 @@ return temp; end, get = GetMultiOption, + confirm = true, 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. arg = "overrideTrackAtCharacters", }, @@ -1143,16 +1145,16 @@ name = "Group Management", desc = "Rename, delete or export this group.", args = { - rename = { + actions = { order = 10, type = "group", - name = "Rename", + name = "Actions", inline = true, args = { rename = { order = 10, type = "input", - name = "New group name", + name = "Rename group - New name", desc = "Change the name of this group to something else. You can also use item links here as you wish.", validate = ValidateGroupName, set = function(info, value) @@ -1170,18 +1172,27 @@ get = function(info) return groupIdToName[info[2]]; end, - width = "double", }, - }, - }, - delete = { - order = 20, - type = "group", - name = "Delete", - inline = true, - args = { + duplicate = { + order = 20, + type = "input", + name = "Duplicate group - New name", + desc = "Duplicate this group. You can also use item links here as you wish.\n\nAll item data will be erased.", + validate = ValidateGroupName, + set = function(info, value) + local oldGroupName = groupIdToName[info[2]]; + + addon.db.global.groups[value] = CopyTable(addon.db.global.groups[oldGroupName]); + + -- Reset item data (duplicate items me no want) + addon.db.global.groups[value].items = nil; + + addon:FillGroupOptions(); + end, + get = false, + }, delete = { - order = 10, + order = 30, type = "execute", name = "Delete group", desc = "Delete the currently selected group.", @@ -1198,7 +1209,7 @@ }, }, export = { - order = 30, + order = 40, type = "group", name = "Export", inline = true, @@ -1455,51 +1466,42 @@ end local result, temp = AceSerializer:Deserialize(current); - local name; if not temp.name then print("|cffff0000The provided data is not supported.|r"); - return; + elseif ValidateGroupName(nil, temp.name) ~= true then + print(("|cffff0000Aborting: A group named \"%s\" already exists.|r"):format(temp.name)); else - name = temp.name; + local name = temp.name; temp.name = nil; print(("Importing %s..."):format(name)); + + -- Remove items that are already in another group + for value, _ in pairs(temp.items) do + local itemId = tonumber(itemid); + + if not itemId then + print(("\"%s\" is not a number."):format(value)); + temp.items[value] = nil; + elseif InGroup(itemId) then + print(("Skipping %s (#%d) as it is already in the group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId))); + temp.items[value] = nil; + else + -- Ensure the keys are numeric + temp.items[value] = nil; + temp.items[itemId] = true; + end + end + + -- Ensure this data isn't received (this would be buggy as exports from other accounts won't know what to do with this) + temp.trackAtCharacters = nil; + temp.overrideTrackAtCharacters = nil; + + self.db.global.groups[name] = temp; end - - local newGroupName = string.trim(string.lower(name or "")); - - for name in pairs(self.db.global.groups) do - if string.lower(name) == newGroupName then - print(("|cffff0000Aborting: A group named \"%s\" already exists.|r"):format(name)); - return; - end - end - - -- Remove items that are already in another group - for value, _ in pairs(temp.items) do - local itemId = tonumber(itemid); - - if not itemId then - print(("\"%s\" is not a number."):format(value)); - temp.items[value] = nil; - elseif InGroup(itemId) then - print(("Skipping %s (#%d) as it is already in the group |cfffed000%s|r."):format(select(2, GetItemInfo(itemId)) or "Unknown", itemId, InGroup(itemId))); - temp.items[value] = nil; - else - -- Ensure the keys are numeric - temp.items[value] = nil; - temp.items[itemId] = true; - end - end - - -- Ensure this data isn't received (this would be buggy as exports from other accounts won't know what to do with this) - temp.trackAtCharacters = nil; - temp.overrideTrackAtCharacters = nil; - - self.db.global.groups[name] = temp; - - self:FillGroupOptions(); end + + self:FillGroupOptions(); end, get = false, width = "full",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Inventorium.toc Tue Oct 12 02:08:37 2010 +0200 @@ -0,0 +1,13 @@ +## Interface: 30300 +## Title: Inventorium +## Notes: Keep track of items you wish to keep enough stock on, and refill. +## Author: Zerotorescue +## Version: @project-version@ +## SavedVariables: InventoryDB +## Dependencies: Altoholic +## OptionalDeps: Auc-Advanced, Auc-ScanData, AdvancedTradeSkillWindow, Skillet, GnomeWorks, Auctionator + +embeds.xml + +Core.lua +Summary.lua
--- a/Inventory.toc Sun Oct 10 04:37:21 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -## Interface: 30300 -## Title: Inventory -## Notes: Keep track of items you wish to keep enough stock on, and refill. -## Author: Zerotorescue -## Version: @project-version@ -## SavedVariables: InventoryDB -## Dependencies: Altoholic -## OptionalDeps: Auc-Advanced, Auc-ScanData, AdvancedTradeSkillWindow, Skillet, GnomeWorks, Auctionator - -embeds.xml - -Core.lua -Summary.lua
--- a/Summary.lua Sun Oct 10 04:37:21 2010 +0200 +++ b/Summary.lua Tue Oct 12 02:08:37 2010 +0200 @@ -67,6 +67,8 @@ function mod:BuildMain() LibStub("AceConfigDialog-3.0"):Close("InventoryOptions"); + self:CloseFrame(); + -- Main Window mod.frame = AceGUI:Create("Frame"); mod.frame:SetTitle("Inventory Summary"); @@ -90,6 +92,15 @@ if mod.frame then mod.frame:Release(); mod.frame = nil; + + -- Stop caching + + -- Stop timer + self:CancelTimer(self.tmrUpdater, true); + + -- Reset trackers + CACHE_ITEMS_TOTAL = 0; + CACHE_ITEMS_CURRENT = 0; end end @@ -105,30 +116,82 @@ mod:Build(); end + +-- From http://www.wowwiki.com/API_sort +local function pairsByKeys (t, f) + local a = {} + for n in pairs(t) do table.insert(a, n) end + table.sort(a, f) + local i = 0 -- iterator variable + local iter = function () -- iterator function + i = i + 1 + if a[i] == nil then return nil + else return a[i], t[a[i]] + end + end + return iter +end function mod:Build() - local start = GetTime(); - - mod.scrollFrame:ReleaseChildren(); + local buildStartTime, times = GetTime(), {}; -- We are going to add hunderds of widgets to this container, but don't want it to also cause hunderds of reflows, thus pause reflowing and just do it once when everything is prepared -- This appears to be required for each container we wish to pause, so also do this for the contents mod.scrollFrame:PauseLayout(); + mod.scrollFrame:ReleaseChildren(); + + -- Refresh button + local btnRefresh = AceGUI:Create("Button"); + btnRefresh:SetText("Refresh"); + -- SetTooltip: Reload all item counts and auction values. + btnRefresh:SetRelativeWidth(.2); + btnRefresh:SetCallback("OnClick", function() + -- Reset items cache + table.wipe(itemsCache); + + -- Rebuild itemlist and start caching + mod:Build(); + end); + + mod.scrollFrame:AddChild(btnRefresh); + + -- Speed slider + local btnRefresh = AceGUI:Create("Slider"); + btnRefresh:SetLabel("Processing speed"); + btnRefresh:SetSliderValues(0.01, 1, 0.01); + btnRefresh:SetIsPercent(true); + -- SetTooltip: Change the speed at which item counts and auction values are being cached. Higher is faster but may drastically reduce your FPS while caching. + btnRefresh:SetRelativeWidth(.3); + btnRefresh:SetCallback("OnMouseUp", function(self, event, value) + CACHE_ITEMS_PER_UPDATE = ceil( value * 100 / 5 ); -- max = 20, min = 1 + end); + btnRefresh:SetValue( CACHE_ITEMS_PER_UPDATE * 5 / 100 ); + + mod.scrollFrame:AddChild(btnRefresh); + + times.init = ceil( ( GetTime() - buildStartTime ) * 1000 ); + addon:Debug("Time spent legend: (init / sorting / preparing / building / all)."); + local playerName = UnitName("player"); -- Go through all our stored groups - for groupName, values in pairs(addon.db.global.groups) do + for groupName, values in pairsByKeys(addon.db.global.groups, function(a, b) return a:lower() < b:lower(); end) do + local groupStartTime, groupTimes = GetTime(), {}; + local trackAt = (values.trackAtCharacters or (values.trackAtCharacters == nil and addon.db.global.defaults.trackAtCharacters)); -- Does this group have any items and do we want to track it at this char? if values.items and trackAt[playerName] then + + -- Get group settings local minimumStock = (values.minimumStock or (values.minimumStock == nil and addon.db.global.defaults.minimumStock)); local showWhenBelow = (values.summaryThresholdShow or (values.summaryThresholdShow == nil and addon.db.global.defaults.summaryThresholdShow)); local priceThreshold = (values.priceThreshold or (values.priceThreshold == nil and addon.db.global.defaults.priceThreshold)); local hideWhenBelowPriceThreshold = (values.hideFromSummaryWhenBelowPriceThreshold or (values.hideFromSummaryWhenBelowPriceThreshold == nil and addon.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold)); + -- Make group container local iGroup = AceGUI:Create("InlineGroupWithButton"); iGroup:PauseLayout(); @@ -143,13 +206,15 @@ end, }); + + -- Headers -- Itemlink local lblItem = AceGUI:Create("InteractiveLabel"); lblItem:SetText("|cfffed000Item|r"); lblItem:SetFontObject(GameFontHighlight); - lblItem:SetRelativeWidth(0.7); + lblItem:SetRelativeWidth(.7); lblItem:SetCallback("OnClick", function() ReSort("item"); end); iGroup:AddChild(lblItem); @@ -158,7 +223,7 @@ local lblQuantity = AceGUI:Create("InteractiveLabel"); lblQuantity:SetText("|cfffed000Cur.|r"); lblQuantity:SetFontObject(GameFontHighlight); - lblQuantity:SetRelativeWidth(0.099); + lblQuantity:SetRelativeWidth(.099); lblQuantity:SetCallback("OnClick", function() ReSort("current"); end); iGroup:AddChild(lblQuantity); @@ -167,7 +232,7 @@ local lblMinimumStock = AceGUI:Create("InteractiveLabel"); lblMinimumStock:SetText("|cfffed000Req.|r"); lblMinimumStock:SetFontObject(GameFontHighlight); - lblMinimumStock:SetRelativeWidth(0.099); + lblMinimumStock:SetRelativeWidth(.099); lblMinimumStock:SetCallback("OnClick", function() ReSort("percentage"); end); iGroup:AddChild(lblMinimumStock); @@ -176,11 +241,13 @@ local lblValue = AceGUI:Create("InteractiveLabel"); lblValue:SetText("|cfffed000Value|r"); lblValue:SetFontObject(GameFontHighlight); - lblValue:SetRelativeWidth(0.099); + lblValue:SetRelativeWidth(.099); lblValue:SetCallback("OnClick", function() ReSort("value"); end); iGroup:AddChild(lblValue); + + -- Retrieve items list if not itemsCache[groupName] then itemsCache[groupName] = {}; @@ -192,7 +259,7 @@ id = itemId, name = itemName, link = itemLink, - value = -3,--addon:GetAuctionValue(itemLink), + value = ((priceThreshold == 0) and 0) or -3,-- if no price threshold is set for this item, then don't look it up either --addon:GetAuctionValue(itemLink), rarity = itemRarity, count = -3,--addon:GetItemCount(itemId), set = {}, @@ -201,6 +268,11 @@ end end + groupTimes.init = ceil( ( GetTime() - groupStartTime ) * 1000 ); + + + + -- Sort items table.sort(itemsCache[groupName], function(a, b) if sortMethod == "item" and a.rarity == b.rarity then -- Do a name-compare for items of the same rarity @@ -224,9 +296,9 @@ end elseif sortMethod == "percentage" then if sortDirectory == "ASC" then - return ( a.count / lblMinimumStock ) < ( b.count / lblMinimumStock ); + return ( a.count / minimumStock ) < ( b.count / minimumStock ); else - return ( a.count / lblMinimumStock ) > ( b.count / lblMinimumStock ); + return ( a.count / minimumStock ) > ( b.count / minimumStock ); end elseif sortMethod == "value" then if sortDirectory == "ASC" then @@ -237,14 +309,19 @@ end end); - -- Show stuff + groupTimes.sorting = ceil( ( GetTime() - groupStartTime ) * 1000 ); + + + + + -- Show itemslist for i, item in pairs(itemsCache[groupName]) do if ( item.count / minimumStock ) < showWhenBelow and not (hideWhenBelowPriceThreshold and item.value < priceThreshold) then local btnItemLink = AceGUI:Create("ItemLinkButton"); - btnItemLink:SetUserData("exec", function() - print("Win."); - end); - btnItemLink:SetRelativeWidth(0.7); + --btnItemLink:SetUserData("exec", function() + -- print("Nothing happening yet."); + --end); + btnItemLink:SetRelativeWidth(.7); btnItemLink:SetItemId(item.id); iGroup:AddChild(btnItemLink); @@ -252,40 +329,58 @@ -- Current quantity local lblQuantity = AceGUI:Create("Label"); lblQuantity:SetText(self:DisplayItemCount(item.count, minimumStock)); - lblQuantity:SetRelativeWidth(0.099); + lblQuantity:SetRelativeWidth(.099); iGroup:AddChild(lblQuantity); -- Required stock local lblMinimumStock = AceGUI:Create("Label"); lblMinimumStock:SetText(minimumStock); - lblMinimumStock:SetRelativeWidth(0.099); + lblMinimumStock:SetRelativeWidth(.099); iGroup:AddChild(lblMinimumStock); -- Value local lblValue = AceGUI:Create("Label"); lblValue:SetText(self:DisplayMoney(item.value, priceThreshold)); - lblValue:SetRelativeWidth(0.099); + lblValue:SetRelativeWidth(.099); iGroup:AddChild(lblValue); -- Remember references to the value and current fields so we can fill them later if item.set then - item.set.value = lblValue; - item.set.current = lblQuantity; + -- -3 means the price is unknown, queue look up + if item.value == -3 then + item.set.value = lblValue; + end + if item.count == -3 then + item.set.current = lblQuantity; + end + + -- Don't queue if we already know everything we want to know + if item.value ~= -3 and item.count ~= -3 then + item.set = nil; + end end end end + groupTimes.preparing = ceil( ( GetTime() - groupStartTime ) * 1000 ); + iGroup:ResumeLayout(); mod.scrollFrame:AddChild(iGroup); -- this can take up to .5 seconds, might need to look into again at a later time + + groupTimes.building = ceil( ( GetTime() - groupStartTime ) * 1000 ); end + + addon:Debug(("Building of %s took %d ms (%d / %d / %d / %d / %d)."):format(groupName, ceil( ( GetTime() - groupStartTime ) * 1000 ), groupTimes.init, groupTimes.sorting, groupTimes.preparing, groupTimes.building, ceil( ( GetTime() - buildStartTime ) * 1000 ))); end mod.scrollFrame:ResumeLayout(); mod.scrollFrame:DoLayout(); + addon:Debug(("Done building summary after %d ms."):format(ceil( ( GetTime() - buildStartTime ) * 1000 ))); + if CACHE_ITEMS_TOTAL > 0 then cacheStart = GetTime(); self:CancelTimer(self.tmrUpdater, true); @@ -299,25 +394,29 @@ for groupName, items in pairs(itemsCache) do local minimumStock = addon:GetOptionByKey(groupName, "minimumStock"); local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold"); - local groupUpdated; for _, item in pairs(items) do if item.set then - item.count = addon:GetItemCount(item.id); - if item.set.current and item.set.current.SetText then - item.set.current:SetText(self:DisplayItemCount(item.count, minimumStock)); + if item.count == -3 then + -- Only if item count was queued, update it + item.count = addon:GetItemCount(item.id); + if item.set.current and item.set.current.SetText then + item.set.current:SetText(self:DisplayItemCount(item.count, minimumStock)); + end end - item.value = addon:GetAuctionValue(item.link); - if item.set.value and item.set.value.SetText then - item.set.value:SetText(self:DisplayMoney(item.value, priceThreshold)); + if item.value == -3 then + -- Only if item value was queued, update it + item.value = addon:GetAuctionValue(item.link); + if item.set.value and item.set.value.SetText then + item.set.value:SetText(self:DisplayMoney(item.value, priceThreshold)); + end end item.set = nil; i = i + 1; CACHE_ITEMS_CURRENT = CACHE_ITEMS_CURRENT + 1; - groupUpdated = true; if mod.frame then mod.frame:SetStatusText(("Caching auction values and item-counts... %d%% has already been processed."):format(floor(CACHE_ITEMS_CURRENT / CACHE_ITEMS_TOTAL * 100))); @@ -328,11 +427,6 @@ end end end - - if groupUpdated then - -- Rebuild list so hidden items due to too low prices get added - self:Build(); - end end -- Reset trackers @@ -341,9 +435,12 @@ -- Stop timer self:CancelTimer(self.tmrUpdater, true); + + -- Rebuild list so hidden items due to too low prices get added + self:Build(); -- Announce - mod.frame:SetStatusText("All prices and itemcounts have been cached. This process took " .. ceil(GetTime() - cacheStart) .. " seconds."); + mod.frame:SetStatusText("All required prices and itemcounts have been cached. This process took " .. ceil(GetTime() - cacheStart) .. " seconds."); -- Forget time cacheStart = nil;