From 098f0f92ee7d3d96eb69074c6353d63752dc0e82 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Tue, 31 Jul 2018 21:29:59 -0400 Subject: [PATCH 1/8] Fix issue with layout-modifying modules (need to build fill() into the recalc itself at some point) --- eos/saveddata/fit.py | 4 +++- gui/fitCommands/guiAddModule.py | 1 + service/fit.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 8f5cc2b36..62eaa2bb1 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -35,7 +35,6 @@ from eos.saveddata.character import Character from eos.saveddata.citadel import Citadel from eos.saveddata.module import Module, State, Slot, Hardpoint from logbook import Logger - pyfalog = Logger(__name__) @@ -913,6 +912,9 @@ class Fit(object): Fill this fit's module slots with enough dummy slots so that all slots are used. This is mostly for making the life of gui's easier. GUI's can call fill() and then stop caring about empty slots completely. + + todo: want to get rid of using this from the gui/commands, and instead make it a more built-in feature within + recalc. Figure out a way to keep track of any changes to slot layout and call this automatically """ if self.ship is None: return diff --git a/gui/fitCommands/guiAddModule.py b/gui/fitCommands/guiAddModule.py index 5abf52651..dad2780e1 100644 --- a/gui/fitCommands/guiAddModule.py +++ b/gui/fitCommands/guiAddModule.py @@ -4,6 +4,7 @@ import gui.mainFrame from gui import globalEvents as GE from .calc.fitAddModule import FitAddModuleCommand from .calc.fitReplaceModule import FitReplaceModuleCommand +from service.fit import Fit class GuiModuleAddCommand(wx.Command): def __init__(self, fitID, itemID, position=None): diff --git a/service/fit.py b/service/fit.py index 016f5989a..d3ed7d9c7 100644 --- a/service/fit.py +++ b/service/fit.py @@ -1256,5 +1256,5 @@ class Fit(object): fit.clear() fit.calculateModifiedAttributes() - + fit.fill() pyfalog.info("=" * 10 + "recalc time: " + str(time() - start_time) + "=" * 10) From fc153915b6adb64302a6acfacfbe80d25f98e879 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Thu, 2 Aug 2018 02:06:03 -0400 Subject: [PATCH 2/8] More work on commands, this time focusing on details with module add / remove functionalities. --- gui/fitCommands/calc/fitAddModule.py | 11 +++++-- gui/fitCommands/calc/fitRemoveModule.py | 9 ++--- gui/fitCommands/calc/fitReplaceModule.py | 21 ++++++++---- gui/fitCommands/calc/fitSetCharge.py | 26 ++++++++------- gui/fitCommands/guiAddCharge.py | 6 ++-- gui/fitCommands/guiAddModule.py | 42 ++++++++++++++---------- gui/fitCommands/guiRemoveModule.py | 15 +++++---- gui/fitCommands/helpers.py | 2 +- 8 files changed, 80 insertions(+), 52 deletions(-) diff --git a/gui/fitCommands/calc/fitAddModule.py b/gui/fitCommands/calc/fitAddModule.py index 8ff72ab74..39dabf7e1 100644 --- a/gui/fitCommands/calc/fitAddModule.py +++ b/gui/fitCommands/calc/fitAddModule.py @@ -16,10 +16,12 @@ class FitAddModuleCommand(wx.Command): from sFit.appendModule """ - def __init__(self, fitID, itemID): + def __init__(self, fitID, itemID, mutaplasmidID=None, baseID=None): wx.Command.__init__(self, True, "Module Add") self.fitID = fitID self.itemID = itemID + self.mutaplasmidID = mutaplasmidID + self.baseID = baseID self.new_position = None self.change = None @@ -30,8 +32,11 @@ class FitAddModuleCommand(wx.Command): fit = eos.db.getFit(fitID) item = eos.db.getItem(itemID, eager=("attributes", "group.category")) + bItem = eos.db.getItem(self.baseID) if self.baseID else None + mItem = next((x for x in bItem.mutaplasmids if x.ID == self.mutaplasmidID)) if self.mutaplasmidID else None + try: - self.module = Module(item) + self.module = Module(item, bItem, mItem) except ValueError: pyfalog.warning("Invalid item: {0}", itemID) return False @@ -52,7 +57,7 @@ class FitAddModuleCommand(wx.Command): # Then, check states of all modules and change where needed. This will recalc if needed # self.checkStates(fit, m) - fit.fill() + #fit.fill() eos.db.commit() self.change = numSlots != len(fit.modules) diff --git a/gui/fitCommands/calc/fitRemoveModule.py b/gui/fitCommands/calc/fitRemoveModule.py index 876545718..9eb2e013a 100644 --- a/gui/fitCommands/calc/fitRemoveModule.py +++ b/gui/fitCommands/calc/fitRemoveModule.py @@ -27,10 +27,10 @@ class FitRemoveModuleCommand(wx.Command): for x in self.positions: mod = fit.modules[x] if not mod.isEmpty: - self.modCache.append(ModuleInfoCache(mod.modPosition, mod.item.ID, mod.state, mod.charge)) + self.modCache.append(ModuleInfoCache(mod.modPosition, mod.item.ID, mod.state, mod.charge, mod.baseItemID, mod.mutaplasmidID)) fit.modules.toDummy(x) - # if no modules have changes, report back None + # if no modules have changes, skip command if not len(self.modCache) > 0: return False @@ -38,7 +38,7 @@ class FitRemoveModuleCommand(wx.Command): # todo: determine if we need to do this still # self.recalc(fit) # self.checkStates(fit, None) - fit.fill() + # fit.fill() eos.db.commit() self.slotsChanged = numSlots != len(fit.modules) return True @@ -46,7 +46,8 @@ class FitRemoveModuleCommand(wx.Command): def Undo(self): from gui.fitCommands.calc.fitAddModule import FitAddModuleCommand # avoids circular import for mod in self.modCache: - cmd = FitAddModuleCommand(self.fitID, mod.itemID) + # todo, send the state and charge? + cmd = FitAddModuleCommand(self.fitID, mod.itemID, mod.mutaplasmidID, mod.baseID) cmd.Do() cmd.module.state = mod.state cmd.module.charge = mod.charge diff --git a/gui/fitCommands/calc/fitReplaceModule.py b/gui/fitCommands/calc/fitReplaceModule.py index 9b1ecf2e3..ddfd2c770 100644 --- a/gui/fitCommands/calc/fitReplaceModule.py +++ b/gui/fitCommands/calc/fitReplaceModule.py @@ -28,7 +28,12 @@ class FitReplaceModuleCommand(wx.Command): return self.change_module(self.fitID, self.position, self.itemID) def Undo(self): - self.change_module(self.fitID, self.position, self.itemID) + if self.old_module is None: + fit = eos.db.getFit(self.fitID) + fit.modules.toDummy(self.position) + return True + + self.change_module(self.fitID, self.position, self.old_module.itemID) self.module.state = self.old_module.state self.module.charge = self.old_module.charge return True @@ -51,10 +56,8 @@ class FitReplaceModuleCommand(wx.Command): item = eos.db.getItem(itemID, eager=("attributes", "group.category")) mod = fit.modules[self.position] - self.old_module.append(ModuleInfoCache(mod.modPosition, mod.item.ID, mod.state, mod.charge)) - - # Dummy it out in case the next bit fails - fit.modules.toDummy(self.position) + if not mod.isEmpty: + self.old_module = ModuleInfoCache(mod.modPosition, mod.item.ID, mod.state, mod.charge, mod.baseItemID, mod.mutaplasmidID) try: self.module = Module(item) @@ -62,6 +65,12 @@ class FitReplaceModuleCommand(wx.Command): pyfalog.warning("Invalid item: {0}", itemID) return False + if self.module.slot != mod.slot: + return False + + # Dummy it out in case the next bit fails + fit.modules.toDummy(self.position) + if self.module.fits(fit): self.module.owner = fit fit.modules.toModule(self.position, self.module) @@ -71,7 +80,7 @@ class FitReplaceModuleCommand(wx.Command): # Then, check states of all modules and change where needed. This will recalc if needed # self.checkStates(fit, m) - fit.fill() + # fit.fill() eos.db.commit() return True return False diff --git a/gui/fitCommands/calc/fitSetCharge.py b/gui/fitCommands/calc/fitSetCharge.py index 111959a18..e97d55adb 100644 --- a/gui/fitCommands/calc/fitSetCharge.py +++ b/gui/fitCommands/calc/fitSetCharge.py @@ -9,34 +9,36 @@ pyfalog = Logger(__name__) import eos.db class FitSetChargeCommand(wx.Command): - def __init__(self, fitID, modules, chargeID=None): + def __init__(self, fitID, positions, chargeID=None): # todo: determine if this command really should be used with a group of modules, or a simple per module basis wx.Command.__init__(self, True, "Module Charge Add") self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.sFit = Fit.getInstance() self.fitID = fitID self.chargeID = chargeID - self.modules = modules - self.positions = {mod.modPosition: mod.chargeID for mod in modules} + self.positions = positions + self.cache = None def Do(self): pyfalog.debug("Set ammo for fit ID: {0}", self.fitID) - if self.fitID is None: - return False - return self.__setAmmo(self.modules, self.chargeID) + return self.__setAmmo(self.positions, self.chargeID) def Undo(self): - fit = eos.db.getFit(self.fitID) - for position, chargeID in self.positions.items(): - self.__setAmmo([fit.modules[position]], chargeID) + for position, chargeID in self.cache.items(): + self.__setAmmo([position], chargeID) return True - @staticmethod - def __setAmmo(modules, chargeID): + def __setAmmo(self, positions, chargeID): + fit = eos.db.getFit(self.fitID) + self.cache = {fit.modules[i].modPosition: fit.modules[i].chargeID for i in positions} ammo = eos.db.getItem(chargeID) if chargeID else None + + if not ammo.isCharge: + return False result = False - for mod in modules: + for pos in positions: + mod = fit.modules[pos] if not mod.isEmpty and mod.isValidCharge(ammo): result = True mod.charge = ammo diff --git a/gui/fitCommands/guiAddCharge.py b/gui/fitCommands/guiAddCharge.py index 49b2a1680..94d7d4249 100644 --- a/gui/fitCommands/guiAddCharge.py +++ b/gui/fitCommands/guiAddCharge.py @@ -13,10 +13,11 @@ class GuiModuleAddChargeCommand(wx.Command): self.internal_history = wx.CommandProcessor() self.fitID = fitID # can set his up no to not have to set variables on our object - self.cmd = FitSetChargeCommand(fitID, modules, itemID) + self.cmd = FitSetChargeCommand(fitID, [mod.modPosition for mod in modules], itemID) def Do(self): if self.internal_history.Submit(self.cmd): + self.sFit.recalc(self.fitID) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) return True return False @@ -24,6 +25,7 @@ class GuiModuleAddChargeCommand(wx.Command): def Undo(self): for x in self.internal_history.Commands: self.internal_history.Undo() - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + self.sFit.recalc(self.fitID) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) return True diff --git a/gui/fitCommands/guiAddModule.py b/gui/fitCommands/guiAddModule.py index dad2780e1..06267919f 100644 --- a/gui/fitCommands/guiAddModule.py +++ b/gui/fitCommands/guiAddModule.py @@ -1,36 +1,48 @@ import wx - +import eos.db import gui.mainFrame from gui import globalEvents as GE from .calc.fitAddModule import FitAddModuleCommand from .calc.fitReplaceModule import FitReplaceModuleCommand +from .calc.fitSetCharge import FitSetChargeCommand from service.fit import Fit + class GuiModuleAddCommand(wx.Command): def __init__(self, fitID, itemID, position=None): - wx.Command.__init__(self, True, "Module Add") - # todo: evaluate mutaplasmid modules + """ + Handles adding an item, usually a module, to the Fitting Window. + + :param fitID: The fit ID that we are modifying + :param itemID: The item that is to be added to the Fitting View. If this turns out to be a charge, we attempt to + set the charge on the underlying module (requires position) + :param position: Optional. The position in fit.modules that we are attempting to set the item to + """ + wx.Command.__init__(self, True, "Module Add: {}".format(itemID)) self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.sFit = Fit.getInstance() self.fitID = fitID self.itemID = itemID self.internal_history = wx.CommandProcessor() - self.new_position = position + self.position = position self.old_mod = None def Do(self): success = False - # if we have a position set, try to apply the module to that position - - # todo: check to see if item is a charge. if it is, dont try to add module, but instead set ammo - if self.new_position: - success = self.internal_history.Submit(FitReplaceModuleCommand(self.fitID, self.new_position, self.itemID)) + item = eos.db.getItem(self.itemID) + if item.isCharge and self.position is not None: + success = self.internal_history.Submit(FitSetChargeCommand(self.fitID, [self.position], self.itemID)) if not success: - # something went wrong with trying to fit the module into specific location, attemp to append it - self.new_position = None + return False # if it's a charge item and this failed, nothing more we can try. + # if we have a position set, try to apply the module to that position + elif self.position is not None: + success = self.internal_history.Submit(FitReplaceModuleCommand(self.fitID, self.position, self.itemID)) + if not success: + # something went wrong with trying to fit the module into specific location, attempt to append it + self.position = None # if we're not trying to set module to a position, simply append - if not self.new_position: + if self.position is None: success = self.internal_history.Submit(FitAddModuleCommand(self.fitID, self.itemID)) if success: @@ -39,12 +51,6 @@ class GuiModuleAddCommand(wx.Command): return True return False - # - # if change is not None: - # print('new position: ',self.new_position ) - # # self.slotsChanged() # unsure how to handle this right now? Perhaps move this to the event itself? - # return True - # return False def Undo(self): for _ in self.internal_history.Commands: diff --git a/gui/fitCommands/guiRemoveModule.py b/gui/fitCommands/guiRemoveModule.py index 9c7c5eef6..508c7178b 100644 --- a/gui/fitCommands/guiRemoveModule.py +++ b/gui/fitCommands/guiRemoveModule.py @@ -10,26 +10,29 @@ from .calc.fitRemoveModule import FitRemoveModuleCommand class GuiModuleRemoveCommand(wx.Command): def __init__(self, fitID, modules): - # todo: evaluate mutaplasmid modules + """ + + :param fitID: The fit ID that we are modifying + :param modules: A list of Module objects that we are attempting to remove. + """ wx.Command.__init__(self, True, "Module Remove") self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.sFit = Fit.getInstance() self.fitID = fitID - self.modCache = [ModuleInfoCache(mod.modPosition, mod.item.ID, mod.state, mod.charge) for mod in modules] + self.modCache = [ModuleInfoCache(mod.modPosition, mod.item.ID, mod.state, mod.charge, mod.baseItemID, mod.mutaplasmidID) for mod in modules if not mod.isEmpty] self.internal_history = wx.CommandProcessor() def Do(self): - # todo: what happens when one remove in an array of removes fucks up? (it really shouldn't it's easy peasy) success = self.internal_history.Submit(FitRemoveModuleCommand(self.fitID, [mod.modPosition for mod in self.modCache])) - if success is not None: - # self.slotsChanged() # todo: fix + if success: self.sFit.recalc(self.fitID) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID, action="moddel", typeID=set([mod.itemID for mod in self.modCache]))) return True + return False def Undo(self): - for x in self.internal_history.Commands: + for _ in self.internal_history.Commands: self.internal_history.Undo() self.sFit.recalc(self.fitID) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID, action="modadd", typeID=set([mod.itemID for mod in self.modCache]))) diff --git a/gui/fitCommands/helpers.py b/gui/fitCommands/helpers.py index 81c862193..63aaf4b76 100644 --- a/gui/fitCommands/helpers.py +++ b/gui/fitCommands/helpers.py @@ -1,3 +1,3 @@ from collections import namedtuple -ModuleInfoCache = namedtuple('ModuleInfoCache', ['modPosition', 'itemID', 'state', 'charge']) +ModuleInfoCache = namedtuple('ModuleInfoCache', ['modPosition', 'itemID', 'state', 'charge', 'baseID', 'mutaplasmidID']) From 36b158637c9e015c019db027dc8e85f448fa147d Mon Sep 17 00:00:00 2001 From: blitzmann Date: Thu, 2 Aug 2018 23:23:52 -0400 Subject: [PATCH 3/8] Some documentation --- eos/effectHandlerHelpers.py | 2 ++ gui/fitCommands/calc/fitAddModule.py | 21 ++++++++++++++++----- gui/fitCommands/calc/fitRemoveModule.py | 9 +++++++-- gui/fitCommands/calc/fitSetCharge.py | 2 +- gui/fitCommands/guiAddModule.py | 9 +++++++++ gui/fitCommands/guiRemoveModule.py | 1 + 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/eos/effectHandlerHelpers.py b/eos/effectHandlerHelpers.py index f890ae0ed..446273a45 100644 --- a/eos/effectHandlerHelpers.py +++ b/eos/effectHandlerHelpers.py @@ -18,6 +18,7 @@ # =============================================================================== from logbook import Logger +from utils.deprecated import deprecated pyfalog = Logger(__name__) @@ -163,6 +164,7 @@ class HandledModuleList(HandledList): mod.position = index self[index] = mod + @deprecated def freeSlot(self, slot): for i in range(len(self)): mod = self[i] diff --git a/gui/fitCommands/calc/fitAddModule.py b/gui/fitCommands/calc/fitAddModule.py index 39dabf7e1..5d1a2c35c 100644 --- a/gui/fitCommands/calc/fitAddModule.py +++ b/gui/fitCommands/calc/fitAddModule.py @@ -12,23 +12,24 @@ pyfalog = Logger(__name__) class FitAddModuleCommand(wx.Command): """" - Fitting command that appends a module to a fit using the first available slot. + Fitting command that appends a module to a fit using the first available slot. In the case of a Subsystem, it checks + if there is already a subsystem with the same slot, and runs the replace command instead. from sFit.appendModule """ def __init__(self, fitID, itemID, mutaplasmidID=None, baseID=None): - wx.Command.__init__(self, True, "Module Add") + wx.Command.__init__(self, True) self.fitID = fitID self.itemID = itemID self.mutaplasmidID = mutaplasmidID self.baseID = baseID self.new_position = None self.change = None + self.replace_cmd = None def Do(self): fitID = self.fitID itemID = self.itemID - pyfalog.debug("Appending module for fit ({0}) using item: {1}", fitID, itemID) fit = eos.db.getFit(fitID) item = eos.db.getItem(itemID, eager=("attributes", "group.category")) @@ -38,13 +39,19 @@ class FitAddModuleCommand(wx.Command): try: self.module = Module(item, bItem, mItem) except ValueError: - pyfalog.warning("Invalid item: {0}", itemID) + pyfalog.warning("Invalid module: {}", item) return False + # If subsystem and we need to replace, run the replace command instead and bypass the rest of this command if self.module.item.category.name == "Subsystem": - fit.modules.freeSlot(self.module.getModifiedItemAttr("subSystemSlot")) + for mod in fit.modules: + if mod.getModifiedItemAttr("subSystemSlot") == self.module.getModifiedItemAttr("subSystemSlot"): + from .fitReplaceModule import FitReplaceModuleCommand + self.replace_cmd = FitReplaceModuleCommand(self.fitID, mod.modPosition, itemID) + return self.replace_cmd.Do() if self.module.fits(fit): + pyfalog.debug("Adding {} as module for fit {}", self.module, fit) self.module.owner = fit numSlots = len(fit.modules) fit.modules.append(self.module) @@ -68,6 +75,10 @@ class FitAddModuleCommand(wx.Command): return True def Undo(self): + # We added a subsystem module, which actually ran the replace command. Run the undo for that guy instead + if self.replace_cmd: + return self.replace_cmd.Undo() + from .fitRemoveModule import FitRemoveModuleCommand # Avoid circular import if self.new_position: cmd = FitRemoveModuleCommand(self.fitID, [self.new_position]) diff --git a/gui/fitCommands/calc/fitRemoveModule.py b/gui/fitCommands/calc/fitRemoveModule.py index 9eb2e013a..79ae52198 100644 --- a/gui/fitCommands/calc/fitRemoveModule.py +++ b/gui/fitCommands/calc/fitRemoveModule.py @@ -13,7 +13,7 @@ class FitRemoveModuleCommand(wx.Command): from sFit.removeModule """ def __init__(self, fitID: int, positions: list = None): - wx.Command.__init__(self, True, "Module Remove") + wx.Command.__init__(self, True) self.fitID = fitID self.positions = positions self.modCache = [] @@ -21,12 +21,14 @@ class FitRemoveModuleCommand(wx.Command): def Do(self): fitID = self.fitID - pyfalog.debug("Removing module from position ({0}) for fit ID: {1}", self.positions, fitID) fit = eos.db.getFit(fitID) + pyfalog.debug("Removing module from position ({0}) for fit ID: {1}", self.positions, fitID) + for x in self.positions: mod = fit.modules[x] if not mod.isEmpty: + pyfalog.debug(" -- Removing {}", mod) self.modCache.append(ModuleInfoCache(mod.modPosition, mod.item.ID, mod.state, mod.charge, mod.baseItemID, mod.mutaplasmidID)) fit.modules.toDummy(x) @@ -44,8 +46,11 @@ class FitRemoveModuleCommand(wx.Command): return True def Undo(self): + pyfalog.debug("Reapplying {} removed module(s) for {}", len(self.modCache), self.fitID) + from gui.fitCommands.calc.fitAddModule import FitAddModuleCommand # avoids circular import for mod in self.modCache: + pyfalog.debug(" -- {}", mod) # todo, send the state and charge? cmd = FitAddModuleCommand(self.fitID, mod.itemID, mod.mutaplasmidID, mod.baseID) cmd.Do() diff --git a/gui/fitCommands/calc/fitSetCharge.py b/gui/fitCommands/calc/fitSetCharge.py index e97d55adb..d06258924 100644 --- a/gui/fitCommands/calc/fitSetCharge.py +++ b/gui/fitCommands/calc/fitSetCharge.py @@ -20,7 +20,6 @@ class FitSetChargeCommand(wx.Command): self.cache = None def Do(self): - pyfalog.debug("Set ammo for fit ID: {0}", self.fitID) return self.__setAmmo(self.positions, self.chargeID) def Undo(self): @@ -40,6 +39,7 @@ class FitSetChargeCommand(wx.Command): for pos in positions: mod = fit.modules[pos] if not mod.isEmpty and mod.isValidCharge(ammo): + pyfalog.debug("Set ammo {} for {} on fit {}", ammo, mod, self.fitID) result = True mod.charge = ammo eos.db.commit() diff --git a/gui/fitCommands/guiAddModule.py b/gui/fitCommands/guiAddModule.py index 06267919f..ae279d506 100644 --- a/gui/fitCommands/guiAddModule.py +++ b/gui/fitCommands/guiAddModule.py @@ -6,6 +6,8 @@ from .calc.fitAddModule import FitAddModuleCommand from .calc.fitReplaceModule import FitReplaceModuleCommand from .calc.fitSetCharge import FitSetChargeCommand from service.fit import Fit +from logbook import Logger +pyfalog = Logger(__name__) class GuiModuleAddCommand(wx.Command): @@ -28,21 +30,27 @@ class GuiModuleAddCommand(wx.Command): self.old_mod = None def Do(self): + pyfalog.debug("{} Do()".format(self)) success = False item = eos.db.getItem(self.itemID) if item.isCharge and self.position is not None: + pyfalog.debug("Trying to add a charge") success = self.internal_history.Submit(FitSetChargeCommand(self.fitID, [self.position], self.itemID)) if not success: + pyfalog.debug(" Failed") return False # if it's a charge item and this failed, nothing more we can try. # if we have a position set, try to apply the module to that position elif self.position is not None: + pyfalog.debug("Trying to add a module to a specific position") success = self.internal_history.Submit(FitReplaceModuleCommand(self.fitID, self.position, self.itemID)) if not success: + pyfalog.debug(" Failed") # something went wrong with trying to fit the module into specific location, attempt to append it self.position = None # if we're not trying to set module to a position, simply append if self.position is None: + pyfalog.debug("Trying to append a module") success = self.internal_history.Submit(FitAddModuleCommand(self.fitID, self.itemID)) if success: @@ -53,6 +61,7 @@ class GuiModuleAddCommand(wx.Command): def Undo(self): + pyfalog.debug("{} Undo()".format(self)) for _ in self.internal_history.Commands: self.internal_history.Undo() self.sFit.recalc(self.fitID) diff --git a/gui/fitCommands/guiRemoveModule.py b/gui/fitCommands/guiRemoveModule.py index 508c7178b..169dbe593 100644 --- a/gui/fitCommands/guiRemoveModule.py +++ b/gui/fitCommands/guiRemoveModule.py @@ -11,6 +11,7 @@ from .calc.fitRemoveModule import FitRemoveModuleCommand class GuiModuleRemoveCommand(wx.Command): def __init__(self, fitID, modules): """ + Handles removing modules from fit.modules, :param fitID: The fit ID that we are modifying :param modules: A list of Module objects that we are attempting to remove. From c84c79c9171395cf39be50d024a45d9d05d46679 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Fri, 3 Aug 2018 01:08:33 -0400 Subject: [PATCH 4/8] More tweaks to existing commands --- gui/fitCommands/calc/fitChangeState.py | 4 +--- gui/fitCommands/calc/fitCloneModule.py | 4 ++-- gui/fitCommands/guiAddCharge.py | 2 +- gui/fitCommands/guiSwapCloneModule.py | 30 ++++++++++++++++--------- gui/fitCommands/guiToggleModuleState.py | 20 ++++++++++------- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/gui/fitCommands/calc/fitChangeState.py b/gui/fitCommands/calc/fitChangeState.py index c800e030e..06ad7bfbd 100644 --- a/gui/fitCommands/calc/fitChangeState.py +++ b/gui/fitCommands/calc/fitChangeState.py @@ -26,9 +26,6 @@ class FitChangeStatesCommand(wx.Command): self.old_states[mod.modPosition] = mod.state def Do(self): - # todo: determine if we've changed state (recalc). If not, store that so we don't attempt to recalc on undo - # self.sFit.toggleModulesState(self.fitID, self.baseMod, self.modules, self.click) - pyfalog.debug("Toggle module state for fit ID: {0}", self.fitID) changed = False proposedState = Module.getProposedState(self.baseMod, self.click) @@ -43,6 +40,7 @@ class FitChangeStatesCommand(wx.Command): if p != mod.state: changed = True + # if we haven't change the state (eg, overheat -> overheat), simply fail the command if changed: self.changed = changed eos.db.commit() diff --git a/gui/fitCommands/calc/fitCloneModule.py b/gui/fitCommands/calc/fitCloneModule.py index b126c5063..14c24ddc6 100644 --- a/gui/fitCommands/calc/fitCloneModule.py +++ b/gui/fitCommands/calc/fitCloneModule.py @@ -10,7 +10,7 @@ from logbook import Logger pyfalog = Logger(__name__) import copy -class FitCloneModduleCommand(wx.Command): +class FitCloneModuleCommand(wx.Command): """ Clone a module from src to dst This will overwrite dst! Checking for empty module must be @@ -25,7 +25,6 @@ class FitCloneModduleCommand(wx.Command): self.dst = dst def Do(self): - pyfalog.debug("Cloning modules from source ({0}) to destination ({1}) for fit ID: {1}", self.src, self.dst, self.fitID) fit = eos.db.getFit(self.fitID) # Gather modules srcMod = fit.modules[self.src] @@ -34,6 +33,7 @@ class FitCloneModduleCommand(wx.Command): new = copy.deepcopy(srcMod) new.owner = fit if new.fits(fit): + pyfalog.debug("Cloning {} from source {} to destination {} for fit ID {}", srcMod, self.src, self.dst, self.fitID) # insert copy if module meets hardpoint restrictions fit.modules.remove(dstMod) fit.modules.insert(self.dst, new) diff --git a/gui/fitCommands/guiAddCharge.py b/gui/fitCommands/guiAddCharge.py index 94d7d4249..6d1e5e70a 100644 --- a/gui/fitCommands/guiAddCharge.py +++ b/gui/fitCommands/guiAddCharge.py @@ -23,7 +23,7 @@ class GuiModuleAddChargeCommand(wx.Command): return False def Undo(self): - for x in self.internal_history.Commands: + for _ in self.internal_history.Commands: self.internal_history.Undo() self.sFit.recalc(self.fitID) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) diff --git a/gui/fitCommands/guiSwapCloneModule.py b/gui/fitCommands/guiSwapCloneModule.py index bc283943c..65ddea591 100644 --- a/gui/fitCommands/guiSwapCloneModule.py +++ b/gui/fitCommands/guiSwapCloneModule.py @@ -4,11 +4,14 @@ from service.fit import Fit import gui.mainFrame from gui import globalEvents as GE from gui.fitCommands.calc.fitSwapModule import FitSwapModuleCommand -from .calc.fitCloneModule import FitCloneModduleCommand +from .calc.fitCloneModule import FitCloneModuleCommand +from logbook import Logger +pyfalog = Logger(__name__) + class GuiModuleSwapOrCloneCommand(wx.Command): + def __init__(self, fitID, srcPosition, dstPosition, clone=False): - # todo: instead of modules, needs to be positions. Dead objects are a thing wx.Command.__init__(self, True, "Module State Change") self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.sFit = Fit.getInstance() @@ -19,17 +22,24 @@ class GuiModuleSwapOrCloneCommand(wx.Command): self.internal_history = wx.CommandProcessor() def Do(self): - result = None - if self.clone: - result = self.internal_history.Submit(FitCloneModduleCommand(self.fitID, self.srcPosition, self.dstPosition)) - else: - result = self.internal_history.Submit(FitSwapModuleCommand(self.fitID, self.srcPosition, self.dstPosition)) + pyfalog.debug("{} Do()".format(self)) - if result: - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) - return result + if self.clone: + pyfalog.debug("Trying to clone module") + if self.internal_history.Submit(FitCloneModuleCommand(self.fitID, self.srcPosition, self.dstPosition)): + self.sFit.recalc(self.fitID) # clone needs a recalc + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + return True + else: + pyfalog.debug("Trying to Swap module") + if self.internal_history.Submit(FitSwapModuleCommand(self.fitID, self.srcPosition, self.dstPosition)): + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + return True + + return False def Undo(self): + pyfalog.debug("{} Undo()".format(self)) for _ in self.internal_history.Commands: self.internal_history.Undo() wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) diff --git a/gui/fitCommands/guiToggleModuleState.py b/gui/fitCommands/guiToggleModuleState.py index 0f2344e64..7fcd824b1 100644 --- a/gui/fitCommands/guiToggleModuleState.py +++ b/gui/fitCommands/guiToggleModuleState.py @@ -5,6 +5,7 @@ import gui.mainFrame from gui import globalEvents as GE from .calc.fitChangeState import FitChangeStatesCommand + class GuiModuleStateChangeCommand(wx.Command): def __init__(self, fitID, baseMod, modules, click): # todo: instead of modules, needs to be positions. Dead objects are a thing @@ -16,16 +17,19 @@ class GuiModuleStateChangeCommand(wx.Command): self.modules = modules self.click = click self.internal_history = wx.CommandProcessor() + self.cmd = FitChangeStatesCommand(self.fitID, self.baseMod, self.modules, self.click) def Do(self): - # todo: determine if we've changed state (recalc). If not, store that so we don't attempt to recalc on undo - self.internal_history.Submit(FitChangeStatesCommand(self.fitID, self.baseMod, self.modules, self.click)) + if self.internal_history.Submit(self.cmd): + self.sFit.recalc(self.fitID) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + return True + return False + + def Undo(self): + for _ in self.internal_history.Commands: + self.internal_history.Undo() + self.sFit.recalc(self.fitID) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) return True - def Undo(self): - for x in self.internal_history.Commands: - self.internal_history.Undo() - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) - return True - From 168622052316f8f840a538ad37dd338f1fd69119 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Fri, 3 Aug 2018 01:42:06 -0400 Subject: [PATCH 5/8] Fix the state change command to not store the modules themselves, but the positions --- gui/builtinViews/fittingView.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 247003b55..74d02295c 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -268,7 +268,9 @@ class FittingView(d.Display): sel = [] row = self.GetFirstSelected() while row != -1: - sel.append(self.mods[self.GetItemData(row)]) + mod = self.mods[self.GetItemData(row)] + if mod and not isinstance(mod, Rack): + sel.append(mod) row = self.GetNextSelected(row) return sel @@ -629,7 +631,7 @@ class FittingView(d.Display): ctrl = event.cmdDown or event.middleIsDown click = "ctrl" if ctrl is True else "right" if event.GetButton() == 3 else "left" - self.mainFrame.command.Submit(cmd.GuiModuleStateChangeCommand(fitID, self.mods[self.GetItemData(row)], mods, click)) + self.mainFrame.command.Submit(cmd.GuiModuleStateChangeCommand(fitID, self.mods[self.GetItemData(row)].modPosition, [mod.modPosition for mod in mods], click)) # update state tooltip tooltip = self.activeColumns[col].getToolTip(self.mods[self.GetItemData(row)]) From aa282990a5a3a08d85fb90e1edc90b308a3bafe5 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Fri, 3 Aug 2018 01:42:06 -0400 Subject: [PATCH 6/8] Fix the state change command to not store the modules themselves, but the positions --- gui/builtinViews/fittingView.py | 6 ++- gui/fitCommands/calc/fitChangeState.py | 59 ++++++++++++++++---------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 247003b55..74d02295c 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -268,7 +268,9 @@ class FittingView(d.Display): sel = [] row = self.GetFirstSelected() while row != -1: - sel.append(self.mods[self.GetItemData(row)]) + mod = self.mods[self.GetItemData(row)] + if mod and not isinstance(mod, Rack): + sel.append(mod) row = self.GetNextSelected(row) return sel @@ -629,7 +631,7 @@ class FittingView(d.Display): ctrl = event.cmdDown or event.middleIsDown click = "ctrl" if ctrl is True else "right" if event.GetButton() == 3 else "left" - self.mainFrame.command.Submit(cmd.GuiModuleStateChangeCommand(fitID, self.mods[self.GetItemData(row)], mods, click)) + self.mainFrame.command.Submit(cmd.GuiModuleStateChangeCommand(fitID, self.mods[self.GetItemData(row)].modPosition, [mod.modPosition for mod in mods], click)) # update state tooltip tooltip = self.activeColumns[col].getToolTip(self.mods[self.GetItemData(row)]) diff --git a/gui/fitCommands/calc/fitChangeState.py b/gui/fitCommands/calc/fitChangeState.py index 06ad7bfbd..a6a1548cd 100644 --- a/gui/fitCommands/calc/fitChangeState.py +++ b/gui/fitCommands/calc/fitChangeState.py @@ -9,40 +9,53 @@ pyfalog = Logger(__name__) import eos.db class FitChangeStatesCommand(wx.Command): - def __init__(self, fitID, baseMod, modules, click): + """ + Fitting command that trys to change the state of modules in [positions]. We use the base module to determine the + state that we will try to apply for all modules. + + + """ + def __init__(self, fitID, baseModPos, positions, click): # todo: instead of modules, needs to be positions. Dead objects are a thing wx.Command.__init__(self, True, "Module State Change") self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.sFit = Fit.getInstance() self.fitID = fitID - self.baseMod = baseMod - self.modules = modules + self.baseModPos = baseModPos + self.positions = positions self.click = click self.changed = None self.old_states = {} - for mod in modules: - # we don't use the actual module as the key, because it may have been deleted in subsequent calls (even if - # we undo a deletion, wouldn't be the same obj). So, we store the position - self.old_states[mod.modPosition] = mod.state def Do(self): - pyfalog.debug("Toggle module state for fit ID: {0}", self.fitID) - changed = False - proposedState = Module.getProposedState(self.baseMod, self.click) + fit = eos.db.getFit(self.fitID) - if proposedState != self.baseMod.state: - changed = True - self.baseMod.state = proposedState - for mod in self.modules: - if mod != self.baseMod: - p = Module.getProposedState(mod, self.click, proposedState) - mod.state = p - if p != mod.state: - changed = True + baseMod = fit.modules[self.baseModPos] + + # make sure positions only include non-empty positions + self.positions = [x for x in self.positions if not fit.modules[x].isEmpty] + + for x in self.positions: + self.old_states[x] = fit.modules[x].state + + proposedState = Module.getProposedState(baseMod, self.click) + pyfalog.debug("Attempting to change modules to {}", proposedState) + + if proposedState != baseMod.state: + pyfalog.debug("Toggle {} state: {} for fit ID: {}", baseMod, proposedState, self.fitID) + + self.changed = True + baseMod.state = proposedState + for i in [x for x in self.positions if x != self.baseModPos]: # dont consider base module position + mod = fit.modules[i] + p = Module.getProposedState(mod, self.click, proposedState) + mod.state = p + if p != mod.state: + pyfalog.debug("Toggle {} state: {} for fit ID: {}", mod, p, self.fitID) + self.changed = True # if we haven't change the state (eg, overheat -> overheat), simply fail the command - if changed: - self.changed = changed + if self.changed: eos.db.commit() # As some items may affect state-limiting attributes of the ship, calculate new attributes first # self.recalc(fit) @@ -55,5 +68,7 @@ class FitChangeStatesCommand(wx.Command): # todo: some sanity checking to make sure that we are applying state back to the same modules? fit = self.sFit.getFit(self.fitID) for k, v in self.old_states.items(): - fit.modules[k].state = v + mod = fit.modules[k] + pyfalog.debug("Reverting {} to state {} for fit ID", mod, v, self.fitID) + mod.state = v return True From 6057a1a7d99018fdf09e6990590d2d447b992ded Mon Sep 17 00:00:00 2001 From: blitzmann Date: Fri, 3 Aug 2018 02:01:26 -0400 Subject: [PATCH 7/8] Fix issue with setting None charge --- gui/fitCommands/calc/fitSetCharge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/fitCommands/calc/fitSetCharge.py b/gui/fitCommands/calc/fitSetCharge.py index d06258924..eeb4df407 100644 --- a/gui/fitCommands/calc/fitSetCharge.py +++ b/gui/fitCommands/calc/fitSetCharge.py @@ -32,7 +32,7 @@ class FitSetChargeCommand(wx.Command): self.cache = {fit.modules[i].modPosition: fit.modules[i].chargeID for i in positions} ammo = eos.db.getItem(chargeID) if chargeID else None - if not ammo.isCharge: + if ammo is not None and not ammo.isCharge: return False result = False From 15ba5c8ace1b1fcb2a22e48d0af87838a06ca37e Mon Sep 17 00:00:00 2001 From: blitzmann Date: Fri, 3 Aug 2018 02:01:42 -0400 Subject: [PATCH 8/8] Convert tactical mode switching --- gui/builtinContextMenus/tacticalMode.py | 6 ++--- gui/fitCommands/__init__.py | 1 + gui/fitCommands/calc/fitSetMode.py | 34 +++++++++++++++++++++++++ gui/fitCommands/guiSetMode.py | 31 ++++++++++++++++++++++ service/fit.py | 1 + 5 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 gui/fitCommands/calc/fitSetMode.py create mode 100644 gui/fitCommands/guiSetMode.py diff --git a/gui/builtinContextMenus/tacticalMode.py b/gui/builtinContextMenus/tacticalMode.py index e09b26940..04c82574f 100644 --- a/gui/builtinContextMenus/tacticalMode.py +++ b/gui/builtinContextMenus/tacticalMode.py @@ -6,7 +6,7 @@ import gui.mainFrame import gui.globalEvents as GE from service.fit import Fit from service.settings import ContextMenuSettings - +import gui.fitCommands as cmd class TacticalMode(ContextMenu): def __init__(self): @@ -60,10 +60,8 @@ class TacticalMode(ContextMenu): event.Skip() return - sFit = Fit.getInstance() fitID = self.mainFrame.getActiveFit() - sFit.setMode(fitID, self.modeIds[event.Id]) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) + self.mainFrame.command.Submit(cmd.GuiSetModeCommand(fitID, self.modeIds[event.Id])) TacticalMode.register() diff --git a/gui/fitCommands/__init__.py b/gui/fitCommands/__init__.py index 89a74b369..c7a37439f 100644 --- a/gui/fitCommands/__init__.py +++ b/gui/fitCommands/__init__.py @@ -7,3 +7,4 @@ from .guiRemoveCargo import GuiRemoveCargoCommand from .guiAddCargo import GuiAddCargoCommand from .guiRemoveImplant import GuiRemoveImplantCommand from .guiAddImplant import GuiAddImplantCommand +from .guiSetMode import GuiSetModeCommand \ No newline at end of file diff --git a/gui/fitCommands/calc/fitSetMode.py b/gui/fitCommands/calc/fitSetMode.py new file mode 100644 index 000000000..183c292aa --- /dev/null +++ b/gui/fitCommands/calc/fitSetMode.py @@ -0,0 +1,34 @@ +import wx +from service.fit import Fit + +import gui.mainFrame +from gui import globalEvents as GE +#from .helpers import ModuleInfoCache +from eos.saveddata.module import Module, State +import eos.db +from logbook import Logger +pyfalog = Logger(__name__) + + +class FitSetModeCommand(wx.Command): + """" + from sFit.setMode + """ + def __init__(self, fitID, mode): + wx.Command.__init__(self, True, "Cargo add") + self.fitID = fitID + self.mode = mode + self.old_mode = None + + def Do(self): + pyfalog.debug("Set mode for fit ID: {0}", self.fitID) + fit = eos.db.getFit(self.fitID) + self.old_mode = fit.mode + fit.mode = self.mode + eos.db.commit() + return True + + def Undo(self): + cmd = FitSetModeCommand(self.fitID, self.old_mode) + cmd.Do() + return True diff --git a/gui/fitCommands/guiSetMode.py b/gui/fitCommands/guiSetMode.py new file mode 100644 index 000000000..2c1e4864c --- /dev/null +++ b/gui/fitCommands/guiSetMode.py @@ -0,0 +1,31 @@ +import wx +from service.fit import Fit + +import gui.mainFrame +from gui import globalEvents as GE +from .calc.fitSetMode import FitSetModeCommand + +class GuiSetModeCommand(wx.Command): + def __init__(self, fitID, mode): + wx.Command.__init__(self, True, "Cargo Add") + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.sFit = Fit.getInstance() + self.internal_history = wx.CommandProcessor() + self.fitID = fitID + # can set his up no to not have to set variables on our object + self.cmd = FitSetModeCommand(fitID, mode) + + def Do(self): + if self.internal_history.Submit(self.cmd): + self.sFit.recalc(self.fitID) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + return True + return False + + def Undo(self): + for _ in self.internal_history.Commands: + self.internal_history.Undo() + self.sFit.recalc(self.fitID) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + return True + diff --git a/service/fit.py b/service/fit.py index d3ed7d9c7..47c9c2960 100644 --- a/service/fit.py +++ b/service/fit.py @@ -1155,6 +1155,7 @@ class Fit(object): self.recalc(fit) + @deprecated def setMode(self, fitID, mode): pyfalog.debug("Set mode for fit ID: {0}", fitID) if fitID is None: