diff --git a/eos/db/saveddata/booster.py b/eos/db/saveddata/booster.py
index e40762cd9..fa29c70b2 100644
--- a/eos/db/saveddata/booster.py
+++ b/eos/db/saveddata/booster.py
@@ -24,6 +24,8 @@ import datetime
from eos.db import saveddata_meta
from eos.saveddata.booster import Booster
+from eos.saveddata.boosterSideEffect import BoosterSideEffect
+from eos.saveddata.fit import Fit
boosters_table = Table("boosters", saveddata_meta,
Column("ID", Integer, primary_key=True),
@@ -34,19 +36,21 @@ boosters_table = Table("boosters", saveddata_meta,
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
)
-# Legacy booster side effect code, should disable but a mapper relies on it.
-activeSideEffects_table = Table("boostersActiveSideEffects", saveddata_meta,
- Column("boosterID", ForeignKey("boosters.ID"), primary_key=True),
- Column("effectID", Integer, primary_key=True))
+
+booster_side_effect_table = Table("boosterSideEffects", saveddata_meta,
+ Column("boosterID", Integer, ForeignKey("boosters.ID"), primary_key=True, index=True),
+ Column("effectID", Integer, nullable=False, primary_key=True),
+ Column("active", Boolean, default=False))
-class ActiveSideEffectsDummy(object):
- def __init__(self, effectID):
- self.effectID = effectID
-
-
-mapper(ActiveSideEffectsDummy, activeSideEffects_table)
mapper(Booster, boosters_table,
- properties={"_Booster__activeSideEffectDummies": relation(ActiveSideEffectsDummy)})
+ properties={
+ "_Booster__sideEffects": relation(
+ BoosterSideEffect,
+ backref="booster",
+ cascade='all, delete, delete-orphan'),
+ }
+)
-Booster._Booster__activeSideEffectIDs = association_proxy("_Booster__activeSideEffectDummies", "effectID")
+
+mapper(BoosterSideEffect, booster_side_effect_table)
diff --git a/eos/saveddata/booster.py b/eos/saveddata/booster.py
index 62eb4d88f..aa5d6bfcb 100644
--- a/eos/saveddata/booster.py
+++ b/eos/saveddata/booster.py
@@ -24,6 +24,7 @@ from sqlalchemy.orm import reconstructor, validates
import eos.db
from eos.effectHandlerHelpers import HandledItem
from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut
+from eos.saveddata.boosterSideEffect import BoosterSideEffect
pyfalog = Logger(__name__)
@@ -37,6 +38,9 @@ class Booster(HandledItem, ItemAttrShortcut):
self.itemID = item.ID if item is not None else None
self.active = True
+
+ self.__sideEffects = self.__getSideEffects()
+
self.build()
@reconstructor
@@ -58,34 +62,23 @@ class Booster(HandledItem, ItemAttrShortcut):
def build(self):
""" Build object. Assumes proper and valid item already set """
- self.__sideEffects = []
self.__itemModifiedAttributes = ModifiedAttributeDict()
self.__itemModifiedAttributes.original = self.__item.attributes
self.__itemModifiedAttributes.overrides = self.__item.overrides
self.__slot = self.__calculateSlot(self.__item)
- # Legacy booster side effect code, disabling as not currently implemented
- '''
- for effect in self.__item.effects.itervalues():
- if effect.isType("boosterSideEffect"):
- s = SideEffect(self)
- s.effect = effect
- s.active = effect.ID in self.__activeSideEffectIDs
- self.__sideEffects.append(s)
- '''
+ if len(self.sideEffects) != len(self.__getSideEffects()):
+ self.__sideEffects = []
+ for ability in self.__getSideEffects():
+ self.__sideEffects.append(ability)
- # Legacy booster side effect code, disabling as not currently implemented
- '''
- def iterSideEffects(self):
- return self.__sideEffects.__iter__()
+ @property
+ def sideEffects(self):
+ return self.__sideEffects or []
- def getSideEffect(self, name):
- for sideEffect in self.iterSideEffects():
- if sideEffect.effect.name == name:
- return sideEffect
-
- raise KeyError("SideEffect with %s as name not found" % name)
- '''
+ def __getSideEffects(self):
+ """Returns list of BoosterSideEffect that are loaded with data"""
+ return [BoosterSideEffect(effect) for effect in self.item.effects.values() if effect.type and 'boosterSideEffect' in effect.type]
@property
def itemModifiedAttributes(self):
@@ -161,41 +154,3 @@ class Booster(HandledItem, ItemAttrShortcut):
'''
return copy
-
-
-# Legacy booster side effect code, disabling as not currently implemented
-'''
- class SideEffect(object):
- def __init__(self, owner):
- self.__owner = owner
- self.__active = False
- self.__effect = None
-
- @property
- def active(self):
- return self.__active
-
- @active.setter
- def active(self, active):
- if not isinstance(active, bool):
- raise TypeError("Expecting a bool, not a " + type(active))
-
- if active != self.__active:
- if active:
- self.__owner._Booster__activeSideEffectIDs.append(self.effect.ID)
- else:
- self.__owner._Booster__activeSideEffectIDs.remove(self.effect.ID)
-
- self.__active = active
-
- @property
- def effect(self):
- return self.__effect
-
- @effect.setter
- def effect(self, effect):
- if not hasattr(effect, "handler"):
- raise TypeError("Need an effect with a handler")
-
- self.__effect = effect
-'''
diff --git a/eos/saveddata/boosterSideEffect.py b/eos/saveddata/boosterSideEffect.py
new file mode 100644
index 000000000..71014c3a7
--- /dev/null
+++ b/eos/saveddata/boosterSideEffect.py
@@ -0,0 +1,63 @@
+# ===============================================================================
+# Copyright (C) 2010 Diego Duclos
+#
+# This file is part of eos.
+#
+# eos is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# eos is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with eos. If not, see .
+# ===============================================================================
+
+from logbook import Logger
+
+from sqlalchemy.orm import reconstructor
+
+pyfalog = Logger(__name__)
+
+
+class BoosterSideEffect(object):
+
+ def __init__(self, effect):
+ """Initialize from the program"""
+ self.__effect = effect
+ self.effectID = effect.ID if effect is not None else None
+ self.active = False
+ self.build()
+
+ @reconstructor
+ def init(self):
+ """Initialize from the database"""
+ self.__effect = None
+
+ if self.effectID:
+ self.__effect = next((x for x in self.booster.item.effects.itervalues() if x.ID == self.effectID), None)
+ if self.__effect is None:
+ pyfalog.error("Effect (id: {0}) does not exist", self.effectID)
+ return
+
+ self.build()
+
+ def build(self):
+ pass
+
+ @property
+ def effect(self):
+ return self.__effect
+
+ @property
+ def name(self):
+ return self.__effect.getattr('displayName') or self.__effect.handlerName
+
+ @property
+ def attrPrefix(self):
+ return self.__effect.getattr('prefix')
+
diff --git a/gui/boosterView.py b/gui/boosterView.py
index 5f43aca04..549c5fd4c 100644
--- a/gui/boosterView.py
+++ b/gui/boosterView.py
@@ -49,6 +49,7 @@ class BoosterView(d.Display):
"State",
"attr:boosterness",
"Base Name",
+ "Side Effects",
"Price",
]
diff --git a/gui/builtinContextMenus/boosterSideEffects.py b/gui/builtinContextMenus/boosterSideEffects.py
new file mode 100644
index 000000000..68cfed1b2
--- /dev/null
+++ b/gui/builtinContextMenus/boosterSideEffects.py
@@ -0,0 +1,64 @@
+# noinspection PyPackageRequirements
+import wx
+from gui.contextMenu import ContextMenu
+import gui.mainFrame
+import gui.globalEvents as GE
+from service.fit import Fit
+from service.settings import ContextMenuSettings
+
+
+class BoosterSideEffect(ContextMenu):
+ def __init__(self):
+ self.mainFrame = gui.mainFrame.MainFrame.getInstance()
+ self.settings = ContextMenuSettings.getInstance()
+
+ def display(self, srcContext, selection):
+ # if not self.settings.get('fighterAbilities'):
+ # return False
+
+ if self.mainFrame.getActiveFit() is None or srcContext not in ("boosterItem"):
+ return False
+
+ self.booster = selection[0]
+ return True
+
+ def getText(self, itmContext, selection):
+ return "Side Effects"
+
+ def addEffect(self, menu, ability):
+ label = ability.name
+ id = ContextMenu.nextID()
+ self.effectIds[id] = ability
+ menuItem = wx.MenuItem(menu, id, label, kind=wx.ITEM_CHECK)
+ menu.Bind(wx.EVT_MENU, self.handleMode, menuItem)
+ return menuItem
+
+ def getSubMenu(self, context, selection, rootMenu, i, pitem):
+ msw = True if "wxMSW" in wx.PlatformInfo else False
+ self.context = context
+ self.effectIds = {}
+
+ sub = wx.Menu()
+
+ for effect in self.booster.sideEffects:
+ if not effect.effect.isImplemented:
+ continue
+ menuItem = self.addEffect(rootMenu if msw else sub, effect)
+ sub.AppendItem(menuItem)
+ menuItem.Check(effect.active)
+
+ return sub
+
+ def handleMode(self, event):
+ effect = self.effectIds[event.Id]
+ if effect is False or effect not in self.booster.sideEffects:
+ event.Skip()
+ return
+
+ sFit = Fit.getInstance()
+ fitID = self.mainFrame.getActiveFit()
+ sFit.toggleBoosterSideEffect(fitID, effect)
+ wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
+
+
+BoosterSideEffect.register()
diff --git a/gui/builtinViewColumns/__init__.py b/gui/builtinViewColumns/__init__.py
index cff8bc614..2a089e176 100644
--- a/gui/builtinViewColumns/__init__.py
+++ b/gui/builtinViewColumns/__init__.py
@@ -1,2 +1,2 @@
__all__ = ["ammo", "ammoIcon", "attributeDisplay", "baseIcon", "baseName",
- "capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc", "abilities"]
+ "capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc", "abilities", "sideEffects"]
diff --git a/gui/builtinViewColumns/sideEffects.py b/gui/builtinViewColumns/sideEffects.py
new file mode 100644
index 000000000..25adb3769
--- /dev/null
+++ b/gui/builtinViewColumns/sideEffects.py
@@ -0,0 +1,46 @@
+# =============================================================================
+# Copyright (C) 2010 Diego Duclos
+#
+# This file is part of pyfa.
+#
+# pyfa is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# pyfa is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with pyfa. If not, see .
+# =============================================================================
+
+
+# noinspection PyPackageRequirements
+import wx
+from eos.saveddata.booster import Booster
+from gui.viewColumn import ViewColumn
+import gui.mainFrame
+
+
+class SideEffects(ViewColumn):
+ name = "Side Effects"
+
+ def __init__(self, fittingView, params):
+ ViewColumn.__init__(self, fittingView)
+
+ self.mainFrame = gui.mainFrame.MainFrame.getInstance()
+ self.columnText = "Active Side Effects"
+ self.mask = wx.LIST_MASK_TEXT
+
+ def getText(self, stuff):
+ if isinstance(stuff, Booster):
+ active = [x.name for x in stuff.sideEffects if x.active]
+ if len(active) == 0:
+ return "None"
+ return ", ".join(active)
+
+
+SideEffects.register()
diff --git a/gui/contextMenu.py b/gui/contextMenu.py
index b56661217..043140db3 100644
--- a/gui/contextMenu.py
+++ b/gui/contextMenu.py
@@ -206,6 +206,7 @@ from gui.builtinContextMenus import ( # noqa: E402,F401
metaSwap,
implantSets,
fighterAbilities,
+ boosterSideEffects,
commandFits,
tabbedFits
)
diff --git a/gui/viewColumn.py b/gui/viewColumn.py
index 34c3c89ce..08f9ca2bb 100644
--- a/gui/viewColumn.py
+++ b/gui/viewColumn.py
@@ -79,5 +79,6 @@ from gui.builtinViewColumns import ( # noqa: E402, F401
misc,
price,
propertyDisplay,
- state
+ state,
+ sideEffects
)
diff --git a/service/fit.py b/service/fit.py
index 896ca689d..da1b2fe0f 100644
--- a/service/fit.py
+++ b/service/fit.py
@@ -991,6 +991,13 @@ class Fit(object):
eos.db.commit()
self.recalc(fit)
+ def toggleBoosterSideEffect(self, fitID, sideEffect):
+ pyfalog.debug("Toggling booster side effect for fit ID: {0}", fitID)
+ fit = eos.db.getFit(fitID)
+ sideEffect.active = not sideEffect.active
+ eos.db.commit()
+ self.recalc(fit)
+
def changeChar(self, fitID, charID):
pyfalog.debug("Changing character ({0}) for fit ID: {1}", charID, fitID)
if fitID is None or charID is None: