diff --git a/eos/db/saveddata/fit.py b/eos/db/saveddata/fit.py index 060d7b2a1..ccc29832a 100644 --- a/eos/db/saveddata/fit.py +++ b/eos/db/saveddata/fit.py @@ -53,6 +53,12 @@ projectedFits_table = Table("projectedFits", saveddata_meta, Column("active", Boolean, nullable = False, default = 1), ) +commandFits_table = Table("commandFits", saveddata_meta, + Column("boosterID", ForeignKey("fits.ID"), primary_key = True), + Column("boostedID", ForeignKey("fits.ID"), primary_key = True), + Column("active", Boolean, nullable = False, default = 1) +) + class ProjectedFit(object): def __init__(self, sourceID, source_fit, amount=1, active=True): self.sourceID = sourceID @@ -83,12 +89,38 @@ class ProjectedFit(object): self.sourceID, self.victimID, self.amount, self.active, hex(id(self)) ) +class CommandFit(object): + def __init__(self, boosterID, booster_fit, active=True): + self.boosterID = boosterID + self.booster_fit = booster_fit + self.active = active + + @reconstructor + def init(self): + if self.booster_fit.isInvalid: + # Very rare for this to happen, but be prepared for it + eos.db.saveddata_session.delete(self.booster_fit) + eos.db.saveddata_session.flush() + eos.db.saveddata_session.refresh(self.boosted_fit) + + def __repr__(self): + return "CommandFit(boosterID={}, boostedID={}, active={}) at {}".format( + self.boosterID, self.boostedID, self.active, hex(id(self)) + ) + + Fit._Fit__projectedFits = association_proxy( "victimOf", # look at the victimOf association... "source_fit", # .. and return the source fits creator=lambda sourceID, source_fit: ProjectedFit(sourceID, source_fit) ) +Fit._Fit__commandFits = association_proxy( + "boostedOf", # look at the boostedOf association... + "booster_fit", # .. and return the booster fit + creator=lambda boosterID, booster_fit: CommandFit(boosterID, booster_fit) +) + mapper(Fit, fits_table, properties = { "_Fit__modules": relation( @@ -169,6 +201,18 @@ mapper(Fit, fits_table, backref='victim_fit', collection_class=attribute_mapped_collection('sourceID'), cascade='all, delete, delete-orphan'), + "boostedOnto": relationship( + CommandFit, + primaryjoin=commandFits_table.c.boosterID == fits_table.c.ID, + backref='booster_fit', + collection_class=attribute_mapped_collection('boostedID'), + cascade='all, delete, delete-orphan'), + "boostedOf": relationship( + CommandFit, + primaryjoin=fits_table.c.ID == commandFits_table.c.boostedID, + backref='boosted_fit', + collection_class=attribute_mapped_collection('boosterID'), + cascade='all, delete, delete-orphan'), } ) @@ -177,3 +221,5 @@ mapper(ProjectedFit, projectedFits_table, "_ProjectedFit__amount": projectedFits_table.c.amount, } ) + +mapper(CommandFit, commandFits_table) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index a3000267f..b6209b5bf 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -232,9 +232,16 @@ class Fit(object): # not return them. return [fit for fit in self.__projectedFits.values() if not fit.isInvalid] + @property + def commandFits(self): + return [fit for fit in self.__commandFits.values() if not fit.isInvalid] + def getProjectionInfo(self, fitID): return self.projectedOnto.get(fitID, None) + def getCommandInfo(self, fitID): + return self.boostedOnto.get(fitID, None) + @property def projectedDrones(self): return self.__projectedDrones diff --git a/gui/commandView.py b/gui/commandView.py index 6d966b175..63bc70221 100644 --- a/gui/commandView.py +++ b/gui/commandView.py @@ -93,7 +93,7 @@ class CommandView(d.Display): sFit = service.Fit.getInstance() row = self.GetFirstSelected() if row != -1: - sFit.removeProjected(fitID, self.get(row)) + sFit.removeCommand(fitID, self.get(row)) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) def handleDrag(self, type, fitID): @@ -103,7 +103,7 @@ class CommandView(d.Display): if activeFit: sFit = service.Fit.getInstance() draggedFit = sFit.getFit(fitID) - sFit.project(activeFit, draggedFit) + sFit.addCommandFit(activeFit, draggedFit) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFit)) def startDrag(self, event): @@ -116,14 +116,6 @@ class CommandView(d.Display): dropSource.SetData(data) dropSource.DoDragDrop() - def _merge(self, src, dst): - dstDrone = self.get(dst) - if isinstance(dstDrone, eos.types.Drone): - sFit = service.Fit.getInstance() - fitID = self.mainFrame.getActiveFit() - if sFit.mergeDrones(fitID, self.get(src), dstDrone, True): - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) - def fitSort(self, fit): return fit.name @@ -142,7 +134,7 @@ class CommandView(d.Display): stuff = [] if fit is not None: - self.fits = fit.projectedFits[:] + self.fits = fit.commandFits[:] self.fits.sort(key=self.fitSort) stuff.extend(self.fits) @@ -158,7 +150,7 @@ class CommandView(d.Display): # todo: verify if stuff == []: - stuff = [DummyEntry("Drag an item or fit, or use right-click menu for system effects")] + stuff = [DummyEntry("Drag a fit to this area")] self.update(stuff) @@ -179,7 +171,7 @@ class CommandView(d.Display): if col == self.getColIndex(State): fitID = self.mainFrame.getActiveFit() sFit = service.Fit.getInstance() - sFit.toggleProjected(fitID, item, "right" if event.Button == 3 else "left") + sFit.toggleCommandFit(fitID, item) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) def scheduleMenu(self, event): @@ -193,36 +185,16 @@ class CommandView(d.Display): if sel != -1: item = self.get(sel) sMkt = service.Market.getInstance() - if isinstance(item, eos.types.Drone): - srcContext = "projectedDrone" - itemContext = sMkt.getCategoryByItem(item.item).name - context = ((srcContext, itemContext),) - elif isinstance(item, eos.types.Fighter): - srcContext = "projectedFighter" - itemContext = sMkt.getCategoryByItem(item.item).name - context = ((srcContext, itemContext),) - elif isinstance(item, eos.types.Module): - modSrcContext = "projectedModule" - modItemContext = sMkt.getCategoryByItem(item.item).name - modFullContext = (modSrcContext, modItemContext) - if item.charge is not None: - chgSrcContext = "projectedCharge" - chgItemContext = sMkt.getCategoryByItem(item.charge).name - chgFullContext = (chgSrcContext, chgItemContext) - context = (modFullContext, chgFullContext) - else: - context = (modFullContext,) - else: - fitSrcContext = "projectedFit" - fitItemContext = item.name - context = ((fitSrcContext,fitItemContext),) - context = context + (("projected",),) + fitSrcContext = "commandFit" + fitItemContext = item.name + context = ((fitSrcContext,fitItemContext),) + context = context + (("command",),) menu = ContextMenu.getMenu((item,), *context) elif sel == -1: fitID = self.mainFrame.getActiveFit() if fitID is None: return - context = (("projected",),) + context = (("command",),) menu = ContextMenu.getMenu([], *context) if menu is not None: self.PopupMenu(menu) @@ -234,5 +206,5 @@ class CommandView(d.Display): if col != self.getColIndex(State): fitID = self.mainFrame.getActiveFit() sFit = service.Fit.getInstance() - sFit.removeProjected(fitID, self.get(row)) + sFit.removeCommand(fitID, self.get(row)) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) diff --git a/service/fit.py b/service/fit.py index 2d3b75be5..aa053cfea 100644 --- a/service/fit.py +++ b/service/fit.py @@ -381,6 +381,25 @@ class Fit(object): self.recalc(fit) return True + def addCommandFit(self, fitID, thing): + if fitID is None: + return + + fit = eos.db.getFit(fitID) + + if thing in fit.commandFits: + return + + fit.__commandFits[thing.ID] = thing + + # this bit is required -- see GH issue # 83 + eos.db.saveddata_session.flush() + eos.db.saveddata_session.refresh(thing) + + eos.db.commit() + self.recalc(fit) + return True + def toggleProjected(self, fitID, thing, click): fit = eos.db.getFit(fitID) if isinstance(thing, eos.types.Drone): @@ -402,6 +421,15 @@ class Fit(object): eos.db.commit() self.recalc(fit) + def toggleCommandFit(self, fitID, thing): + fit = eos.db.getFit(fitID) + commandInfo = thing.getCommandInfo(fitID) + if commandInfo: + commandInfo.active = not commandInfo.active + + eos.db.commit() + self.recalc(fit) + def changeAmount(self, fitID, projected_fit, amount): """Change amount of projected fits""" fit = eos.db.getFit(fitID) @@ -435,6 +463,13 @@ class Fit(object): eos.db.commit() self.recalc(fit) + def removeCommand(self, fitID, thing): + fit = eos.db.getFit(fitID) + del fit.__commandFits[thing.ID] + + eos.db.commit() + self.recalc(fit) + def appendModule(self, fitID, itemID): fit = eos.db.getFit(fitID) item = eos.db.getItem(itemID, eager=("attributes", "group.category"))