break out market browser to individual class files
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
import wx
|
||||
import gui.display as d
|
||||
import gui.globalEvents as GE
|
||||
import gui.marketBrowser as marketBrowser
|
||||
from gui.builtinMarketBrowser.events import ItemSelected, ITEM_SELECTED
|
||||
from gui.builtinViewColumns.state import State
|
||||
from gui.contextMenu import ContextMenu
|
||||
from gui.utils.staticHelpers import DragDropHelper
|
||||
@@ -58,7 +58,7 @@ class BoosterView(d.Display):
|
||||
self.lastFitId = None
|
||||
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
|
||||
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
|
||||
self.mainFrame.Bind(ITEM_SELECTED, self.addItem)
|
||||
|
||||
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
|
||||
self.Bind(wx.EVT_LEFT_DOWN, self.click)
|
||||
@@ -81,7 +81,7 @@ class BoosterView(d.Display):
|
||||
"""
|
||||
|
||||
if data[0] == "market":
|
||||
wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1])))
|
||||
wx.PostEvent(self.mainFrame, ItemSelected(itemID=int(data[1])))
|
||||
|
||||
def kbEvent(self, event):
|
||||
keycode = event.GetKeyCode()
|
||||
|
||||
0
gui/builtinMarketBrowser/__init__.py
Normal file
0
gui/builtinMarketBrowser/__init__.py
Normal file
7
gui/builtinMarketBrowser/events.py
Normal file
7
gui/builtinMarketBrowser/events.py
Normal file
@@ -0,0 +1,7 @@
|
||||
# noinspection PyPackageRequirements
|
||||
import wx.lib.newevent
|
||||
|
||||
ItemSelected, ITEM_SELECTED = wx.lib.newevent.NewEvent()
|
||||
|
||||
RECENTLY_USED_MODULES = -2
|
||||
MAX_RECENTLY_USED_MODULES = 20
|
||||
273
gui/builtinMarketBrowser/itemView.py
Normal file
273
gui/builtinMarketBrowser/itemView.py
Normal file
@@ -0,0 +1,273 @@
|
||||
import wx
|
||||
|
||||
import gui.builtinMarketBrowser.pfSearchBox as SBox
|
||||
from gui.contextMenu import ContextMenu
|
||||
from gui.display import Display
|
||||
from service.attribute import Attribute
|
||||
from service.fit import Fit
|
||||
from gui.utils.staticHelpers import DragDropHelper
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
from gui.builtinMarketBrowser.events import *
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class ItemView(Display):
|
||||
DEFAULT_COLS = ["Base Icon",
|
||||
"Base Name",
|
||||
"attr:power,,,True",
|
||||
"attr:cpu,,,True"]
|
||||
|
||||
def __init__(self, parent, marketBrowser):
|
||||
Display.__init__(self, parent)
|
||||
pyfalog.debug("Initialize ItemView")
|
||||
marketBrowser.Bind(wx.EVT_TREE_SEL_CHANGED, self.selectionMade)
|
||||
|
||||
self.unfilteredStore = set()
|
||||
self.filteredStore = set()
|
||||
self.recentlyUsedModules = set()
|
||||
self.sMkt = marketBrowser.sMkt
|
||||
self.searchMode = marketBrowser.searchMode
|
||||
|
||||
self.marketBrowser = marketBrowser
|
||||
self.marketView = marketBrowser.marketView
|
||||
|
||||
# Set up timer for delaying search on every EVT_TEXT
|
||||
self.searchTimer = wx.Timer(self)
|
||||
self.Bind(wx.EVT_TIMER, self.scheduleSearch, self.searchTimer)
|
||||
|
||||
# Make sure our search actually does interesting stuff
|
||||
self.marketBrowser.search.Bind(SBox.EVT_TEXT_ENTER, self.scheduleSearch)
|
||||
self.marketBrowser.search.Bind(SBox.EVT_SEARCH_BTN, self.scheduleSearch)
|
||||
self.marketBrowser.search.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
|
||||
self.marketBrowser.search.Bind(SBox.EVT_TEXT, self.delaySearch)
|
||||
|
||||
# Make sure WE do interesting stuff too
|
||||
self.Bind(wx.EVT_CONTEXT_MENU, self.contextMenu)
|
||||
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
|
||||
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
|
||||
|
||||
# Make reverse map, used by sorter
|
||||
self.metaMap = self.makeReverseMetaMap()
|
||||
|
||||
# Fill up recently used modules set
|
||||
pyfalog.debug("Fill up recently used modules set")
|
||||
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
|
||||
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
|
||||
|
||||
def delaySearch(self, evt):
|
||||
sFit = Fit.getInstance()
|
||||
self.searchTimer.Stop()
|
||||
self.searchTimer.Start(sFit.serviceFittingOptions["marketSearchDelay"], True) # 150ms
|
||||
|
||||
def startDrag(self, event):
|
||||
row = self.GetFirstSelected()
|
||||
|
||||
if row != -1:
|
||||
data = wx.PyTextDataObject()
|
||||
dataStr = "market:" + str(self.active[row].ID)
|
||||
pyfalog.debug("Dragging from market: " + dataStr)
|
||||
|
||||
data.SetText(dataStr)
|
||||
dropSource = wx.DropSource(self)
|
||||
dropSource.SetData(data)
|
||||
DragDropHelper.data = dataStr
|
||||
dropSource.DoDragDrop()
|
||||
|
||||
def itemActivated(self, event=None):
|
||||
# Check if something is selected, if so, spawn the menu for it
|
||||
sel = self.GetFirstSelected()
|
||||
if sel == -1:
|
||||
return
|
||||
|
||||
if self.mainFrame.getActiveFit():
|
||||
|
||||
self.storeRecentlyUsedMarketItem(self.active[sel].ID)
|
||||
self.recentlyUsedModules = set()
|
||||
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
|
||||
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
|
||||
|
||||
wx.PostEvent(self.mainFrame, ItemSelected(itemID=self.active[sel].ID))
|
||||
|
||||
def storeRecentlyUsedMarketItem(self, itemID):
|
||||
if len(self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]) > MAX_RECENTLY_USED_MODULES:
|
||||
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].pop(0)
|
||||
|
||||
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].append(itemID)
|
||||
|
||||
def selectionMade(self, event=None):
|
||||
self.marketBrowser.searchMode = False
|
||||
# Grab the threeview selection and check if it's fine
|
||||
sel = self.marketView.GetSelection()
|
||||
if sel.IsOk():
|
||||
# Get data field of the selected item (which is a marketGroup ID if anything was selected)
|
||||
seldata = self.marketView.GetPyData(sel)
|
||||
if seldata is not None and seldata != RECENTLY_USED_MODULES:
|
||||
# If market group treeview item doesn't have children (other market groups or dummies),
|
||||
# then it should have items in it and we want to request them
|
||||
if self.marketView.ItemHasChildren(sel) is False:
|
||||
sMkt = self.sMkt
|
||||
# Get current market group
|
||||
mg = sMkt.getMarketGroup(seldata, eager=("items", "items.metaGroup"))
|
||||
# Get all its items
|
||||
items = sMkt.getItemsByMarketGroup(mg)
|
||||
else:
|
||||
items = set()
|
||||
else:
|
||||
# If method was called but selection wasn't actually made or we have a hit on recently used modules
|
||||
if seldata == RECENTLY_USED_MODULES:
|
||||
items = self.recentlyUsedModules
|
||||
else:
|
||||
items = set()
|
||||
|
||||
# Fill store
|
||||
self.updateItemStore(items)
|
||||
|
||||
# Set toggle buttons / use search mode flag if recently used modules category is selected (in order to have all modules listed and not filtered)
|
||||
if seldata is not RECENTLY_USED_MODULES:
|
||||
self.setToggles()
|
||||
else:
|
||||
self.marketBrowser.searchMode = True
|
||||
self.setToggles()
|
||||
|
||||
# Update filtered items
|
||||
self.filterItemStore()
|
||||
|
||||
def updateItemStore(self, items):
|
||||
self.unfilteredStore = items
|
||||
|
||||
def filterItemStore(self):
|
||||
sMkt = self.sMkt
|
||||
selectedMetas = set()
|
||||
for btn in self.marketBrowser.metaButtons:
|
||||
if btn.GetValue():
|
||||
selectedMetas.update(sMkt.META_MAP[btn.metaName])
|
||||
self.filteredStore = sMkt.filterItemsByMeta(self.unfilteredStore, selectedMetas)
|
||||
self.update(list(self.filteredStore))
|
||||
|
||||
def setToggles(self):
|
||||
metaIDs = set()
|
||||
sMkt = self.sMkt
|
||||
for item in self.unfilteredStore:
|
||||
metaIDs.add(sMkt.getMetaGroupIdByItem(item))
|
||||
|
||||
for btn in self.marketBrowser.metaButtons:
|
||||
btn.reset()
|
||||
btnMetas = sMkt.META_MAP[btn.metaName]
|
||||
if len(metaIDs.intersection(btnMetas)) > 0:
|
||||
btn.setMetaAvailable(True)
|
||||
else:
|
||||
btn.setMetaAvailable(False)
|
||||
|
||||
def scheduleSearch(self, event=None):
|
||||
self.searchTimer.Stop() # Cancel any pending timers
|
||||
search = self.marketBrowser.search.GetLineText(0)
|
||||
# Make sure we do not count wildcard as search symbol
|
||||
realsearch = search.replace("*", "")
|
||||
# Re-select market group if search query has zero length
|
||||
if len(realsearch) == 0:
|
||||
self.selectionMade()
|
||||
return
|
||||
# Show nothing if query is too short
|
||||
elif len(realsearch) < 3:
|
||||
self.clearSearch()
|
||||
return
|
||||
|
||||
self.marketBrowser.searchMode = True
|
||||
self.sMkt.searchItems(search, self.populateSearch)
|
||||
|
||||
def clearSearch(self, event=None):
|
||||
# Wipe item store and update everything to accomodate with it
|
||||
# If clearSearch was generated by SearchCtrl's Cancel button, clear the content also
|
||||
|
||||
if event:
|
||||
self.marketBrowser.search.Clear()
|
||||
|
||||
self.marketBrowser.searchMode = False
|
||||
self.updateItemStore(set())
|
||||
self.setToggles()
|
||||
self.filterItemStore()
|
||||
|
||||
def populateSearch(self, items):
|
||||
# If we're no longer searching, dump the results
|
||||
if self.marketBrowser.searchMode is False:
|
||||
return
|
||||
self.updateItemStore(items)
|
||||
self.setToggles()
|
||||
self.filterItemStore()
|
||||
|
||||
def itemSort(self, item):
|
||||
sMkt = self.sMkt
|
||||
catname = sMkt.getCategoryByItem(item).name
|
||||
try:
|
||||
mktgrpid = sMkt.getMarketGroupByItem(item).ID
|
||||
except AttributeError:
|
||||
mktgrpid = None
|
||||
print("unable to find market group for", item.name)
|
||||
parentname = sMkt.getParentItemByItem(item).name
|
||||
# Get position of market group
|
||||
metagrpid = sMkt.getMetaGroupIdByItem(item)
|
||||
metatab = self.metaMap.get(metagrpid)
|
||||
metalvl = self.metalvls.get(item.ID, 0)
|
||||
return catname, mktgrpid, parentname, metatab, metalvl, item.name
|
||||
|
||||
def contextMenu(self, event):
|
||||
# Check if something is selected, if so, spawn the menu for it
|
||||
sel = self.GetFirstSelected()
|
||||
if sel == -1:
|
||||
return
|
||||
|
||||
item = self.active[sel]
|
||||
|
||||
sMkt = self.sMkt
|
||||
sourceContext = "marketItemGroup" if self.marketBrowser.searchMode is False else "marketItemMisc"
|
||||
itemContext = sMkt.getCategoryByItem(item).name
|
||||
|
||||
menu = ContextMenu.getMenu((item,), (sourceContext, itemContext))
|
||||
self.PopupMenu(menu)
|
||||
|
||||
def populate(self, items):
|
||||
if len(items) > 0:
|
||||
# Get dictionary with meta level attribute
|
||||
sAttr = Attribute.getInstance()
|
||||
attrs = sAttr.getAttributeInfo("metaLevel")
|
||||
sMkt = self.sMkt
|
||||
self.metalvls = sMkt.directAttrRequest(items, attrs)
|
||||
# Clear selection
|
||||
self.deselectItems()
|
||||
# Perform sorting, using item's meta levels besides other stuff
|
||||
items.sort(key=self.itemSort)
|
||||
# Mark current item list as active
|
||||
self.active = items
|
||||
# Show them
|
||||
Display.populate(self, items)
|
||||
|
||||
def refresh(self, items):
|
||||
if len(items) > 1:
|
||||
# Get dictionary with meta level attribute
|
||||
sAttr = Attribute.getInstance()
|
||||
attrs = sAttr.getAttributeInfo("metaLevel")
|
||||
sMkt = self.sMkt
|
||||
self.metalvls = sMkt.directAttrRequest(items, attrs)
|
||||
# Re-sort stuff
|
||||
items.sort(key=self.itemSort)
|
||||
|
||||
for i, item in enumerate(items[:9]):
|
||||
# set shortcut info for first 9 modules
|
||||
item.marketShortcut = i + 1
|
||||
|
||||
Display.refresh(self, items)
|
||||
|
||||
def makeReverseMetaMap(self):
|
||||
"""
|
||||
Form map which tells in which tab items of given metagroup are located
|
||||
"""
|
||||
revmap = {}
|
||||
i = 0
|
||||
for mgids in self.sMkt.META_MAP.itervalues():
|
||||
for mgid in mgids:
|
||||
revmap[mgid] = i
|
||||
i += 1
|
||||
return revmap
|
||||
99
gui/builtinMarketBrowser/marketTree.py
Normal file
99
gui/builtinMarketBrowser/marketTree.py
Normal file
@@ -0,0 +1,99 @@
|
||||
import wx
|
||||
|
||||
from gui.cachingImageList import CachingImageList
|
||||
from gui.builtinMarketBrowser.events import *
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class MarketTree(wx.TreeCtrl):
|
||||
def __init__(self, parent, marketBrowser):
|
||||
wx.TreeCtrl.__init__(self, parent, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
|
||||
pyfalog.debug("Initialize marketTree")
|
||||
self.root = self.AddRoot("root")
|
||||
|
||||
self.imageList = CachingImageList(16, 16)
|
||||
self.SetImageList(self.imageList)
|
||||
|
||||
self.sMkt = marketBrowser.sMkt
|
||||
self.marketBrowser = marketBrowser
|
||||
|
||||
# Form market tree root
|
||||
sMkt = self.sMkt
|
||||
for mktGrp in sMkt.getMarketRoot():
|
||||
iconId = self.addImage(sMkt.getIconByMarketGroup(mktGrp))
|
||||
childId = self.AppendItem(self.root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
|
||||
# All market groups which were never expanded are dummies, here we assume
|
||||
# that all root market groups are expandable
|
||||
self.AppendItem(childId, "dummy")
|
||||
self.SortChildren(self.root)
|
||||
|
||||
# Add recently used modules node
|
||||
rumIconId = self.addImage("market_small", "gui")
|
||||
self.AppendItem(self.root, "Recently Used Modules", rumIconId, data=wx.TreeItemData(RECENTLY_USED_MODULES))
|
||||
|
||||
# Bind our lookup method to when the tree gets expanded
|
||||
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
|
||||
|
||||
def addImage(self, iconFile, location="icons"):
|
||||
if iconFile is None:
|
||||
return -1
|
||||
return self.imageList.GetImageIndex(iconFile, location)
|
||||
|
||||
def expandLookup(self, event):
|
||||
"""Process market tree expands"""
|
||||
root = event.Item
|
||||
child = self.GetFirstChild(root)[0]
|
||||
# If child of given market group is a dummy
|
||||
if self.GetItemText(child) == "dummy":
|
||||
# Delete it
|
||||
self.Delete(child)
|
||||
# And add real market group contents
|
||||
sMkt = self.sMkt
|
||||
currentMktGrp = sMkt.getMarketGroup(self.GetPyData(root), eager="children")
|
||||
for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
|
||||
# If market should have items but it doesn't, do not show it
|
||||
if sMkt.marketGroupValidityCheck(childMktGrp) is False:
|
||||
continue
|
||||
iconId = self.addImage(sMkt.getIconByMarketGroup(childMktGrp))
|
||||
try:
|
||||
childId = self.AppendItem(root, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID))
|
||||
except Exception as e:
|
||||
pyfalog.debug("Error appending item.")
|
||||
pyfalog.debug(e)
|
||||
continue
|
||||
if sMkt.marketGroupHasTypesCheck(childMktGrp) is False:
|
||||
self.AppendItem(childId, "dummy")
|
||||
|
||||
self.SortChildren(root)
|
||||
|
||||
def jump(self, item):
|
||||
"""Open market group and meta tab of given item"""
|
||||
self.marketBrowser.searchMode = False
|
||||
sMkt = self.sMkt
|
||||
mg = sMkt.getMarketGroupByItem(item)
|
||||
|
||||
jumpList = []
|
||||
while mg is not None:
|
||||
jumpList.append(mg.ID)
|
||||
mg = mg.parent
|
||||
|
||||
for id in sMkt.ROOT_MARKET_GROUPS:
|
||||
if id in jumpList:
|
||||
jumpList = jumpList[:jumpList.index(id) + 1]
|
||||
|
||||
item = self.root
|
||||
for i in range(len(jumpList) - 1, -1, -1):
|
||||
target = jumpList[i]
|
||||
child, cookie = self.GetFirstChild(item)
|
||||
while self.GetItemPyData(child) != target:
|
||||
child, cookie = self.GetNextChild(item, cookie)
|
||||
|
||||
item = child
|
||||
self.Expand(item)
|
||||
|
||||
self.SelectItem(item)
|
||||
self.marketBrowser.itemView.selectionMade()
|
||||
|
||||
24
gui/builtinMarketBrowser/metaButton.py
Normal file
24
gui/builtinMarketBrowser/metaButton.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from gui.builtinMarketBrowser.events import *
|
||||
from logbook import Logger
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class MetaButton(wx.ToggleButton):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MetaButton, self).__init__(*args, **kwargs)
|
||||
self.setUserSelection(True)
|
||||
|
||||
def setUserSelection(self, isSelected):
|
||||
self.userSelected = isSelected
|
||||
self.SetValue(isSelected)
|
||||
|
||||
def setMetaAvailable(self, isAvailable):
|
||||
self.Enable(isAvailable)
|
||||
# need to also SetValue(False) for windows because Enabled=False AND SetValue(True) looks enabled.
|
||||
if not isAvailable:
|
||||
self.SetValue(False)
|
||||
|
||||
def reset(self):
|
||||
self.Enable(True)
|
||||
self.SetValue(self.userSelected)
|
||||
13
gui/builtinMarketBrowser/searchBox.py
Normal file
13
gui/builtinMarketBrowser/searchBox.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from gui.bitmapLoader import BitmapLoader
|
||||
from pfSearchBox import PFSearchBox
|
||||
|
||||
|
||||
class SearchBox(PFSearchBox):
|
||||
def __init__(self, parent, **kwargs):
|
||||
PFSearchBox.__init__(self, parent, **kwargs)
|
||||
cancelBitmap = BitmapLoader.getBitmap("fit_delete_small", "gui")
|
||||
searchBitmap = BitmapLoader.getBitmap("fsearch_small", "gui")
|
||||
self.SetSearchBitmap(searchBitmap)
|
||||
self.SetCancelBitmap(cancelBitmap)
|
||||
self.ShowSearchButton()
|
||||
self.ShowCancelButton()
|
||||
@@ -22,7 +22,7 @@ import wx
|
||||
# noinspection PyPackageRequirements
|
||||
import wx.lib.newevent
|
||||
import gui.mainFrame
|
||||
import gui.marketBrowser
|
||||
from gui.builtinMarketBrowser.events import ItemSelected, ITEM_SELECTED
|
||||
import gui.display as d
|
||||
from gui.contextMenu import ContextMenu
|
||||
from gui.builtinShipBrowser.events import *
|
||||
@@ -140,7 +140,7 @@ class FittingView(d.Display):
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
|
||||
self.mainFrame.Bind(EVT_FIT_RENAMED, self.fitRenamed)
|
||||
self.mainFrame.Bind(EVT_FIT_REMOVED, self.fitRemoved)
|
||||
self.mainFrame.Bind(gui.marketBrowser.ITEM_SELECTED, self.appendItem)
|
||||
self.mainFrame.Bind(ITEM_SELECTED, self.appendItem)
|
||||
|
||||
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
|
||||
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
|
||||
@@ -217,7 +217,7 @@ class FittingView(d.Display):
|
||||
self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.fitChanged)
|
||||
self.mainFrame.Unbind(EVT_FIT_RENAMED, handler=self.fitRenamed)
|
||||
self.mainFrame.Unbind(EVT_FIT_REMOVED, handler=self.fitRemoved)
|
||||
self.mainFrame.Unbind(gui.marketBrowser.ITEM_SELECTED, handler=self.appendItem)
|
||||
self.mainFrame.Unbind(ITEM_SELECTED, handler=self.appendItem)
|
||||
|
||||
d.Display.Destroy(self)
|
||||
|
||||
@@ -394,7 +394,7 @@ class FittingView(d.Display):
|
||||
moduleChanged = sFit.changeModule(fitID, self.mods[dstRow].modPosition, srcIdx)
|
||||
if moduleChanged is None:
|
||||
# the new module doesn't fit in specified slot, try to simply append it
|
||||
wx.PostEvent(self.mainFrame, gui.marketBrowser.ItemSelected(itemID=srcIdx))
|
||||
wx.PostEvent(self.mainFrame, ItemSelected(itemID=srcIdx))
|
||||
|
||||
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit(), action="modadd", typeID=srcIdx))
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ import wx
|
||||
# noinspection PyPackageRequirements
|
||||
from wx.lib.buttons import GenBitmapButton
|
||||
|
||||
from service.market import Market
|
||||
import gui.builtinMarketBrowser.pfSearchBox as SBox
|
||||
import gui.display as d
|
||||
import gui.PFSearchBox as SBox
|
||||
from gui.bitmapLoader import BitmapLoader
|
||||
from gui.marketBrowser import SearchBox
|
||||
from service.market import Market
|
||||
|
||||
|
||||
class BaseImplantEditorView(wx.Panel):
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
import wx
|
||||
|
||||
import gui.globalEvents as GE
|
||||
from gui.marketBrowser import ITEM_SELECTED, ItemSelected
|
||||
from gui.builtinMarketBrowser.events import ItemSelected, ITEM_SELECTED
|
||||
from gui.display import Display
|
||||
from gui.builtinViewColumns.state import State
|
||||
from gui.contextMenu import ContextMenu
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
import wx
|
||||
|
||||
import gui.globalEvents as GE
|
||||
import gui.marketBrowser as marketBrowser
|
||||
from gui.builtinMarketBrowser.events import ItemSelected, ITEM_SELECTED
|
||||
import gui.mainFrame
|
||||
import gui.display as d
|
||||
from gui.builtinViewColumns.state import State
|
||||
@@ -129,7 +129,7 @@ class FighterDisplay(d.Display):
|
||||
self.hoveredColumn = None
|
||||
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
|
||||
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
|
||||
self.mainFrame.Bind(ITEM_SELECTED, self.addItem)
|
||||
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
|
||||
self.Bind(wx.EVT_LEFT_DOWN, self.click)
|
||||
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
|
||||
@@ -208,7 +208,7 @@ class FighterDisplay(d.Display):
|
||||
if srcRow != -1 and dstRow != -1:
|
||||
self._merge(srcRow, dstRow)
|
||||
elif data[0] == "market":
|
||||
wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1])))
|
||||
wx.PostEvent(self.mainFrame, ItemSelected(itemID=int(data[1])))
|
||||
|
||||
@staticmethod
|
||||
def _merge(src, dst):
|
||||
|
||||
@@ -45,7 +45,8 @@ import gui.globalEvents as GE
|
||||
from gui.bitmapLoader import BitmapLoader
|
||||
from gui.mainMenuBar import MainMenuBar
|
||||
from gui.additionsPane import AdditionsPane
|
||||
from gui.marketBrowser import MarketBrowser, ItemSelected
|
||||
from gui.marketBrowser import MarketBrowser
|
||||
from gui.builtinMarketBrowser.events import ItemSelected
|
||||
from gui.multiSwitch import MultiSwitch
|
||||
from gui.statsPane import StatsPane
|
||||
from gui.shipBrowser import ShipBrowser
|
||||
|
||||
@@ -19,44 +19,19 @@
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
|
||||
from service.market import Market
|
||||
from service.fit import Fit
|
||||
from service.attribute import Attribute
|
||||
from gui.display import Display
|
||||
import gui.PFSearchBox as SBox
|
||||
from gui.cachingImageList import CachingImageList
|
||||
from gui.contextMenu import ContextMenu
|
||||
from gui.bitmapLoader import BitmapLoader
|
||||
|
||||
from gui.builtinMarketBrowser.searchBox import SearchBox
|
||||
from gui.builtinMarketBrowser.itemView import ItemView
|
||||
from gui.builtinMarketBrowser.metaButton import MetaButton
|
||||
from gui.builtinMarketBrowser.marketTree import MarketTree
|
||||
from gui.builtinMarketBrowser.events import *
|
||||
|
||||
from logbook import Logger
|
||||
from utils.staticHelpers import DragDropHelper
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
ItemSelected, ITEM_SELECTED = wx.lib.newevent.NewEvent()
|
||||
|
||||
RECENTLY_USED_MODULES = -2
|
||||
MAX_RECENTLY_USED_MODULES = 20
|
||||
|
||||
|
||||
class MetaButton(wx.ToggleButton):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MetaButton, self).__init__(*args, **kwargs)
|
||||
self.setUserSelection(True)
|
||||
|
||||
def setUserSelection(self, isSelected):
|
||||
self.userSelected = isSelected
|
||||
self.SetValue(isSelected)
|
||||
|
||||
def setMetaAvailable(self, isAvailable):
|
||||
self.Enable(isAvailable)
|
||||
# need to also SetValue(False) for windows because Enabled=False AND SetValue(True) looks enabled.
|
||||
if not isAvailable:
|
||||
self.SetValue(False)
|
||||
|
||||
def reset(self):
|
||||
self.Enable(True)
|
||||
self.SetValue(self.userSelected)
|
||||
|
||||
|
||||
class MarketBrowser(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
@@ -125,362 +100,3 @@ class MarketBrowser(wx.Panel):
|
||||
def jump(self, item):
|
||||
self.marketView.jump(item)
|
||||
|
||||
|
||||
class SearchBox(SBox.PFSearchBox):
|
||||
def __init__(self, parent, **kwargs):
|
||||
SBox.PFSearchBox.__init__(self, parent, **kwargs)
|
||||
cancelBitmap = BitmapLoader.getBitmap("fit_delete_small", "gui")
|
||||
searchBitmap = BitmapLoader.getBitmap("fsearch_small", "gui")
|
||||
self.SetSearchBitmap(searchBitmap)
|
||||
self.SetCancelBitmap(cancelBitmap)
|
||||
self.ShowSearchButton()
|
||||
self.ShowCancelButton()
|
||||
|
||||
|
||||
class MarketTree(wx.TreeCtrl):
|
||||
def __init__(self, parent, marketBrowser):
|
||||
wx.TreeCtrl.__init__(self, parent, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
|
||||
pyfalog.debug("Initialize marketTree")
|
||||
self.root = self.AddRoot("root")
|
||||
|
||||
self.imageList = CachingImageList(16, 16)
|
||||
self.SetImageList(self.imageList)
|
||||
|
||||
self.sMkt = marketBrowser.sMkt
|
||||
self.marketBrowser = marketBrowser
|
||||
|
||||
# Form market tree root
|
||||
sMkt = self.sMkt
|
||||
for mktGrp in sMkt.getMarketRoot():
|
||||
iconId = self.addImage(sMkt.getIconByMarketGroup(mktGrp))
|
||||
childId = self.AppendItem(self.root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
|
||||
# All market groups which were never expanded are dummies, here we assume
|
||||
# that all root market groups are expandable
|
||||
self.AppendItem(childId, "dummy")
|
||||
self.SortChildren(self.root)
|
||||
|
||||
# Add recently used modules node
|
||||
rumIconId = self.addImage("market_small", "gui")
|
||||
self.AppendItem(self.root, "Recently Used Modules", rumIconId, data=wx.TreeItemData(RECENTLY_USED_MODULES))
|
||||
|
||||
# Bind our lookup method to when the tree gets expanded
|
||||
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
|
||||
|
||||
def addImage(self, iconFile, location="icons"):
|
||||
if iconFile is None:
|
||||
return -1
|
||||
return self.imageList.GetImageIndex(iconFile, location)
|
||||
|
||||
def expandLookup(self, event):
|
||||
"""Process market tree expands"""
|
||||
root = event.Item
|
||||
child = self.GetFirstChild(root)[0]
|
||||
# If child of given market group is a dummy
|
||||
if self.GetItemText(child) == "dummy":
|
||||
# Delete it
|
||||
self.Delete(child)
|
||||
# And add real market group contents
|
||||
sMkt = self.sMkt
|
||||
currentMktGrp = sMkt.getMarketGroup(self.GetPyData(root), eager="children")
|
||||
for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
|
||||
# If market should have items but it doesn't, do not show it
|
||||
if sMkt.marketGroupValidityCheck(childMktGrp) is False:
|
||||
continue
|
||||
iconId = self.addImage(sMkt.getIconByMarketGroup(childMktGrp))
|
||||
try:
|
||||
childId = self.AppendItem(root, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID))
|
||||
except Exception as e:
|
||||
pyfalog.debug("Error appending item.")
|
||||
pyfalog.debug(e)
|
||||
continue
|
||||
if sMkt.marketGroupHasTypesCheck(childMktGrp) is False:
|
||||
self.AppendItem(childId, "dummy")
|
||||
|
||||
self.SortChildren(root)
|
||||
|
||||
def jump(self, item):
|
||||
"""Open market group and meta tab of given item"""
|
||||
self.marketBrowser.searchMode = False
|
||||
sMkt = self.sMkt
|
||||
mg = sMkt.getMarketGroupByItem(item)
|
||||
|
||||
jumpList = []
|
||||
while mg is not None:
|
||||
jumpList.append(mg.ID)
|
||||
mg = mg.parent
|
||||
|
||||
for id in sMkt.ROOT_MARKET_GROUPS:
|
||||
if id in jumpList:
|
||||
jumpList = jumpList[:jumpList.index(id) + 1]
|
||||
|
||||
item = self.root
|
||||
for i in range(len(jumpList) - 1, -1, -1):
|
||||
target = jumpList[i]
|
||||
child, cookie = self.GetFirstChild(item)
|
||||
while self.GetItemPyData(child) != target:
|
||||
child, cookie = self.GetNextChild(item, cookie)
|
||||
|
||||
item = child
|
||||
self.Expand(item)
|
||||
|
||||
self.SelectItem(item)
|
||||
self.marketBrowser.itemView.selectionMade()
|
||||
|
||||
|
||||
class ItemView(Display):
|
||||
DEFAULT_COLS = ["Base Icon",
|
||||
"Base Name",
|
||||
"attr:power,,,True",
|
||||
"attr:cpu,,,True"]
|
||||
|
||||
def __init__(self, parent, marketBrowser):
|
||||
Display.__init__(self, parent)
|
||||
pyfalog.debug("Initialize ItemView")
|
||||
marketBrowser.Bind(wx.EVT_TREE_SEL_CHANGED, self.selectionMade)
|
||||
|
||||
self.unfilteredStore = set()
|
||||
self.filteredStore = set()
|
||||
self.recentlyUsedModules = set()
|
||||
self.sMkt = marketBrowser.sMkt
|
||||
self.searchMode = marketBrowser.searchMode
|
||||
|
||||
self.marketBrowser = marketBrowser
|
||||
self.marketView = marketBrowser.marketView
|
||||
|
||||
# Set up timer for delaying search on every EVT_TEXT
|
||||
self.searchTimer = wx.Timer(self)
|
||||
self.Bind(wx.EVT_TIMER, self.scheduleSearch, self.searchTimer)
|
||||
|
||||
# Make sure our search actually does interesting stuff
|
||||
self.marketBrowser.search.Bind(SBox.EVT_TEXT_ENTER, self.scheduleSearch)
|
||||
self.marketBrowser.search.Bind(SBox.EVT_SEARCH_BTN, self.scheduleSearch)
|
||||
self.marketBrowser.search.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
|
||||
self.marketBrowser.search.Bind(SBox.EVT_TEXT, self.delaySearch)
|
||||
|
||||
# Make sure WE do interesting stuff too
|
||||
self.Bind(wx.EVT_CONTEXT_MENU, self.contextMenu)
|
||||
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
|
||||
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
|
||||
|
||||
# Make reverse map, used by sorter
|
||||
self.metaMap = self.makeReverseMetaMap()
|
||||
|
||||
# Fill up recently used modules set
|
||||
pyfalog.debug("Fill up recently used modules set")
|
||||
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
|
||||
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
|
||||
|
||||
def delaySearch(self, evt):
|
||||
sFit = Fit.getInstance()
|
||||
self.searchTimer.Stop()
|
||||
self.searchTimer.Start(sFit.serviceFittingOptions["marketSearchDelay"], True) # 150ms
|
||||
|
||||
def startDrag(self, event):
|
||||
row = self.GetFirstSelected()
|
||||
|
||||
if row != -1:
|
||||
data = wx.PyTextDataObject()
|
||||
dataStr = "market:" + str(self.active[row].ID)
|
||||
pyfalog.debug("Dragging from market: " + dataStr)
|
||||
|
||||
data.SetText(dataStr)
|
||||
dropSource = wx.DropSource(self)
|
||||
dropSource.SetData(data)
|
||||
DragDropHelper.data = dataStr
|
||||
dropSource.DoDragDrop()
|
||||
|
||||
def itemActivated(self, event=None):
|
||||
# Check if something is selected, if so, spawn the menu for it
|
||||
sel = self.GetFirstSelected()
|
||||
if sel == -1:
|
||||
return
|
||||
|
||||
if self.mainFrame.getActiveFit():
|
||||
|
||||
self.storeRecentlyUsedMarketItem(self.active[sel].ID)
|
||||
self.recentlyUsedModules = set()
|
||||
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
|
||||
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
|
||||
|
||||
wx.PostEvent(self.mainFrame, ItemSelected(itemID=self.active[sel].ID))
|
||||
|
||||
def storeRecentlyUsedMarketItem(self, itemID):
|
||||
if len(self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]) > MAX_RECENTLY_USED_MODULES:
|
||||
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].pop(0)
|
||||
|
||||
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].append(itemID)
|
||||
|
||||
def selectionMade(self, event=None):
|
||||
self.marketBrowser.searchMode = False
|
||||
# Grab the threeview selection and check if it's fine
|
||||
sel = self.marketView.GetSelection()
|
||||
if sel.IsOk():
|
||||
# Get data field of the selected item (which is a marketGroup ID if anything was selected)
|
||||
seldata = self.marketView.GetPyData(sel)
|
||||
if seldata is not None and seldata != RECENTLY_USED_MODULES:
|
||||
# If market group treeview item doesn't have children (other market groups or dummies),
|
||||
# then it should have items in it and we want to request them
|
||||
if self.marketView.ItemHasChildren(sel) is False:
|
||||
sMkt = self.sMkt
|
||||
# Get current market group
|
||||
mg = sMkt.getMarketGroup(seldata, eager=("items", "items.metaGroup"))
|
||||
# Get all its items
|
||||
items = sMkt.getItemsByMarketGroup(mg)
|
||||
else:
|
||||
items = set()
|
||||
else:
|
||||
# If method was called but selection wasn't actually made or we have a hit on recently used modules
|
||||
if seldata == RECENTLY_USED_MODULES:
|
||||
items = self.recentlyUsedModules
|
||||
else:
|
||||
items = set()
|
||||
|
||||
# Fill store
|
||||
self.updateItemStore(items)
|
||||
|
||||
# Set toggle buttons / use search mode flag if recently used modules category is selected (in order to have all modules listed and not filtered)
|
||||
if seldata is not RECENTLY_USED_MODULES:
|
||||
self.setToggles()
|
||||
else:
|
||||
self.marketBrowser.searchMode = True
|
||||
self.setToggles()
|
||||
|
||||
# Update filtered items
|
||||
self.filterItemStore()
|
||||
|
||||
def updateItemStore(self, items):
|
||||
self.unfilteredStore = items
|
||||
|
||||
def filterItemStore(self):
|
||||
sMkt = self.sMkt
|
||||
selectedMetas = set()
|
||||
for btn in self.marketBrowser.metaButtons:
|
||||
if btn.GetValue():
|
||||
selectedMetas.update(sMkt.META_MAP[btn.metaName])
|
||||
self.filteredStore = sMkt.filterItemsByMeta(self.unfilteredStore, selectedMetas)
|
||||
self.update(list(self.filteredStore))
|
||||
|
||||
def setToggles(self):
|
||||
metaIDs = set()
|
||||
sMkt = self.sMkt
|
||||
for item in self.unfilteredStore:
|
||||
metaIDs.add(sMkt.getMetaGroupIdByItem(item))
|
||||
|
||||
for btn in self.marketBrowser.metaButtons:
|
||||
btn.reset()
|
||||
btnMetas = sMkt.META_MAP[btn.metaName]
|
||||
if len(metaIDs.intersection(btnMetas)) > 0:
|
||||
btn.setMetaAvailable(True)
|
||||
else:
|
||||
btn.setMetaAvailable(False)
|
||||
|
||||
def scheduleSearch(self, event=None):
|
||||
self.searchTimer.Stop() # Cancel any pending timers
|
||||
search = self.marketBrowser.search.GetLineText(0)
|
||||
# Make sure we do not count wildcard as search symbol
|
||||
realsearch = search.replace("*", "")
|
||||
# Re-select market group if search query has zero length
|
||||
if len(realsearch) == 0:
|
||||
self.selectionMade()
|
||||
return
|
||||
# Show nothing if query is too short
|
||||
elif len(realsearch) < 3:
|
||||
self.clearSearch()
|
||||
return
|
||||
|
||||
self.marketBrowser.searchMode = True
|
||||
self.sMkt.searchItems(search, self.populateSearch)
|
||||
|
||||
def clearSearch(self, event=None):
|
||||
# Wipe item store and update everything to accomodate with it
|
||||
# If clearSearch was generated by SearchCtrl's Cancel button, clear the content also
|
||||
|
||||
if event:
|
||||
self.marketBrowser.search.Clear()
|
||||
|
||||
self.marketBrowser.searchMode = False
|
||||
self.updateItemStore(set())
|
||||
self.setToggles()
|
||||
self.filterItemStore()
|
||||
|
||||
def populateSearch(self, items):
|
||||
# If we're no longer searching, dump the results
|
||||
if self.marketBrowser.searchMode is False:
|
||||
return
|
||||
self.updateItemStore(items)
|
||||
self.setToggles()
|
||||
self.filterItemStore()
|
||||
|
||||
def itemSort(self, item):
|
||||
sMkt = self.sMkt
|
||||
catname = sMkt.getCategoryByItem(item).name
|
||||
try:
|
||||
mktgrpid = sMkt.getMarketGroupByItem(item).ID
|
||||
except AttributeError:
|
||||
mktgrpid = None
|
||||
print("unable to find market group for", item.name)
|
||||
parentname = sMkt.getParentItemByItem(item).name
|
||||
# Get position of market group
|
||||
metagrpid = sMkt.getMetaGroupIdByItem(item)
|
||||
metatab = self.metaMap.get(metagrpid)
|
||||
metalvl = self.metalvls.get(item.ID, 0)
|
||||
return catname, mktgrpid, parentname, metatab, metalvl, item.name
|
||||
|
||||
def contextMenu(self, event):
|
||||
# Check if something is selected, if so, spawn the menu for it
|
||||
sel = self.GetFirstSelected()
|
||||
if sel == -1:
|
||||
return
|
||||
|
||||
item = self.active[sel]
|
||||
|
||||
sMkt = self.sMkt
|
||||
sourceContext = "marketItemGroup" if self.marketBrowser.searchMode is False else "marketItemMisc"
|
||||
itemContext = sMkt.getCategoryByItem(item).name
|
||||
|
||||
menu = ContextMenu.getMenu((item,), (sourceContext, itemContext))
|
||||
self.PopupMenu(menu)
|
||||
|
||||
def populate(self, items):
|
||||
if len(items) > 0:
|
||||
# Get dictionary with meta level attribute
|
||||
sAttr = Attribute.getInstance()
|
||||
attrs = sAttr.getAttributeInfo("metaLevel")
|
||||
sMkt = self.sMkt
|
||||
self.metalvls = sMkt.directAttrRequest(items, attrs)
|
||||
# Clear selection
|
||||
self.deselectItems()
|
||||
# Perform sorting, using item's meta levels besides other stuff
|
||||
items.sort(key=self.itemSort)
|
||||
# Mark current item list as active
|
||||
self.active = items
|
||||
# Show them
|
||||
Display.populate(self, items)
|
||||
|
||||
def refresh(self, items):
|
||||
if len(items) > 1:
|
||||
# Get dictionary with meta level attribute
|
||||
sAttr = Attribute.getInstance()
|
||||
attrs = sAttr.getAttributeInfo("metaLevel")
|
||||
sMkt = self.sMkt
|
||||
self.metalvls = sMkt.directAttrRequest(items, attrs)
|
||||
# Re-sort stuff
|
||||
items.sort(key=self.itemSort)
|
||||
|
||||
for i, item in enumerate(items[:9]):
|
||||
# set shortcut info for first 9 modules
|
||||
item.marketShortcut = i + 1
|
||||
|
||||
Display.refresh(self, items)
|
||||
|
||||
def makeReverseMetaMap(self):
|
||||
"""
|
||||
Form map which tells in which tab items of given metagroup are located
|
||||
"""
|
||||
revmap = {}
|
||||
i = 0
|
||||
for mgids in self.sMkt.META_MAP.itervalues():
|
||||
for mgid in mgids:
|
||||
revmap[mgid] = i
|
||||
i += 1
|
||||
return revmap
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import csv
|
||||
from logbook import Logger
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
try:
|
||||
# noinspection PyPackageRequirements
|
||||
@@ -17,7 +17,7 @@ from eos.db.gamedata.queries import getItem, getAttributeInfo
|
||||
from service.market import Market
|
||||
import gui.display as d
|
||||
import gui.globalEvents as GE
|
||||
import gui.PFSearchBox as SBox
|
||||
import gui.builtinMarketBrowser.pfSearchBox as SBox
|
||||
from gui.marketBrowser import SearchBox
|
||||
from gui.bitmapLoader import BitmapLoader
|
||||
|
||||
|
||||
Reference in New Issue
Block a user