Merge branch 'master' into wx3
Conflicts: config.py staticdata/icons/icon01_08.png staticdata/icons/icon02_11.png staticdata/icons/icon105_46.png staticdata/icons/icon105_47.png staticdata/icons/icon105_48.png staticdata/icons/icon105_49.png staticdata/icons/icon108_5.png staticdata/icons/icon113_64_1.png staticdata/icons/icon113_64_2.png staticdata/icons/icon113_64_3.png staticdata/icons/icon34_16.png staticdata/icons/iconMarketIcon_16px_Amarr.png staticdata/icons/iconMarketIcon_16px_Caldari.png staticdata/icons/iconMarketIcon_16px_Gallente.png staticdata/icons/iconMarketIcon_16px_Minmatar.png
This commit is contained in:
@@ -14,8 +14,9 @@ __all__ = [
|
||||
"whProjector",
|
||||
"cargo",
|
||||
"shipJump",
|
||||
#"changeAffectingSkills",
|
||||
"changeAffectingSkills",
|
||||
"tacticalMode",
|
||||
"targetResists",
|
||||
"priceClear"
|
||||
"priceClear",
|
||||
"amount",
|
||||
]
|
||||
|
||||
75
gui/builtinContextMenus/amount.py
Normal file
75
gui/builtinContextMenus/amount.py
Normal file
@@ -0,0 +1,75 @@
|
||||
from gui.contextMenu import ContextMenu
|
||||
from gui.itemStats import ItemStatsDialog
|
||||
import eos.types
|
||||
import gui.mainFrame
|
||||
import service
|
||||
import gui.globalEvents as GE
|
||||
import wx
|
||||
|
||||
class ChangeAmount(ContextMenu):
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def display(self, srcContext, selection):
|
||||
return srcContext in ("cargoItem","projectedFit")
|
||||
|
||||
def getText(self, itmContext, selection):
|
||||
return "Change {0} Quantity".format(itmContext)
|
||||
|
||||
def activate(self, fullContext, selection, i):
|
||||
srcContext = fullContext[0]
|
||||
dlg = AmountChanger(self.mainFrame, selection[0], srcContext)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
ChangeAmount.register()
|
||||
|
||||
class AmountChanger(wx.Dialog):
|
||||
|
||||
def __init__(self, parent, thing, context):
|
||||
wx.Dialog.__init__(self, parent, title="Select Amount", size=wx.Size(220, 60))
|
||||
self.thing = thing
|
||||
self.context = context
|
||||
|
||||
bSizer1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
|
||||
|
||||
bSizer1.Add(self.input, 1, wx.ALL, 5)
|
||||
self.input.Bind(wx.EVT_CHAR, self.onChar)
|
||||
self.input.Bind(wx.EVT_TEXT_ENTER, self.change)
|
||||
self.button = wx.Button(self, wx.ID_OK, u"Done")
|
||||
bSizer1.Add(self.button, 0, wx.ALL, 5)
|
||||
|
||||
self.SetSizer(bSizer1)
|
||||
self.Layout()
|
||||
self.Centre(wx.BOTH)
|
||||
self.button.Bind(wx.EVT_BUTTON, self.change)
|
||||
|
||||
def change(self, event):
|
||||
sFit = service.Fit.getInstance()
|
||||
mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
fitID = mainFrame.getActiveFit()
|
||||
|
||||
if isinstance(self.thing, eos.types.Cargo):
|
||||
sFit.addCargo(fitID, self.thing.item.ID, int(self.input.GetLineText(0)), replace=True)
|
||||
elif isinstance(self.thing, eos.types.Fit):
|
||||
sFit.changeAmount(fitID, self.thing, int(self.input.GetLineText(0)))
|
||||
|
||||
wx.PostEvent(mainFrame, GE.FitChanged(fitID=fitID))
|
||||
|
||||
event.Skip()
|
||||
self.Destroy()
|
||||
|
||||
## checks to make sure it's valid number
|
||||
def onChar(self, event):
|
||||
key = event.GetKeyCode()
|
||||
|
||||
acceptable_characters = "1234567890"
|
||||
acceptable_keycode = [3, 22, 13, 8, 127] # modifiers like delete, copy, paste
|
||||
if key in acceptable_keycode or key >= 255 or (key < 255 and chr(key) in acceptable_characters):
|
||||
event.Skip()
|
||||
return
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -29,67 +29,3 @@ class Cargo(ContextMenu):
|
||||
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
|
||||
|
||||
Cargo.register()
|
||||
|
||||
class CargoAmount(ContextMenu):
|
||||
def __init__(self):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def display(self, srcContext, selection):
|
||||
return srcContext in ("cargoItem",) and selection[0].amount >= 0
|
||||
|
||||
def getText(self, itmContext, selection):
|
||||
return "Change {0} Quantity".format(itmContext)
|
||||
|
||||
def activate(self, fullContext, selection, i):
|
||||
srcContext = fullContext[0]
|
||||
dlg = CargoChanger(self.mainFrame, selection[0], srcContext)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
CargoAmount.register()
|
||||
|
||||
class CargoChanger(wx.Dialog):
|
||||
|
||||
def __init__(self, parent, cargo, context):
|
||||
wx.Dialog.__init__(self, parent, title="Select Amount", size=wx.Size(220, 60))
|
||||
self.cargo = cargo
|
||||
self.context = context
|
||||
|
||||
bSizer1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.input = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
|
||||
|
||||
bSizer1.Add(self.input, 1, wx.ALL, 5)
|
||||
self.input.Bind(wx.EVT_CHAR, self.onChar)
|
||||
self.input.Bind(wx.EVT_TEXT_ENTER, self.change)
|
||||
self.button = wx.Button(self, wx.ID_OK, u"Done")
|
||||
bSizer1.Add(self.button, 0, wx.ALL, 5)
|
||||
|
||||
self.SetSizer(bSizer1)
|
||||
self.Layout()
|
||||
self.Centre(wx.BOTH)
|
||||
self.button.Bind(wx.EVT_BUTTON, self.change)
|
||||
|
||||
def change(self, event):
|
||||
sFit = service.Fit.getInstance()
|
||||
mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
fitID = mainFrame.getActiveFit()
|
||||
|
||||
sFit.addCargo(fitID, self.cargo.item.ID, int(self.input.GetLineText(0)), replace=True)
|
||||
|
||||
wx.PostEvent(mainFrame, GE.FitChanged(fitID=fitID))
|
||||
|
||||
event.Skip()
|
||||
self.Destroy()
|
||||
## checks to make sure it's valid number
|
||||
def onChar(self, event):
|
||||
key = event.GetKeyCode()
|
||||
|
||||
acceptable_characters = "1234567890"
|
||||
acceptable_keycode = [3, 22, 13, 8, 127] # modifiers like delete, copy, paste
|
||||
if key in acceptable_keycode or key >= 255 or (key < 255 and chr(key) in acceptable_characters):
|
||||
event.Skip()
|
||||
return
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class ChangeAffectingSkills(ContextMenu):
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def display(self, srcContext, selection):
|
||||
if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule", "fittingShip"):
|
||||
if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule", "fittingCharge", "fittingShip"):
|
||||
return False
|
||||
|
||||
self.sChar = service.Character.getInstance()
|
||||
@@ -32,7 +32,7 @@ class ChangeAffectingSkills(ContextMenu):
|
||||
self.stuff = selection[0]
|
||||
|
||||
cont = self.stuff.itemModifiedAttributes
|
||||
self.skills = []
|
||||
skills = set()
|
||||
|
||||
for attrName in cont.iterAfflictions():
|
||||
if cont[attrName] == 0:
|
||||
@@ -44,9 +44,9 @@ class ChangeAffectingSkills(ContextMenu):
|
||||
if not isinstance(afflictor, Skill):
|
||||
continue
|
||||
|
||||
self.skills.append(afflictor)
|
||||
self.skills.sort(key=lambda x: x.item.name)
|
||||
skills.add(afflictor)
|
||||
|
||||
self.skills = sorted(skills, key=lambda x: x.item.name)
|
||||
return len(self.skills) > 0
|
||||
|
||||
def getText(self, itmContext, selection):
|
||||
@@ -81,7 +81,8 @@ class ChangeAffectingSkills(ContextMenu):
|
||||
for i in xrange(-1, 6):
|
||||
levelItem = self.addSkill(rootMenu if msw else grandSub, skill, i)
|
||||
grandSub.AppendItem(levelItem)
|
||||
#@ todo: add check to current level. Need to fix #109 first
|
||||
if (not skill.learned and i == -1) or (skill.learned and skill.level == i):
|
||||
levelItem.Check(True)
|
||||
sub.AppendItem(skillItem)
|
||||
|
||||
return sub
|
||||
|
||||
@@ -15,7 +15,8 @@ class ItemStats(ContextMenu):
|
||||
"cargoItem", "droneItem",
|
||||
"implantItem", "boosterItem",
|
||||
"skillItem", "projectedModule",
|
||||
"projectedDrone", "projectedCharge")
|
||||
"projectedDrone", "projectedCharge",
|
||||
"itemStats")
|
||||
|
||||
def getText(self, itmContext, selection):
|
||||
return "{0} Stats".format(itmContext if itmContext is not None else "Item")
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from gui import builtinViewColumns
|
||||
from gui.viewColumn import ViewColumn
|
||||
from gui import bitmapLoader
|
||||
import gui.mainFrame
|
||||
|
||||
import wx
|
||||
from eos.types import Drone, Cargo, Fit, Module, Slot, Rack
|
||||
import service
|
||||
@@ -29,9 +29,12 @@ class BaseName(ViewColumn):
|
||||
name = "Base Name"
|
||||
def __init__(self, fittingView, params):
|
||||
ViewColumn.__init__(self, fittingView)
|
||||
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.columnText = "Name"
|
||||
self.shipImage = fittingView.imageList.GetImageIndex("ship_small", "icons")
|
||||
self.mask = wx.LIST_MASK_TEXT
|
||||
self.projectedView = isinstance(fittingView, gui.projectedView.ProjectedView)
|
||||
|
||||
def getText(self, stuff):
|
||||
if isinstance(stuff, Drone):
|
||||
@@ -39,7 +42,12 @@ class BaseName(ViewColumn):
|
||||
elif isinstance(stuff, Cargo):
|
||||
return "%dx %s" % (stuff.amount, stuff.item.name)
|
||||
elif isinstance(stuff, Fit):
|
||||
return "%s (%s)" % (stuff.name, stuff.ship.item.name)
|
||||
if self.projectedView:
|
||||
# we need a little more information for the projected view
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
return "%dx %s (%s)" % (stuff.getProjectionInfo(fitID).amount, stuff.name, stuff.ship.item.name)
|
||||
else:
|
||||
return "%s (%s)" % (stuff.name, stuff.ship.item.name)
|
||||
elif isinstance(stuff, Rack):
|
||||
if service.Fit.getInstance().serviceFittingOptions["rackLabels"]:
|
||||
if stuff.slot == Slot.MODE:
|
||||
|
||||
@@ -19,27 +19,21 @@
|
||||
|
||||
from gui.viewColumn import ViewColumn
|
||||
from gui import bitmapLoader
|
||||
import gui.mainFrame
|
||||
|
||||
import wx
|
||||
from eos.types import Drone, Module, Rack
|
||||
from eos.types import Drone, Module, Rack, Fit
|
||||
from eos.types import State as State_
|
||||
|
||||
class State(ViewColumn):
|
||||
name = "State"
|
||||
def __init__(self, fittingView, params):
|
||||
ViewColumn.__init__(self, fittingView)
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
self.resizable = False
|
||||
self.size = 16
|
||||
self.maxsize = self.size
|
||||
self.mask = wx.LIST_MASK_IMAGE
|
||||
for name, state in (("checked", wx.CONTROL_CHECKED), ("unchecked", 0)):
|
||||
bitmap = wx.EmptyBitmap(16, 16)
|
||||
dc = wx.MemoryDC()
|
||||
dc.SelectObject(bitmap)
|
||||
dc.SetBackground(wx.TheBrushList.FindOrCreateBrush(fittingView.GetBackgroundColour(), wx.SOLID))
|
||||
dc.Clear()
|
||||
wx.RendererNative.Get().DrawCheckBox(fittingView, dc, wx.Rect(0, 0, 16, 16), state)
|
||||
dc.Destroy()
|
||||
setattr(self, "%sId" % name, fittingView.imageList.Add(bitmap))
|
||||
|
||||
def getText(self, mod):
|
||||
return ""
|
||||
@@ -49,8 +43,14 @@ class State(ViewColumn):
|
||||
return State_.getName(mod.state).title()
|
||||
|
||||
def getImageId(self, stuff):
|
||||
generic_active = self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(1).lower(), "icons")
|
||||
generic_inactive = self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(-1).lower(), "icons")
|
||||
|
||||
if isinstance(stuff, Drone):
|
||||
return self.checkedId if stuff.amountActive > 0 else self.uncheckedId
|
||||
if stuff.amountActive > 0:
|
||||
return generic_active
|
||||
else:
|
||||
return generic_inactive
|
||||
elif isinstance(stuff, Rack):
|
||||
return -1
|
||||
elif isinstance(stuff, Module):
|
||||
@@ -58,11 +58,21 @@ class State(ViewColumn):
|
||||
return -1
|
||||
else:
|
||||
return self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(stuff.state).lower(), "icons")
|
||||
elif isinstance(stuff, Fit):
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
projectionInfo = stuff.getProjectionInfo(fitID)
|
||||
|
||||
if projectionInfo is None:
|
||||
return -1
|
||||
if projectionInfo.active:
|
||||
return generic_active
|
||||
return generic_inactive
|
||||
else:
|
||||
active = getattr(stuff, "active", None)
|
||||
if active is None:
|
||||
return -1
|
||||
else:
|
||||
return self.checkedId if active else self.uncheckedId
|
||||
if active:
|
||||
return generic_active
|
||||
return generic_inactive
|
||||
|
||||
State.register()
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#===============================================================================
|
||||
|
||||
import wx
|
||||
import os
|
||||
import bitmapLoader
|
||||
import gui.display
|
||||
import gui.globalEvents as GE
|
||||
@@ -41,6 +42,11 @@ class GraphFrame(wx.Frame):
|
||||
|
||||
try:
|
||||
import matplotlib as mpl
|
||||
cache_dir = mpl._get_cachedir()
|
||||
cache_file = os.path.join(cache_dir, 'fontList.cache')
|
||||
if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file):
|
||||
# remove matplotlib font cache, see #234
|
||||
os.remove(cache_file)
|
||||
if not mplImported:
|
||||
mpl.use('wxagg')
|
||||
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
|
||||
|
||||
375
gui/itemStats.py
375
gui/itemStats.py
@@ -24,10 +24,11 @@ import bitmapLoader
|
||||
import sys
|
||||
import wx.lib.mixins.listctrl as listmix
|
||||
import wx.html
|
||||
from eos.types import Ship, Module, Skill, Booster, Implant, Drone, Mode
|
||||
from eos.types import Fit, Ship, Module, Skill, Booster, Implant, Drone, Mode
|
||||
from gui.utils.numberFormatter import formatAmount
|
||||
import service
|
||||
import config
|
||||
from gui.contextMenu import ContextMenu
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
@@ -549,15 +550,20 @@ class ItemEffects (wx.Panel):
|
||||
|
||||
|
||||
class ItemAffectedBy (wx.Panel):
|
||||
ORDER = [Ship, Mode, Module, Drone, Implant, Booster, Skill]
|
||||
ORDER = [Fit, Ship, Mode, Module, Drone, Implant, Booster, Skill]
|
||||
def __init__(self, parent, stuff, item):
|
||||
wx.Panel.__init__ (self, parent)
|
||||
wx.Panel.__init__(self, parent)
|
||||
self.stuff = stuff
|
||||
self.item = item
|
||||
|
||||
self.toggleView = 1
|
||||
self.activeFit = gui.mainFrame.MainFrame.getInstance().getActiveFit()
|
||||
|
||||
self.showRealNames = False
|
||||
self.showAttrView = False
|
||||
self.expand = -1
|
||||
|
||||
self.treeItems = []
|
||||
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
self.affectedBy = wx.TreeCtrl(self, style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.NO_BORDER)
|
||||
@@ -571,7 +577,10 @@ class ItemAffectedBy (wx.Panel):
|
||||
self.toggleExpandBtn = wx.ToggleButton( self, wx.ID_ANY, u"Expand All", wx.DefaultPosition, wx.DefaultSize, 0 )
|
||||
bSizer.Add( self.toggleExpandBtn, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
|
||||
self.toggleViewBtn = wx.ToggleButton( self, wx.ID_ANY, u"Toggle view mode", wx.DefaultPosition, wx.DefaultSize, 0 )
|
||||
self.toggleNameBtn = wx.ToggleButton( self, wx.ID_ANY, u"Toggle Names", wx.DefaultPosition, wx.DefaultSize, 0 )
|
||||
bSizer.Add( self.toggleNameBtn, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
|
||||
self.toggleViewBtn = wx.ToggleButton( self, wx.ID_ANY, u"Toggle View", wx.DefaultPosition, wx.DefaultSize, 0 )
|
||||
bSizer.Add( self.toggleViewBtn, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
|
||||
if stuff is not None:
|
||||
@@ -579,13 +588,36 @@ class ItemAffectedBy (wx.Panel):
|
||||
bSizer.Add( self.refreshBtn, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.refreshBtn.Bind( wx.EVT_BUTTON, self.RefreshTree )
|
||||
|
||||
self.toggleViewBtn.Bind(wx.EVT_TOGGLEBUTTON,self.ToggleViewMode)
|
||||
self.toggleNameBtn.Bind(wx.EVT_TOGGLEBUTTON,self.ToggleNameMode)
|
||||
self.toggleExpandBtn.Bind(wx.EVT_TOGGLEBUTTON,self.ToggleExpand)
|
||||
self.toggleViewBtn.Bind(wx.EVT_TOGGLEBUTTON,self.ToggleViewMode)
|
||||
|
||||
mainSizer.Add( bSizer, 0, wx.ALIGN_RIGHT)
|
||||
self.SetSizer(mainSizer)
|
||||
self.PopulateTree()
|
||||
self.Layout()
|
||||
self.affectedBy.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.scheduleMenu)
|
||||
|
||||
def scheduleMenu(self, event):
|
||||
event.Skip()
|
||||
wx.CallAfter(self.spawnMenu, event.Item)
|
||||
|
||||
def spawnMenu(self, item):
|
||||
self.affectedBy.SelectItem(item)
|
||||
|
||||
stuff = self.affectedBy.GetPyData(item)
|
||||
# String is set as data when we are dealing with attributes, not stuff containers
|
||||
if stuff is None or isinstance(stuff, basestring):
|
||||
return
|
||||
contexts = []
|
||||
|
||||
# Skills are different in that they don't have itemModifiedAttributes,
|
||||
# which is needed if we send the container to itemStats dialog. So
|
||||
# instead, we send the item.
|
||||
type = stuff.__class__.__name__
|
||||
contexts.append(("itemStats", type))
|
||||
menu = ContextMenu.getMenu(stuff if type != "Skill" else stuff.item, *contexts)
|
||||
self.PopupMenu(menu)
|
||||
|
||||
def ExpandCollapseTree(self):
|
||||
|
||||
@@ -607,18 +639,11 @@ class ItemAffectedBy (wx.Panel):
|
||||
def ToggleViewTree(self):
|
||||
self.Freeze()
|
||||
|
||||
root = self.affectedBy.GetRootItem()
|
||||
child,cookie = self.affectedBy.GetFirstChild(root)
|
||||
while child.IsOk():
|
||||
item,childcookie = self.affectedBy.GetFirstChild(child)
|
||||
while item.IsOk():
|
||||
change = self.affectedBy.GetPyData(item)
|
||||
display = self.affectedBy.GetItemText(item)
|
||||
self.affectedBy.SetItemText(item,change)
|
||||
self.affectedBy.SetPyData(item,display)
|
||||
item,childcookie = self.affectedBy.GetNextChild(child,childcookie)
|
||||
|
||||
child,cookie = self.affectedBy.GetNextChild(root,cookie)
|
||||
for item in self.treeItems:
|
||||
change = self.affectedBy.GetPyData(item)
|
||||
display = self.affectedBy.GetItemText(item)
|
||||
self.affectedBy.SetItemText(item, change)
|
||||
self.affectedBy.SetPyData(item, display)
|
||||
|
||||
self.Thaw()
|
||||
|
||||
@@ -633,33 +658,214 @@ class ItemAffectedBy (wx.Panel):
|
||||
event.Skip()
|
||||
|
||||
def ToggleViewMode(self, event):
|
||||
self.toggleView *=-1
|
||||
self.showAttrView = not self.showAttrView
|
||||
self.affectedBy.DeleteAllItems()
|
||||
self.PopulateTree()
|
||||
event.Skip()
|
||||
|
||||
def ToggleNameMode(self, event):
|
||||
self.showRealNames = not self.showRealNames
|
||||
self.ToggleViewTree()
|
||||
event.Skip()
|
||||
|
||||
def PopulateTree(self):
|
||||
# sheri was here
|
||||
del self.treeItems[:]
|
||||
root = self.affectedBy.AddRoot("WINPWNZ0R")
|
||||
self.affectedBy.SetPyData(root, None)
|
||||
|
||||
self.imageList = wx.ImageList(16, 16)
|
||||
self.affectedBy.SetImageList(self.imageList)
|
||||
|
||||
cont = self.stuff.itemModifiedAttributes if self.item == self.stuff.item else self.stuff.chargeModifiedAttributes
|
||||
things = {}
|
||||
if self.showAttrView:
|
||||
self.buildAttributeView(root)
|
||||
else:
|
||||
self.buildModuleView(root)
|
||||
|
||||
for attrName in cont.iterAfflictions():
|
||||
self.ExpandCollapseTree()
|
||||
|
||||
def sortAttrDisplayName(self, attr):
|
||||
info = self.stuff.item.attributes.get(attr)
|
||||
if info and info.displayName != "":
|
||||
return info.displayName
|
||||
|
||||
return attr
|
||||
|
||||
def buildAttributeView(self, root):
|
||||
# We first build a usable dictionary of items. The key is either a fit
|
||||
# if the afflictions stem from a projected fit, or self.stuff if they
|
||||
# are local afflictions (everything else, even gang boosts at this time)
|
||||
# The value of this is yet another dictionary in the following format:
|
||||
#
|
||||
# "attribute name": {
|
||||
# "Module Name": [
|
||||
# class of affliction,
|
||||
# affliction item (required due to GH issue #335)
|
||||
# modifier type
|
||||
# amount of modification
|
||||
# whether this affliction was projected
|
||||
# ]
|
||||
# }
|
||||
|
||||
attributes = self.stuff.itemModifiedAttributes if self.item == self.stuff.item else self.stuff.chargeModifiedAttributes
|
||||
container = {}
|
||||
for attrName in attributes.iterAfflictions():
|
||||
# if value is 0 or there has been no change from original to modified, return
|
||||
if cont[attrName] == (cont.getOriginal(attrName) or 0):
|
||||
if attributes[attrName] == (attributes.getOriginal(attrName) or 0):
|
||||
continue
|
||||
for fit, afflictors in cont.getAfflictions(attrName).iteritems():
|
||||
|
||||
for fit, afflictors in attributes.getAfflictions(attrName).iteritems():
|
||||
for afflictor, modifier, amount, used in afflictors:
|
||||
|
||||
if not used or afflictor.item is None:
|
||||
continue
|
||||
|
||||
if afflictor.item.name not in things:
|
||||
things[afflictor.item.name] = [type(afflictor), set(), []]
|
||||
if fit.ID != self.activeFit:
|
||||
# affliction fit does not match our fit
|
||||
if fit not in container:
|
||||
container[fit] = {}
|
||||
items = container[fit]
|
||||
else:
|
||||
# local afflictions
|
||||
if self.stuff not in container:
|
||||
container[self.stuff] = {}
|
||||
items = container[self.stuff]
|
||||
|
||||
info = things[afflictor.item.name]
|
||||
# items hold our module: info mappings
|
||||
if attrName not in items:
|
||||
items[attrName] = []
|
||||
|
||||
if afflictor == self.stuff and getattr(afflictor, 'charge', None):
|
||||
# we are showing a charges modifications, see #335
|
||||
item = afflictor.charge
|
||||
else:
|
||||
item = afflictor.item
|
||||
|
||||
items[attrName].append((type(afflictor), afflictor, item, modifier, amount, getattr(afflictor, "projected", False)))
|
||||
|
||||
# Make sure projected fits are on top
|
||||
rootOrder = container.keys()
|
||||
rootOrder.sort(key=lambda x: self.ORDER.index(type(x)))
|
||||
|
||||
# Now, we take our created dictionary and start adding stuff to our tree
|
||||
for thing in rootOrder:
|
||||
# This block simply directs which parent we are adding to (root or projected fit)
|
||||
if thing == self.stuff:
|
||||
parent = root
|
||||
else: # projected fit
|
||||
icon = self.imageList.Add(bitmapLoader.getBitmap("ship_small", "icons"))
|
||||
child = self.affectedBy.AppendItem(root, "{} ({})".format(thing.name, thing.ship.item.name), icon)
|
||||
parent = child
|
||||
|
||||
attributes = container[thing]
|
||||
attrOrder = sorted(attributes.keys(), key=self.sortAttrDisplayName)
|
||||
|
||||
for attrName in attrOrder:
|
||||
attrInfo = self.stuff.item.attributes.get(attrName)
|
||||
displayName = attrInfo.displayName if attrInfo and attrInfo.displayName != "" else attrName
|
||||
|
||||
if attrInfo:
|
||||
if attrInfo.icon is not None:
|
||||
iconFile = attrInfo.icon.iconFile
|
||||
icon = bitmapLoader.getBitmap(iconFile, "pack")
|
||||
if icon is None:
|
||||
icon = bitmapLoader.getBitmap("transparent16x16", "icons")
|
||||
attrIcon = self.imageList.Add(icon)
|
||||
else:
|
||||
attrIcon = self.imageList.Add(bitmapLoader.getBitmap("07_15", "pack"))
|
||||
else:
|
||||
attrIcon = self.imageList.Add(bitmapLoader.getBitmap("07_15", "pack"))
|
||||
|
||||
if self.showRealNames:
|
||||
display = attrName
|
||||
saved = displayName
|
||||
else:
|
||||
display = displayName
|
||||
saved = attrName
|
||||
|
||||
# this is the attribute node
|
||||
child = self.affectedBy.AppendItem(parent, display, attrIcon)
|
||||
self.affectedBy.SetPyData(child, saved)
|
||||
self.treeItems.append(child)
|
||||
|
||||
items = attributes[attrName]
|
||||
items.sort(key=lambda x: self.ORDER.index(x[0]))
|
||||
for itemInfo in items:
|
||||
afflictorType, afflictor, item, attrModifier, attrAmount, projected = itemInfo
|
||||
|
||||
if afflictorType == Ship:
|
||||
itemIcon = self.imageList.Add(bitmapLoader.getBitmap("ship_small", "icons"))
|
||||
elif item.icon:
|
||||
bitmap = bitmapLoader.getBitmap(item.icon.iconFile, "pack")
|
||||
itemIcon = self.imageList.Add(bitmap) if bitmap else -1
|
||||
else:
|
||||
itemIcon = -1
|
||||
|
||||
displayStr = item.name
|
||||
|
||||
if projected:
|
||||
displayStr += " (projected)"
|
||||
|
||||
if attrModifier == "s*":
|
||||
attrModifier = "*"
|
||||
penalized = "(penalized)"
|
||||
else:
|
||||
penalized = ""
|
||||
|
||||
# this is the Module node, the attribute will be attached to this
|
||||
display = "%s %s %.2f %s" % (displayStr, attrModifier, attrAmount, penalized)
|
||||
treeItem = self.affectedBy.AppendItem(child, display, itemIcon)
|
||||
self.affectedBy.SetPyData(treeItem, afflictor)
|
||||
|
||||
|
||||
def buildModuleView(self, root):
|
||||
# We first build a usable dictionary of items. The key is either a fit
|
||||
# if the afflictions stem from a projected fit, or self.stuff if they
|
||||
# are local afflictions (everything else, even gang boosts at this time)
|
||||
# The value of this is yet another dictionary in the following format:
|
||||
#
|
||||
# "Module Name": [
|
||||
# class of affliction,
|
||||
# set of afflictors (such as 2 of the same module),
|
||||
# info on affliction (attribute name, modifier, and modification amount),
|
||||
# item that will be used to determine icon (required due to GH issue #335)
|
||||
# whether this affliction is actually used (unlearned skills are not used)
|
||||
# ]
|
||||
|
||||
attributes = self.stuff.itemModifiedAttributes if self.item == self.stuff.item else self.stuff.chargeModifiedAttributes
|
||||
container = {}
|
||||
for attrName in attributes.iterAfflictions():
|
||||
# if value is 0 or there has been no change from original to modified, return
|
||||
if attributes[attrName] == (attributes.getOriginal(attrName) or 0):
|
||||
continue
|
||||
|
||||
for fit, afflictors in attributes.getAfflictions(attrName).iteritems():
|
||||
for afflictor, modifier, amount, used in afflictors:
|
||||
if not used or getattr(afflictor, 'item', None) is None:
|
||||
continue
|
||||
|
||||
if fit.ID != self.activeFit:
|
||||
# affliction fit does not match our fit
|
||||
if fit not in container:
|
||||
container[fit] = {}
|
||||
items = container[fit]
|
||||
else:
|
||||
# local afflictions
|
||||
if self.stuff not in container:
|
||||
container[self.stuff] = {}
|
||||
items = container[self.stuff]
|
||||
|
||||
if afflictor == self.stuff and getattr(afflictor, 'charge', None):
|
||||
# we are showing a charges modifications, see #335
|
||||
item = afflictor.charge
|
||||
else:
|
||||
item = afflictor.item
|
||||
|
||||
# items hold our module: info mappings
|
||||
if item.name not in items:
|
||||
items[item.name] = [type(afflictor), set(), [], item, getattr(afflictor, "projected", False)]
|
||||
|
||||
info = items[item.name]
|
||||
info[1].add(afflictor)
|
||||
# If info[1] > 1, there are two separate modules working.
|
||||
# Check to make sure we only include the modifier once
|
||||
@@ -668,63 +874,86 @@ class ItemAffectedBy (wx.Panel):
|
||||
continue
|
||||
info[2].append((attrName, modifier, amount))
|
||||
|
||||
order = things.keys()
|
||||
order.sort(key=lambda x: (self.ORDER.index(things[x][0]), x))
|
||||
# Make sure projected fits are on top
|
||||
rootOrder = container.keys()
|
||||
rootOrder.sort(key=lambda x: self.ORDER.index(type(x)))
|
||||
|
||||
for itemName in order:
|
||||
info = things[itemName]
|
||||
# Now, we take our created dictionary and start adding stuff to our tree
|
||||
for thing in rootOrder:
|
||||
# This block simply directs which parent we are adding to (root or projected fit)
|
||||
if thing == self.stuff:
|
||||
parent = root
|
||||
else: # projected fit
|
||||
icon = self.imageList.Add(bitmapLoader.getBitmap("ship_small", "icons"))
|
||||
child = self.affectedBy.AppendItem(root, "{} ({})".format(thing.name, thing.ship.item.name), icon)
|
||||
parent = child
|
||||
|
||||
afflictorType, afflictors, attrData = info
|
||||
counter = len(afflictors)
|
||||
items = container[thing]
|
||||
order = items.keys()
|
||||
order.sort(key=lambda x: (self.ORDER.index(items[x][0]), x))
|
||||
|
||||
baseAfflictor = afflictors.pop()
|
||||
if afflictorType == Ship:
|
||||
itemIcon = self.imageList.Add(bitmapLoader.getBitmap("ship_small", "icons"))
|
||||
elif baseAfflictor.item.icon:
|
||||
bitmap = bitmapLoader.getBitmap(baseAfflictor.item.icon.iconFile, "pack")
|
||||
itemIcon = self.imageList.Add(bitmap) if bitmap else -1
|
||||
else:
|
||||
itemIcon = -1
|
||||
for itemName in order:
|
||||
info = items[itemName]
|
||||
afflictorType, afflictors, attrData, item, projected = info
|
||||
counter = len(afflictors)
|
||||
if afflictorType == Ship:
|
||||
itemIcon = self.imageList.Add(bitmapLoader.getBitmap("ship_small", "icons"))
|
||||
elif item.icon:
|
||||
bitmap = bitmapLoader.getBitmap(item.icon.iconFile, "pack")
|
||||
itemIcon = self.imageList.Add(bitmap) if bitmap else -1
|
||||
else:
|
||||
itemIcon = -1
|
||||
|
||||
child = self.affectedBy.AppendItem(root, "%s" % itemName if counter == 1 else "%s x %d" % (itemName,counter), itemIcon)
|
||||
displayStr = itemName
|
||||
|
||||
if counter > 0:
|
||||
attributes = []
|
||||
for attrName, attrModifier, attrAmount in attrData:
|
||||
attrInfo = self.stuff.item.attributes.get(attrName)
|
||||
displayName = attrInfo.displayName if attrInfo else ""
|
||||
if counter > 1:
|
||||
displayStr += " x {}".format(counter)
|
||||
|
||||
if attrInfo:
|
||||
if attrInfo.icon is not None:
|
||||
iconFile = attrInfo.icon.iconFile
|
||||
icon = bitmapLoader.getBitmap(iconFile, "pack")
|
||||
if icon is None:
|
||||
icon = bitmapLoader.getBitmap("transparent16x16", "icons")
|
||||
if projected:
|
||||
displayStr += " (projected)"
|
||||
|
||||
attrIcon = self.imageList.Add(icon)
|
||||
# this is the Module node, the attribute will be attached to this
|
||||
child = self.affectedBy.AppendItem(parent, displayStr, itemIcon)
|
||||
self.affectedBy.SetPyData(child, afflictors.pop())
|
||||
|
||||
if counter > 0:
|
||||
attributes = []
|
||||
for attrName, attrModifier, attrAmount in attrData:
|
||||
attrInfo = self.stuff.item.attributes.get(attrName)
|
||||
displayName = attrInfo.displayName if attrInfo else ""
|
||||
|
||||
if attrInfo:
|
||||
if attrInfo.icon is not None:
|
||||
iconFile = attrInfo.icon.iconFile
|
||||
icon = bitmapLoader.getBitmap(iconFile, "pack")
|
||||
if icon is None:
|
||||
icon = bitmapLoader.getBitmap("transparent16x16", "icons")
|
||||
|
||||
attrIcon = self.imageList.Add(icon)
|
||||
else:
|
||||
attrIcon = self.imageList.Add(bitmapLoader.getBitmap("07_15", "pack"))
|
||||
else:
|
||||
attrIcon = self.imageList.Add(bitmapLoader.getBitmap("07_15", "pack"))
|
||||
else:
|
||||
attrIcon = self.imageList.Add(bitmapLoader.getBitmap("07_15", "pack"))
|
||||
|
||||
if attrModifier == "s*":
|
||||
attrModifier = "*"
|
||||
penalized = "(penalized)"
|
||||
else:
|
||||
penalized = ""
|
||||
if attrModifier == "s*":
|
||||
attrModifier = "*"
|
||||
penalized = "(penalized)"
|
||||
else:
|
||||
penalized = ""
|
||||
|
||||
attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized, attrIcon))
|
||||
attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized, attrIcon))
|
||||
|
||||
attrSorted = sorted(attributes, key = lambda attribName: attribName[0])
|
||||
attrSorted = sorted(attributes, key = lambda attribName: attribName[0])
|
||||
for attr in attrSorted:
|
||||
attrName, displayName, attrModifier, attrAmount, penalized, attrIcon = attr
|
||||
|
||||
for attr in attrSorted:
|
||||
attrName, displayName, attrModifier, attrAmount, penalized, attrIcon = attr
|
||||
if self.toggleView == 1:
|
||||
treeitem = self.affectedBy.AppendItem(child, "%s %s %.2f %s" % ((displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized), attrIcon)
|
||||
self.affectedBy.SetPyData(treeitem,"%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized))
|
||||
else:
|
||||
treeitem = self.affectedBy.AppendItem(child, "%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized), attrIcon)
|
||||
self.affectedBy.SetPyData(treeitem,"%s %s %.2f %s" % ((displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized))
|
||||
|
||||
self.ExpandCollapseTree()
|
||||
if self.showRealNames:
|
||||
display = "%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized)
|
||||
saved = "%s %s %.2f %s" % ((displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
|
||||
else:
|
||||
display = "%s %s %.2f %s" % ((displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
|
||||
saved = "%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized)
|
||||
|
||||
treeitem = self.affectedBy.AppendItem(child, display, attrIcon)
|
||||
self.affectedBy.SetPyData(treeitem, saved)
|
||||
self.treeItems.append(treeitem)
|
||||
|
||||
Reference in New Issue
Block a user