diff --git a/gui/builtinContextMenus/itemRemove.py b/gui/builtinContextMenus/itemRemove.py index d6b8f79f1..c1c11fde5 100644 --- a/gui/builtinContextMenus/itemRemove.py +++ b/gui/builtinContextMenus/itemRemove.py @@ -36,10 +36,10 @@ class ItemRemove(ContextMenu): if srcContext == "fittingModule": modules = [module for module in selection if module is not None] - self.mainFrame.command.Submit(cmd.FitModuleRemoveCommand(fitID, modules)) + self.mainFrame.command.Submit(cmd.GuiModuleRemoveCommand(fitID, modules)) return # the command takes care of the PostEvent elif srcContext in ("fittingCharge", "projectedCharge"): - self.mainFrame.command.Submit(cmd.FitModuleAddChargeCommand(fitID, None, selection)) + self.mainFrame.command.Submit(cmd.GuiModuleAddChargeCommand(fitID, None, selection)) elif srcContext == "droneItem": sFit.removeDrone(fitID, fit.drones.index(selection[0])) elif srcContext == "fighterItem": diff --git a/gui/builtinContextMenus/moduleAmmoPicker.py b/gui/builtinContextMenus/moduleAmmoPicker.py index 59f6c3391..9b9a3a308 100644 --- a/gui/builtinContextMenus/moduleAmmoPicker.py +++ b/gui/builtinContextMenus/moduleAmmoPicker.py @@ -229,7 +229,7 @@ class ModuleAmmoPicker(ContextMenu): return fitID = self.mainFrame.getActiveFit() - self.mainFrame.command.Submit(cmd.FitModuleAddChargeCommand(fitID, charge.ID if charge is not None else None, self.modules)) + self.mainFrame.command.Submit(cmd.GuiModuleAddChargeCommand(fitID, charge.ID if charge is not None else None, self.modules)) ModuleAmmoPicker.register() diff --git a/gui/builtinContextMenus/moduleGlobalAmmoPicker.py b/gui/builtinContextMenus/moduleGlobalAmmoPicker.py index 81bce6649..6f19aec96 100644 --- a/gui/builtinContextMenus/moduleGlobalAmmoPicker.py +++ b/gui/builtinContextMenus/moduleGlobalAmmoPicker.py @@ -40,7 +40,7 @@ class ModuleGlobalAmmoPicker(ModuleAmmoPicker): if mod.itemID == selectedModule.itemID: allModules.append(mod) - self.mainFrame.command.Submit(cmd.FitModuleAddChargeCommand(fitID, charge.ID if charge is not None else None, allModules)) + self.mainFrame.command.Submit(cmd.GuiModuleAddChargeCommand(fitID, charge.ID if charge is not None else None, allModules)) def display(self, srcContext, selection): if not self.settings.get('moduleGlobalAmmoPicker'): diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index d74474bbd..f57d54adc 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -383,9 +383,9 @@ class FittingView(d.Display): sel = self.GetNextSelected(sel) if len(modules) > 0: - self.mainFrame.command.Submit(cmd.FitModuleAddChargeCommand(fitID, itemID, modules)) + self.mainFrame.command.Submit(cmd.GuiModuleAddChargeCommand(fitID, itemID, modules)) else: - self.mainFrame.command.Submit(cmd.FitModuleAddCommand(fitID, itemID)) + self.mainFrame.command.Submit(cmd.GuiModuleAddCommand(fitID, itemID)) event.Skip() @@ -407,7 +407,7 @@ class FittingView(d.Display): if not isinstance(modules, list): modules = [modules] - self.mainFrame.command.Submit(cmd.FitModuleRemoveCommand(self.activeFitID, modules)) + self.mainFrame.command.Submit(cmd.GuiModuleRemoveCommand(self.activeFitID, modules)) def addModule(self, x, y, itemID): """Add a module from the market browser (from dragging it)""" @@ -419,7 +419,7 @@ class FittingView(d.Display): if not isinstance(mod, Module): # make sure we're not adding something to a T3D Mode return - self.mainFrame.command.Submit(cmd.FitModuleAddCommand(fitID, itemID, self.mods[dstRow].modPosition)) + self.mainFrame.command.Submit(cmd.GuiModuleAddCommand(fitID, itemID, self.mods[dstRow].modPosition)) def swapCargo(self, x, y, srcIdx): """Swap a module from cargo to fitting window""" @@ -465,7 +465,7 @@ class FittingView(d.Display): fitID = self.mainFrame.getActiveFit() if getattr(mod2, "modPosition") is not None: - self.mainFrame.command.Submit(cmd.FitModuleSwapOrCloneCommand(fitID, srcIdx, mod2.modPosition, clone)) + self.mainFrame.command.Submit(cmd.GuiModuleSwapOrCloneCommand(fitID, srcIdx, mod2.modPosition, clone)) else: pyfalog.error("Missing module position for: {0}", str(getattr(mod2, "ID", "Unknown"))) @@ -625,7 +625,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.FitModuleStateChangeCommand(fitID, self.mods[self.GetItemData(row)], mods, click)) + self.mainFrame.command.Submit(cmd.GuiModuleStateChangeCommand(fitID, self.mods[self.GetItemData(row)], mods, click)) # update state tooltip tooltip = self.activeColumns[col].getToolTip(self.mods[self.GetItemData(row)]) diff --git a/gui/fitCommands/__init__.py b/gui/fitCommands/__init__.py index c9bbf25da..b3cb622fc 100644 --- a/gui/fitCommands/__init__.py +++ b/gui/fitCommands/__init__.py @@ -1,5 +1,5 @@ -from .moduleStateChange import FitModuleStateChangeCommand -from .moduleAdd import FitModuleAddCommand -from .moduleRemove import FitModuleRemoveCommand -from .moduleAddCharge import FitModuleAddChargeCommand -from .moduleSwapOrClone import FitModuleSwapOrCloneCommand \ No newline at end of file +from .moduleStateChange import GuiModuleStateChangeCommand +from .moduleAdd import GuiModuleAddCommand +from .moduleRemove import GuiModuleRemoveCommand +from .moduleAddCharge import GuiModuleAddChargeCommand +from .moduleSwapOrClone import GuiModuleSwapOrCloneCommand \ No newline at end of file diff --git a/gui/fitCommands/fitAddModule.py b/gui/fitCommands/fitAddModule.py new file mode 100644 index 000000000..8ff72ab74 --- /dev/null +++ b/gui/fitCommands/fitAddModule.py @@ -0,0 +1,70 @@ +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 FitAddModuleCommand(wx.Command): + """" + Fitting command that appends a module to a fit using the first available slot. + + from sFit.appendModule + """ + def __init__(self, fitID, itemID): + wx.Command.__init__(self, True, "Module Add") + self.fitID = fitID + self.itemID = itemID + self.new_position = None + self.change = 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")) + + try: + self.module = Module(item) + except ValueError: + pyfalog.warning("Invalid item: {0}", itemID) + return False + + if self.module.item.category.name == "Subsystem": + fit.modules.freeSlot(self.module.getModifiedItemAttr("subSystemSlot")) + + if self.module.fits(fit): + self.module.owner = fit + numSlots = len(fit.modules) + fit.modules.append(self.module) + if self.module.isValidState(State.ACTIVE): + self.module.state = State.ACTIVE + + # todo: fix these + # As some items may affect state-limiting attributes of the ship, calculate new attributes first + # self.recalc(fit) + # Then, check states of all modules and change where needed. This will recalc if needed + # self.checkStates(fit, m) + + fit.fill() + eos.db.commit() + + self.change = numSlots != len(fit.modules) + self.new_position = self.module.modPosition + else: + return False + + return True + + def Undo(self): + from .fitRemoveModule import FitRemoveModuleCommand # Avoid circular import + if self.new_position: + cmd = FitRemoveModuleCommand(self.fitID, [self.new_position]) + cmd.Do() + return True diff --git a/gui/fitCommands/fitRemoveModule.py b/gui/fitCommands/fitRemoveModule.py new file mode 100644 index 000000000..02d4c193b --- /dev/null +++ b/gui/fitCommands/fitRemoveModule.py @@ -0,0 +1,57 @@ +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 FitRemoveModuleCommand(wx.Command): + """" + Fitting command that removes a module at a specified positions + + from sFit.removeModule + """ + def __init__(self, fitID: int, positions: list = None): + wx.Command.__init__(self, True, "Module Remove") + self.fitID = fitID + self.positions = positions + self.modCache = [] + self.change = None + + 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) + + 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)) + fit.modules.toDummy(x) + + # if no modules have changes, report back None + if not len(self.modCache) > 0: + return False + + numSlots = len(fit.modules) + # todo: determine if we need to do this still + # self.recalc(fit) + # self.checkStates(fit, None) + fit.fill() + eos.db.commit() + self.slotsChanged = numSlots != len(fit.modules) + return True + + def Undo(self): + from .fitAddModule import FitAddModuleCommand # avoids circular import + for mod in self.modCache: + cmd = FitAddModuleCommand(self.fitID, mod.itemID) + cmd.Do() + cmd.module.state = mod.state + cmd.module.charge = mod.charge + return True diff --git a/gui/fitCommands/fitReplaceModule.py b/gui/fitCommands/fitReplaceModule.py new file mode 100644 index 000000000..0d9900b0e --- /dev/null +++ b/gui/fitCommands/fitReplaceModule.py @@ -0,0 +1,77 @@ +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 FitReplaceModuleCommand(wx.Command): + """" + Fitting command that changes an existing module into another. + + from sFit.changeModule + """ + def __init__(self, fitID, position, itemID): + wx.Command.__init__(self, True, "Change Module") + self.fitID = fitID + self.itemID = itemID + self.position = position + self.module = None # the module version of itemID + self.old_module = None + + def Do(self): + return self.change_module(self.fitID, self.position, self.itemID) + + def Undo(self): + self.change_module(self.fitID, self.position, self.itemID) + self.module.state = self.old_module.state + self.module.charge = self.old_module.charge + return True + + def change_module(self, fitID, position, itemID): + fit = eos.db.getFit(fitID) + + # We're trying to add a charge to a slot, which won't work. Instead, try to add the charge to the module in that slot. + # todo: evaluate if this is still a thing + # actually, this seems like it should be handled higher up... + # + # if self.isAmmo(itemID): + # module = fit.modules[self.position] + # if not module.isEmpty: + # self.setAmmo(fitID, itemID, [module]) + # return True + + pyfalog.debug("Changing position of module from position ({0}) for fit ID: {1}", self.position, fitID) + + 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) + + try: + self.module = Module(item) + except ValueError: + pyfalog.warning("Invalid item: {0}", itemID) + return False + + if self.module.fits(fit): + self.module.owner = fit + fit.modules.toModule(self.position, self.module) + if self.module.isValidState(State.ACTIVE): + self.module.state = State.ACTIVE + + # Then, check states of all modules and change where needed. This will recalc if needed + # self.checkStates(fit, m) + + fit.fill() + eos.db.commit() + return True + return False diff --git a/gui/fitCommands/moduleAdd.py b/gui/fitCommands/moduleAdd.py index ee631cc65..a783c241d 100644 --- a/gui/fitCommands/moduleAdd.py +++ b/gui/fitCommands/moduleAdd.py @@ -4,9 +4,10 @@ from service.fit import Fit import gui.mainFrame from gui import globalEvents as GE from .helpers import ModuleInfoCache +from .fitAddModule import FitAddModuleCommand +from .fitReplaceModule import FitReplaceModuleCommand - -class FitModuleAddCommand(wx.Command): +class GuiModuleAddCommand(wx.Command): def __init__(self, fitID, itemID, position=None): wx.Command.__init__(self, True, "Module Add") # todo: evaluate mutaplasmid modules @@ -14,45 +15,37 @@ class FitModuleAddCommand(wx.Command): self.sFit = Fit.getInstance() self.fitID = fitID self.itemID = itemID + self.internal_history = wx.CommandProcessor() self.new_position = position self.old_mod = None def Do(self): - change = None - + success = False # if we have a position set, try to apply the module to that position if self.new_position: - fit = self.sFit.getFit(self.fitID) - old_mod = fit.modules[self.new_position] - cache = ModuleInfoCache(old_mod.modPosition, old_mod.itemID, old_mod.state, old_mod.charge) - change = self.sFit.changeModule(self.fitID, self.new_position, self.itemID) - if change is None: - # the new module doesn't fit in specified slot, remove the position + success = self.internal_history.Submit(FitReplaceModuleCommand(self.fitID, self.new_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 - elif not old_mod.isEmpty: - self.old_mod = cache # if we're not trying to set module to a position, simply append if not self.new_position: - change, self.new_position = self.sFit.appendModule(self.fitID, self.itemID) + success = self.internal_history.Submit(FitAddModuleCommand(self.fitID, self.itemID)) - 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? + if success: wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID, action="modadd", typeID=self.itemID)) 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): - if self.new_position: - if self.old_mod: - # we added a module on top of another one - m = self.sFit.changeModule(self.fitID, self.old_mod.modPosition, self.old_mod.itemID, False) - m.state = self.old_mod.state - m.charge = self.old_mod.charge - else: - # todo: self.slotsChanged() - # we simply added a module, so simply remove - result = self.sFit.removeModule(self.fitID, [self.new_position]) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID, action="moddel", typeID=self.itemID)) + for _ in self.internal_history.Commands: + self.internal_history.Undo() + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID, action="moddel", typeID=self.itemID)) return True diff --git a/gui/fitCommands/moduleAddCharge.py b/gui/fitCommands/moduleAddCharge.py index c125230b9..c696b51c5 100644 --- a/gui/fitCommands/moduleAddCharge.py +++ b/gui/fitCommands/moduleAddCharge.py @@ -5,7 +5,7 @@ import gui.mainFrame from gui import globalEvents as GE -class FitModuleAddChargeCommand(wx.Command): +class GuiModuleAddChargeCommand(wx.Command): def __init__(self, fitID, itemID, modules): wx.Command.__init__(self, True, "Module Charge Add") # todo: evaluate mutaplasmid modules diff --git a/gui/fitCommands/moduleRemove.py b/gui/fitCommands/moduleRemove.py index b70423beb..25ce96658 100644 --- a/gui/fitCommands/moduleRemove.py +++ b/gui/fitCommands/moduleRemove.py @@ -6,8 +6,10 @@ from gui import globalEvents as GE from collections import namedtuple from .helpers import ModuleInfoCache +from .fitRemoveModule import FitRemoveModuleCommand -class FitModuleRemoveCommand(wx.Command): + +class GuiModuleRemoveCommand(wx.Command): def __init__(self, fitID, modules): # todo: evaluate mutaplasmid modules wx.Command.__init__(self, True, "Module Remove") @@ -15,22 +17,19 @@ class FitModuleRemoveCommand(wx.Command): self.sFit = Fit.getInstance() self.fitID = fitID self.modCache = [ModuleInfoCache(mod.modPosition, mod.item.ID, mod.state, mod.charge) for mod in modules] + self.internal_history = wx.CommandProcessor() def Do(self): - self.sFit.getFit(self.fitID) - result = self.sFit.removeModule(self.fitID, [mod.modPosition for mod in self.modCache]) + # 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 result is not None: + if success is not None: # self.slotsChanged() # todo: fix wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID, action="moddel", typeID=set([mod.itemID for mod in self.modCache]))) - return True + return True def Undo(self): - for mod in self.modCache: - m = self.sFit.changeModule(self.fitID, mod.modPosition, mod.itemID, False) - m.state = mod.state - m.charge = mod.charge - self.sFit.recalc(self.fitID) + for x in self.internal_history.Commands: + self.internal_history.Undo() wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID, action="modadd", typeID=set([mod.itemID for mod in self.modCache]))) - return True diff --git a/gui/fitCommands/moduleStateChange.py b/gui/fitCommands/moduleStateChange.py index c490115e2..340526972 100644 --- a/gui/fitCommands/moduleStateChange.py +++ b/gui/fitCommands/moduleStateChange.py @@ -5,7 +5,7 @@ import gui.mainFrame from gui import globalEvents as GE -class FitModuleStateChangeCommand(wx.Command): +class GuiModuleStateChangeCommand(wx.Command): def __init__(self, fitID, baseMod, modules, click): # todo: instead of modules, needs to be positions. Dead objects are a thing wx.Command.__init__(self, True, "Module State Change") diff --git a/gui/fitCommands/moduleSwapOrClone.py b/gui/fitCommands/moduleSwapOrClone.py index 65b6a10dc..58a3c00c5 100644 --- a/gui/fitCommands/moduleSwapOrClone.py +++ b/gui/fitCommands/moduleSwapOrClone.py @@ -5,7 +5,7 @@ import gui.mainFrame from gui import globalEvents as GE -class FitModuleSwapOrCloneCommand(wx.Command): +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") diff --git a/service/fit.py b/service/fit.py index 1172cd2fb..c4c0c15e6 100644 --- a/service/fit.py +++ b/service/fit.py @@ -37,7 +37,7 @@ from eos.saveddata.fit import Fit as FitType, ImplantLocation from service.character import Character from service.damagePattern import DamagePattern from service.settings import SettingsProvider - +from utils.deprecated import deprecated pyfalog = Logger(__name__) @@ -538,6 +538,7 @@ class Fit(object): eos.db.commit() return mutator.value + @deprecated def appendModule(self, fitID, itemID): pyfalog.debug("Appending module for fit ({0}) using item: {1}", fitID, itemID) fit = eos.db.getFit(fitID) @@ -570,6 +571,7 @@ class Fit(object): else: return None, None + @deprecated def removeModule(self, fitID, positions): """Removes modules based on a number of positions.""" pyfalog.debug("Removing module from position ({0}) for fit ID: {1}", positions, fitID) @@ -627,6 +629,7 @@ class Fit(object): else: return None + @deprecated def changeModule(self, fitID, position, newItemID, recalc=True): fit = eos.db.getFit(fitID) diff --git a/utils/deprecated.py b/utils/deprecated.py new file mode 100644 index 000000000..e7eeb9fad --- /dev/null +++ b/utils/deprecated.py @@ -0,0 +1,16 @@ +import warnings +import functools + +def deprecated(func): + """This is a decorator which can be used to mark functions + as deprecated. It will result in a warning being emitted + when the function is used.""" + @functools.wraps(func) + def new_func(*args, **kwargs): + warnings.simplefilter('always', DeprecationWarning) # turn off filter + warnings.warn("Call to deprecated function {}.".format(func.__name__), + category=DeprecationWarning, + stacklevel=2) + warnings.simplefilter('default', DeprecationWarning) # reset filter + return func(*args, **kwargs) + return new_func