From 6c1d949cef58d0a601a6056257cd3f657f1c397f Mon Sep 17 00:00:00 2001 From: blitzman Date: Wed, 22 Mar 2017 21:50:02 -0400 Subject: [PATCH 1/5] Proof of concept for gathering fits based on modules that are fit --- eos/db/saveddata/queries.py | 16 ++++++---------- gui/commandView.py | 10 ++++++++++ service/fit.py | 11 +++-------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/eos/db/saveddata/queries.py b/eos/db/saveddata/queries.py index 16f6a3bf9..f1f947296 100644 --- a/eos/db/saveddata/queries.py +++ b/eos/db/saveddata/queries.py @@ -30,6 +30,7 @@ from eos.saveddata.targetResists import TargetResists from eos.saveddata.character import Character from eos.saveddata.implantSet import ImplantSet from eos.saveddata.fit import Fit +from eos.saveddata.module import Module from eos.saveddata.miscData import MiscData from eos.saveddata.override import Override @@ -241,22 +242,17 @@ def getFitsWithShip(shipID, ownerID=None, where=None, eager=None): return fits -def getBoosterFits(ownerID=None, where=None, eager=None): +def getFitsWithModules(typeIDs, eager=None): """ - Get all the fits that are flagged as a boosting ship - If no user is passed, do this for all users. + Get all the fits that have typeIDs fitted to them """ - if ownerID is not None and not isinstance(ownerID, int): - raise TypeError("OwnerID must be integer") - filter = Fit.booster == 1 - if ownerID is not None: - filter = and_(filter, Fit.ownerID == ownerID) + if not hasattr(typeIDs, "__iter__"): + typeIDs = (typeIDs,) - filter = processWhere(filter, where) eager = processEager(eager) with sd_lock: - fits = removeInvalid(saveddata_session.query(Fit).options(*eager).filter(filter).all()) + fits = removeInvalid(saveddata_session.query(Fit).join(Module).options(*eager).filter(Module.itemID.in_(typeIDs)).all()) return fits diff --git a/gui/commandView.py b/gui/commandView.py index 38dec46c9..d32629974 100644 --- a/gui/commandView.py +++ b/gui/commandView.py @@ -26,6 +26,7 @@ import gui.droneView from gui.builtinViewColumns.state import State from gui.contextMenu import ContextMenu from service.fit import Fit +from service.market import Market from eos.saveddata.drone import Drone as es_Drone @@ -63,6 +64,15 @@ class CommandView(d.Display): self.lastFitId = None + # Get list of items that define a command fit + sMkt = Market.getInstance() + grp = sMkt.getGroup(1770) # Command burst group + self.commandTypeIDs = [item.ID for item in grp.items] + + sFit = Fit.getInstance() + commandFits = sFit.getFitsWithModules(self.commandTypeIDs) + print (commandFits) + self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged) self.Bind(wx.EVT_LEFT_DOWN, self.click) self.Bind(wx.EVT_RIGHT_DOWN, self.click) diff --git a/service/fit.py b/service/fit.py index 0bb385894..58410f200 100644 --- a/service/fit.py +++ b/service/fit.py @@ -95,15 +95,10 @@ class Fit(object): return names @staticmethod - def getBoosterFits(): + def getFitsWithModules(typeIDs): """ Lists fits flagged as booster """ - pyfalog.debug("Fetching all fits flagged as a booster.") - fits = eos.db.getBoosterFits() - names = [] - for fit in fits: - names.append((fit.ID, fit.name, fit.shipID)) - - return names + fits = eos.db.getFitsWithModules(typeIDs) + return fits @staticmethod def countAllFits(): From 40650228663b803dac958f1453e2f9c6d5df1a0b Mon Sep 17 00:00:00 2001 From: blitzman Date: Wed, 22 Mar 2017 23:00:20 -0400 Subject: [PATCH 2/5] Initial work on caching command fits unless needing to update. FitChanged event can now carry an action and typeID, only used in the CommandFit context menu (for now, can use this elsewhere). If the module being added or removed, we update the cached list. --- gui/builtinContextMenus/commandFits.py | 46 ++++++++++++++++++++++++++ gui/builtinViews/fittingView.py | 12 ++++--- gui/cargoView.py | 2 +- gui/commandView.py | 13 ++------ gui/contextMenu.py | 1 + 5 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 gui/builtinContextMenus/commandFits.py diff --git a/gui/builtinContextMenus/commandFits.py b/gui/builtinContextMenus/commandFits.py new file mode 100644 index 000000000..bb26766e8 --- /dev/null +++ b/gui/builtinContextMenus/commandFits.py @@ -0,0 +1,46 @@ +# noinspection PyPackageRequirements +import wx + +from service.fit import Fit +from service.market import Market +import gui.mainFrame +from gui.contextMenu import ContextMenu +from service.settings import ContextMenuSettings + +class CommandFits(ContextMenu): + # Get list of items that define a command fit + sMkt = Market.getInstance() + grp = sMkt.getGroup(1770) # Command burst group + commandTypeIDs = [item.ID for item in grp.items] + commandFits = [] + menu = None + + @classmethod + def populateFits(cls, evt): + if evt is None or (getattr(evt, 'action', None) in ("modadd", "moddel") and getattr(evt, 'typeID', None) in cls.commandTypeIDs): + # we are adding or removing an item that defines a command fit. Need to refresh fit list + sFit = Fit.getInstance() + cls.commandFits = sFit.getFitsWithModules(cls.commandTypeIDs) + print (cls.commandFits) + #todo: create menu here. + pass + + def __init__(self): + print (self.__class__.commandTypeIDs) + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.settings = ContextMenuSettings.getInstance() + + def display(self, srcContext, selection): + # todo: the whole thing + return False + + def getText(self, itmContext, selection): + return "Command Fits" + + def getSubMenu(self, context, selection, rootMenu, i, pitem): + if self.__class__.menu is None: + self.__class__.populateFits() + return self.__class__.menu + + +CommandFits.register() diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 496cf4fb8..01eb3ff66 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -334,7 +334,7 @@ class FittingView(d.Display): populate = sFit.appendModule(fitID, itemID) if populate is not None: self.slotsChanged() - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID, action="modadd", typeID=itemID)) event.Skip() @@ -355,7 +355,7 @@ class FittingView(d.Display): if populate is not None: self.slotsChanged() - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID)) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID, action="moddel", typeID=module.item.ID)) def addModule(self, x, y, srcIdx): """Add a module from the market browser""" @@ -368,7 +368,8 @@ class FittingView(d.Display): 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, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit(), action="modadd", typeID=srcIdx)) def swapCargo(self, x, y, srcIdx): """Swap a module from cargo to fitting window""" @@ -379,10 +380,13 @@ class FittingView(d.Display): module = self.mods[dstRow] sFit = Fit.getInstance() + fit = sFit.getFit(self.activeFitID) + typeID = fit.cargo[srcIdx].item.ID + sFit.moveCargoToModule(self.mainFrame.getActiveFit(), module.modPosition, srcIdx, mstate.CmdDown() and module.isEmpty) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit(), action="modadd", typeID=typeID)) def swapItems(self, x, y, srcIdx): """Swap two modules in fitting window""" diff --git a/gui/cargoView.py b/gui/cargoView.py index d997afa79..cd560c1c2 100644 --- a/gui/cargoView.py +++ b/gui/cargoView.py @@ -125,7 +125,7 @@ class CargoView(d.Display): if not mstate.CmdDown(): # if not copying, remove module sFit.removeModule(self.mainFrame.getActiveFit(), module.position) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit())) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit(), action="moddel", typeID=module.item.ID)) def fitChanged(self, event): sFit = Fit.getInstance() diff --git a/gui/commandView.py b/gui/commandView.py index d32629974..7b79f6b85 100644 --- a/gui/commandView.py +++ b/gui/commandView.py @@ -23,10 +23,11 @@ import gui.display as d import gui.globalEvents as GE import gui.droneView +import gui.marketBrowser as marketBrowser from gui.builtinViewColumns.state import State from gui.contextMenu import ContextMenu +from gui.builtinContextMenus.commandFits import CommandFits from service.fit import Fit -from service.market import Market from eos.saveddata.drone import Drone as es_Drone @@ -64,15 +65,7 @@ class CommandView(d.Display): self.lastFitId = None - # Get list of items that define a command fit - sMkt = Market.getInstance() - grp = sMkt.getGroup(1770) # Command burst group - self.commandTypeIDs = [item.ID for item in grp.items] - - sFit = Fit.getInstance() - commandFits = sFit.getFitsWithModules(self.commandTypeIDs) - print (commandFits) - + self.mainFrame.Bind(GE.FIT_CHANGED, CommandFits.populateFits) self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged) self.Bind(wx.EVT_LEFT_DOWN, self.click) self.Bind(wx.EVT_RIGHT_DOWN, self.click) diff --git a/gui/contextMenu.py b/gui/contextMenu.py index a35c73282..adfeeb324 100644 --- a/gui/contextMenu.py +++ b/gui/contextMenu.py @@ -205,4 +205,5 @@ from gui.builtinContextMenus import ( # noqa: E402,F401 metaSwap, implantSets, fighterAbilities, + commandFits, ) From 732386b83abe00d3dc4ce6c0b8936c6de3d11c39 Mon Sep 17 00:00:00 2001 From: blitzman Date: Thu, 23 Mar 2017 00:29:31 -0400 Subject: [PATCH 3/5] Get command fit menu up and running. Had to revert to a non-cached version of the menu, as the instance has root menu, which we need in order to properly bind. Don't think caching the menu would have really given a large performance gain anyway. --- gui/builtinContextMenus/commandFits.py | 67 ++++++++++++++++++++++---- gui/commandView.py | 4 +- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/gui/builtinContextMenus/commandFits.py b/gui/builtinContextMenus/commandFits.py index bb26766e8..17f60f512 100644 --- a/gui/builtinContextMenus/commandFits.py +++ b/gui/builtinContextMenus/commandFits.py @@ -21,26 +21,75 @@ class CommandFits(ContextMenu): # we are adding or removing an item that defines a command fit. Need to refresh fit list sFit = Fit.getInstance() cls.commandFits = sFit.getFitsWithModules(cls.commandTypeIDs) - print (cls.commandFits) - #todo: create menu here. - pass def __init__(self): - print (self.__class__.commandTypeIDs) self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.settings = ContextMenuSettings.getInstance() def display(self, srcContext, selection): - # todo: the whole thing - return False + if self.mainFrame.getActiveFit() is None or len(self.__class__.commandFits) == 0 or srcContext != "commandView": + return False + + return True def getText(self, itmContext, selection): return "Command Fits" + def addFit(self, menu, fit, includeShip=False): + label = fit.name if not includeShip else "({}) {}".format(fit.ship.item.name, fit.name) + id = ContextMenu.nextID() + self.fitMenuItemIds[id] = fit + menuItem = wx.MenuItem(menu, id, label) + menu.Bind(wx.EVT_MENU, self.handleSelection, menuItem) + return menuItem + def getSubMenu(self, context, selection, rootMenu, i, pitem): - if self.__class__.menu is None: - self.__class__.populateFits() - return self.__class__.menu + msw = True if "wxMSW" in wx.PlatformInfo else False + self.context = context + self.fitMenuItemIds = {} + sub = wx.Menu() + if len(self.__class__.commandFits) < 15: + for fit in sorted(self.__class__.commandFits, key=lambda x: x.name): + print fit + menuItem = self.addFit(rootMenu if msw else sub, fit, True) + sub.AppendItem(menuItem) + else: + typeDict = {} + + for fit in self.__class__.commandFits: + shipName = fit.ship.item.name + if shipName not in typeDict: + typeDict[shipName] = [] + typeDict[shipName].append(fit) + + for ship in sorted(typeDict.keys()): + shipItem = wx.MenuItem(sub, ContextMenu.nextID(), ship) + grandSub = wx.Menu() + shipItem.SetSubMenu(grandSub) + + for fit in sorted(typeDict[ship], key=lambda x: x.name): + fitItem = self.addFit(rootMenu if msw else grandSub, fit, False) + grandSub.AppendItem(fitItem) + + sub.AppendItem(shipItem) + + return sub + + def handleSelection(self, event): + fit = self.fitMenuItemIds[event.Id] + if fit is False or fit not in self.__class__.commandFits: + event.Skip() + return + + sFit = Fit.getInstance() + fitID = self.mainFrame.getActiveFit() + + print fit, 'selected' + # add command fit + # sFit.toggleFighterAbility(fitID, fit) + # wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + +CommandFits.populateFits(None) CommandFits.register() diff --git a/gui/commandView.py b/gui/commandView.py index 7b79f6b85..7b74a39e9 100644 --- a/gui/commandView.py +++ b/gui/commandView.py @@ -197,13 +197,13 @@ class CommandView(d.Display): fitSrcContext = "commandFit" fitItemContext = item.name context = ((fitSrcContext, fitItemContext),) - context += ("command",), + context += ("commandView",), menu = ContextMenu.getMenu((item,), *context) elif sel == -1: fitID = self.mainFrame.getActiveFit() if fitID is None: return - context = (("command",),) + context = (("commandView",),) menu = ContextMenu.getMenu([], *context) if menu is not None: self.PopupMenu(menu) From cbcc81d42e2e143247f2185e2f60653ab5334c2d Mon Sep 17 00:00:00 2001 From: blitzman Date: Thu, 23 Mar 2017 00:33:06 -0400 Subject: [PATCH 4/5] Actually apply the command fit, and remove print statement --- gui/builtinContextMenus/commandFits.py | 7 +++---- gui/builtinStatsViews/targetingMiscViewMinimal.py | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/gui/builtinContextMenus/commandFits.py b/gui/builtinContextMenus/commandFits.py index 17f60f512..0490aa44b 100644 --- a/gui/builtinContextMenus/commandFits.py +++ b/gui/builtinContextMenus/commandFits.py @@ -4,6 +4,7 @@ import wx from service.fit import Fit from service.market import Market import gui.mainFrame +import gui.globalEvents as GE from gui.contextMenu import ContextMenu from service.settings import ContextMenuSettings @@ -86,10 +87,8 @@ class CommandFits(ContextMenu): sFit = Fit.getInstance() fitID = self.mainFrame.getActiveFit() - print fit, 'selected' - # add command fit - # sFit.toggleFighterAbility(fitID, fit) - # wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + sFit.addCommandFit(fitID, fit) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) CommandFits.populateFits(None) CommandFits.register() diff --git a/gui/builtinStatsViews/targetingMiscViewMinimal.py b/gui/builtinStatsViews/targetingMiscViewMinimal.py index 4dffc9e40..df0d9f70a 100644 --- a/gui/builtinStatsViews/targetingMiscViewMinimal.py +++ b/gui/builtinStatsViews/targetingMiscViewMinimal.py @@ -242,7 +242,6 @@ class TargetingMiscViewMinimal(StatsView): # forces update of probe size, since this stat is used by both sig radius and sensor str if labelName == "labelFullSigRadius": - print "labelName" if fit: label.SetToolTip(wx.ToolTip("Probe Size: %.3f" % (fit.probeSize or 0))) else: From 79040adf1a846d159d52b518356d3f75562ae731 Mon Sep 17 00:00:00 2001 From: blitzman Date: Thu, 23 Mar 2017 01:13:41 -0400 Subject: [PATCH 5/5] tox fixes --- gui/builtinContextMenus/cargoAmmo.py | 1 - gui/builtinContextMenus/commandFits.py | 4 +++- gui/builtinContextMenus/droneStack.py | 1 - gui/commandView.py | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gui/builtinContextMenus/cargoAmmo.py b/gui/builtinContextMenus/cargoAmmo.py index 57ae42517..12ebe552f 100644 --- a/gui/builtinContextMenus/cargoAmmo.py +++ b/gui/builtinContextMenus/cargoAmmo.py @@ -1,6 +1,5 @@ from gui.contextMenu import ContextMenu import gui.mainFrame -import service import gui.globalEvents as GE import wx from service.settings import ContextMenuSettings diff --git a/gui/builtinContextMenus/commandFits.py b/gui/builtinContextMenus/commandFits.py index 0490aa44b..9640a83ef 100644 --- a/gui/builtinContextMenus/commandFits.py +++ b/gui/builtinContextMenus/commandFits.py @@ -8,6 +8,7 @@ import gui.globalEvents as GE from gui.contextMenu import ContextMenu from service.settings import ContextMenuSettings + class CommandFits(ContextMenu): # Get list of items that define a command fit sMkt = Market.getInstance() @@ -80,7 +81,7 @@ class CommandFits(ContextMenu): def handleSelection(self, event): fit = self.fitMenuItemIds[event.Id] - if fit is False or fit not in self.__class__.commandFits: + if fit is False or fit not in self.__class__.commandFits: event.Skip() return @@ -90,5 +91,6 @@ class CommandFits(ContextMenu): sFit.addCommandFit(fitID, fit) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + CommandFits.populateFits(None) CommandFits.register() diff --git a/gui/builtinContextMenus/droneStack.py b/gui/builtinContextMenus/droneStack.py index 150b76676..99a253796 100644 --- a/gui/builtinContextMenus/droneStack.py +++ b/gui/builtinContextMenus/droneStack.py @@ -1,6 +1,5 @@ from gui.contextMenu import ContextMenu import gui.mainFrame -import service import gui.globalEvents as GE import wx from service.settings import ContextMenuSettings diff --git a/gui/commandView.py b/gui/commandView.py index 7b74a39e9..d295c7939 100644 --- a/gui/commandView.py +++ b/gui/commandView.py @@ -23,7 +23,6 @@ import gui.display as d import gui.globalEvents as GE import gui.droneView -import gui.marketBrowser as marketBrowser from gui.builtinViewColumns.state import State from gui.contextMenu import ContextMenu from gui.builtinContextMenus.commandFits import CommandFits