Merge branch 'development' into More_Variations

Conflicts:
	gui/builtinContextMenus/metaSwap.py
This commit is contained in:
blitzmann
2017-02-26 02:24:38 -05:00
416 changed files with 17820 additions and 9680 deletions

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,13 +15,16 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
class PFListPane(wx.ScrolledWindow):
def __init__(self, parent):
wx.ScrolledWindow.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(1, 1), style=wx.TAB_TRAVERSAL)
wx.ScrolledWindow.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(1, 1),
style=wx.TAB_TRAVERSAL)
self._wList = []
self._wCount = 0
@@ -29,19 +32,18 @@ class PFListPane(wx.ScrolledWindow):
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
self.SetVirtualSize((1, 1))
self.SetScrollRate(0, 1)
self.Bind(wx.EVT_SCROLLWIN_LINEUP, self.MScrollUp)
self.Bind(wx.EVT_SCROLLWIN_LINEDOWN, self.MScrollDown)
# self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus)
# self.Bind(wx.EVT_LEFT_DOWN, self.ForceFocus)
# self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus)
# self.Bind(wx.EVT_LEFT_DOWN, self.ForceFocus)
self.SetFocus()
# self.Bind(wx.EVT_MOUSE_CAPTURE_CHANGED, self.ForceFocus)
# self.Bind(wx.EVT_MOUSE_CAPTURE_CHANGED, self.ForceFocus)
self.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.ForceFocus)
def ForceFocus(self,event):
def ForceFocus(self, event):
if self.FindFocus() and self.FindFocus().Parent != self:
self.SetFocus()
event.Skip()
@@ -67,23 +69,22 @@ class PFListPane(wx.ScrolledWindow):
event.Skip()
def ScrollChildIntoView(self, child):
"""
Scrolls the panel such that the specified child window is in view.
"""
sppu_x, sppu_y = self.GetScrollPixelsPerUnit()
vs_x, vs_y = self.GetViewStart()
vs_x, vs_y = self.GetViewStart()
cr = child.GetRect()
clntsz = self.GetSize()
new_vs_x, new_vs_y = -1, -1
# is it before the left edge?
if cr.x < 0 and sppu_x > 0:
if cr.x < 0 < sppu_x:
new_vs_x = vs_x + (cr.x / sppu_x)
# is it above the top?
if cr.y < 0 and sppu_y > 0:
if cr.y < 0 < sppu_y:
new_vs_y = vs_y + (cr.y / sppu_y)
# For the right and bottom edges, scroll enough to show the
@@ -110,8 +111,6 @@ class PFListPane(wx.ScrolledWindow):
if new_vs_x != -1 or new_vs_y != -1:
self.Scroll(new_vs_x, new_vs_y)
def AddWidget(self, widget):
widget.Reparent(self)
self._wList.append(widget)
@@ -124,13 +123,11 @@ class PFListPane(wx.ScrolledWindow):
def IsWidgetSelectedByContext(self, widget):
return False
def RefreshList(self, doRefresh = False, doFocus = False):
ypos = 0
def RefreshList(self, doRefresh=False, doFocus=False):
maxy = 0
scrollTo = 0
selected = None
for i in xrange( len(self._wList) ):
for i in xrange(len(self._wList)):
iwidth, iheight = self._wList[i].GetSize()
xa, ya = self.CalcScrolledPosition((0, maxy))
self._wList[i].SetPosition((xa, ya))
@@ -143,16 +140,14 @@ class PFListPane(wx.ScrolledWindow):
if selected:
self.ScrollChildIntoView(selected)
#selected.SetFocus()
# selected.SetFocus()
elif doFocus:
self.SetFocus()
clientW,clientH = self.GetSize()
for i in xrange( len(self._wList) ):
for i in xrange(len(self._wList)):
iwidth, iheight = self._wList[i].GetSize()
itemX,itemY = self._wList[i].GetPosition()
self._wList[i].SetSize((cwidth, iheight))
if doRefresh == True:
if doRefresh is True:
self._wList[i].Refresh()
self.itemsHeight = max(self.itemsHeight, iheight - 1)
@@ -160,7 +155,6 @@ class PFListPane(wx.ScrolledWindow):
child.Destroy()
self._wList.remove(child)
def RemoveAllChildren(self):
for widget in self._wList:
widget.Destroy()

View File

@@ -1,17 +1,17 @@
# noinspection PyPackageRequirements
import wx
import gui.utils.colorUtils as colorUtils
import gui.utils.drawUtils as drawUtils
from gui.bitmapLoader import BitmapLoader
SearchButton, EVT_SEARCH_BTN = wx.lib.newevent.NewEvent()
CancelButton, EVT_CANCEL_BTN = wx.lib.newevent.NewEvent()
TextEnter, EVT_TEXT_ENTER = wx.lib.newevent.NewEvent()
TextTyped, EVT_TEXT = wx.lib.newevent.NewEvent()
class PFSearchBox(wx.Window):
def __init__(self, parent, id = wx.ID_ANY, value = "", pos = wx.DefaultPosition, size = wx.Size(-1,24), style = 0):
wx.Window.__init__(self, parent, id, pos, size, style = style)
def __init__(self, parent, id=wx.ID_ANY, value="", pos=wx.DefaultPosition, size=wx.Size(-1, 24), style=0):
wx.Window.__init__(self, parent, id, pos, size, style=style)
self.isSearchButtonVisible = False
self.isCancelButtonVisible = False
@@ -35,13 +35,14 @@ class PFSearchBox(wx.Window):
self.editX = 0
self.editY = 0
self.padding = 4
self._hl = False
w,h = size
self.EditBox = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, (-1, h - 2 if 'wxGTK' in wx.PlatformInfo else -1 ), wx.TE_PROCESS_ENTER | (wx.BORDER_NONE if 'wxGTK' in wx.PlatformInfo else 0))
w, h = size
self.EditBox = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition,
(-1, h - 2 if 'wxGTK' in wx.PlatformInfo else -1),
wx.TE_PROCESS_ENTER | (wx.BORDER_NONE if 'wxGTK' in wx.PlatformInfo else 0))
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBk)
@@ -50,7 +51,7 @@ class PFSearchBox(wx.Window):
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
# self.EditBox.ChangeValue(self.descriptiveText)
# self.EditBox.ChangeValue(self.descriptiveText)
self.EditBox.Bind(wx.EVT_SET_FOCUS, self.OnEditSetFocus)
self.EditBox.Bind(wx.EVT_KILL_FOCUS, self.OnEditKillFocus)
@@ -68,11 +69,11 @@ class PFSearchBox(wx.Window):
wx.PostEvent(self, TextEnter())
event.Skip()
def OnEditSetFocus(self, event):
# value = self.EditBox.GetValue()
# if value == self.descriptiveText:
# self.EditBox.ChangeValue("")
@staticmethod
def OnEditSetFocus(event):
# value = self.EditBox.GetValue()
# if value == self.descriptiveText:
# self.EditBox.ChangeValue("")
event.Skip()
def OnEditKillFocus(self, event):
@@ -80,10 +81,9 @@ class PFSearchBox(wx.Window):
self.Clear()
event.Skip()
def Clear(self):
self.EditBox.Clear()
# self.EditBox.ChangeValue(self.descriptiveText)
# self.EditBox.ChangeValue(self.descriptiveText)
def Focus(self):
self.EditBox.SetFocus()
@@ -104,14 +104,15 @@ class PFSearchBox(wx.Window):
x, y = target
px, py = position
aX, aY = area
if (px > x and px < x + aX) and (py > y and py < y + aY):
if (x < px < x + aX) and (y < py < y + aY):
return True
return False
def GetButtonsPos(self):
btnpos = []
btnpos.append( (self.searchButtonX, self.searchButtonY) )
btnpos.append( (self.cancelButtonX, self.cancelButtonY) )
btnpos = [
(self.searchButtonX, self.searchButtonY),
(self.cancelButtonX, self.cancelButtonY)
]
return btnpos
def GetButtonsSize(self):
@@ -131,8 +132,8 @@ class PFSearchBox(wx.Window):
cw = 0
ch = 0
btnsize.append( (sw,sh))
btnsize.append( (cw,ch))
btnsize.append((sw, sh))
btnsize.append((cw, ch))
return btnsize
def OnLeftDown(self, event):
@@ -140,7 +141,7 @@ class PFSearchBox(wx.Window):
btnsize = self.GetButtonsSize()
self.CaptureMouse()
for btn in xrange(2):
for btn in range(2):
if self.HitTest(btnpos[btn], event.GetPosition(), btnsize[btn]):
if btn == 0:
if not self.searchButtonPressed:
@@ -158,7 +159,7 @@ class PFSearchBox(wx.Window):
if self.HasCapture():
self.ReleaseMouse()
for btn in xrange(2):
for btn in range(2):
if self.HitTest(btnpos[btn], event.GetPosition(), btnsize[btn]):
if btn == 0:
if self.searchButtonPressed:
@@ -218,9 +219,9 @@ class PFSearchBox(wx.Window):
editWidth, editHeight = self.EditBox.GetSize()
self.editY = (cheight - editHeight)/2
self.editY = (cheight - editHeight) / 2
self.EditBox.SetPosition((self.editX, self.editY))
self.EditBox.SetSize( (self.cancelButtonX - self.padding - self.editX, -1))
self.EditBox.SetSize((self.cancelButtonX - self.padding - self.editX, -1))
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self)
@@ -246,7 +247,6 @@ class PFSearchBox(wx.Window):
dc.DrawBitmap(self.searchBitmapShadow, self.searchButtonX + 1, self.searchButtonY + 1)
dc.DrawBitmap(self.searchBitmap, self.searchButtonX + spad, self.searchButtonY + spad)
if self.isCancelButtonVisible:
if self.cancelBitmap:
if self.cancelButtonPressed:
@@ -256,8 +256,8 @@ class PFSearchBox(wx.Window):
dc.DrawBitmap(self.cancelBitmapShadow, self.cancelButtonX + 1, self.cancelButtonY + 1)
dc.DrawBitmap(self.cancelBitmap, self.cancelButtonX + cpad, self.cancelButtonY + cpad)
dc.SetPen(wx.Pen(sepColor,1))
dc.DrawLine(0,rect.height - 1, rect.width, rect.height - 1)
dc.SetPen(wx.Pen(sepColor, 1))
dc.DrawLine(0, rect.height - 1, rect.width, rect.height - 1)
def SetSearchBitmap(self, bitmap):
self.searchBitmap = bitmap
@@ -273,10 +273,10 @@ class PFSearchBox(wx.Window):
def IsCancelButtonVisible(self):
return self.isCancelButtonVisible
def ShowSearchButton(self, show = True):
def ShowSearchButton(self, show=True):
self.isSearchButtonVisible = show
def ShowCancelButton(self, show = True):
def ShowCancelButton(self, show=True):
self.isCancelButtonVisible = show
def SetDescriptiveText(self, text):
@@ -284,4 +284,3 @@ class PFSearchBox(wx.Window):
def GetDescriptiveText(self):
return self.descriptiveText

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,7 +15,8 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
import config
versionString = "{0} {1} - {2} {3}".format(config.version, config.tag, config.expansionName, config.expansionVersion)
@@ -27,7 +28,7 @@ licenses = (
)
developers = (
"blitzmann \tSable Blitzmann (maintainer)",
"cncfanatics \tSakari Orisi (retired)" ,
"cncfanatics \tSakari Orisi (retired)",
"DarkPhoenix \tKadesh Priestess (retired)",
"Darriele \t\tDarriele (retired)",
"Ebag333 \t\tEbag Trescientas"

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,10 +15,10 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from gui.boosterView import BoosterView
from gui.droneView import DroneView
from gui.fighterView import FighterView
@@ -31,13 +31,13 @@ from gui.notesView import NotesView
from gui.pyfatogglepanel import TogglePanel
from gui.bitmapLoader import BitmapLoader
import gui.chromeTabs
from gui.chromeTabs import PFNotebook
class AdditionsPane(TogglePanel):
def __init__(self, parent):
TogglePanel.__init__(self, parent, forceLayout = 1)
TogglePanel.__init__(self, parent, forceLayout=1)
self.SetLabel("Additions")
pane = self.GetContentPane()
@@ -45,9 +45,7 @@ class AdditionsPane(TogglePanel):
baseSizer = wx.BoxSizer(wx.HORIZONTAL)
pane.SetSizer(baseSizer)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.notebook = gui.chromeTabs.PFNotebook(pane, False)
self.notebook = PFNotebook(pane, False)
self.notebook.SetMinSize((-1, 1000))
baseSizer.Add(self.notebook, 1, wx.EXPAND)
@@ -62,28 +60,28 @@ class AdditionsPane(TogglePanel):
notesImg = BitmapLoader.getImage("skill_small", "gui")
self.drone = DroneView(self.notebook)
self.notebook.AddPage(self.drone, "Drones", tabImage = droneImg, showClose = False)
self.notebook.AddPage(self.drone, "Drones", tabImage=droneImg, showClose=False)
self.fighter = FighterView(self.notebook)
self.notebook.AddPage(self.fighter, "Fighters", tabImage = fighterImg, showClose = False)
self.notebook.AddPage(self.fighter, "Fighters", tabImage=fighterImg, showClose=False)
self.cargo = CargoView(self.notebook)
self.notebook.AddPage(self.cargo, "Cargo", tabImage = cargoImg, showClose = False)
self.notebook.AddPage(self.cargo, "Cargo", tabImage=cargoImg, showClose=False)
self.implant = ImplantView(self.notebook)
self.notebook.AddPage(self.implant, "Implants", tabImage = implantImg, showClose = False)
self.notebook.AddPage(self.implant, "Implants", tabImage=implantImg, showClose=False)
self.booster = BoosterView(self.notebook)
self.notebook.AddPage(self.booster, "Boosters", tabImage = boosterImg, showClose = False)
self.notebook.AddPage(self.booster, "Boosters", tabImage=boosterImg, showClose=False)
self.projectedPage = ProjectedView(self.notebook)
self.notebook.AddPage(self.projectedPage, "Projected", tabImage = projectedImg, showClose = False)
self.notebook.AddPage(self.projectedPage, "Projected", tabImage=projectedImg, showClose=False)
self.gangPage = CommandView(self.notebook)
self.notebook.AddPage(self.gangPage, "Command", tabImage = gangImg, showClose = False)
self.notebook.AddPage(self.gangPage, "Command", tabImage=gangImg, showClose=False)
self.notes = NotesView(self.notebook)
self.notebook.AddPage(self.notes, "Notes", tabImage = notesImg, showClose = False)
self.notebook.AddPage(self.notes, "Notes", tabImage=notesImg, showClose=False)
self.notebook.SetSelection(0)
@@ -92,20 +90,17 @@ class AdditionsPane(TogglePanel):
def select(self, name):
self.notebook.SetSelection(self.PANES.index(name))
def toggleBoosters(self, event):
self.notebook.ToggleShown(self.booster)
def getName(self, idx):
return self.PANES[idx]
def toggleContent(self, event):
TogglePanel.toggleContent(self, event)
h = self.headerPanel.GetSize()[1]+4
h = self.headerPanel.GetSize()[1] + 4
if self.IsCollapsed():
self.old_pos = self.parent.GetSashPosition()
self.parent.SetMinimumPaneSize(h)
self.parent.SetSashPosition(h*-1, True)
self.parent.SetSashPosition(h * -1, True)
# only available in >= wx2.9
if getattr(self.parent, "SetSashInvisible", None):
self.parent.SetSashInvisible(True)
@@ -114,4 +109,3 @@ class AdditionsPane(TogglePanel):
self.parent.SetSashInvisible(False)
self.parent.SetMinimumPaneSize(200)
self.parent.SetSashPosition(self.old_pos, True)

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,24 +15,32 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
import os.path
import config
import wx
import zipfile
import cStringIO
import os.path
import zipfile
# noinspection PyPackageRequirements
import wx
import config
from logbook import Logger
logging = Logger(__name__)
try:
from collections import OrderedDict
except ImportError:
from utils.compat import OrderedDict
class BitmapLoader():
class BitmapLoader(object):
try:
archive = zipfile.ZipFile(os.path.join(config.pyfaPath, 'imgs.zip'), 'r')
logging.info("Using zipped image files.")
except IOError:
logging.info("Using local image files.")
archive = None
cachedBitmaps = OrderedDict()
@@ -42,7 +50,7 @@ class BitmapLoader():
@classmethod
def getStaticBitmap(cls, name, parent, location):
static = wx.StaticBitmap(parent)
static.SetBitmap(cls.getBitmap(name,location))
static.SetBitmap(cls.getBitmap(name, location))
return static
@classmethod
@@ -83,11 +91,11 @@ class BitmapLoader():
sbuf = cStringIO.StringIO(img_data)
return wx.ImageFromStream(sbuf)
except KeyError:
print "Missing icon file from zip: {0}".format(path)
print("Missing icon file from zip: {0}".format(path))
else:
path = os.path.join(config.pyfaPath, 'imgs', location, filename)
path = os.path.join(config.pyfaPath, 'imgs' + os.sep + location + os.sep + filename)
if os.path.exists(path):
return wx.Image(path)
else:
print "Missing icon file: {0}".format(path)
print("Missing icon file: {0}".format(path))

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,29 +15,32 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import service
import gui.display as d
import gui.globalEvents as GE
import gui.marketBrowser as mb
import gui.marketBrowser as marketBrowser
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
from service.fit import Fit
class BoosterViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def __init__(self, dropFn, *args, **kwargs):
super(BoosterViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
class BoosterView(d.Display):
DEFAULT_COLS = ["State",
@@ -50,7 +53,7 @@ class BoosterView(d.Display):
self.lastFitId = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem)
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
@@ -58,24 +61,24 @@ class BoosterView(d.Display):
self.SetDropTarget(BoosterViewDrop(self.handleListDrag))
if "__WXGTK__" in wx.PlatformInfo:
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
def handleListDrag(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "market":
wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1])))
wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1])))
def kbEvent(self,event):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
row = self.GetFirstSelected()
@@ -85,12 +88,12 @@ class BoosterView(d.Display):
event.Skip()
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
#Clear list and get out if current fitId is None
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
@@ -115,7 +118,7 @@ class BoosterView(d.Display):
event.Skip()
def addItem(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
@@ -139,7 +142,7 @@ class BoosterView(d.Display):
def removeBooster(self, booster):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.removeBooster(fitID, self.origional.index(booster))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -150,11 +153,10 @@ class BoosterView(d.Display):
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.toggleBooster(fitID, row)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def scheduleMenu(self, event):
event.Skip()
if self.getColumn(event.Position) != self.getColIndex(State):
@@ -163,7 +165,7 @@ class BoosterView(d.Display):
def spawnMenu(self):
sel = self.GetFirstSelected()
if sel != -1:
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
item = fit.boosters[sel]

View File

@@ -1,6 +1,6 @@
__all__ = [
"openFit",
#"moduleGlobalAmmoPicker",
# "moduleGlobalAmmoPicker",
"moduleAmmoPicker",
"itemStats",
"damagePattern",

View File

@@ -1,35 +1,38 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
import wx
import gui.globalEvents as GE
class AmmoPattern(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None:
return False
item = selection[0]
for attr in ("emDamage", "thermalDamage", "explosiveDamage", "kineticDamage"):
if item.getAttribute(attr) is not None:
return True
return False
def getText(self, itmContext, selection):
return "Set {0} as Damage Pattern".format(itmContext if itmContext is not None else "Item")
def activate(self, fullContext, selection, i):
item = selection[0]
fit = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit.setAsPattern(fit, item)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fit))
def getBitmap(self, context, selection):
return None
AmmoPattern.register()
from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
from service.fit import Fit
class AmmoPattern(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None:
return False
item = selection[0]
for attr in ("emDamage", "thermalDamage", "explosiveDamage", "kineticDamage"):
if item.getAttribute(attr) is not None:
return True
return False
def getText(self, itmContext, selection):
return "Set {0} as Damage Pattern".format(itmContext if itmContext is not None else "Item")
def activate(self, fullContext, selection, i):
item = selection[0]
fit = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.setAsPattern(fit, item)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fit))
def getBitmap(self, context, selection):
return None
AmmoPattern.register()

View File

@@ -1,17 +1,20 @@
from gui.contextMenu import ContextMenu
from gui.itemStats import ItemStatsDialog
import eos.types
from eos.saveddata.fit import Fit as es_Fit
import gui.mainFrame
import service
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
from eos.saveddata.cargo import Cargo as es_Cargo
from eos.saveddata.fighter import Fighter as es_Fighter
class ChangeAmount(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext in ("cargoItem","projectedFit","fighterItem","projectedFighter")
return srcContext in ("cargoItem", "projectedFit", "fighterItem", "projectedFighter")
def getText(self, itmContext, selection):
return "Change {0} Quantity".format(itmContext)
@@ -21,10 +24,11 @@ class ChangeAmount(ContextMenu):
dlg = AmountChanger(self.mainFrame, selection[0], srcContext)
dlg.ShowModal()
ChangeAmount.register()
class AmountChanger(wx.Dialog):
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
@@ -46,31 +50,36 @@ class AmountChanger(wx.Dialog):
self.button.Bind(wx.EVT_BUTTON, self.change)
def change(self, event):
sFit = service.Fit.getInstance()
if self.input.GetLineText(0).strip() == '':
event.Skip()
self.Close()
return
sFit = 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)))
elif isinstance(self.thing, eos.types.Fighter):
sFit.changeActiveFighters(fitID, self.thing, int(self.input.GetLineText(0)))
if isinstance(self.thing, es_Cargo):
sFit.addCargo(fitID, self.thing.item.ID, int(float(self.input.GetLineText(0))), replace=True)
elif isinstance(self.thing, es_Fit):
sFit.changeAmount(fitID, self.thing, int(float(self.input.GetLineText(0))))
elif isinstance(self.thing, es_Fighter):
sFit.changeActiveFighters(fitID, self.thing, int(float(self.input.GetLineText(0))))
wx.PostEvent(mainFrame, GE.FitChanged(fitID=fitID))
event.Skip()
self.Close()
## checks to make sure it's valid number
def onChar(self, event):
# checks to make sure it's valid number
@staticmethod
def onChar(event):
key = event.GetKeyCode()
acceptable_characters = "1234567890"
acceptable_keycode = [3, 22, 13, 8, 127] # modifiers like delete, copy, paste
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

View File

@@ -1,17 +1,17 @@
from gui.contextMenu import ContextMenu
from gui.itemStats import ItemStatsDialog
import eos.types
import gui.mainFrame
import service
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
class Cargo(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
@@ -24,7 +24,7 @@ class Cargo(ContextMenu):
return "Add {0} to Cargo".format(itmContext)
def activate(self, fullContext, selection, i):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
typeID = int(selection[0].ID)
@@ -32,4 +32,5 @@ class Cargo(ContextMenu):
self.mainFrame.additionsPane.select("Cargo")
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
Cargo.register()

View File

@@ -1,11 +1,14 @@
# -*- coding: utf-8 -*-
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from eos.types import Skill
from eos.saveddata.character import Skill
import gui.globalEvents as GE
from service.fit import Fit
from service.character import Character
class ChangeAffectingSkills(ContextMenu):
def __init__(self):
@@ -15,18 +18,18 @@ class ChangeAffectingSkills(ContextMenu):
if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule", "fittingCharge", "fittingShip"):
return False
self.sChar = service.Character.getInstance()
self.sFit = service.Fit.getInstance()
self.sChar = Character.getInstance()
self.sFit = Fit.getInstance()
fit = self.sFit.getFit(self.mainFrame.getActiveFit())
self.charID = fit.character.ID
#if self.sChar.getCharName(self.charID) in ("All 0", "All 5"):
# if self.sChar.getCharName(self.charID) in ("All 0", "All 5"):
# return False
if srcContext == "fittingShip":
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
self.stuff = sFit.getFit(fitID).ship
cont = sFit.getFit(fitID).ship.itemModifiedAttributes
elif srcContext == "fittingCharge":
@@ -99,4 +102,5 @@ class ChangeAffectingSkills(ContextMenu):
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
ChangeAffectingSkills.register()

View File

@@ -1,14 +1,17 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from service.fit import Fit
from service.damagePattern import DamagePattern as import_DamagePattern
try:
from collections import OrderedDict
except ImportError:
from gui.utils.compat import OrderedDict
from utils.compat import OrderedDict
class DamagePattern(ContextMenu):
def __init__(self):
@@ -18,8 +21,8 @@ class DamagePattern(ContextMenu):
return srcContext == "resistancesViewFull" and self.mainFrame.getActiveFit() is not None
def getText(self, itmContext, selection):
sDP = service.DamagePattern.getInstance()
sFit = service.Fit.getInstance()
sDP = import_DamagePattern.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
self.fit = sFit.getFit(fitID)
@@ -34,9 +37,9 @@ class DamagePattern(ContextMenu):
for pattern in self.patterns:
start, end = pattern.name.find('['), pattern.name.find(']')
if start is not -1 and end is not -1:
currBase = pattern.name[start+1:end]
currBase = pattern.name[start + 1:end]
# set helper attr
setattr(pattern, "_name", pattern.name[end+1:].strip())
setattr(pattern, "_name", pattern.name[end + 1:].strip())
if currBase not in self.subMenus:
self.subMenus[currBase] = []
self.subMenus[currBase].append(pattern)
@@ -59,7 +62,7 @@ class DamagePattern(ContextMenu):
menuItem.pattern = pattern
# determine active pattern
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
f = sFit.getFit(fitID)
dp = f.damagePattern
@@ -98,10 +101,11 @@ class DamagePattern(ContextMenu):
event.Skip()
return
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.setDamagePattern(fitID, pattern)
setattr(self.mainFrame,"_activeDmgPattern", pattern)
setattr(self.mainFrame, "_activeDmgPattern", pattern)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
DamagePattern.register()

View File

@@ -1,8 +1,10 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
from service.fit import Fit
class ItemRemove(ContextMenu):
def __init__(self):
@@ -15,7 +17,7 @@ class ItemRemove(ContextMenu):
return "Remove {0} Stack".format(itmContext)
def activate(self, fullContext, selection, i):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
@@ -24,4 +26,5 @@ class ItemRemove(ContextMenu):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
ItemRemove.register()

View File

@@ -1,59 +1,60 @@
from gui.contextMenu import ContextMenu
from gui.itemStats import ItemStatsDialog
import gui.mainFrame
import gui.globalEvents as GE
import service
import wx
class DroneSplit(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext in ("droneItem", "projectedDrone") and selection[0].amount > 1
def getText(self, itmContext, selection):
return "Split {0} Stack".format(itmContext)
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
dlg = DroneSpinner(self.mainFrame, selection[0], srcContext)
dlg.ShowModal()
dlg.Destroy()
DroneSplit.register()
class DroneSpinner(wx.Dialog):
def __init__(self, parent, drone, context):
wx.Dialog.__init__(self, parent, title="Select Amount", size=wx.Size(220, 60))
self.drone = drone
self.context = context
bSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.spinner = wx.SpinCtrl(self)
self.spinner.SetRange(1, drone.amount - 1)
self.spinner.SetValue(1)
bSizer1.Add(self.spinner, 0, wx.ALL, 5)
self.button = wx.Button(self, wx.ID_OK, u"Split")
bSizer1.Add(self.button, 0, wx.ALL, 5)
self.SetSizer(bSizer1)
self.Layout()
self.Centre(wx.BOTH)
self.button.Bind(wx.EVT_BUTTON, self.split)
def split(self, event):
sFit = service.Fit.getInstance()
mainFrame = gui.mainFrame.MainFrame.getInstance()
fitID = mainFrame.getActiveFit()
if self.context == "droneItem":
sFit.splitDroneStack(fitID, self.drone, self.spinner.GetValue())
else:
sFit.splitProjectedDroneStack(fitID, self.drone, self.spinner.GetValue())
wx.PostEvent(mainFrame, GE.FitChanged(fitID=fitID))
event.Skip()
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
from service.fit import Fit
# noinspection PyPackageRequirements
import wx
class DroneSplit(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext in ("droneItem", "projectedDrone") and selection[0].amount > 1
def getText(self, itmContext, selection):
return "Split {0} Stack".format(itmContext)
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
dlg = DroneSpinner(self.mainFrame, selection[0], srcContext)
dlg.ShowModal()
dlg.Destroy()
DroneSplit.register()
class DroneSpinner(wx.Dialog):
def __init__(self, parent, drone, context):
wx.Dialog.__init__(self, parent, title="Select Amount", size=wx.Size(220, 60))
self.drone = drone
self.context = context
bSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.spinner = wx.SpinCtrl(self)
self.spinner.SetRange(1, drone.amount - 1)
self.spinner.SetValue(1)
bSizer1.Add(self.spinner, 0, wx.ALL, 5)
self.button = wx.Button(self, wx.ID_OK, u"Split")
bSizer1.Add(self.button, 0, wx.ALL, 5)
self.SetSizer(bSizer1)
self.Layout()
self.Centre(wx.BOTH)
self.button.Bind(wx.EVT_BUTTON, self.split)
def split(self, event):
sFit = Fit.getInstance()
mainFrame = gui.mainFrame.MainFrame.getInstance()
fitID = mainFrame.getActiveFit()
if self.context == "droneItem":
sFit.splitDroneStack(fitID, self.drone, self.spinner.GetValue())
else:
sFit.splitProjectedDroneStack(fitID, self.drone, self.spinner.GetValue())
wx.PostEvent(mainFrame, GE.FitChanged(fitID=fitID))
event.Skip()

View File

@@ -1,35 +1,37 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
import gui.globalEvents as GE
import wx
from gui.bitmapLoader import BitmapLoader
class FactorReload(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext == "firepowerViewFull" and self.mainFrame.getActiveFit() is not None
def getText(self, itmContext, selection):
return "Factor in Reload Time"
def activate(self, fullContext, selection, i):
sFit = service.Fit.getInstance()
sFit.serviceFittingOptions["useGlobalForceReload"] = not sFit.serviceFittingOptions["useGlobalForceReload"]
fitID = self.mainFrame.getActiveFit()
sFit.refreshFit(fitID)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def getBitmap(self, context, selection):
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
if fit.factorReload:
return BitmapLoader.getBitmap("state_active_small", "gui")
else:
return None
FactorReload.register()
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from service.fit import Fit
class FactorReload(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext == "firepowerViewFull" and self.mainFrame.getActiveFit() is not None
def getText(self, itmContext, selection):
return "Factor in Reload Time"
def activate(self, fullContext, selection, i):
sFit = Fit.getInstance()
sFit.serviceFittingOptions["useGlobalForceReload"] = not sFit.serviceFittingOptions["useGlobalForceReload"]
fitID = self.mainFrame.getActiveFit()
sFit.refreshFit(fitID)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def getBitmap(self, context, selection):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
if fit.factorReload:
return BitmapLoader.getBitmap("state_active_small", "gui")
else:
return None
FactorReload.register()

View File

@@ -1,8 +1,10 @@
# noinspection PyPackageRequirements
import wx
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
import gui.globalEvents as GE
from service.fit import Fit
class FighterAbility(ContextMenu):
def __init__(self):
@@ -48,9 +50,10 @@ class FighterAbility(ContextMenu):
event.Skip()
return
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.toggleFighterAbility(fitID, ability)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
FighterAbility.register()

View File

@@ -1,8 +1,12 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from service.implantSet import ImplantSets as s_ImplantSets
from service.character import Character
from service.fit import Fit
class ImplantSets(ContextMenu):
def __init__(self):
@@ -32,7 +36,7 @@ class ImplantSets(ContextMenu):
m = wx.Menu()
bindmenu = rootMenu if "wxMSW" in wx.PlatformInfo else m
sIS = service.ImplantSets.getInstance()
sIS = s_ImplantSets.getInstance()
implantSets = sIS.getImplantSetList()
self.context = context
@@ -59,7 +63,7 @@ class ImplantSets(ContextMenu):
if self.context == "implantEditor":
# we are calling from character editor, the implant source is different
sChar = service.Character.getInstance()
sChar = Character.getInstance()
charID = self.selection.getActiveCharacter()
for implant in set.implants:
@@ -67,7 +71,7 @@ class ImplantSets(ContextMenu):
wx.PostEvent(self.selection, GE.CharChanged())
else:
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
for implant in set.implants:
sFit.addImplant(fitID, implant.item.ID, recalc=implant == set.implants[-1])

View File

@@ -1,8 +1,10 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
from service.fit import Fit
class ItemRemove(ContextMenu):
def __init__(self):
@@ -21,15 +23,15 @@ class ItemRemove(ContextMenu):
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
if srcContext == "fittingModule":
for module in selection:
if module is not None:
sFit.removeModule(fitID,fit.modules.index(module))
elif srcContext in ("fittingCharge" , "projectedCharge"):
sFit.removeModule(fitID, fit.modules.index(module))
elif srcContext in ("fittingCharge", "projectedCharge"):
sFit.setAmmo(fitID, None, selection)
elif srcContext == "droneItem":
sFit.removeDrone(fitID, fit.drones.index(selection[0]))
@@ -47,6 +49,4 @@ class ItemRemove(ContextMenu):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
ItemRemove.register()

View File

@@ -1,65 +1,68 @@
from gui.contextMenu import ContextMenu
from gui.itemStats import ItemStatsDialog
import gui.mainFrame
import service
import wx
class ItemStats(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext in ("marketItemGroup", "marketItemMisc",
"fittingModule", "fittingCharge",
"fittingShip", "baseShip",
"cargoItem", "droneItem",
"implantItem", "boosterItem",
"skillItem", "projectedModule",
"projectedDrone", "projectedCharge",
"itemStats", "fighterItem",
"implantItemChar", "projectedFighter",
"fittingMode")
def getText(self, itmContext, selection):
return "{0} Stats".format(itmContext if itmContext is not None else "Item")
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
if srcContext == "fittingShip":
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
stuff = sFit.getFit(fitID).ship
elif srcContext == "fittingMode":
stuff = selection[0].item
else:
stuff = selection[0]
if srcContext == "fittingModule" and stuff.isEmpty:
return
mstate = wx.GetMouseState()
reuse = False
if mstate.CmdDown():
reuse = True
if self.mainFrame.GetActiveStatsWindow() is None and reuse:
ItemStatsDialog(stuff, fullContext)
elif reuse:
lastWnd = self.mainFrame.GetActiveStatsWindow()
pos = lastWnd.GetPosition()
maximized = lastWnd.IsMaximized()
if not maximized:
size = lastWnd.GetSize()
else:
size = wx.DefaultSize
pos = wx.DefaultPosition
ItemStatsDialog(stuff, fullContext, pos, size, maximized)
lastWnd.closeEvent(None)
else:
ItemStatsDialog(stuff, fullContext)
ItemStats.register()
from gui.contextMenu import ContextMenu
from gui.itemStats import ItemStatsDialog
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
class ItemStats(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext in ("marketItemGroup", "marketItemMisc",
"fittingModule", "fittingCharge",
"fittingShip", "baseShip",
"cargoItem", "droneItem",
"implantItem", "boosterItem",
"skillItem", "projectedModule",
"projectedDrone", "projectedCharge",
"itemStats", "fighterItem",
"implantItemChar", "projectedFighter",
"fittingMode")
def getText(self, itmContext, selection):
return "{0} Stats".format(itmContext if itmContext is not None else "Item")
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
if srcContext == "fittingShip":
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
stuff = sFit.getFit(fitID).ship
elif srcContext == "fittingMode":
stuff = selection[0].item
else:
stuff = selection[0]
if srcContext == "fittingModule" and stuff.isEmpty:
return
mstate = wx.GetMouseState()
reuse = False
if mstate.CmdDown():
reuse = True
if self.mainFrame.GetActiveStatsWindow() is None and reuse:
ItemStatsDialog(stuff, fullContext)
elif reuse:
lastWnd = self.mainFrame.GetActiveStatsWindow()
pos = lastWnd.GetPosition()
maximized = lastWnd.IsMaximized()
if not maximized:
size = lastWnd.GetSize()
else:
size = wx.DefaultSize
pos = wx.DefaultPosition
ItemStatsDialog(stuff, fullContext, pos, size, maximized)
lastWnd.closeEvent(None)
else:
ItemStatsDialog(stuff, fullContext)
ItemStats.register()

View File

@@ -1,48 +1,49 @@
from gui.contextMenu import ContextMenu
from gui.itemStats import ItemStatsDialog
import gui.mainFrame
import service
class MarketJump(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
validContexts = ("marketItemMisc", "fittingModule",
"fittingCharge", "droneItem",
"implantItem", "boosterItem",
"projectedModule", "projectedDrone",
"projectedCharge", "cargoItem",
"implantItemChar", "fighterItem",
"projectedDrone")
if not srcContext in validContexts or selection is None or len(selection) < 1:
return False
sMkt = service.Market.getInstance()
item = getattr(selection[0], "item", selection[0])
mktGrp = sMkt.getMarketGroupByItem(item)
# 1663 is Special Edition Festival Assets, we don't have root group for it
if mktGrp is None or mktGrp.ID == 1663:
return False
doit = not selection[0].isEmpty if srcContext == "fittingModule" else True
return doit
def getText(self, itmContext, selection):
return "{0} Market Group".format(itmContext if itmContext is not None else "Item")
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
if srcContext in ("fittingCharge", "projectedCharge"):
item = selection[0].charge
elif hasattr(selection[0], "item"):
item = selection[0].item
else:
item = selection[0]
self.mainFrame.notebookBrowsers.SetSelection(0)
self.mainFrame.marketBrowser.jump(item)
MarketJump.register()
from gui.contextMenu import ContextMenu
import gui.mainFrame
from service.market import Market
class MarketJump(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
validContexts = ("marketItemMisc", "fittingModule",
"fittingCharge", "droneItem",
"implantItem", "boosterItem",
"projectedModule", "projectedDrone",
"projectedCharge", "cargoItem",
"implantItemChar", "fighterItem",
"projectedDrone")
if srcContext not in validContexts or selection is None or len(selection) < 1:
return False
sMkt = Market.getInstance()
item = getattr(selection[0], "item", selection[0])
mktGrp = sMkt.getMarketGroupByItem(item)
# 1663 is Special Edition Festival Assets, we don't have root group for it
if mktGrp is None or mktGrp.ID == 1663:
return False
doit = not selection[0].isEmpty if srcContext == "fittingModule" else True
return doit
def getText(self, itmContext, selection):
return "{0} Market Group".format(itmContext if itmContext is not None else "Item")
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
if srcContext in ("fittingCharge", "projectedCharge"):
item = selection[0].charge
elif hasattr(selection[0], "item"):
item = selection[0].item
else:
item = selection[0]
self.mainFrame.notebookBrowsers.SetSelection(0)
self.mainFrame.marketBrowser.jump(item)
MarketJump.register()

View File

@@ -1,10 +1,14 @@
# -*- coding: utf-8 -*-
from gui.contextMenu import ContextMenu
from gui.itemStats import ItemStatsDialog
import gui.mainFrame
import service
# coding: utf-8
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
from service.market import Market
import gui.mainFrame
import gui.globalEvents as GE
from gui.contextMenu import ContextMenu
class MetaSwap(ContextMenu):
def __init__(self):
@@ -23,7 +27,7 @@ class MetaSwap(ContextMenu):
# Check if list of variations is same for all of selection
# If not - don't show the menu
mkt = service.Market.getInstance()
mkt = Market.getInstance()
self.variations = None
for i in selection:
variations = mkt.getVariationsByItems([i.item])
@@ -47,7 +51,8 @@ class MetaSwap(ContextMenu):
self.moduleLookup = {}
def get_metalevel(x):
if "metaLevel" not in x.attributes: return 0
if "metaLevel" not in x.attributes:
return 0
return x.attributes["metaLevel"].value
def get_metagroup(x):
@@ -94,10 +99,10 @@ class MetaSwap(ContextMenu):
event.Skip()
return
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
for selected_item in self.selection:
if type(selected_item).__name__== 'Module':
pos = fit.modules.index(selected_item)
@@ -153,4 +158,5 @@ class MetaSwap(ContextMenu):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
MetaSwap.register()

View File

@@ -1,223 +1,233 @@
# -*- coding: utf-8 -*-
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
import wx
from gui.bitmapLoader import BitmapLoader
from eos.types import Hardpoint
import gui.globalEvents as GE
class ModuleAmmoPicker(ContextMenu):
DAMAGE_TYPES = ("em", "explosive", "kinetic", "thermal")
MISSILE_ORDER = ("em", "thermal", "kinetic", "explosive", "mixed")
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule", "projectedModule"):
return False
modules = selection if srcContext == "fittingModule" else (selection[0],)
validCharges = None
checkedTypes = set()
for mod in modules:
# loop through modules and gather list of valid charges
if mod.item.ID in checkedTypes:
continue
checkedTypes.add(mod.item.ID)
currCharges = mod.getValidCharges()
if len(currCharges) > 0:
if validCharges is not None and validCharges != currCharges:
return False
validCharges = currCharges
self.module = mod
if validCharges is None:
return False
self.modules = modules
self.charges = list(filter(lambda charge: service.Market.getInstance().getPublicityByItem(charge), validCharges))
return len(self.charges) > 0
def getText(self, itmContext, selection):
return "Charge"
def turretSorter(self, charge):
damage = 0
range = (self.module.getModifiedItemAttr("maxRange") or 0) * (charge.getAttribute("weaponRangeMultiplier") or 1)
falloff = (self.module.getModifiedItemAttr("falloff") or 0) * (charge.getAttribute("fallofMultiplier") or 1)
for type in self.DAMAGE_TYPES:
d = charge.getAttribute("%sDamage" % type)
if d > 0:
damage += d
# Take optimal and half falloff as range factor
rangeFactor = range + falloff / 2
return - rangeFactor, charge.name.rsplit()[-2:], damage, charge.name
def missileSorter(self, charge):
# Get charge damage type and total damage
chargeDamageType, totalDamage = self.damageInfo(charge)
# Find its position in sort list
position = self.MISSILE_ORDER.index(chargeDamageType)
return position, totalDamage, charge.name
def damageInfo(self, charge):
# Set up data storage for missile damage stuff
damageMap = {}
totalDamage = 0
# Fill them with the data about charge
for damageType in self.DAMAGE_TYPES:
currentDamage = charge.getAttribute("{0}Damage".format(damageType)) or 0
damageMap[damageType] = currentDamage
totalDamage += currentDamage
# Detect type of ammo
chargeDamageType = None
for damageType in damageMap:
# If all damage belongs to certain type purely, set appropriate
# ammoType
if damageMap[damageType] == totalDamage:
chargeDamageType = damageType
break
# Else consider ammo as mixed damage
if chargeDamageType is None:
chargeDamageType = "mixed"
return chargeDamageType, totalDamage
def numericConverter(self, string):
return int(string) if string.isdigit() else string
def nameSorter(self, charge):
parts = charge.name.split(" ")
return map(self.numericConverter, parts)
def addCharge(self, menu, charge):
id = ContextMenu.nextID()
name = charge.name if charge is not None else "Empty"
self.chargeIds[id] = charge
item = wx.MenuItem(menu, id, name)
menu.Bind(wx.EVT_MENU, self.handleAmmoSwitch, item)
item.charge = charge
if charge is not None and charge.icon is not None:
bitmap = BitmapLoader.getBitmap(charge.icon.iconFile, "icons")
if bitmap is not None:
item.SetBitmap(bitmap)
return item
def addSeperator(self, m, text):
id = ContextMenu.nextID()
m.Append(id, u'%s' % text)
m.Enable(id, False)
def getSubMenu(self, context, selection, rootMenu, i, pitem):
msw = True if "wxMSW" in wx.PlatformInfo else False
m = wx.Menu()
self.chargeIds = {}
hardpoint = self.module.hardpoint
moduleName = self.module.item.name
# Make sure we do not consider mining turrets as combat turrets
if hardpoint == Hardpoint.TURRET and self.module.getModifiedItemAttr("miningAmount") is None:
self.addSeperator(m, "Long Range")
items = []
range = None
nameBase = None
sub = None
self.charges.sort(key=self.turretSorter)
for charge in self.charges:
# fix issue 71 - will probably have to change if CCP adds more Orbital ammo
if "Orbital" in charge.name:
# uncomment if we ever want to include Oribital ammo in ammo picker - see issue #71
# This allows us to hide the ammo, but it's still loadable from the market
#item = self.addCharge(m, charge)
#items.append(item)
continue
currBase = charge.name.rsplit()[-2:]
currRange = charge.getAttribute("weaponRangeMultiplier")
if nameBase is None or range != currRange or nameBase != currBase:
if sub is not None:
self.addSeperator(sub, "More Damage")
sub = None
base = charge
nameBase = currBase
range = currRange
item = self.addCharge(rootMenu if msw else m, charge)
items.append(item)
else:
if sub is None:
sub = wx.Menu()
sub.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
self.addSeperator(sub, "Less Damage")
item.SetSubMenu(sub)
sub.AppendItem(self.addCharge(rootMenu if msw else sub, base))
sub.AppendItem(self.addCharge(rootMenu if msw else sub, charge))
if sub is not None:
self.addSeperator(sub, "More Damage")
for item in items:
m.AppendItem(item)
self.addSeperator(m, "Short Range")
elif hardpoint == Hardpoint.MISSILE and moduleName != 'Festival Launcher':
self.charges.sort(key=self.missileSorter)
type = None
sub = None
defender = None
for charge in self.charges:
currType = self.damageInfo(charge)[0]
if currType != type or type is None:
if sub is not None:
self.addSeperator(sub, "More Damage")
type = currType
item = wx.MenuItem(m, wx.ID_ANY, type.capitalize())
bitmap = BitmapLoader.getBitmap("%s_small" % type, "gui")
if bitmap is not None:
item.SetBitmap(bitmap)
sub = wx.Menu()
sub.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
self.addSeperator(sub, "Less Damage")
item.SetSubMenu(sub)
m.AppendItem(item)
if charge.name not in ("Light Defender Missile I", "Heavy Defender Missile I"):
sub.AppendItem(self.addCharge(rootMenu if msw else sub, charge))
else:
defender = charge
if defender is not None:
m.AppendItem(self.addCharge(rootMenu if msw else m, defender))
if sub is not None:
self.addSeperator(sub, "More Damage")
else:
self.charges.sort(key=self.nameSorter)
for charge in self.charges:
m.AppendItem(self.addCharge(rootMenu if msw else m, charge))
m.AppendItem(self.addCharge(rootMenu if msw else m, None))
return m
def handleAmmoSwitch(self, event):
charge = self.chargeIds.get(event.Id, False)
if charge is False:
event.Skip()
return
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.setAmmo(fitID, charge.ID if charge is not None else None, self.modules)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
ModuleAmmoPicker.register()
# coding: utf-8
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
from service.market import Market
from eos.saveddata.module import Hardpoint
import gui.mainFrame
import gui.globalEvents as GE
from gui.contextMenu import ContextMenu
from gui.bitmapLoader import BitmapLoader
class ModuleAmmoPicker(ContextMenu):
DAMAGE_TYPES = ("em", "explosive", "kinetic", "thermal")
MISSILE_ORDER = ("em", "thermal", "kinetic", "explosive", "mixed")
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule", "projectedModule"):
return False
modules = selection if srcContext == "fittingModule" else (selection[0],)
validCharges = None
checkedTypes = set()
for mod in modules:
# loop through modules and gather list of valid charges
if mod.item.ID in checkedTypes:
continue
checkedTypes.add(mod.item.ID)
currCharges = mod.getValidCharges()
if len(currCharges) > 0:
if validCharges is not None and validCharges != currCharges:
return False
validCharges = currCharges
self.module = mod
if validCharges is None:
return False
self.modules = modules
self.charges = list(filter(lambda charge: Market.getInstance().getPublicityByItem(charge), validCharges))
return len(self.charges) > 0
def getText(self, itmContext, selection):
return "Charge"
def turretSorter(self, charge):
damage = 0
range_ = (self.module.getModifiedItemAttr("maxRange") or 0) * \
(charge.getAttribute("weaponRangeMultiplier") or 1)
falloff = (self.module.getModifiedItemAttr("falloff") or 0) * \
(charge.getAttribute("fallofMultiplier") or 1)
for type_ in self.DAMAGE_TYPES:
d = charge.getAttribute("%sDamage" % type_)
if d > 0:
damage += d
# Take optimal and half falloff as range factor
rangeFactor = range_ + falloff / 2
return - rangeFactor, charge.name.rsplit()[-2:], damage, charge.name
def missileSorter(self, charge):
# Get charge damage type and total damage
chargeDamageType, totalDamage = self.damageInfo(charge)
# Find its position in sort list
position = self.MISSILE_ORDER.index(chargeDamageType)
return position, totalDamage, charge.name
def damageInfo(self, charge):
# Set up data storage for missile damage stuff
damageMap = {}
totalDamage = 0
# Fill them with the data about charge
for damageType in self.DAMAGE_TYPES:
currentDamage = charge.getAttribute("{0}Damage".format(damageType)) or 0
damageMap[damageType] = currentDamage
totalDamage += currentDamage
# Detect type of ammo
chargeDamageType = None
for damageType in damageMap:
# If all damage belongs to certain type purely, set appropriate
# ammoType
if damageMap[damageType] == totalDamage:
chargeDamageType = damageType
break
# Else consider ammo as mixed damage
if chargeDamageType is None:
chargeDamageType = "mixed"
return chargeDamageType, totalDamage
@staticmethod
def numericConverter(string):
return int(string) if string.isdigit() else string
def nameSorter(self, charge):
parts = charge.name.split(" ")
return map(self.numericConverter, parts)
def addCharge(self, menu, charge):
id_ = ContextMenu.nextID()
name = charge.name if charge is not None else "Empty"
self.chargeIds[id_] = charge
item = wx.MenuItem(menu, id_, name)
menu.Bind(wx.EVT_MENU, self.handleAmmoSwitch, item)
item.charge = charge
if charge is not None and charge.icon is not None:
bitmap = BitmapLoader.getBitmap(charge.icon.iconFile, "icons")
if bitmap is not None:
item.SetBitmap(bitmap)
return item
@staticmethod
def addSeperator(m, text):
id_ = ContextMenu.nextID()
m.Append(id_, u'%s' % text)
m.Enable(id_, False)
def getSubMenu(self, context, selection, rootMenu, i, pitem):
msw = True if "wxMSW" in wx.PlatformInfo else False
m = wx.Menu()
self.chargeIds = {}
hardpoint = self.module.hardpoint
moduleName = self.module.item.name
# Make sure we do not consider mining turrets as combat turrets
if hardpoint == Hardpoint.TURRET and self.module.getModifiedItemAttr("miningAmount") is None:
self.addSeperator(m, "Long Range")
items = []
range_ = None
nameBase = None
sub = None
self.charges.sort(key=self.turretSorter)
for charge in self.charges:
# fix issue 71 - will probably have to change if CCP adds more Orbital ammo
if "Orbital" in charge.name:
# uncomment if we ever want to include Oribital ammo in ammo picker - see issue #71
# This allows us to hide the ammo, but it's still loadable from the market
# item = self.addCharge(m, charge)
# items.append(item)
continue
currBase = charge.name.rsplit()[-2:]
currRange = charge.getAttribute("weaponRangeMultiplier")
if nameBase is None or range_ != currRange or nameBase != currBase:
if sub is not None:
self.addSeperator(sub, "More Damage")
sub = None
base = charge
nameBase = currBase
range_ = currRange
item = self.addCharge(rootMenu if msw else m, charge)
items.append(item)
else:
if sub is None and item and base:
sub = wx.Menu()
sub.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
self.addSeperator(sub, "Less Damage")
item.SetSubMenu(sub)
sub.AppendItem(self.addCharge(rootMenu if msw else sub, base))
sub.AppendItem(self.addCharge(rootMenu if msw else sub, charge))
if sub is not None:
self.addSeperator(sub, "More Damage")
for item in items:
m.AppendItem(item)
self.addSeperator(m, "Short Range")
elif hardpoint == Hardpoint.MISSILE and moduleName != 'Festival Launcher':
self.charges.sort(key=self.missileSorter)
type_ = None
sub = None
defender = None
for charge in self.charges:
currType = self.damageInfo(charge)[0]
if currType != type_ or type_ is None:
if sub is not None:
self.addSeperator(sub, "More Damage")
type_ = currType
item = wx.MenuItem(m, wx.ID_ANY, type_.capitalize())
bitmap = BitmapLoader.getBitmap("%s_small" % type, "gui")
if bitmap is not None:
item.SetBitmap(bitmap)
sub = wx.Menu()
sub.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
self.addSeperator(sub, "Less Damage")
item.SetSubMenu(sub)
m.AppendItem(item)
if charge.name not in ("Light Defender Missile I", "Heavy Defender Missile I"):
sub.AppendItem(self.addCharge(rootMenu if msw else sub, charge))
else:
defender = charge
if defender is not None:
m.AppendItem(self.addCharge(rootMenu if msw else m, defender))
if sub is not None:
self.addSeperator(sub, "More Damage")
else:
self.charges.sort(key=self.nameSorter)
for charge in self.charges:
m.AppendItem(self.addCharge(rootMenu if msw else m, charge))
m.AppendItem(self.addCharge(rootMenu if msw else m, None))
return m
def handleAmmoSwitch(self, event):
charge = self.chargeIds.get(event.Id, False)
if charge is False:
event.Skip()
return
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.setAmmo(fitID, charge.ID if charge is not None else None, self.modules)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
ModuleAmmoPicker.register()

View File

@@ -1,16 +1,16 @@
# -*- coding: utf-8 -*-
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from eos.types import Hardpoint
import gui.globalEvents as GE
from gui.builtinContextMenus.moduleAmmoPicker import ModuleAmmoPicker
import eos.db
from eos.db.saveddata.queries import getFit as db_getFit
from service.fit import Fit
class ModuleGlobalAmmoPicker(ModuleAmmoPicker):
def __init__(self):
super(ModuleGlobalAmmoPicker, self).__init__()
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getText(self, itmContext, selection):
@@ -26,9 +26,9 @@ class ModuleGlobalAmmoPicker(ModuleAmmoPicker):
event.Skip()
return
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = eos.db.getFit(fitID)
fit = db_getFit(fitID)
selectedModule = self.modules[0]
allModules = []

View File

@@ -1,8 +1,10 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
from gui.shipBrowser import FitSelected
class OpenFit(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
@@ -17,4 +19,5 @@ class OpenFit(ContextMenu):
fit = selection[0]
wx.PostEvent(self.mainFrame, FitSelected(fitID=fit.ID, startup=2))
OpenFit.register()

View File

@@ -1,8 +1,10 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
import service
from service.market import Market
class PriceClear(ContextMenu):
def __init__(self):
@@ -15,8 +17,9 @@ class PriceClear(ContextMenu):
return "Reset Price Cache"
def activate(self, fullContext, selection, i):
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
sMkt.clearPriceCache()
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
PriceClear.register()

View File

@@ -1,37 +1,39 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
import gui.globalEvents as GE
import wx
import eos.db
class Project(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None:
return False
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
if fit.isStructure:
return False
item = selection[0]
return item.isType("projected")
def getText(self, itmContext, selection):
return "Project {0} onto Fit".format(itmContext)
def activate(self, fullContext, selection, i):
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
trigger = sFit.project(fitID, selection[0])
if trigger:
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
self.mainFrame.additionsPane.select("Projected")
Project.register()
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
class Project(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None:
return False
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
if fit.isStructure:
return False
item = selection[0]
return item.isType("projected")
def getText(self, itmContext, selection):
return "Project {0} onto Fit".format(itmContext)
def activate(self, fullContext, selection, i):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
trigger = sFit.project(fitID, selection[0])
if trigger:
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
self.mainFrame.additionsPane.select("Projected")
Project.register()

View File

@@ -1,8 +1,10 @@
# noinspection PyPackageRequirements
import wx
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
from gui.shipBrowser import Stage3Selected
from service.fit import Fit
class ShipJump(ContextMenu):
def __init__(self):
@@ -16,11 +18,12 @@ class ShipJump(ContextMenu):
def activate(self, fullContext, selection, i):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
stuff = sFit.getFit(fitID).ship
groupID = stuff.item.group.ID
self.mainFrame.notebookBrowsers.SetSelection(1)
wx.PostEvent(self.mainFrame.shipBrowser,Stage3Selected(shipID=stuff.item.ID, back=groupID))
wx.PostEvent(self.mainFrame.shipBrowser, Stage3Selected(shipID=stuff.item.ID, back=groupID))
ShipJump.register()

View File

@@ -1,8 +1,11 @@
# noinspection PyPackageRequirements
import wx
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
import gui.globalEvents as GE
from service.fit import Fit
class TacticalMode(ContextMenu):
def __init__(self):
@@ -12,7 +15,7 @@ class TacticalMode(ContextMenu):
if self.mainFrame.getActiveFit() is None or srcContext != "fittingShip":
return False
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
@@ -52,9 +55,10 @@ class TacticalMode(ContextMenu):
event.Skip()
return
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.setMode(fitID, self.modeIds[event.Id])
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
TacticalMode.register()

View File

@@ -1,14 +1,17 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from service.targetResists import TargetResists as svc_TargetResists
from service.fit import Fit
try:
from collections import OrderedDict
except ImportError:
from gui.utils.compat import OrderedDict
from utils.compat import OrderedDict
class TargetResists(ContextMenu):
def __init__(self):
@@ -18,7 +21,7 @@ class TargetResists(ContextMenu):
if self.mainFrame.getActiveFit() is None or srcContext != "firepowerViewFull":
return False
sTR = service.TargetResists.getInstance()
sTR = svc_TargetResists.getInstance()
self.patterns = sTR.getTargetResistsList()
self.patterns.sort(key=lambda p: (p.name in ["None"], p.name))
@@ -33,7 +36,7 @@ class TargetResists(ContextMenu):
event.Skip()
return
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.setTargetResists(fitID, pattern)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -50,7 +53,7 @@ class TargetResists(ContextMenu):
item.pattern = pattern
# determine active pattern
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
f = sFit.getFit(fitID)
tr = f.targetResists
@@ -64,15 +67,15 @@ class TargetResists(ContextMenu):
msw = True if "wxMSW" in wx.PlatformInfo else False
self.patternIds = {}
self.subMenus = OrderedDict()
self.singles = []
self.singles = []
sub = wx.Menu()
for pattern in self.patterns:
start, end = pattern.name.find('['), pattern.name.find(']')
if start is not -1 and end is not -1:
currBase = pattern.name[start+1:end]
currBase = pattern.name[start + 1:end]
# set helper attr
setattr(pattern, "_name", pattern.name[end+1:].strip())
setattr(pattern, "_name", pattern.name[end + 1:].strip())
if currBase not in self.subMenus:
self.subMenus[currBase] = []
self.subMenus[currBase].append(pattern)
@@ -93,7 +96,7 @@ class TargetResists(ContextMenu):
# Create menu for child items
grandSub = wx.Menu()
#sub.Bind(wx.EVT_MENU, self.handleResistSwitch)
# sub.Bind(wx.EVT_MENU, self.handleResistSwitch)
# Apply child menu to parent item
item.SetSubMenu(grandSub)
@@ -101,8 +104,9 @@ class TargetResists(ContextMenu):
# Append child items to child menu
for pattern in patterns:
grandSub.AppendItem(self.addPattern(rootMenu if msw else grandSub, pattern))
sub.AppendItem(item) #finally, append parent item to root menu
sub.AppendItem(item) # finally, append parent item to root menu
return sub
TargetResists.register()

View File

@@ -1,8 +1,11 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
import service
# noinspection PyPackageRequirements
import wx
from service.market import Market
from service.fit import Fit
class WhProjector(ContextMenu):
def __init__(self):
@@ -16,7 +19,7 @@ class WhProjector(ContextMenu):
def getSubMenu(self, context, selection, rootMenu, i, pitem):
msw = True if "wxMSW" in wx.PlatformInfo else False
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
effdata = sMkt.getSystemWideEffects()
self.idmap = {}
@@ -41,16 +44,17 @@ class WhProjector(ContextMenu):
return sub
def handleSelection(self, event):
#Skip events ids that aren't mapped
# Skip events ids that aren't mapped
swObj, swName = self.idmap.get(event.Id, (False, False))
if not swObj and not swName:
event.Skip()
return
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.project(fitID, swObj)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
WhProjector.register()

View File

@@ -1 +1 @@
__all__ = ["fitDps"]
__all__ = ["fitDps"]

View File

@@ -1,94 +1,95 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
from gui.graph import Graph
import service
from gui.bitmapLoader import BitmapLoader
from eos.graph.fitDps import FitDpsGraph as FitDps
from eos.graph import Data
import gui.mainFrame
import service
class FitDpsGraph(Graph):
propertyAttributeMap = {"angle": "maxVelocity",
"distance": "maxRange",
"signatureRadius": "signatureRadius",
"velocity": "maxVelocity"}
propertyLabelMap = {"angle": "Target Angle (degrees)",
"distance": "Distance to Target (km)",
"signatureRadius": "Target Signature Radius (m)",
"velocity": "Target Velocity (m/s)"}
defaults = FitDps.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["distance"] = "0-20"
self.name = "DPS"
self.fitDps = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getFields(self):
return self.defaults
def getLabels(self):
return self.propertyLabelMap
def getIcons(self):
icons = {}
sAttr = service.Attribute.getInstance()
for key, attrName in self.propertyAttributeMap.iteritems():
iconFile = sAttr.getAttributeInfo(attrName).icon.iconFile
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
if bitmap:
icons[key] = bitmap
return icons
def getPoints(self, fit, fields):
fitDps = getattr(self, "fitDps", None)
if fitDps is None or fitDps.fit != fit:
fitDps = self.fitDps = FitDps(fit)
fitDps.clearData()
variable = None
for fieldName, value in fields.iteritems():
d = Data(fieldName, value)
if not d.isConstant():
if variable is None:
variable = fieldName
else:
#We can't handle more then one variable atm, OOPS FUCK OUT
return False, "Can only handle 1 variable"
fitDps.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in fitDps.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDpsGraph.register()
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
from gui.graph import Graph
from gui.bitmapLoader import BitmapLoader
from eos.graph.fitDps import FitDpsGraph as FitDps
from eos.graph import Data
import gui.mainFrame
from service.attribute import Attribute
class FitDpsGraph(Graph):
propertyAttributeMap = {"angle": "maxVelocity",
"distance": "maxRange",
"signatureRadius": "signatureRadius",
"velocity": "maxVelocity"}
propertyLabelMap = {"angle": "Target Angle (degrees)",
"distance": "Distance to Target (km)",
"signatureRadius": "Target Signature Radius (m)",
"velocity": "Target Velocity (m/s)"}
defaults = FitDps.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["distance"] = "0-20"
self.name = "DPS"
self.fitDps = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getFields(self):
return self.defaults
def getLabels(self):
return self.propertyLabelMap
def getIcons(self):
icons = {}
sAttr = Attribute.getInstance()
for key, attrName in self.propertyAttributeMap.iteritems():
iconFile = sAttr.getAttributeInfo(attrName).icon.iconFile
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
if bitmap:
icons[key] = bitmap
return icons
def getPoints(self, fit, fields):
fitDps = getattr(self, "fitDps", None)
if fitDps is None or fitDps.fit != fit:
fitDps = self.fitDps = FitDps(fit)
fitDps.clearData()
variable = None
for fieldName, value in fields.iteritems():
d = Data(fieldName, value)
if not d.isConstant():
if variable is None:
variable = fieldName
else:
# We can't handle more then one variable atm, OOPS FUCK OUT
return False, "Can only handle 1 variable"
fitDps.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in fitDps.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDpsGraph.register()

View File

@@ -1,6 +1,8 @@
__all__ = ["pyfaGeneralPreferences","pyfaHTMLExportPreferences","pyfaUpdatePreferences","pyfaNetworkPreferences"]
# noinspection PyPackageRequirements
import wx
if not 'wxMac' in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3,0)):
__all__ = ["pyfaGeneralPreferences", "pyfaHTMLExportPreferences", "pyfaUpdatePreferences",
"pyfaNetworkPreferences"] # noqa
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
__all__.append("pyfaCrestPreferences")

View File

@@ -1,94 +1,95 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
from gui.preferenceView import PreferenceView
from gui.bitmapLoader import BitmapLoader
class DummyView(PreferenceView):
title = "Dummy"
def populatePanel(self, panel):
mainSizer = wx.BoxSizer( wx.VERTICAL )
headerSizer = self.initHeader(panel)
mainSizer.Add( headerSizer, 0, wx.EXPAND, 5 )
self.stline1 = wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.stline1, 0, wx.EXPAND, 5 )
contentSizer = self.initContent(panel)
mainSizer.Add( contentSizer, 1, wx.EXPAND|wx.TOP|wx.BOTTOM|wx.LEFT, 10 )
self.stline2 = wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.stline2, 0, wx.EXPAND, 5 )
footerSizer = self.initFooter(panel)
mainSizer.Add( footerSizer, 0, wx.EXPAND, 5 )
panel.SetSizer( mainSizer )
panel.Layout()
def refreshPanel(self, fit):
pass
def initHeader(self, panel):
headerSizer = wx.BoxSizer( wx.VERTICAL )
self.stTitle = wx.StaticText( panel, wx.ID_ANY, u"Dummy", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stTitle.Wrap( -1 )
self.stTitle.SetFont( wx.Font( 14, 70, 90, 90, False, wx.EmptyString ) )
headerSizer.Add( self.stTitle, 0, wx.ALL, 5)
return headerSizer
def initContent(self, panel):
contentSizer = wx.BoxSizer( wx.VERTICAL )
self.m_checkBox2 = wx.CheckBox( panel, wx.ID_ANY, u"Check Me!", wx.DefaultPosition, wx.DefaultSize, 0 )
contentSizer.Add( self.m_checkBox2, 0, wx.ALL, 5 )
self.m_radioBtn2 = wx.RadioButton( panel, wx.ID_ANY, u"RadioBtn", wx.DefaultPosition, wx.DefaultSize, 0 )
contentSizer.Add( self.m_radioBtn2, 0, wx.ALL, 5 )
self.m_slider2 = wx.Slider( panel, wx.ID_ANY, 50, 0, 100, wx.DefaultPosition, wx.DefaultSize, wx.SL_HORIZONTAL )
contentSizer.Add( self.m_slider2, 0, wx.ALL, 5 )
self.m_gauge1 = wx.Gauge( panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.GA_HORIZONTAL )
contentSizer.Add( self.m_gauge1, 0, wx.ALL, 5 )
self.m_textCtrl2 = wx.TextCtrl( panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
contentSizer.Add( self.m_textCtrl2, 0, wx.ALL, 5 )
return contentSizer
def initFooter(self, panel):
footerSizer = wx.BoxSizer( wx.HORIZONTAL )
footerSizer.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 )
self.btnRestore = wx.Button( panel, wx.ID_ANY, u"Restore", wx.DefaultPosition, wx.DefaultSize, 0 )
self.btnRestore.Enable( False )
footerSizer.Add( self.btnRestore, 0, wx.ALL, 5 )
self.btnApply = wx.Button( panel, wx.ID_ANY, u"Apply", wx.DefaultPosition, wx.DefaultSize, 0 )
footerSizer.Add( self.btnApply, 0, wx.ALL, 5 )
return footerSizer
DummyView.register()
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView
class DummyView(PreferenceView):
title = "Dummy"
def populatePanel(self, panel):
mainSizer = wx.BoxSizer(wx.VERTICAL)
headerSizer = self.initHeader(panel)
mainSizer.Add(headerSizer, 0, wx.EXPAND, 5)
self.stline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.stline1, 0, wx.EXPAND, 5)
contentSizer = self.initContent(panel)
mainSizer.Add(contentSizer, 1, wx.EXPAND | wx.TOP | wx.BOTTOM | wx.LEFT, 10)
self.stline2 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.stline2, 0, wx.EXPAND, 5)
footerSizer = self.initFooter(panel)
mainSizer.Add(footerSizer, 0, wx.EXPAND, 5)
panel.SetSizer(mainSizer)
panel.Layout()
def refreshPanel(self, fit):
pass
def initHeader(self, panel):
headerSizer = wx.BoxSizer(wx.VERTICAL)
self.stTitle = wx.StaticText(panel, wx.ID_ANY, u"Dummy", wx.DefaultPosition, wx.DefaultSize, 0)
self.stTitle.Wrap(-1)
self.stTitle.SetFont(wx.Font(14, 70, 90, 90, False, wx.EmptyString))
headerSizer.Add(self.stTitle, 0, wx.ALL, 5)
return headerSizer
def initContent(self, panel):
contentSizer = wx.BoxSizer(wx.VERTICAL)
self.m_checkBox2 = wx.CheckBox(panel, wx.ID_ANY, u"Check Me!", wx.DefaultPosition, wx.DefaultSize, 0)
contentSizer.Add(self.m_checkBox2, 0, wx.ALL, 5)
self.m_radioBtn2 = wx.RadioButton(panel, wx.ID_ANY, u"RadioBtn", wx.DefaultPosition, wx.DefaultSize, 0)
contentSizer.Add(self.m_radioBtn2, 0, wx.ALL, 5)
self.m_slider2 = wx.Slider(panel, wx.ID_ANY, 50, 0, 100, wx.DefaultPosition, wx.DefaultSize, wx.SL_HORIZONTAL)
contentSizer.Add(self.m_slider2, 0, wx.ALL, 5)
self.m_gauge1 = wx.Gauge(panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.GA_HORIZONTAL)
contentSizer.Add(self.m_gauge1, 0, wx.ALL, 5)
self.m_textCtrl2 = wx.TextCtrl(panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
contentSizer.Add(self.m_textCtrl2, 0, wx.ALL, 5)
return contentSizer
def initFooter(self, panel):
footerSizer = wx.BoxSizer(wx.HORIZONTAL)
footerSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
self.btnRestore = wx.Button(panel, wx.ID_ANY, u"Restore", wx.DefaultPosition, wx.DefaultSize, 0)
self.btnRestore.Enable(False)
footerSizer.Add(self.btnRestore, 0, wx.ALL, 5)
self.btnApply = wx.Button(panel, wx.ID_ANY, u"Apply", wx.DefaultPosition, wx.DefaultSize, 0)
footerSizer.Add(self.btnApply, 0, wx.ALL, 5)
return footerSizer
DummyView.register()

View File

@@ -1,104 +1,117 @@
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView
from gui.bitmapLoader import BitmapLoader
import gui.mainFrame
import service
from service.crest import CrestModes
from service.settings import CRESTSettings
# noinspection PyPackageRequirements
from wx.lib.intctrl import IntCtrl
class PFCrestPref ( PreferenceView):
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
from service.crest import Crest
class PFCrestPref(PreferenceView):
title = "CREST"
def populatePanel( self, panel ):
def populatePanel(self, panel):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.settings = service.settings.CRESTSettings.getInstance()
self.settings = CRESTSettings.getInstance()
self.dirtySettings = False
dlgWidth = panel.GetParent().GetParent().ClientSize.width
mainSizer = wx.BoxSizer( wx.VERTICAL )
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.stTitle = wx.StaticText( panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stTitle.Wrap( -1 )
self.stTitle.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0)
self.stTitle.Wrap(-1)
self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add( self.stTitle, 0, wx.ALL, 5 )
mainSizer.Add(self.stTitle, 0, wx.ALL, 5)
self.m_staticline1 = wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.m_staticline1, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5 )
self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.stInfo = wx.StaticText( panel, wx.ID_ANY, u"Please see the pyfa wiki on GitHub for information regarding these options.", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stInfo = wx.StaticText(panel, wx.ID_ANY,
u"Please see the pyfa wiki on GitHub for information regarding these options.",
wx.DefaultPosition, wx.DefaultSize, 0)
self.stInfo.Wrap(dlgWidth - 50)
mainSizer.Add( self.stInfo, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5 )
mainSizer.Add(self.stInfo, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
rbSizer = wx.BoxSizer(wx.HORIZONTAL)
self.rbMode = wx.RadioBox(panel, -1, "Mode", wx.DefaultPosition, wx.DefaultSize, ['Implicit', 'User-supplied details'], 1, wx.RA_SPECIFY_COLS)
self.rbServer = wx.RadioBox(panel, -1, "Server", wx.DefaultPosition, wx.DefaultSize, ['Tranquility', 'Singularity'], 1, wx.RA_SPECIFY_COLS)
self.rbMode = wx.RadioBox(panel, -1, "Mode", wx.DefaultPosition, wx.DefaultSize,
['Implicit', 'User-supplied details'], 1, wx.RA_SPECIFY_COLS)
self.rbServer = wx.RadioBox(panel, -1, "Server", wx.DefaultPosition, wx.DefaultSize,
['Tranquility', 'Singularity'], 1, wx.RA_SPECIFY_COLS)
self.rbMode.SetSelection(self.settings.get('mode'))
self.rbServer.SetSelection(self.settings.get('server'))
rbSizer.Add(self.rbMode, 1, wx.TOP | wx.RIGHT, 5 )
rbSizer.Add(self.rbServer, 1, wx.ALL, 5 )
rbSizer.Add(self.rbMode, 1, wx.TOP | wx.RIGHT, 5)
rbSizer.Add(self.rbServer, 1, wx.ALL, 5)
self.rbMode.Bind(wx.EVT_RADIOBOX, self.OnModeChange)
self.rbServer.Bind(wx.EVT_RADIOBOX, self.OnServerChange)
mainSizer.Add(rbSizer, 1, wx.ALL|wx.EXPAND, 0)
mainSizer.Add(rbSizer, 1, wx.ALL | wx.EXPAND, 0)
timeoutSizer = wx.BoxSizer(wx.HORIZONTAL)
self.stTimout = wx.StaticText( panel, wx.ID_ANY, u"Timeout (seconds):", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stTimout.Wrap( -1 )
self.stTimout = wx.StaticText(panel, wx.ID_ANY, u"Timeout (seconds):", wx.DefaultPosition, wx.DefaultSize, 0)
self.stTimout.Wrap(-1)
timeoutSizer.Add( self.stTimout, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
timeoutSizer.Add(self.stTimout, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.intTimeout = IntCtrl(panel, max=300000, limited=True, value=self.settings.get('timeout'))
timeoutSizer.Add(self.intTimeout, 0, wx.ALL, 5 )
timeoutSizer.Add(self.intTimeout, 0, wx.ALL, 5)
self.intTimeout.Bind(wx.lib.intctrl.EVT_INT, self.OnTimeoutChange)
mainSizer.Add(timeoutSizer, 0, wx.ALL|wx.EXPAND, 0)
mainSizer.Add(timeoutSizer, 0, wx.ALL | wx.EXPAND, 0)
detailsTitle = wx.StaticText( panel, wx.ID_ANY, "CREST client details", wx.DefaultPosition, wx.DefaultSize, 0 )
detailsTitle.Wrap( -1 )
detailsTitle.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
detailsTitle = wx.StaticText(panel, wx.ID_ANY, "CREST client details", wx.DefaultPosition, wx.DefaultSize, 0)
detailsTitle.Wrap(-1)
detailsTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add( detailsTitle, 0, wx.ALL, 5 )
mainSizer.Add( wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ), 0, wx.EXPAND, 5 )
mainSizer.Add(detailsTitle, 0, wx.ALL, 5)
mainSizer.Add(wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
wx.EXPAND, 5)
fgAddrSizer = wx.FlexGridSizer( 2, 2, 0, 0 )
fgAddrSizer.AddGrowableCol( 1 )
fgAddrSizer.SetFlexibleDirection( wx.BOTH )
fgAddrSizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
fgAddrSizer = wx.FlexGridSizer(2, 2, 0, 0)
fgAddrSizer.AddGrowableCol(1)
fgAddrSizer.SetFlexibleDirection(wx.BOTH)
fgAddrSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
self.stSetID = wx.StaticText( panel, wx.ID_ANY, u"Client ID:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stSetID.Wrap( -1 )
fgAddrSizer.Add( self.stSetID, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.stSetID = wx.StaticText(panel, wx.ID_ANY, u"Client ID:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stSetID.Wrap(-1)
fgAddrSizer.Add(self.stSetID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.inputClientID = wx.TextCtrl( panel, wx.ID_ANY, self.settings.get('clientID'), wx.DefaultPosition, wx.DefaultSize, 0 )
self.inputClientID = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientID'), wx.DefaultPosition,
wx.DefaultSize, 0)
fgAddrSizer.Add( self.inputClientID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5 )
fgAddrSizer.Add(self.inputClientID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
self.stSetSecret = wx.StaticText( panel, wx.ID_ANY, u"Client Secret:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stSetSecret.Wrap( -1 )
self.stSetSecret = wx.StaticText(panel, wx.ID_ANY, u"Client Secret:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stSetSecret.Wrap(-1)
fgAddrSizer.Add( self.stSetSecret, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
fgAddrSizer.Add(self.stSetSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.inputClientSecret = wx.TextCtrl( panel, wx.ID_ANY, self.settings.get('clientSecret'), wx.DefaultPosition, wx.DefaultSize, 0 )
self.inputClientSecret = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientSecret'), wx.DefaultPosition,
wx.DefaultSize, 0)
fgAddrSizer.Add( self.inputClientSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5 )
fgAddrSizer.Add(self.inputClientSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
self.btnApply = wx.Button( panel, wx.ID_ANY, u"Save Client Settings", wx.DefaultPosition, wx.DefaultSize, 0 )
self.btnApply = wx.Button(panel, wx.ID_ANY, u"Save Client Settings", wx.DefaultPosition, wx.DefaultSize, 0)
self.btnApply.Bind(wx.EVT_BUTTON, self.OnBtnApply)
mainSizer.Add( fgAddrSizer, 0, wx.EXPAND, 5)
mainSizer.Add( self.btnApply, 0, wx.ALIGN_RIGHT, 5)
mainSizer.Add(fgAddrSizer, 0, wx.EXPAND, 5)
mainSizer.Add(self.btnApply, 0, wx.ALIGN_RIGHT, 5)
self.ToggleProxySettings(self.settings.get('mode'))
panel.SetSizer( mainSizer )
panel.SetSizer(mainSizer)
panel.Layout()
def OnTimeoutChange(self, event):
@@ -107,16 +120,16 @@ class PFCrestPref ( PreferenceView):
def OnModeChange(self, event):
self.settings.set('mode', event.GetInt())
self.ToggleProxySettings(self.settings.get('mode'))
service.Crest.restartService()
Crest.restartService()
def OnServerChange(self, event):
self.settings.set('server', event.GetInt())
service.Crest.restartService()
Crest.restartService()
def OnBtnApply(self, event):
self.settings.set('clientID', self.inputClientID.GetValue().strip())
self.settings.set('clientSecret', self.inputClientSecret.GetValue().strip())
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
sCrest.delAllCharacters()
def ToggleProxySettings(self, mode):
@@ -134,4 +147,5 @@ class PFCrestPref ( PreferenceView):
def getImage(self):
return BitmapLoader.getBitmap("eve", "gui")
PFCrestPref.register()

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# noinspection PyPackageRequirements
import wx
import copy
@@ -10,13 +11,15 @@ from gui.bitmapLoader import BitmapLoader
from gui.utils import colorUtils
import gui.utils.drawUtils as drawUtils
###########################################################################
## Class PFGaugePref
# Class PFGaugePref
###########################################################################
class PFGaugePreview(wx.Window):
def __init__ (self, parent, id = wx.ID_ANY, value = 0, pos = wx.DefaultPosition, size = wx.DefaultSize, style = 0):
wx.Window.__init__(self, parent, id, pos = pos, size = size, style = style)
def __init__(self, parent, id=wx.ID_ANY, value=0, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
wx.Window.__init__(self, parent, id, pos=pos, size=size, style=style)
self.value = float(value)
self.oldValue = self.value
@@ -28,14 +31,14 @@ class PFGaugePreview(wx.Window):
self.animDir = 1
self._fractionDigits = 2
self.colorS = wx.Colour(0,0,0,255)
self.colorE = wx.Colour(0,0,0,255)
self.colorS = wx.Colour(0, 0, 0, 255)
self.colorE = wx.Colour(0, 0, 0, 255)
self.gradientStart = 0
self.bkColor = wx.Colour(0,0,0,255)
self.SetMinSize((100,-1))
self.bkColor = wx.Colour(0, 0, 0, 255)
self.SetMinSize((100, -1))
self.font = wx.FontFromPixelSize((0,13),wx.SWISS, wx.NORMAL, wx.NORMAL, False)
self.font = wx.FontFromPixelSize((0, 13), wx.SWISS, wx.NORMAL, wx.NORMAL, False)
self.timerID = wx.NewId()
self.timer = wx.Timer(self, self.timerID)
@@ -56,7 +59,7 @@ class PFGaugePreview(wx.Window):
if self.value > 100:
self.value = 100
self.animDir = -1
if self.value <0:
if self.value < 0:
self.value = 0
self.animDir = 1
self.Refresh()
@@ -79,7 +82,7 @@ class PFGaugePreview(wx.Window):
self.Refresh()
event.Skip()
def CanAnimate(self, anim = True):
def CanAnimate(self, anim=True):
self.animate = anim
if self.timer.IsRunning():
self.timer.Stop()
@@ -97,7 +100,7 @@ class PFGaugePreview(wx.Window):
self.Refresh()
def SetValue(self, value):
self.value = min(max(value,0),100)
self.value = min(max(value, 0), 100)
self.Refresh()
def SetPercentages(self, start, end):
@@ -119,198 +122,210 @@ class PFGaugePreview(wx.Window):
r = copy.copy(rect)
r.width = w
color = colorUtils.CalculateTransitionColor(self.colorS, self.colorE, float(value)/100)
color = colorUtils.CalculateTransitionColor(self.colorS, self.colorE, float(value) / 100)
if self.gradientStart > 0:
gcolor = colorUtils.BrightenColor(color, float(self.gradientStart) / 100)
gMid = colorUtils.BrightenColor(color, float(self.gradientStart/2) / 100)
gcolor = colorUtils.BrightenColor(color, float(self.gradientStart) / 100)
gMid = colorUtils.BrightenColor(color, float(self.gradientStart / 2) / 100)
else:
gcolor = colorUtils.DarkenColor(color, float(-self.gradientStart) / 100)
gMid = colorUtils.DarkenColor(color, float(-self.gradientStart/2) / 100)
gcolor = colorUtils.DarkenColor(color, float(-self.gradientStart) / 100)
gMid = colorUtils.DarkenColor(color, float(-self.gradientStart / 2) / 100)
gBmp = drawUtils.DrawGradientBar(r.width, r.height, gMid, color, gcolor)
dc.DrawBitmap(gBmp,0,0)
dc.DrawBitmap(gBmp, 0, 0)
dc.SetFont(self.font)
r = copy.copy(rect)
r.left +=1
r.top +=1
r.left += 1
r.top += 1
formatStr = "{0:." + str(self._fractionDigits) + "f}%"
value = (self.percE - self.percS) * value / (self.percE - self.percS)
value = self.percS + (self.percE - self.percS) * value / 100
dc.SetTextForeground(wx.Colour(80,80,80))
dc.SetTextForeground(wx.Colour(80, 80, 80))
dc.DrawLabel(formatStr.format(value), r, wx.ALIGN_CENTER)
dc.SetTextForeground(wx.Colour(255,255,255))
dc.SetTextForeground(wx.Colour(255, 255, 255))
dc.DrawLabel(formatStr.format(value), rect, wx.ALIGN_CENTER)
class PFGaugePref ( PreferenceView):
class PFGaugePref(PreferenceView):
title = "Pyfa Gauge Theme"
def populatePanel( self, panel ):
def populatePanel(self, panel):
self.InitDefaultColours()
mainSizer = wx.BoxSizer( wx.VERTICAL )
mainSizer = wx.BoxSizer(wx.VERTICAL)
gSizer1 = wx.BoxSizer( wx.HORIZONTAL )
gSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.st0100 = wx.StaticText( panel, wx.ID_ANY, u"0 - 100", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT )
self.st0100.Wrap( -1 )
gSizer1.Add( self.st0100, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.st0100 = wx.StaticText(panel, wx.ID_ANY, u"0 - 100", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT)
self.st0100.Wrap(-1)
gSizer1.Add(self.st0100, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.cp0100S = wx.ColourPickerCtrl( panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize, wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL )
gSizer1.Add( self.cp0100S, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.cp0100S = wx.ColourPickerCtrl(panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize,
wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL)
gSizer1.Add(self.cp0100S, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.cp0100E = wx.ColourPickerCtrl( panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize, wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL )
gSizer1.Add( self.cp0100E, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.cp0100E = wx.ColourPickerCtrl(panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize,
wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL)
gSizer1.Add(self.cp0100E, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.gauge0100S = PFGaugePreview( panel, wx.ID_ANY, 33, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer1.Add( self.gauge0100S, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5 )
self.gauge0100S = PFGaugePreview(panel, wx.ID_ANY, 33, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer1.Add(self.gauge0100S, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.gauge0100M = PFGaugePreview( panel, wx.ID_ANY, 66, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer1.Add( self.gauge0100M, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5 )
self.gauge0100M = PFGaugePreview(panel, wx.ID_ANY, 66, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer1.Add(self.gauge0100M, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.gauge0100E = PFGaugePreview( panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer1.Add( self.gauge0100E, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.LEFT, 5 )
self.gauge0100E = PFGaugePreview(panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer1.Add(self.gauge0100E, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 5)
mainSizer.Add( gSizer1, 0, wx.EXPAND, 5 )
mainSizer.Add(gSizer1, 0, wx.EXPAND, 5)
gSizer2 = wx.BoxSizer( wx.HORIZONTAL )
gSizer2 = wx.BoxSizer(wx.HORIZONTAL)
self.st100101 = wx.StaticText( panel, wx.ID_ANY, u"100 - 101", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT )
self.st100101.Wrap( -1 )
gSizer2.Add( self.st100101, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.st100101 = wx.StaticText(panel, wx.ID_ANY, u"100 - 101", wx.DefaultPosition, wx.DefaultSize,
wx.ALIGN_RIGHT)
self.st100101.Wrap(-1)
gSizer2.Add(self.st100101, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.cp100101S = wx.ColourPickerCtrl( panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize, wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL )
gSizer2.Add( self.cp100101S, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.cp100101S = wx.ColourPickerCtrl(panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize,
wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL)
gSizer2.Add(self.cp100101S, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.cp100101E = wx.ColourPickerCtrl( panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize, wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL )
gSizer2.Add( self.cp100101E, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.cp100101E = wx.ColourPickerCtrl(panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize,
wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL)
gSizer2.Add(self.cp100101E, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.gauge100101S = PFGaugePreview( panel, wx.ID_ANY, 33, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer2.Add( self.gauge100101S, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5 )
self.gauge100101S = PFGaugePreview(panel, wx.ID_ANY, 33, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer2.Add(self.gauge100101S, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.gauge100101M = PFGaugePreview( panel, wx.ID_ANY, 66, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer2.Add( self.gauge100101M, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5 )
self.gauge100101M = PFGaugePreview(panel, wx.ID_ANY, 66, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer2.Add(self.gauge100101M, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.gauge100101E = PFGaugePreview( panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer2.Add( self.gauge100101E, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.LEFT, 5 )
self.gauge100101E = PFGaugePreview(panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer2.Add(self.gauge100101E, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 5)
mainSizer.Add( gSizer2, 0, wx.EXPAND, 5 )
mainSizer.Add(gSizer2, 0, wx.EXPAND, 5)
gSizer3 = wx.BoxSizer( wx.HORIZONTAL )
gSizer3 = wx.BoxSizer(wx.HORIZONTAL)
self.st101103 = wx.StaticText( panel, wx.ID_ANY, u"101 - 103", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT )
self.st101103.Wrap( -1 )
gSizer3.Add( self.st101103, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.st101103 = wx.StaticText(panel, wx.ID_ANY, u"101 - 103", wx.DefaultPosition, wx.DefaultSize,
wx.ALIGN_RIGHT)
self.st101103.Wrap(-1)
gSizer3.Add(self.st101103, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.cp101103S = wx.ColourPickerCtrl( panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize, wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL )
gSizer3.Add( self.cp101103S, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.cp101103S = wx.ColourPickerCtrl(panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize,
wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL)
gSizer3.Add(self.cp101103S, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.cp101103E = wx.ColourPickerCtrl( panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize, wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL )
gSizer3.Add( self.cp101103E, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.cp101103E = wx.ColourPickerCtrl(panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize,
wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL)
gSizer3.Add(self.cp101103E, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.gauge101103S = PFGaugePreview( panel, wx.ID_ANY, 33, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer3.Add( self.gauge101103S, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5 )
self.gauge101103S = PFGaugePreview(panel, wx.ID_ANY, 33, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer3.Add(self.gauge101103S, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.gauge101103M = PFGaugePreview( panel, wx.ID_ANY, 66, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer3.Add( self.gauge101103M, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5 )
self.gauge101103M = PFGaugePreview(panel, wx.ID_ANY, 66, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer3.Add(self.gauge101103M, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.gauge101103E = PFGaugePreview( panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer3.Add( self.gauge101103E, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.LEFT, 5 )
self.gauge101103E = PFGaugePreview(panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer3.Add(self.gauge101103E, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 5)
mainSizer.Add( gSizer3, 0, wx.EXPAND, 5 )
mainSizer.Add(gSizer3, 0, wx.EXPAND, 5)
gSizer4 = wx.BoxSizer( wx.HORIZONTAL )
gSizer4 = wx.BoxSizer(wx.HORIZONTAL)
self.st103105 = wx.StaticText( panel, wx.ID_ANY, u"103 - 105", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT )
self.st103105.Wrap( -1 )
gSizer4.Add( self.st103105, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.st103105 = wx.StaticText(panel, wx.ID_ANY, u"103 - 105", wx.DefaultPosition, wx.DefaultSize,
wx.ALIGN_RIGHT)
self.st103105.Wrap(-1)
gSizer4.Add(self.st103105, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.cp103105S = wx.ColourPickerCtrl( panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize, wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL )
gSizer4.Add( self.cp103105S, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.cp103105S = wx.ColourPickerCtrl(panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize,
wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL)
gSizer4.Add(self.cp103105S, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.cp103105E = wx.ColourPickerCtrl( panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize, wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL )
gSizer4.Add( self.cp103105E, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.cp103105E = wx.ColourPickerCtrl(panel, wx.ID_ANY, wx.BLACK, wx.DefaultPosition, wx.DefaultSize,
wx.CLRP_DEFAULT_STYLE | wx.CLRP_SHOW_LABEL)
gSizer4.Add(self.cp103105E, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.gauge103105S = PFGaugePreview( panel, wx.ID_ANY, 33, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer4.Add( self.gauge103105S, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5 )
self.gauge103105S = PFGaugePreview(panel, wx.ID_ANY, 33, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer4.Add(self.gauge103105S, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.gauge103105M = PFGaugePreview( panel, wx.ID_ANY, 66, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer4.Add( self.gauge103105M, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5 )
self.gauge103105M = PFGaugePreview(panel, wx.ID_ANY, 66, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer4.Add(self.gauge103105M, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
self.gauge103105E = PFGaugePreview( panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER )
gSizer4.Add( self.gauge103105E, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.LEFT, 5 )
self.gauge103105E = PFGaugePreview(panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER)
gSizer4.Add(self.gauge103105E, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 5)
mainSizer.Add( gSizer4, 0, wx.EXPAND, 5 )
mainSizer.Add(gSizer4, 0, wx.EXPAND, 5)
footerSizer = wx.BoxSizer( wx.VERTICAL )
footerSizer = wx.BoxSizer(wx.VERTICAL)
self.sl1 = wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
footerSizer.Add( self.sl1, 0, wx.EXPAND |wx.ALL, 5 )
self.sl1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
footerSizer.Add(self.sl1, 0, wx.EXPAND | wx.ALL, 5)
previewSizer = wx.BoxSizer( wx.HORIZONTAL )
previewSizer = wx.BoxSizer(wx.HORIZONTAL)
self.wndPreview0100 = PFGaugePreview( panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, 0)
previewSizer.Add( self.wndPreview0100, 1, wx.ALIGN_CENTER_VERTICAL, 5 )
self.wndPreview0100 = PFGaugePreview(panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, 0)
previewSizer.Add(self.wndPreview0100, 1, wx.ALIGN_CENTER_VERTICAL, 5)
self.wndPreview100101 = PFGaugePreview( panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, 0)
previewSizer.Add( self.wndPreview100101, 1, wx.ALIGN_CENTER_VERTICAL, 5 )
self.wndPreview100101 = PFGaugePreview(panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, 0)
previewSizer.Add(self.wndPreview100101, 1, wx.ALIGN_CENTER_VERTICAL, 5)
self.wndPreview101103 = PFGaugePreview( panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, 0)
previewSizer.Add( self.wndPreview101103, 1, wx.ALIGN_CENTER_VERTICAL, 5 )
self.wndPreview101103 = PFGaugePreview(panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, 0)
previewSizer.Add(self.wndPreview101103, 1, wx.ALIGN_CENTER_VERTICAL, 5)
self.wndPreview103105 = PFGaugePreview( panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, 0)
previewSizer.Add( self.wndPreview103105, 1, wx.ALIGN_CENTER_VERTICAL, 5 )
self.wndPreview103105 = PFGaugePreview(panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, 0)
previewSizer.Add(self.wndPreview103105, 1, wx.ALIGN_CENTER_VERTICAL, 5)
footerSizer.Add( previewSizer, 1, wx.EXPAND | wx.ALL, 5 )
footerSizer.Add(previewSizer, 1, wx.EXPAND | wx.ALL, 5)
buttonsSizer = wx.BoxSizer( wx.HORIZONTAL )
buttonsSizer = wx.BoxSizer(wx.HORIZONTAL)
self.cbLink = wx.CheckBox( panel, wx.ID_ANY, u"Link Colors", wx.DefaultPosition, wx.DefaultSize, 0 )
buttonsSizer.Add( self.cbLink, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 5 )
self.cbLink = wx.CheckBox(panel, wx.ID_ANY, u"Link Colors", wx.DefaultPosition, wx.DefaultSize, 0)
buttonsSizer.Add(self.cbLink, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 5)
self.sliderGradientStart = wx.Slider( panel, wx.ID_ANY, self.gradientStart, -100, 100, wx.DefaultPosition, (127,-1), wx.SL_HORIZONTAL|wx.SL_LABELS )
buttonsSizer.Add( self.sliderGradientStart, 1, wx.EXPAND | wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
self.sliderGradientStart = wx.Slider(panel, wx.ID_ANY, self.gradientStart, -100, 100, wx.DefaultPosition,
(127, -1), wx.SL_HORIZONTAL | wx.SL_LABELS)
buttonsSizer.Add(self.sliderGradientStart, 1, wx.EXPAND | wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.btnRestore = wx.Button( panel, wx.ID_ANY, u"Restore Defaults", wx.DefaultPosition, wx.DefaultSize, 0 )
buttonsSizer.Add( self.btnRestore, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
self.btnRestore = wx.Button(panel, wx.ID_ANY, u"Restore Defaults", wx.DefaultPosition, wx.DefaultSize, 0)
buttonsSizer.Add(self.btnRestore, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.btnDump = wx.Button( panel, wx.ID_ANY, u"Dump Colors", wx.DefaultPosition, wx.DefaultSize, 0 )
buttonsSizer.Add( self.btnDump, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
self.btnDump = wx.Button(panel, wx.ID_ANY, u"Dump Colors", wx.DefaultPosition, wx.DefaultSize, 0)
buttonsSizer.Add(self.btnDump, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.btnOk = wx.Button( panel, wx.ID_ANY, u"Apply", wx.DefaultPosition, wx.DefaultSize, 0 )
buttonsSizer.Add( self.btnOk, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
self.btnOk = wx.Button(panel, wx.ID_ANY, u"Apply", wx.DefaultPosition, wx.DefaultSize, 0)
buttonsSizer.Add(self.btnOk, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
footerSizer.Add( buttonsSizer, 1, wx.ALIGN_RIGHT, 5 )
mainSizer.Add( footerSizer, 0, wx.EXPAND, 5 )
footerSizer.Add(buttonsSizer, 1, wx.ALIGN_RIGHT, 5)
mainSizer.Add(footerSizer, 0, wx.EXPAND, 5)
panel.SetSizer( mainSizer )
panel.SetSizer(mainSizer)
self.SetColours()
# self.Fit()
# self.Layout()
# self.Fit()
# self.Layout()
self.sliderGradientStart.Bind(wx.EVT_SCROLL, self.OnGradientStartScroll)
self.btnRestore.Bind(wx.EVT_BUTTON, self.RestoreDefaults)
self.btnDump.Bind(wx.EVT_BUTTON, self.DumpColours)
self.btnOk.Bind(wx.EVT_BUTTON, self.OnOk)
self.cp0100S.Bind( wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged )
self.cp0100E.Bind( wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged )
self.cp0100S.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged)
self.cp0100E.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged)
self.cp100101S.Bind( wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged )
self.cp100101E.Bind( wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged )
self.cp100101S.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged)
self.cp100101E.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged)
self.cp101103S.Bind( wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged )
self.cp101103E.Bind( wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged )
self.cp101103S.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged)
self.cp101103E.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged)
self.cp103105S.Bind( wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged )
self.cp103105E.Bind( wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged )
self.cp103105S.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged)
self.cp103105E.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnColourChanged)
def getImage(self):
return BitmapLoader.getBitmap("pref-gauges_big", "gui")
@@ -344,7 +359,6 @@ class PFGaugePref ( PreferenceView):
self.gauge0100M.SetGradientStart(self.sliderGradientStart.GetValue())
self.gauge0100E.SetGradientStart(self.sliderGradientStart.GetValue())
self.cp100101S.SetColour(self.c100101S)
self.cp100101E.SetColour(self.c100101E)
self.gauge100101S.SetColour(self.c100101S, self.c100101E)
@@ -363,7 +377,6 @@ class PFGaugePref ( PreferenceView):
self.gauge100101M.SetGradientStart(self.sliderGradientStart.GetValue())
self.gauge100101E.SetGradientStart(self.sliderGradientStart.GetValue())
self.cp101103S.SetColour(self.c101103S)
self.cp101103E.SetColour(self.c101103E)
self.gauge101103S.SetColour(self.c101103S, self.c101103E)
@@ -378,7 +391,6 @@ class PFGaugePref ( PreferenceView):
self.gauge101103M.SetGradientStart(self.sliderGradientStart.GetValue())
self.gauge101103E.SetGradientStart(self.sliderGradientStart.GetValue())
self.cp103105S.SetColour(self.c103105S)
self.cp103105E.SetColour(self.c103105E)
self.gauge103105S.SetColour(self.c103105S, self.c103105E)
@@ -406,7 +418,7 @@ class PFGaugePref ( PreferenceView):
self.wndPreview101103.SetGradientStart(self.sliderGradientStart.GetValue())
self.wndPreview103105.SetColour(self.c103105S, self.c103105E)
self.wndPreview103105.SetPercentages(103,104.99)
self.wndPreview103105.SetPercentages(103, 104.99)
self.wndPreview103105.SetGradientStart(self.sliderGradientStart.GetValue())
def OnGradientStartScroll(self, event):
@@ -414,16 +426,17 @@ class PFGaugePref ( PreferenceView):
self.SetColours()
event.Skip()
def OnOk(self, event):
#Apply New Settings
@staticmethod
def OnOk(event):
# Apply New Settings
event.Skip()
def DumpColours(self, event):
print "Gradient start: %d" % self.sliderGradientStart.GetValue()
print " 0 <-> 100 Start: ", self.c0100S, " End: ", self.c0100E
print "100 <-> 101 Start: ", self.c100101S, " End: ", self.c100101E
print "101 <-> 103 Start: ", self.c101103S, " End: ", self.c101103E
print "103 <-> 105 Start: ", self.c103105S, " End: ", self.c103105E
print("Gradient start: %d" % self.sliderGradientStart.GetValue())
print(" 0 <-> 100 Start: ", self.c0100S, " End: ", self.c0100E)
print("100 <-> 101 Start: ", self.c100101S, " End: ", self.c100101E)
print("101 <-> 103 Start: ", self.c101103S, " End: ", self.c101103E)
print("103 <-> 105 Start: ", self.c103105S, " End: ", self.c103105E)
event.Skip()
@@ -478,7 +491,8 @@ class PFGaugePref ( PreferenceView):
self.SetColours()
event.Skip()
def __del__( self ):
def __del__(self):
pass
PFGaugePref.register()

View File

@@ -1,76 +1,99 @@
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView
from gui.bitmapLoader import BitmapLoader
import gui.mainFrame
import service
import gui.globalEvents as GE
from service.settings import SettingsProvider
from service.fit import Fit
from service.price import Price
from service.market import Market
class PFGeneralPref ( PreferenceView):
class PFGeneralPref(PreferenceView):
title = "General"
def populatePanel( self, panel ):
def populatePanel(self, panel):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.dirtySettings = False
self.openFitsSettings = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []})
self.openFitsSettings = SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits",
{"enabled": False, "pyfaOpenFits": []})
mainSizer = wx.BoxSizer( wx.VERTICAL )
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.stTitle = wx.StaticText( panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stTitle.Wrap( -1 )
self.stTitle.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0)
self.stTitle.Wrap(-1)
self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add( self.stTitle, 0, wx.ALL, 5 )
mainSizer.Add(self.stTitle, 0, wx.ALL, 5)
self.m_staticline1 = wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.m_staticline1, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5 )
self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.cbGlobalChar = wx.CheckBox( panel, wx.ID_ANY, u"Use global character", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbGlobalChar, 0, wx.ALL|wx.EXPAND, 5 )
self.cbGlobalChar = wx.CheckBox(panel, wx.ID_ANY, u"Use global character", wx.DefaultPosition, wx.DefaultSize,
0)
mainSizer.Add(self.cbGlobalChar, 0, wx.ALL | wx.EXPAND, 5)
self.cbGlobalDmgPattern = wx.CheckBox( panel, wx.ID_ANY, u"Use global damage pattern", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbGlobalDmgPattern, 0, wx.ALL|wx.EXPAND, 5 )
self.cbGlobalDmgPattern = wx.CheckBox(panel, wx.ID_ANY, u"Use global damage pattern", wx.DefaultPosition,
wx.DefaultSize, 0)
mainSizer.Add(self.cbGlobalDmgPattern, 0, wx.ALL | wx.EXPAND, 5)
self.cbGlobalForceReload = wx.CheckBox( panel, wx.ID_ANY, u"Factor in reload time", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbGlobalForceReload, 0, wx.ALL|wx.EXPAND, 5 )
self.cbGlobalForceReload = wx.CheckBox(panel, wx.ID_ANY, u"Factor in reload time", wx.DefaultPosition,
wx.DefaultSize, 0)
mainSizer.Add(self.cbGlobalForceReload, 0, wx.ALL | wx.EXPAND, 5)
self.cbCompactSkills = wx.CheckBox( panel, wx.ID_ANY, u"Compact skills needed tooltip", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbCompactSkills, 0, wx.ALL|wx.EXPAND, 5 )
self.cbCompactSkills = wx.CheckBox(panel, wx.ID_ANY, u"Compact skills needed tooltip", wx.DefaultPosition,
wx.DefaultSize, 0)
mainSizer.Add(self.cbCompactSkills, 0, wx.ALL | wx.EXPAND, 5)
self.cbFitColorSlots = wx.CheckBox( panel, wx.ID_ANY, u"Color fitting view by slot", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbFitColorSlots, 0, wx.ALL|wx.EXPAND, 5 )
self.cbFitColorSlots = wx.CheckBox(panel, wx.ID_ANY, u"Color fitting view by slot", wx.DefaultPosition,
wx.DefaultSize, 0)
mainSizer.Add(self.cbFitColorSlots, 0, wx.ALL | wx.EXPAND, 5)
self.cbReopenFits = wx.CheckBox( panel, wx.ID_ANY, u"Reopen previous fits on startup", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbReopenFits, 0, wx.ALL|wx.EXPAND, 5 )
self.cbReopenFits = wx.CheckBox(panel, wx.ID_ANY, u"Reopen previous fits on startup", wx.DefaultPosition,
wx.DefaultSize, 0)
mainSizer.Add(self.cbReopenFits, 0, wx.ALL | wx.EXPAND, 5)
self.cbRackSlots = wx.CheckBox( panel, wx.ID_ANY, u"Separate Racks", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbRackSlots, 0, wx.ALL|wx.EXPAND, 5 )
self.cbRackSlots = wx.CheckBox(panel, wx.ID_ANY, u"Separate Racks", wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.cbRackSlots, 0, wx.ALL | wx.EXPAND, 5)
labelSizer = wx.BoxSizer( wx.VERTICAL )
self.cbRackLabels = wx.CheckBox( panel, wx.ID_ANY, u"Show Rack Labels", wx.DefaultPosition, wx.DefaultSize, 0 )
labelSizer.Add( self.cbRackLabels, 0, wx.ALL|wx.EXPAND, 5 )
mainSizer.Add( labelSizer, 0, wx.LEFT|wx.EXPAND, 30 )
labelSizer = wx.BoxSizer(wx.VERTICAL)
self.cbRackLabels = wx.CheckBox(panel, wx.ID_ANY, u"Show Rack Labels", wx.DefaultPosition, wx.DefaultSize, 0)
labelSizer.Add(self.cbRackLabels, 0, wx.ALL | wx.EXPAND, 5)
mainSizer.Add(labelSizer, 0, wx.LEFT | wx.EXPAND, 30)
self.cbShowTooltip = wx.CheckBox( panel, wx.ID_ANY, u"Show tab tooltips", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbShowTooltip, 0, wx.ALL|wx.EXPAND, 5 )
self.cbShowTooltip = wx.CheckBox(panel, wx.ID_ANY, u"Show tab tooltips", wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.cbShowTooltip, 0, wx.ALL | wx.EXPAND, 5)
self.cbMarketShortcuts = wx.CheckBox( panel, wx.ID_ANY, u"Show market shortcuts", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbMarketShortcuts, 0, wx.ALL|wx.EXPAND, 5 )
self.cbMarketShortcuts = wx.CheckBox(panel, wx.ID_ANY, u"Show market shortcuts", wx.DefaultPosition,
wx.DefaultSize, 0)
mainSizer.Add(self.cbMarketShortcuts, 0, wx.ALL | wx.EXPAND, 5)
self.cbGaugeAnimation = wx.CheckBox( panel, wx.ID_ANY, u"Animate gauges", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbGaugeAnimation, 0, wx.ALL|wx.EXPAND, 5 )
self.cbGaugeAnimation = wx.CheckBox(panel, wx.ID_ANY, u"Animate gauges", wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.cbGaugeAnimation, 0, wx.ALL | wx.EXPAND, 5)
self.cbExportCharges = wx.CheckBox( panel, wx.ID_ANY, u"Export loaded charges", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbExportCharges, 0, wx.ALL|wx.EXPAND, 5 )
self.cbOpenFitInNew = wx.CheckBox( panel, wx.ID_ANY, u"Open fittings in a new page by default", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbOpenFitInNew, 0, wx.ALL|wx.EXPAND, 5 )
self.cbExportCharges = wx.CheckBox(panel, wx.ID_ANY, u"Export loaded charges", wx.DefaultPosition,
wx.DefaultSize, 0)
mainSizer.Add(self.cbExportCharges, 0, wx.ALL | wx.EXPAND, 5)
defCharSizer = wx.BoxSizer( wx.HORIZONTAL )
self.cbOpenFitInNew = wx.CheckBox(panel, wx.ID_ANY, u"Open fittings in a new page by default",
wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.cbOpenFitInNew, 0, wx.ALL | wx.EXPAND, 5)
self.sFit = service.Fit.getInstance()
priceSizer = wx.BoxSizer(wx.HORIZONTAL)
self.stDefaultSystem = wx.StaticText(panel, wx.ID_ANY, u"Default Market Prices:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stDefaultSystem.Wrap(-1)
priceSizer.Add(self.stDefaultSystem, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.chPriceSystem = wx.Choice(panel, choices=Price.systemsList.keys())
priceSizer.Add(self.chPriceSystem, 1, wx.ALL | wx.EXPAND, 5)
mainSizer.Add(priceSizer, 0, wx.ALL | wx.EXPAND, 0)
self.sFit = Fit.getInstance()
self.cbGlobalChar.SetValue(self.sFit.serviceFittingOptions["useGlobalCharacter"])
self.cbGlobalDmgPattern.SetValue(self.sFit.serviceFittingOptions["useGlobalDamagePattern"])
@@ -85,6 +108,7 @@ class PFGeneralPref ( PreferenceView):
self.cbGaugeAnimation.SetValue(self.sFit.serviceFittingOptions["enableGaugeAnimation"])
self.cbExportCharges.SetValue(self.sFit.serviceFittingOptions["exportCharges"])
self.cbOpenFitInNew.SetValue(self.sFit.serviceFittingOptions["openFitInNew"])
self.chPriceSystem.SetStringSelection(self.sFit.serviceFittingOptions["priceSystem"])
self.cbGlobalChar.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalCharStateChange)
self.cbGlobalDmgPattern.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalDmgPatternStateChange)
@@ -99,10 +123,11 @@ class PFGeneralPref ( PreferenceView):
self.cbGaugeAnimation.Bind(wx.EVT_CHECKBOX, self.onCBGaugeAnimation)
self.cbExportCharges.Bind(wx.EVT_CHECKBOX, self.onCBExportCharges)
self.cbOpenFitInNew.Bind(wx.EVT_CHECKBOX, self.onCBOpenFitInNew)
self.chPriceSystem.Bind(wx.EVT_CHOICE, self.onPriceSelection)
self.cbRackLabels.Enable(self.sFit.serviceFittingOptions["rackSlots"] or False)
panel.SetSizer( mainSizer )
panel.SetSizer(mainSizer)
panel.Layout()
def onCBGlobalColorBySlot(self, event):
@@ -163,11 +188,25 @@ class PFGeneralPref ( PreferenceView):
def onCBExportCharges(self, event):
self.sFit.serviceFittingOptions["exportCharges"] = self.cbExportCharges.GetValue()
def onCBOpenFitInNew(self, event):
self.sFit.serviceFittingOptions["openFitInNew"] = self.cbOpenFitInNew.GetValue()
def getImage(self):
return BitmapLoader.getBitmap("prefs_settings", "gui")
PFGeneralPref.register()
def onPriceSelection(self, event):
system = self.chPriceSystem.GetString(self.chPriceSystem.GetSelection())
self.sFit.serviceFittingOptions["priceSystem"] = system
fitID = self.mainFrame.getActiveFit()
sMkt = Market.getInstance()
sMkt.clearPriceCache()
self.sFit.refreshFit(fitID)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
event.Skip()
PFGeneralPref.register()

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
import os
@@ -5,78 +6,82 @@ from gui.preferenceView import PreferenceView
from gui.bitmapLoader import BitmapLoader
import gui.mainFrame
import service
import gui.globalEvents as GE
from service.settings import HTMLExportSettings
class PFHTMLExportPref ( PreferenceView):
class PFHTMLExportPref(PreferenceView):
title = "HTML Export"
desc = "HTML Export (File > Export HTML) allows you to export your entire fitting "+\
"database into an HTML file at the specified location. This file can be "+\
"used in the in-game browser to easily open and import your fits, or used "+\
"in a regular web browser to open them at NULL-SEC.com or Osmium."
desc2 = "Enabling automatic exporting will update the HTML file after any change "+\
"to a fit is made. Under certain circumstance, this may cause performance issues."
desc4 = "Export Fittings in a minmal HTML Version, just containing the Fittingslinks " +\
"without any visual styling or javscript features"
desc = ("HTML Export (File > Export HTML) allows you to export your entire fitting "
"database into an HTML file at the specified location. This file can be "
"used in the in-game browser to easily open and import your fits, or used "
"in a regular web browser to open them at NULL-SEC.com or Osmium.")
desc2 = ("Enabling automatic exporting will update the HTML file after any change "
"to a fit is made. Under certain circumstance, this may cause performance issues.")
desc4 = ("Export Fittings in a minmal HTML Version, just containing the Fittingslinks "
"without any visual styling or javscript features")
def populatePanel( self, panel ):
def populatePanel(self, panel):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.HTMLExportSettings = service.settings.HTMLExportSettings.getInstance()
self.HTMLExportSettings = HTMLExportSettings.getInstance()
self.dirtySettings = False
dlgWidth = panel.GetParent().GetParent().ClientSize.width
mainSizer = wx.BoxSizer( wx.VERTICAL )
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.stTitle = wx.StaticText( panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stTitle.Wrap( -1 )
self.stTitle.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
mainSizer.Add( self.stTitle, 0, wx.ALL, 5 )
self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0)
self.stTitle.Wrap(-1)
self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add(self.stTitle, 0, wx.ALL, 5)
self.m_staticline1 = wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.m_staticline1, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5 )
self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.stDesc = wx.StaticText( panel, wx.ID_ANY, self.desc, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stDesc = wx.StaticText(panel, wx.ID_ANY, self.desc, wx.DefaultPosition, wx.DefaultSize, 0)
self.stDesc.Wrap(dlgWidth - 50)
mainSizer.Add( self.stDesc, 0, wx.ALL, 5 )
mainSizer.Add(self.stDesc, 0, wx.ALL, 5)
self.PathLinkCtrl = wx.HyperlinkCtrl( panel, wx.ID_ANY, self.HTMLExportSettings.getPath(), u'file:///{}'.format(self.HTMLExportSettings.getPath()), wx.DefaultPosition, wx.DefaultSize, wx.HL_ALIGN_LEFT|wx.NO_BORDER|wx.HL_CONTEXTMENU )
mainSizer.Add( self.PathLinkCtrl, 0, wx.ALL|wx.EXPAND, 5)
self.PathLinkCtrl = wx.HyperlinkCtrl(panel, wx.ID_ANY, self.HTMLExportSettings.getPath(),
u'file:///{}'.format(self.HTMLExportSettings.getPath()),
wx.DefaultPosition, wx.DefaultSize,
wx.HL_ALIGN_LEFT | wx.NO_BORDER | wx.HL_CONTEXTMENU)
mainSizer.Add(self.PathLinkCtrl, 0, wx.ALL | wx.EXPAND, 5)
self.fileSelectDialog = wx.FileDialog(None, "Save Fitting As...", wildcard = "EVE IGB HTML fitting file (*.html)|*.html", style = wx.FD_SAVE)
self.fileSelectDialog = wx.FileDialog(None, "Save Fitting As...",
wildcard="EVE IGB HTML fitting file (*.html)|*.html", style=wx.FD_SAVE)
self.fileSelectDialog.SetPath(self.HTMLExportSettings.getPath())
self.fileSelectDialog.SetFilename(os.path.basename(self.HTMLExportSettings.getPath()));
self.fileSelectDialog.SetFilename(os.path.basename(self.HTMLExportSettings.getPath()))
self.fileSelectButton = wx.Button(panel, -1, "Set export destination", pos=(0,0))
self.fileSelectButton = wx.Button(panel, -1, "Set export destination", pos=(0, 0))
self.fileSelectButton.Bind(wx.EVT_BUTTON, self.selectHTMLExportFilePath)
mainSizer.Add( self.fileSelectButton, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
mainSizer.Add(self.fileSelectButton, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.stDesc2 = wx.StaticText( panel, wx.ID_ANY, self.desc2, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stDesc2 = wx.StaticText(panel, wx.ID_ANY, self.desc2, wx.DefaultPosition, wx.DefaultSize, 0)
self.stDesc2.Wrap(dlgWidth - 50)
mainSizer.Add( self.stDesc2, 0, wx.ALL, 5 )
mainSizer.Add(self.stDesc2, 0, wx.ALL, 5)
self.exportEnabled = wx.CheckBox( panel, wx.ID_ANY, u"Enable automatic HTML export", wx.DefaultPosition, wx.DefaultSize, 0 )
self.exportEnabled = wx.CheckBox(panel, wx.ID_ANY, u"Enable automatic HTML export", wx.DefaultPosition,
wx.DefaultSize, 0)
self.exportEnabled.SetValue(self.HTMLExportSettings.getEnabled())
self.exportEnabled.Bind(wx.EVT_CHECKBOX, self.OnExportEnabledChange)
mainSizer.Add( self.exportEnabled, 0, wx.ALL|wx.EXPAND, 5 )
mainSizer.Add(self.exportEnabled, 0, wx.ALL | wx.EXPAND, 5)
self.stDesc4 = wx.StaticText( panel, wx.ID_ANY, self.desc4, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stDesc4 = wx.StaticText(panel, wx.ID_ANY, self.desc4, wx.DefaultPosition, wx.DefaultSize, 0)
self.stDesc4.Wrap(dlgWidth - 50)
mainSizer.Add( self.stDesc4, 0, wx.ALL, 5 )
mainSizer.Add(self.stDesc4, 0, wx.ALL, 5)
self.exportMinimal = wx.CheckBox( panel, wx.ID_ANY, u"Enable minimal export Format", wx.DefaultPosition, wx.DefaultSize, 0 )
self.exportMinimal = wx.CheckBox(panel, wx.ID_ANY, u"Enable minimal export Format", wx.DefaultPosition,
wx.DefaultSize, 0)
self.exportMinimal.SetValue(self.HTMLExportSettings.getMinimalEnabled())
self.exportMinimal.Bind(wx.EVT_CHECKBOX, self.OnMinimalEnabledChange)
mainSizer.Add( self.exportMinimal, 0, wx.ALL|wx.EXPAND, 5 )
mainSizer.Add(self.exportMinimal, 0, wx.ALL | wx.EXPAND, 5)
panel.SetSizer( mainSizer )
panel.SetSizer(mainSizer)
panel.Layout()
def setPathLinkCtrlValues(self, path):
self.PathLinkCtrl.SetLabel(self.HTMLExportSettings.getPath())
self.PathLinkCtrl.SetURL(u'file:///{}'.format(self.HTMLExportSettings.getPath()))
self.PathLinkCtrl.SetSize(wx.DefaultSize);
self.PathLinkCtrl.SetSize(wx.DefaultSize)
self.PathLinkCtrl.Refresh()
def selectHTMLExportFilePath(self, event):
@@ -94,4 +99,5 @@ class PFHTMLExportPref ( PreferenceView):
def getImage(self):
return BitmapLoader.getBitmap("prefs_html", "gui")
PFHTMLExportPref.register()

View File

@@ -1,53 +1,58 @@
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView
from gui.bitmapLoader import BitmapLoader
import gui.mainFrame
import service
from service.settings import NetworkSettings
from service.network import Network
class PFNetworkPref ( PreferenceView):
class PFNetworkPref(PreferenceView):
title = "Network"
def populatePanel( self, panel ):
def populatePanel(self, panel):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.settings = service.settings.NetworkSettings.getInstance()
self.network = service.Network.getInstance()
self.settings = NetworkSettings.getInstance()
self.network = Network.getInstance()
self.dirtySettings = False
mainSizer = wx.BoxSizer( wx.VERTICAL )
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.stTitle = wx.StaticText( panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stTitle.Wrap( -1 )
self.stTitle.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0)
self.stTitle.Wrap(-1)
self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add( self.stTitle, 0, wx.ALL, 5 )
mainSizer.Add(self.stTitle, 0, wx.ALL, 5)
self.m_staticline1 = wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.m_staticline1, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5 )
self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.cbEnableNetwork = wx.CheckBox( panel, wx.ID_ANY, u"Enable Network", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.cbEnableNetwork, 0, wx.ALL|wx.EXPAND, 5 )
self.cbEnableNetwork = wx.CheckBox(panel, wx.ID_ANY, u"Enable Network", wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.cbEnableNetwork, 0, wx.ALL | wx.EXPAND, 5)
subSizer = wx.BoxSizer( wx.VERTICAL )
self.cbEve = wx.CheckBox( panel, wx.ID_ANY, u"EVE Servers (API && CREST import)", wx.DefaultPosition, wx.DefaultSize, 0 )
subSizer.Add( self.cbEve, 0, wx.ALL|wx.EXPAND, 5 )
subSizer = wx.BoxSizer(wx.VERTICAL)
self.cbEve = wx.CheckBox(panel, wx.ID_ANY, u"EVE Servers (API && CREST import)", wx.DefaultPosition,
wx.DefaultSize, 0)
subSizer.Add(self.cbEve, 0, wx.ALL | wx.EXPAND, 5)
self.cbPricing = wx.CheckBox( panel, wx.ID_ANY, u"Pricing updates", wx.DefaultPosition, wx.DefaultSize, 0 )
subSizer.Add( self.cbPricing, 0, wx.ALL|wx.EXPAND, 5 )
self.cbPricing = wx.CheckBox(panel, wx.ID_ANY, u"Pricing updates", wx.DefaultPosition, wx.DefaultSize, 0)
subSizer.Add(self.cbPricing, 0, wx.ALL | wx.EXPAND, 5)
self.cbPyfaUpdate = wx.CheckBox( panel, wx.ID_ANY, u"Pyfa Update checks", wx.DefaultPosition, wx.DefaultSize, 0 )
subSizer.Add( self.cbPyfaUpdate, 0, wx.ALL|wx.EXPAND, 5 )
self.cbPyfaUpdate = wx.CheckBox(panel, wx.ID_ANY, u"Pyfa Update checks", wx.DefaultPosition, wx.DefaultSize, 0)
subSizer.Add(self.cbPyfaUpdate, 0, wx.ALL | wx.EXPAND, 5)
mainSizer.Add( subSizer, 0, wx.LEFT|wx.EXPAND, 30 )
mainSizer.Add(subSizer, 0, wx.LEFT | wx.EXPAND, 30)
proxyTitle = wx.StaticText( panel, wx.ID_ANY, "Proxy settings", wx.DefaultPosition, wx.DefaultSize, 0 )
proxyTitle.Wrap( -1 )
proxyTitle.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
proxyTitle = wx.StaticText(panel, wx.ID_ANY, "Proxy settings", wx.DefaultPosition, wx.DefaultSize, 0)
proxyTitle.Wrap(-1)
proxyTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add( proxyTitle, 0, wx.ALL, 5 )
mainSizer.Add( wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ), 0, wx.EXPAND, 5 )
mainSizer.Add(proxyTitle, 0, wx.ALL, 5)
mainSizer.Add(wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
wx.EXPAND, 5)
self.cbEnableNetwork.SetValue(self.settings.isEnabled(self.network.ENABLED))
self.cbEve.SetValue(self.settings.isEnabled(self.network.EVE))
@@ -61,9 +66,9 @@ class PFNetworkPref ( PreferenceView):
self.toggleNetworks(self.cbEnableNetwork.GetValue())
#---------------
# ---------------
# Proxy
#---------------
# ---------------
self.nMode = self.settings.getMode()
self.nAddr = self.settings.getAddress()
@@ -73,51 +78,50 @@ class PFNetworkPref ( PreferenceView):
if self.nAuth is None:
self.nAuth = ("", "") # we don't want None here, it should be a tuple
ptypeSizer = wx.BoxSizer( wx.HORIZONTAL )
ptypeSizer = wx.BoxSizer(wx.HORIZONTAL)
self.stPType = wx.StaticText( panel, wx.ID_ANY, u"Mode:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stPType.Wrap( -1 )
ptypeSizer.Add( self.stPType, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.stPType = wx.StaticText(panel, wx.ID_ANY, u"Mode:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stPType.Wrap(-1)
ptypeSizer.Add(self.stPType, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.chProxyTypeChoices = [ u"No proxy", u"Auto-detected proxy settings", u"Manual proxy settings" ]
self.chProxyType = wx.Choice( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, self.chProxyTypeChoices, 0 )
self.chProxyTypeChoices = [u"No proxy", u"Auto-detected proxy settings", u"Manual proxy settings"]
self.chProxyType = wx.Choice(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, self.chProxyTypeChoices, 0)
self.chProxyType.SetSelection(self.nMode)
self.chProxyType.SetSelection( self.nMode )
ptypeSizer.Add(self.chProxyType, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
ptypeSizer.Add( self.chProxyType, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
mainSizer.Add(ptypeSizer, 0, wx.EXPAND, 5)
mainSizer.Add( ptypeSizer, 0, wx.EXPAND, 5 )
fgAddrSizer = wx.FlexGridSizer(2, 2, 0, 0)
fgAddrSizer.AddGrowableCol(1)
fgAddrSizer.SetFlexibleDirection(wx.BOTH)
fgAddrSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
fgAddrSizer = wx.FlexGridSizer( 2, 2, 0, 0 )
fgAddrSizer.AddGrowableCol( 1 )
fgAddrSizer.SetFlexibleDirection( wx.BOTH )
fgAddrSizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
self.stPSetAddr = wx.StaticText(panel, wx.ID_ANY, u"Addr:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stPSetAddr.Wrap(-1)
fgAddrSizer.Add(self.stPSetAddr, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.editProxySettingsAddr = wx.TextCtrl(panel, wx.ID_ANY, self.nAddr, wx.DefaultPosition, wx.DefaultSize, 0)
self.stPSetAddr = wx.StaticText( panel, wx.ID_ANY, u"Addr:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stPSetAddr.Wrap( -1 )
fgAddrSizer.Add( self.stPSetAddr, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
fgAddrSizer.Add(self.editProxySettingsAddr, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
self.editProxySettingsAddr = wx.TextCtrl( panel, wx.ID_ANY, self.nAddr, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stPSetPort = wx.StaticText(panel, wx.ID_ANY, u"Port:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stPSetPort.Wrap(-1)
fgAddrSizer.Add( self.editProxySettingsAddr, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5 )
fgAddrSizer.Add(self.stPSetPort, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.stPSetPort = wx.StaticText( panel, wx.ID_ANY, u"Port:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stPSetPort.Wrap( -1 )
self.editProxySettingsPort = wx.TextCtrl(panel, wx.ID_ANY, self.nPort, wx.DefaultPosition, wx.DefaultSize, 0)
fgAddrSizer.Add( self.stPSetPort, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
fgAddrSizer.Add(self.editProxySettingsPort, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
self.editProxySettingsPort = wx.TextCtrl( panel, wx.ID_ANY, self.nPort, wx.DefaultPosition, wx.DefaultSize, 0 )
fgAddrSizer.Add( self.editProxySettingsPort, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5 )
mainSizer.Add( fgAddrSizer, 0, wx.EXPAND, 5)
mainSizer.Add(fgAddrSizer, 0, wx.EXPAND, 5)
# proxy auth information: login and pass
self.stPSetLogin = wx.StaticText(panel, wx.ID_ANY, u"Username:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stPSetLogin.Wrap(-1)
self.editProxySettingsLogin = wx.TextCtrl(panel, wx.ID_ANY, self.nAuth[0], wx.DefaultPosition, wx.DefaultSize, 0)
self.editProxySettingsLogin = wx.TextCtrl(panel, wx.ID_ANY, self.nAuth[0], wx.DefaultPosition, wx.DefaultSize,
0)
self.stPSetPassword = wx.StaticText(panel, wx.ID_ANY, u"Password:", wx.DefaultPosition, wx.DefaultSize, 0)
self.stPSetPassword.Wrap(-1)
self.editProxySettingsPassword = wx.TextCtrl(panel, wx.ID_ANY, self.nAuth[1], wx.DefaultPosition,
@@ -129,23 +133,24 @@ class PFNetworkPref ( PreferenceView):
pAuthSizer.Add(self.editProxySettingsPassword, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
mainSizer.Add(pAuthSizer, 0, wx.EXPAND, 5)
self.stPSAutoDetected = wx.StaticText( panel, wx.ID_ANY, u"Auto-detected: ", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stPSAutoDetected.Wrap( -1 )
mainSizer.Add( self.stPSAutoDetected, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.stPSAutoDetected = wx.StaticText(panel, wx.ID_ANY, u"Auto-detected: ", wx.DefaultPosition, wx.DefaultSize,
0)
self.stPSAutoDetected.Wrap(-1)
mainSizer.Add(self.stPSAutoDetected, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
btnSizer = wx.BoxSizer( wx.HORIZONTAL )
btnSizer.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 )
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
self.btnApply = wx.Button( panel, wx.ID_ANY, u"Apply Proxy Settings", wx.DefaultPosition, wx.DefaultSize, 0 )
self.btnApply = wx.Button(panel, wx.ID_ANY, u"Apply Proxy Settings", wx.DefaultPosition, wx.DefaultSize, 0)
btnSizer.Add( self.btnApply, 0, wx.ALL, 5 )
btnSizer.Add(self.btnApply, 0, wx.ALL, 5)
mainSizer.Add(btnSizer, 0, wx.EXPAND,5)
mainSizer.Add(btnSizer, 0, wx.EXPAND, 5)
proxy = self.settings.autodetect()
if proxy is not None:
addr,port = proxy
addr, port = proxy
txt = addr + ":" + str(port)
else:
txt = "None"
@@ -159,17 +164,16 @@ class PFNetworkPref ( PreferenceView):
self.editProxySettingsLogin.Bind(wx.EVT_TEXT, self.OnEditPSLoginText)
self.editProxySettingsPassword.Bind(wx.EVT_TEXT, self.OnEditPSPasswordText)
self.btnApply.Bind(wx.EVT_BUTTON, self.OnBtnApply)
self.UpdateApplyButtonState()
if self.nMode is not service.settings.NetworkSettings.PROXY_MODE_MANUAL: # == 2
if self.nMode is not NetworkSettings.PROXY_MODE_MANUAL: # == 2
self.ToggleProxySettings(False)
else:
self.ToggleProxySettings(True)
panel.SetSizer( mainSizer )
panel.SetSizer(mainSizer)
panel.Layout()
def toggleNetworks(self, toggle):
@@ -236,7 +240,7 @@ class PFNetworkPref ( PreferenceView):
self.UpdateApplyButtonState()
if choice is not service.settings.NetworkSettings.PROXY_MODE_MANUAL:
if choice is not NetworkSettings.PROXY_MODE_MANUAL:
self.ToggleProxySettings(False)
else:
self.ToggleProxySettings(True)
@@ -264,4 +268,5 @@ class PFNetworkPref ( PreferenceView):
def getImage(self):
return BitmapLoader.getBitmap("prefs_proxy", "gui")
PFNetworkPref.register()

View File

@@ -1,84 +1,83 @@
# noinspection PyPackageRequirements
import wx
import service
import os
from gui.preferenceView import PreferenceView
from gui.bitmapLoader import BitmapLoader
import service
import gui.globalEvents as GE
from service.settings import UpdateSettings
class PFUpdatePref (PreferenceView):
class PFUpdatePref(PreferenceView):
title = "Updates"
desc = "Pyfa can automatically check and notify you of new releases. "+\
"This feature is toggled in the Network settings. "+\
"Here, you may allow pre-release notifications and view "+\
"suppressed release notifications, if any."
desc = ("Pyfa can automatically check and notify you of new releases. "
"This feature is toggled in the Network settings. "
"Here, you may allow pre-release notifications and view "
"suppressed release notifications, if any.")
def populatePanel( self, panel ):
self.UpdateSettings = service.settings.UpdateSettings.getInstance()
def populatePanel(self, panel):
self.UpdateSettings = UpdateSettings.getInstance()
self.dirtySettings = False
dlgWidth = panel.GetParent().GetParent().ClientSize.width
mainSizer = wx.BoxSizer( wx.VERTICAL )
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.stTitle = wx.StaticText( panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stTitle.Wrap( -1 )
self.stTitle.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
mainSizer.Add( self.stTitle, 0, wx.ALL, 5 )
self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0)
self.stTitle.Wrap(-1)
self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add(self.stTitle, 0, wx.ALL, 5)
self.m_staticline1 = wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.m_staticline1, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5 )
self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.stDesc = wx.StaticText( panel, wx.ID_ANY, self.desc, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stDesc = wx.StaticText(panel, wx.ID_ANY, self.desc, wx.DefaultPosition, wx.DefaultSize, 0)
self.stDesc.Wrap(dlgWidth - 50)
mainSizer.Add( self.stDesc, 0, wx.ALL, 5 )
mainSizer.Add(self.stDesc, 0, wx.ALL, 5)
self.suppressPrerelease = wx.CheckBox( panel, wx.ID_ANY, u"Allow pre-release notifications", wx.DefaultPosition, wx.DefaultSize, 0 )
self.suppressPrerelease = wx.CheckBox(panel, wx.ID_ANY, u"Allow pre-release notifications", wx.DefaultPosition,
wx.DefaultSize, 0)
self.suppressPrerelease.Bind(wx.EVT_CHECKBOX, self.OnPrereleaseStateChange)
self.suppressPrerelease.SetValue(not self.UpdateSettings.get('prerelease'))
mainSizer.Add( self.suppressPrerelease, 0, wx.ALL|wx.EXPAND, 5 )
mainSizer.Add(self.suppressPrerelease, 0, wx.ALL | wx.EXPAND, 5)
if (self.UpdateSettings.get('version')):
self.versionSizer = wx.BoxSizer( wx.VERTICAL )
if self.UpdateSettings.get('version'):
self.versionSizer = wx.BoxSizer(wx.VERTICAL)
self.versionTitle = wx.StaticText(panel, wx.ID_ANY, "Suppressing {0} Notifications".format(
self.UpdateSettings.get('version')), wx.DefaultPosition, wx.DefaultSize, 0)
self.versionTitle.Wrap(-1)
self.versionTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
self.versionTitle = wx.StaticText( panel, wx.ID_ANY, "Suppressing "+self.UpdateSettings.get('version')+" Notifications", wx.DefaultPosition, wx.DefaultSize, 0 )
self.versionTitle.Wrap( -1 )
self.versionTitle.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
self.versionInfo = ("There is a release available which you have chosen to suppress. "
"You can choose to reset notification suppression for this release, "
"or download the new release from GitHub.")
self.versionInfo = "There is a release available which you have chosen to suppress. "+\
"You can choose to reset notification suppression for this release, "+\
"or download the new release from GitHub."
self.versionSizer.AddSpacer((5, 5), 0, wx.EXPAND, 5)
self.versionSizer.AddSpacer( ( 5, 5), 0, wx.EXPAND, 5 )
self.versionSizer.Add(wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL),
0, wx.EXPAND, 5)
self.versionSizer.AddSpacer((5, 5), 0, wx.EXPAND, 5)
self.versionSizer.Add( wx.StaticLine( panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ), 0, wx.EXPAND, 5 )
self.versionSizer.AddSpacer( ( 5, 5), 0, wx.EXPAND, 5 )
self.versionSizer.Add( self.versionTitle, 0, wx.EXPAND, 5 )
self.versionDesc = wx.StaticText( panel, wx.ID_ANY, self.versionInfo, wx.DefaultPosition, wx.DefaultSize, 0 )
self.versionSizer.Add(self.versionTitle, 0, wx.EXPAND, 5)
self.versionDesc = wx.StaticText(panel, wx.ID_ANY, self.versionInfo, wx.DefaultPosition, wx.DefaultSize, 0)
self.versionDesc.Wrap(dlgWidth - 50)
self.versionSizer.Add( self.versionDesc, 0, wx.ALL, 5 )
self.versionSizer.Add(self.versionDesc, 0, wx.ALL, 5)
actionSizer = wx.BoxSizer( wx.HORIZONTAL )
resetSizer = wx.BoxSizer( wx.VERTICAL )
actionSizer = wx.BoxSizer(wx.HORIZONTAL)
resetSizer = wx.BoxSizer(wx.VERTICAL)
self.downloadButton = wx.Button( panel, wx.ID_ANY, "Download", wx.DefaultPosition, wx.DefaultSize, 0 )
self.downloadButton = wx.Button(panel, wx.ID_ANY, "Download", wx.DefaultPosition, wx.DefaultSize, 0)
self.downloadButton.Bind(wx.EVT_BUTTON, self.OnDownload)
resetSizer.Add( self.downloadButton, 0, wx.ALL, 5 )
actionSizer.Add( resetSizer, 1, wx.EXPAND, 5 )
resetSizer.Add(self.downloadButton, 0, wx.ALL, 5)
actionSizer.Add(resetSizer, 1, wx.EXPAND, 5)
self.resetButton = wx.Button( panel, wx.ID_ANY, "Reset Suppression", wx.DefaultPosition, wx.DefaultSize, 0 )
self.resetButton = wx.Button(panel, wx.ID_ANY, "Reset Suppression", wx.DefaultPosition, wx.DefaultSize, 0)
self.resetButton.Bind(wx.EVT_BUTTON, self.ResetSuppression)
actionSizer.Add( self.resetButton, 0, wx.ALL, 5 )
self.versionSizer.Add( actionSizer, 0, wx.EXPAND, 5 )
mainSizer.Add( self.versionSizer, 0, wx.EXPAND, 5 )
actionSizer.Add(self.resetButton, 0, wx.ALL, 5)
self.versionSizer.Add(actionSizer, 0, wx.EXPAND, 5)
mainSizer.Add(self.versionSizer, 0, wx.EXPAND, 5)
panel.SetSizer( mainSizer )
panel.SetSizer(mainSizer)
panel.Layout()
def OnPrereleaseStateChange(self, event):
@@ -96,9 +95,10 @@ class PFUpdatePref (PreferenceView):
self.resetButton.Hide()
def OnDownload(self, event):
wx.LaunchDefaultBrowser('https://github.com/pyfa-org/Pyfa/releases/tag/'+self.UpdateSettings.get('version'))
wx.LaunchDefaultBrowser('https://github.com/pyfa-org/Pyfa/releases/tag/' + self.UpdateSettings.get('version'))
def getImage(self):
return BitmapLoader.getBitmap("prefs_update", "gui")
PFUpdatePref.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,24 +15,27 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui import builtinStatsViews
from gui.bitmapLoader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
class CapacitorViewFull(StatsView):
name = "capacitorViewFull"
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
def getHeaderText(self, fit):
return "Capacitor"
def getTextExtentW(self, text):
width, height = self.parent.GetTextExtent( text )
width, height = self.parent.GetTextExtent(text)
return width
def populatePanel(self, contentPanel, headerPanel):
@@ -104,12 +107,13 @@ class CapacitorViewFull(StatsView):
chargeSizer.Add(lbl, 0, wx.ALIGN_CENTER)
chargeSizer.Add(wx.StaticText(parent, wx.ID_ANY, " GJ/s"), 0, wx.ALIGN_CENTER)
def refreshPanel(self, fit):
#If we did anything intresting, we'd update our labels to reflect the new fit's stats here
stats= (("label%sCapacitorCapacity", lambda: fit.ship.getModifiedItemAttr("capacitorCapacity"), 3, 0, 9),
("label%sCapacitorRecharge", lambda: fit.capRecharge, 3, 0, 0),
("label%sCapacitorDischarge", lambda: fit.capUsed, 3, 0, 0))
# If we did anything intresting, we'd update our labels to reflect the new fit's stats here
stats = (
("label%sCapacitorCapacity", lambda: fit.ship.getModifiedItemAttr("capacitorCapacity"), 3, 0, 9),
("label%sCapacitorRecharge", lambda: fit.capRecharge, 3, 0, 0),
("label%sCapacitorDischarge", lambda: fit.capUsed, 3, 0, 0),
)
panel = "Full"
for labelName, value, prec, lowest, highest in stats:
@@ -127,8 +131,8 @@ class CapacitorViewFull(StatsView):
capStable = fit.capStable if fit is not None else False
lblNameTime = "label%sCapacitorTime"
lblNameState = "label%sCapacitorState"
if isinstance(capState, tuple):
t = "%.1f%%-%.1f%%" % capState
if isinstance(capState, tuple) and len(capState) >= 2:
t = ("{0}%-{1}%", capState[0], capState[1])
s = ""
else:
if capStable:
@@ -147,4 +151,5 @@ class CapacitorViewFull(StatsView):
self.panel.Layout()
self.headerPanel.Layout()
CapacitorViewFull.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,17 +15,20 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import service
import gui.mainFrame
from gui.statsView import StatsView
from gui.bitmapLoader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
from service.fit import Fit
class FirepowerViewFull(StatsView):
name = "firepowerViewFull"
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
@@ -35,7 +38,7 @@ class FirepowerViewFull(StatsView):
return "Firepower"
def getTextExtentW(self, text):
width, height = self.parent.GetTextExtent( text )
width, height = self.parent.GetTextExtent(text)
return width
def populatePanel(self, contentPanel, headerPanel):
@@ -84,7 +87,7 @@ class FirepowerViewFull(StatsView):
baseBox.Add(BitmapLoader.getStaticBitmap("volley_big", parent, "gui"), 0, wx.ALIGN_CENTER)
gridS = wx.GridSizer(2,2,0,0)
gridS = wx.GridSizer(2, 2, 0, 0)
baseBox.Add(gridS, 0)
@@ -114,7 +117,7 @@ class FirepowerViewFull(StatsView):
def switchToMiningYieldView(self, event):
# Getting the active fit
mainFrame = gui.mainFrame.MainFrame.getInstance()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(mainFrame.getActiveFit())
# Remove ourselves from statsPane's view list
self.parent.views.remove(self)
@@ -139,20 +142,20 @@ class FirepowerViewFull(StatsView):
view.refreshPanel(fit)
def refreshPanel(self, fit):
#If we did anything intresting, we'd update our labels to reflect the new fit's stats here
# If we did anything intresting, we'd update our labels to reflect the new fit's stats here
if fit is not None and fit.targetResists is not None:
self.stEff.Show()
else:
self.stEff.Hide()
stats = (("labelFullDpsWeapon", lambda: fit.weaponDPS, 3, 0, 0, "%s DPS",None),
stats = (("labelFullDpsWeapon", lambda: fit.weaponDPS, 3, 0, 0, "%s DPS", None),
("labelFullDpsDrone", lambda: fit.droneDPS, 3, 0, 0, "%s DPS", None),
("labelFullVolleyTotal", lambda: fit.totalVolley, 3, 0, 0, "%s", "Volley: %.1f"),
("labelFullDpsTotal", lambda: fit.totalDPS, 3, 0, 0, "%s", None))
# See GH issue #
#if fit is not None and fit.totalYield > 0:
# if fit is not None and fit.totalYield > 0:
# self.miningyield.Show()
#else:
# else:
# self.miningyield.Hide()
counter = 0
@@ -166,9 +169,10 @@ class FirepowerViewFull(StatsView):
tipStr = valueFormat % valueStr if altFormat is None else altFormat % value
label.SetToolTip(wx.ToolTip(tipStr))
self._cachedValues[counter] = value
counter +=1
counter += 1
self.panel.Layout()
self.headerPanel.Layout()
FirepowerViewFull.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2014 Alexandros Kosiaris
#
# This file is part of pyfa.
@@ -15,26 +15,30 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import service
import gui.mainFrame
from gui.statsView import StatsView
from gui.bitmapLoader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
from service.fit import Fit
class MiningYieldViewFull(StatsView):
name = "miningyieldViewFull"
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
self._cachedValues = []
def getHeaderText(self, fit):
return "Mining Yield"
def getTextExtentW(self, text):
width, height = self.parent.GetTextExtent( text )
width, height = self.parent.GetTextExtent(text)
return width
def populatePanel(self, contentPanel, headerPanel):
@@ -47,11 +51,11 @@ class MiningYieldViewFull(StatsView):
sizerMiningYield = wx.FlexGridSizer(1, 4)
sizerMiningYield.AddGrowableCol(1)
contentSizer.Add( sizerMiningYield, 0, wx.EXPAND, 0)
contentSizer.Add(sizerMiningYield, 0, wx.EXPAND, 0)
counter = 0
for miningType, image in (("miner", "mining") , ("drone", "drones")):
for miningType, image in (("miner", "mining"), ("drone", "drones")):
baseBox = wx.BoxSizer(wx.HORIZONTAL)
sizerMiningYield.Add(baseBox, 1, wx.ALIGN_LEFT if counter == 0 else wx.ALIGN_CENTER_HORIZONTAL)
@@ -66,7 +70,7 @@ class MiningYieldViewFull(StatsView):
box.Add(hbox, 1, wx.ALIGN_CENTER)
lbl = wx.StaticText(parent, wx.ID_ANY, u"0.0 m\u00B3/s")
setattr(self, "label%sminingyield%s" % (panel.capitalize() ,miningType.capitalize()), lbl)
setattr(self, "label%sminingyield%s" % (panel.capitalize(), miningType.capitalize()), lbl)
hbox.Add(lbl, 0, wx.ALIGN_CENTER)
self._cachedValues.append(0)
@@ -103,7 +107,7 @@ class MiningYieldViewFull(StatsView):
def switchToFirepowerView(self, event):
# Getting the active fit
mainFrame = gui.mainFrame.MainFrame.getInstance()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(mainFrame.getActiveFit())
# Remove ourselves from statsPane's view list
self.parent.views.remove(self)
@@ -122,11 +126,11 @@ class MiningYieldViewFull(StatsView):
view.refreshPanel(fit)
def refreshPanel(self, fit):
#If we did anything intresting, we'd update our labels to reflect the new fit's stats here
# If we did anything intresting, we'd update our labels to reflect the new fit's stats here
stats = (("labelFullminingyieldMiner", lambda: fit.minerYield * 3600, 3, 0, 0, u"%s m\u00B3/h",None),
("labelFullminingyieldDrone", lambda: fit.droneYield * 3600, 3, 0, 0, u"%s m\u00B3/h", None),
("labelFullminingyieldTotal", lambda: fit.totalYield * 3600, 3, 0, 0, u"%s m\u00B3/h", None))
stats = (("labelFullminingyieldMiner", lambda: fit.minerYield, 3, 0, 0, u"%s m\u00B3/s", None),
("labelFullminingyieldDrone", lambda: fit.droneYield, 3, 0, 0, u"%s m\u00B3/s", None),
("labelFullminingyieldTotal", lambda: fit.totalYield, 3, 0, 0, u"%s m\u00B3/s", None))
counter = 0
for labelName, value, prec, lowest, highest, valueFormat, altFormat in stats:
@@ -136,11 +140,12 @@ class MiningYieldViewFull(StatsView):
if self._cachedValues[counter] != value:
valueStr = formatAmount(value, prec, lowest, highest)
label.SetLabel(valueFormat % valueStr)
tipStr = valueFormat % valueStr if altFormat is None else altFormat % value
tipStr = "Mining Yield per second ({0} per hour)".format(formatAmount(value * 3600, 3, 0, 3))
label.SetToolTip(wx.ToolTip(tipStr))
self._cachedValues[counter] = value
counter +=1
counter += 1
self.panel.Layout()
self.headerPanel.Layout()
MiningYieldViewFull.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,17 +15,20 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui import builtinStatsViews
from gui.bitmapLoader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
import service
from service.market import Market
from service.price import Price
class PriceViewFull(StatsView):
name = "priceViewFull"
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
@@ -72,27 +75,10 @@ class PriceViewFull(StatsView):
def refreshPanel(self, fit):
if fit is not None:
self.fit = fit
# Compose a list of all the data we need & request it
typeIDs = []
typeIDs.append(fit.ship.item.ID)
for mod in fit.modules:
if not mod.isEmpty:
typeIDs.append(mod.itemID)
typeIDs = Price.fitItemsList(fit)
for drone in fit.drones:
for _ in xrange(drone.amount):
typeIDs.append(drone.itemID)
for fighter in fit.fighters:
for _ in xrange(fighter.amountActive):
typeIDs.append(fighter.itemID)
for cargo in fit.cargo:
for _ in xrange(cargo.amount):
typeIDs.append(cargo.itemID)
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
sMkt.getPrices(typeIDs, self.processPrices)
self.labelEMStatus.SetLabel("Updating prices...")
else:
@@ -117,10 +103,11 @@ class PriceViewFull(StatsView):
self.labelPriceFittings.SetLabel("%s ISK" % formatAmount(modPrice, 3, 3, 9, currency=True))
self.labelPriceFittings.SetToolTip(wx.ToolTip('{:,.2f}'.format(modPrice)))
self._cachedFittings = modPrice
if self._cachedTotal != (shipPrice+modPrice):
if self._cachedTotal != (shipPrice + modPrice):
self.labelPriceTotal.SetLabel("%s ISK" % formatAmount(shipPrice + modPrice, 3, 3, 9, currency=True))
self.labelPriceTotal.SetToolTip(wx.ToolTip('{:,.2f}'.format(shipPrice + modPrice)))
self._cachedTotal = shipPrice + modPrice
self.panel.Layout()
PriceViewFull.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,35 +15,38 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui.bitmapLoader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
import gui.mainFrame
import gui.builtinStatsViews.resistancesViewFull as rvf
import service
from gui.builtinStatsViews.resistancesViewFull import EFFECTIVE_HP_TOGGLED
from service.fit import Fit
class RechargeViewFull(StatsView):
name = "rechargeViewFull"
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.mainFrame.Bind(rvf.EFFECTIVE_HP_TOGGLED, self.toggleEffective)
self.mainFrame.Bind(EFFECTIVE_HP_TOGGLED, self.toggleEffective)
self.effective = True
def getHeaderText(self, fit):
return "Recharge rates"
def getTextExtentW(self, text):
width, height = self.parent.GetTextExtent( text )
width, height = self.parent.GetTextExtent(text)
return width
def toggleEffective(self, event):
self.effective = event.effective
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
self.refreshPanel(sFit.getFit(self.mainFrame.getActiveFit()))
event.Skip()
@@ -53,21 +56,22 @@ class RechargeViewFull(StatsView):
self.panel = contentPanel
self.headerPanel = headerPanel
sizerTankStats = wx.FlexGridSizer(3, 5)
for i in xrange(4):
for i in range(4):
sizerTankStats.AddGrowableCol(i + 1)
contentSizer.Add(sizerTankStats, 0, wx.EXPAND, 0)
#Add an empty label first for correct alignment.
# Add an empty label first for correct alignment.
sizerTankStats.Add(wx.StaticText(contentPanel, wx.ID_ANY, ""), 0)
toolTipText = {"shieldPassive" : "Passive shield recharge", "shieldActive" : "Active shield boost", "armorActive" : "Armor repair amount", "hullActive" : "Hull repair amount"}
toolTipText = {"shieldPassive": "Passive shield recharge", "shieldActive": "Active shield boost",
"armorActive": "Armor repair amount", "hullActive": "Hull repair amount"}
for tankType in ("shieldPassive", "shieldActive", "armorActive", "hullActive"):
bitmap = BitmapLoader.getStaticBitmap("%s_big" % tankType, contentPanel, "gui")
tooltip = wx.ToolTip(toolTipText[tankType])
bitmap.SetToolTip(tooltip)
sizerTankStats.Add(bitmap, 0, wx.ALIGN_CENTER)
toolTipText = {"reinforced" : "Reinforced", "sustained" : "Sustained"}
toolTipText = {"reinforced": "Reinforced", "sustained": "Sustained"}
for stability in ("reinforced", "sustained"):
bitmap = BitmapLoader.getStaticBitmap("regen%s_big" % stability.capitalize(), contentPanel, "gui")
tooltip = wx.ToolTip(toolTipText[stability])
@@ -79,7 +83,7 @@ class RechargeViewFull(StatsView):
continue
tankTypeCap = tankType[0].capitalize() + tankType[1:]
lbl = wx.StaticText(contentPanel, wx.ID_ANY, "0.0", style = wx.ALIGN_RIGHT)
lbl = wx.StaticText(contentPanel, wx.ID_ANY, "0.0", style=wx.ALIGN_RIGHT)
setattr(self, "labelTank%s%s" % (stability.capitalize(), tankTypeCap), lbl)
box = wx.BoxSizer(wx.HORIZONTAL)
@@ -91,12 +95,12 @@ class RechargeViewFull(StatsView):
contentPanel.Layout()
def refreshPanel(self, fit):
#If we did anything intresting, we'd update our labels to reflect the new fit's stats here
# If we did anything intresting, we'd update our labels to reflect the new fit's stats here
for stability in ("reinforced", "sustained"):
if stability == "reinforced" and fit != None:
if stability == "reinforced" and fit is not None:
tank = fit.effectiveTank if self.effective else fit.tank
elif stability == "sustained" and fit != None:
elif stability == "sustained" and fit is not None:
tank = fit.effectiveSustainableTank if self.effective else fit.sustainableTank
else:
tank = None
@@ -122,4 +126,5 @@ class RechargeViewFull(StatsView):
self.panel.Layout()
self.headerPanel.Layout()
RechargeViewFull.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,23 +15,23 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui import builtinStatsViews
from gui.bitmapLoader import BitmapLoader
from gui import pygauge as PG
from gui.pygauge import PyGauge
from gui.utils.numberFormatter import formatAmount
import service
import gui.mainFrame
import gui.builtinViews.fittingView as fv
import gui.globalEvents as GE
EffectiveHpToggled, EFFECTIVE_HP_TOGGLED = wx.lib.newevent.NewEvent()
class ResistancesViewFull(StatsView):
name = "resistancesViewFull"
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
@@ -45,7 +45,7 @@ class ResistancesViewFull(StatsView):
return "Resistances"
def getTextExtentW(self, text):
width, height = self.parent.GetTextExtent( text )
width, height = self.parent.GetTextExtent(text)
return width
def populatePanel(self, contentPanel, headerPanel):
@@ -56,7 +56,7 @@ class ResistancesViewFull(StatsView):
# Custom header EHP
headerContentSizer = wx.BoxSizer(wx.HORIZONTAL)
hsizer = headerPanel.GetSizer()
hsizer.Add(headerContentSizer,0,0,0)
hsizer.Add(headerContentSizer, 0, 0, 0)
self.stEff = wx.StaticText(headerPanel, wx.ID_ANY, "( Effective HP: ")
headerContentSizer.Add(self.stEff)
headerPanel.GetParent().AddToggleItem(self.stEff)
@@ -67,81 +67,83 @@ class ResistancesViewFull(StatsView):
stCls = wx.StaticText(headerPanel, wx.ID_ANY, " )")
headerPanel.GetParent().AddToggleItem( stCls )
headerContentSizer.Add( stCls )
# headerContentSizer.Add(wx.StaticLine(headerPanel, wx.ID_ANY), 1, wx.ALIGN_CENTER)
headerPanel.GetParent().AddToggleItem(stCls)
headerContentSizer.Add(stCls)
# headerContentSizer.Add(wx.StaticLine(headerPanel, wx.ID_ANY), 1, wx.ALIGN_CENTER)
# Display table
col = 0
row = 0
sizerResistances = wx.GridBagSizer()
contentSizer.Add( sizerResistances, 0, wx.EXPAND , 0)
contentSizer.Add(sizerResistances, 0, wx.EXPAND, 0)
# Add an empty label, then the rest.
sizerResistances.Add(wx.StaticText(contentPanel, wx.ID_ANY), wx.GBPosition( row, col ), wx.GBSpan( 1, 1 ))
col+=1
toolTipText = {"em" : "Electromagnetic resistance", "thermal" : "Thermal resistance", "kinetic" : "Kinetic resistance", "explosive" : "Explosive resistance"}
sizerResistances.Add(wx.StaticText(contentPanel, wx.ID_ANY), wx.GBPosition(row, col), wx.GBSpan(1, 1))
col += 1
toolTipText = {"em": "Electromagnetic resistance", "thermal": "Thermal resistance",
"kinetic": "Kinetic resistance", "explosive": "Explosive resistance"}
for damageType in ("em", "thermal", "kinetic", "explosive"):
bitmap = BitmapLoader.getStaticBitmap("%s_big" % damageType, contentPanel, "gui")
tooltip = wx.ToolTip(toolTipText[damageType])
bitmap.SetToolTip(tooltip)
sizerResistances.Add(bitmap, wx.GBPosition( row, col ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER)
col+=1
self.stEHPs = wx.Button(contentPanel, style = wx.BU_EXACTFIT, label = "EHP")
sizerResistances.Add(bitmap, wx.GBPosition(row, col), wx.GBSpan(1, 1), wx.ALIGN_CENTER)
col += 1
self.stEHPs = wx.Button(contentPanel, style=wx.BU_EXACTFIT, label="EHP")
self.stEHPs.SetToolTip(wx.ToolTip("Click to toggle between effective HP and raw HP"))
self.stEHPs.Bind(wx.EVT_BUTTON, self.toggleEHP)
for i in xrange(4):
sizerResistances.AddGrowableCol(i+1)
sizerResistances.AddGrowableCol(i + 1)
sizerResistances.Add(self.stEHPs, wx.GBPosition( row, col ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER)
col=0
row+=1
sizerResistances.Add(self.stEHPs, wx.GBPosition(row, col), wx.GBSpan(1, 1), wx.ALIGN_CENTER)
col = 0
row += 1
gaugeColours=( ((38,133,198),(52,86,98)), ((198,38,38),(83,65,67)), ((163,163,163),(74,90,93)), ((198,133,38),(81,83,67)) )
gaugeColours = (((38, 133, 198), (52, 86, 98)), ((198, 38, 38), (83, 65, 67)), ((163, 163, 163), (74, 90, 93)),
((198, 133, 38), (81, 83, 67)))
toolTipText = {"shield" : "Shield resistance", "armor" : "Armor resistance", "hull" : "Hull resistance", "damagePattern" : "Incoming damage pattern"}
toolTipText = {"shield": "Shield resistance", "armor": "Armor resistance", "hull": "Hull resistance",
"damagePattern": "Incoming damage pattern"}
for tankType in ("shield", "armor", "hull", "separator", "damagePattern"):
if tankType != "separator":
bitmap = BitmapLoader.getStaticBitmap("%s_big" % tankType, contentPanel, "gui")
tooltip = wx.ToolTip(toolTipText[tankType])
bitmap.SetToolTip(tooltip)
sizerResistances.Add(bitmap, wx.GBPosition( row, col ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER)
col+=1
sizerResistances.Add(bitmap, wx.GBPosition(row, col), wx.GBSpan(1, 1), wx.ALIGN_CENTER)
col += 1
else:
sizerResistances.Add(wx.StaticLine(contentPanel, wx.ID_ANY), wx.GBPosition( row, col ), wx.GBSpan( 1, 6 ), wx.EXPAND|wx.ALIGN_CENTER)
row+=1
col=0
sizerResistances.Add(wx.StaticLine(contentPanel, wx.ID_ANY), wx.GBPosition(row, col), wx.GBSpan(1, 6),
wx.EXPAND | wx.ALIGN_CENTER)
row += 1
col = 0
continue
currGColour=0
currGColour = 0
for damageType in ("em", "thermal", "kinetic", "explosive"):
box = wx.BoxSizer(wx.HORIZONTAL)
sizerResistances.Add(box, wx.GBPosition( row, col ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER)
sizerResistances.Add(box, wx.GBPosition(row, col), wx.GBSpan(1, 1), wx.ALIGN_CENTER)
# Fancy gauges addon
#Fancy gauges addon
pgColour= gaugeColours[currGColour]
pgColour = gaugeColours[currGColour]
fc = pgColour[0]
bc = pgColour[1]
currGColour+=1
currGColour += 1
lbl = PG.PyGauge(contentPanel, wx.ID_ANY, 100)
lbl = PyGauge(contentPanel, wx.ID_ANY, 100)
lbl.SetMinSize((48, 16))
lbl.SetBackgroundColour(wx.Colour(bc[0],bc[1],bc[2]))
lbl.SetBarColour(wx.Colour(fc[0],fc[1],fc[2]))
lbl.SetBackgroundColour(wx.Colour(bc[0], bc[1], bc[2]))
lbl.SetBarColour(wx.Colour(fc[0], fc[1], fc[2]))
lbl.SetBarGradient()
lbl.SetFractionDigits(1)
setattr(self, "gaugeResistance%s%s" % (tankType.capitalize(), damageType.capitalize()), lbl)
box.Add(lbl, 0, wx.ALIGN_CENTER)
col+=1
col += 1
box = wx.BoxSizer(wx.VERTICAL)
box.SetMinSize(wx.Size(self.getTextExtentW("WWWWk"), -1))
@@ -149,9 +151,9 @@ class ResistancesViewFull(StatsView):
box.Add(lbl, 0, wx.ALIGN_CENTER)
setattr(self, "labelResistance%sEhp" % tankType.capitalize(), lbl)
sizerResistances.Add(box, wx.GBPosition( row, col ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER)
row+=1
col=0
sizerResistances.Add(box, wx.GBPosition(row, col), wx.GBSpan(1, 1), wx.ALIGN_CENTER)
row += 1
col = 0
self.stEHPs.SetToolTip(wx.ToolTip("Click to toggle between effective HP and raw HP"))
@@ -163,7 +165,7 @@ class ResistancesViewFull(StatsView):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
def refreshPanel(self, fit):
#If we did anything intresting, we'd update our labels to reflect the new fit's stats here
# If we did anything intresting, we'd update our labels to reflect the new fit's stats here
if fit is None and not self.showEffective:
self.showEffective = True
wx.PostEvent(self.mainFrame, EffectiveHpToggled(effective=True))
@@ -194,11 +196,11 @@ class ResistancesViewFull(StatsView):
total += ehp[tankType]
rrFactor = fit.ehp[tankType] / fit.hp[tankType]
lbl.SetLabel(formatAmount(ehp[tankType], 3, 0, 9))
lbl.SetToolTip(wx.ToolTip("%s: %d\nResist Multiplier: x%.2f" % (tankType.capitalize(), ehp[tankType], rrFactor)))
lbl.SetToolTip(
wx.ToolTip("%s: %d\nResist Multiplier: x%.2f" % (tankType.capitalize(), ehp[tankType], rrFactor)))
else:
lbl.SetLabel("0")
self.labelEhp.SetLabel("%s" % formatAmount(total, 3, 0, 9))
if self.showEffective:
self.stEff.SetLabel("( Effective HP: ")
@@ -207,10 +209,9 @@ class ResistancesViewFull(StatsView):
self.stEff.SetLabel("( Raw HP: ")
self.labelEhp.SetToolTip(wx.ToolTip("Raw: %d HP" % total))
damagePattern = fit.damagePattern if fit is not None and self.showEffective else None
damagePattern = fit.damagePattern if fit is not None and self.showEffective else None
total = sum((damagePattern.emAmount, damagePattern.thermalAmount,
damagePattern.kineticAmount, damagePattern.explosiveAmount)) if damagePattern is not None else 0
damagePattern.kineticAmount, damagePattern.explosiveAmount)) if damagePattern is not None else 0
for damageType in ("em", "thermal", "kinetic", "explosive"):
lbl = getattr(self, "gaugeResistanceDamagepattern%s" % damageType.capitalize())
@@ -223,5 +224,5 @@ class ResistancesViewFull(StatsView):
self.panel.Layout()
self.headerPanel.Layout()
ResistancesViewFull.register()
ResistancesViewFull.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,20 +15,21 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui import builtinStatsViews
from gui.bitmapLoader import BitmapLoader
from gui import pygauge as PG
from gui.pygauge import PyGauge
import gui.mainFrame
import gui.chromeTabs
from gui.chromeTabs import EVT_NOTEBOOK_PAGE_CHANGED
from eos.types import Hardpoint
from eos.saveddata.module import Hardpoint
from gui.utils.numberFormatter import formatAmount
class ResourcesViewFull(StatsView):
name = "resourcesViewFull"
contexts = ["drone", "fighter", "cargo"]
@@ -37,7 +38,7 @@ class ResourcesViewFull(StatsView):
StatsView.__init__(self)
self.parent = parent
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.mainFrame.additionsPane.notebook.Bind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
self.mainFrame.additionsPane.notebook.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
def pageChanged(self, event):
page = self.mainFrame.additionsPane.getName(event.GetSelection())
@@ -79,7 +80,7 @@ class ResourcesViewFull(StatsView):
return "Resources"
def getTextExtentW(self, text):
width, height = self.parent.GetTextExtent( text )
width, height = self.parent.GetTextExtent(text)
return width
def populatePanel(self, contentPanel, headerPanel):
@@ -99,54 +100,56 @@ class ResourcesViewFull(StatsView):
self.headerPanel = headerPanel
panel = "full"
base = sizerResources
sizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
#Turrets & launcher hardslots display
tooltipText = {"turret":"Turret hardpoints", "launcher":"Launcher hardpoints", "drones":"Drones active", "fighter": "Fighter squadrons active", "calibration":"Calibration"}
for type in ("turret", "launcher", "drones", "fighter", "calibration"):
# Turrets & launcher hardslots display
tooltipText = {"turret": "Turret hardpoints", "launcher": "Launcher hardpoints", "drones": "Drones active",
"fighter": "Fighter squadrons active", "calibration": "Calibration"}
for type_ in ("turret", "launcher", "drones", "fighter", "calibration"):
box = wx.BoxSizer(wx.HORIZONTAL)
bitmap = BitmapLoader.getStaticBitmap("%s_big" % type, parent, "gui")
tooltip = wx.ToolTip(tooltipText[type])
bitmap = BitmapLoader.getStaticBitmap("%s_big" % type_, parent, "gui")
tooltip = wx.ToolTip(tooltipText[type_])
bitmap.SetToolTip(tooltip)
box.Add(bitmap, 0, wx.ALIGN_CENTER)
sizer.Add(box, 0, wx.ALIGN_CENTER)
suffix = {'turret':'Hardpoints', 'launcher':'Hardpoints', 'drones':'Active', 'fighter':'Tubes', 'calibration':'Points'}
suffix = {'turret': 'Hardpoints', 'launcher': 'Hardpoints', 'drones': 'Active', 'fighter': 'Tubes',
'calibration': 'Points'}
lbl = wx.StaticText(parent, wx.ID_ANY, "0")
setattr(self, "label%sUsed%s%s" % (panel.capitalize(), type.capitalize(), suffix[type].capitalize()), lbl)
setattr(self, "label%sUsed%s%s" % (panel.capitalize(), type_.capitalize(), suffix[type_].capitalize()), lbl)
box.Add(lbl, 0, wx.ALIGN_CENTER | wx.LEFT, 5)
box.Add(wx.StaticText(parent, wx.ID_ANY, "/"), 0, wx.ALIGN_CENTER)
lbl = wx.StaticText(parent, wx.ID_ANY, "0")
setattr(self, "label%sTotal%s%s" % (panel.capitalize(), type.capitalize(), suffix[type].capitalize()), lbl)
setattr(self, "label%sTotal%s%s" % (panel.capitalize(), type_.capitalize(), suffix[type_].capitalize()),
lbl)
box.Add(lbl, 0, wx.ALIGN_CENTER)
setattr(self, "boxSizer{}".format(type.capitalize()), box)
setattr(self, "boxSizer{}".format(type_.capitalize()), box)
# Hack - We add a spacer after each thing, but we are always hiding something. The spacer is stil there.
# This way, we only have one space after the drones/fighters
if type != "drones":
if type_ != "drones":
sizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
#PG, Cpu & drone stuff
tooltipText = {"cpu":"CPU", "pg":"PowerGrid", "droneBay":"Drone bay", "fighterBay": "Fighter bay", "droneBandwidth":"Drone bandwidth", "cargoBay":"Cargo bay"}
# PG, Cpu & drone stuff
tooltipText = {"cpu": "CPU", "pg": "PowerGrid", "droneBay": "Drone bay", "fighterBay": "Fighter bay",
"droneBandwidth": "Drone bandwidth", "cargoBay": "Cargo bay"}
for i, group in enumerate((("cpu", "pg"), ("cargoBay", "droneBay", "fighterBay", "droneBandwidth"))):
main = wx.BoxSizer(wx.VERTICAL)
base.Add(main, 1 , wx.ALIGN_CENTER)
base.Add(main, 1, wx.ALIGN_CENTER)
for type in group:
capitalizedType = type[0].capitalize() + type[1:]
bitmap = BitmapLoader.getStaticBitmap(type + "_big", parent, "gui")
tooltip = wx.ToolTip(tooltipText[type])
for type_ in group:
capitalizedType = type_[0].capitalize() + type_[1:]
bitmap = BitmapLoader.getStaticBitmap(type_ + "_big", parent, "gui")
tooltip = wx.ToolTip(tooltipText[type_])
bitmap.SetToolTip(tooltip)
stats = wx.BoxSizer(wx.VERTICAL)
absolute = wx.BoxSizer(wx.HORIZONTAL)
absolute = wx.BoxSizer(wx.HORIZONTAL)
stats.Add(absolute, 0, wx.EXPAND)
b = wx.BoxSizer(wx.HORIZONTAL)
@@ -166,18 +169,19 @@ class ResourcesViewFull(StatsView):
setattr(self, "label%sTotal%s" % (panel.capitalize(), capitalizedType), lbl)
absolute.Add(lbl, 0, wx.ALIGN_LEFT)
units = {"cpu":" tf", "pg":" MW", "droneBandwidth":" mbit/s", "droneBay":u" m\u00B3", "fighterBay":u" m\u00B3", "cargoBay":u" m\u00B3"}
lbl = wx.StaticText(parent, wx.ID_ANY, "%s" % units[type])
units = {"cpu": " tf", "pg": " MW", "droneBandwidth": " mbit/s", "droneBay": u" m\u00B3",
"fighterBay": u" m\u00B3", "cargoBay": u" m\u00B3"}
lbl = wx.StaticText(parent, wx.ID_ANY, "%s" % units[type_])
absolute.Add(lbl, 0, wx.ALIGN_LEFT)
# Gauges modif. - Darriele
gauge = PG.PyGauge(parent, wx.ID_ANY, 1)
gauge = PyGauge(parent, wx.ID_ANY, 1)
gauge.SetValueRange(0, 0)
gauge.SetMinSize((self.getTextExtentW("1.999M/1.99M MW"), 23))
gauge.SetFractionDigits(2)
setattr(self, "gauge%s%s" % (panel.capitalize(),capitalizedType), gauge)
setattr(self, "gauge%s%s" % (panel.capitalize(), capitalizedType), gauge)
stats.Add(gauge, 0, wx.ALIGN_CENTER)
setattr(self, "base%s%s" % (panel.capitalize(), capitalizedType), b)
@@ -186,77 +190,88 @@ class ResourcesViewFull(StatsView):
self.toggleContext("drone")
def refreshPanel(self, fit):
#If we did anything intresting, we'd update our labels to reflect the new fit's stats here
# If we did anything intresting, we'd update our labels to reflect the new fit's stats here
stats = (("label%sUsedTurretHardpoints", lambda: fit.getHardpointsUsed(Hardpoint.TURRET), 0, 0, 0),
("label%sTotalTurretHardpoints", lambda: fit.ship.getModifiedItemAttr('turretSlotsLeft'), 0, 0, 0),
("label%sUsedLauncherHardpoints", lambda: fit.getHardpointsUsed(Hardpoint.MISSILE), 0, 0, 0),
("label%sTotalLauncherHardpoints", lambda: fit.ship.getModifiedItemAttr('launcherSlotsLeft'), 0, 0, 0),
("label%sUsedDronesActive", lambda: fit.activeDrones, 0, 0, 0),
("label%sTotalDronesActive", lambda: fit.extraAttributes["maxActiveDrones"], 0, 0, 0),
("label%sUsedFighterTubes", lambda: fit.fighterTubesUsed, 3, 0, 9),
("label%sTotalFighterTubes", lambda: fit.ship.getModifiedItemAttr("fighterTubes"), 3, 0, 9),
("label%sUsedCalibrationPoints", lambda: fit.calibrationUsed, 0, 0, 0),
("label%sTotalCalibrationPoints", lambda: fit.ship.getModifiedItemAttr('upgradeCapacity'), 0, 0, 0),
("label%sUsedPg", lambda: fit.pgUsed, 4, 0, 9),
("label%sUsedCpu", lambda: fit.cpuUsed, 4, 0, 9),
("label%sTotalPg", lambda: fit.ship.getModifiedItemAttr("powerOutput"), 4, 0, 9),
("label%sTotalCpu", lambda: fit.ship.getModifiedItemAttr("cpuOutput"), 4, 0, 9),
("label%sUsedDroneBay", lambda: fit.droneBayUsed, 3, 0, 9),
("label%sUsedFighterBay", lambda: fit.fighterBayUsed, 3, 0, 9),
("label%sUsedDroneBandwidth", lambda: fit.droneBandwidthUsed, 3, 0, 9),
("label%sTotalDroneBay", lambda: fit.ship.getModifiedItemAttr("droneCapacity"), 3, 0, 9),
("label%sTotalDroneBandwidth", lambda: fit.ship.getModifiedItemAttr("droneBandwidth"), 3, 0, 9),
("label%sTotalFighterBay", lambda: fit.ship.getModifiedItemAttr("fighterCapacity"), 3, 0, 9),
("label%sUsedCargoBay", lambda: fit.cargoBayUsed, 3, 0, 9),
("label%sTotalCargoBay", lambda: fit.ship.getModifiedItemAttr("capacity"), 3, 0, 9))
stats = (
("label%sUsedTurretHardpoints", lambda: fit.getHardpointsUsed(Hardpoint.TURRET), 0, 0, 0),
("label%sTotalTurretHardpoints", lambda: fit.ship.getModifiedItemAttr('turretSlotsLeft'), 0, 0, 0),
("label%sUsedLauncherHardpoints", lambda: fit.getHardpointsUsed(Hardpoint.MISSILE), 0, 0, 0),
("label%sTotalLauncherHardpoints", lambda: fit.ship.getModifiedItemAttr('launcherSlotsLeft'), 0, 0, 0),
("label%sUsedDronesActive", lambda: fit.activeDrones, 0, 0, 0),
("label%sTotalDronesActive", lambda: fit.extraAttributes["maxActiveDrones"], 0, 0, 0),
("label%sUsedFighterTubes", lambda: fit.fighterTubesUsed, 3, 0, 9),
("label%sTotalFighterTubes", lambda: fit.ship.getModifiedItemAttr("fighterTubes"), 3, 0, 9),
("label%sUsedCalibrationPoints", lambda: fit.calibrationUsed, 0, 0, 0),
("label%sTotalCalibrationPoints", lambda: fit.ship.getModifiedItemAttr('upgradeCapacity'), 0, 0, 0),
("label%sUsedPg", lambda: fit.pgUsed, 4, 0, 9),
("label%sUsedCpu", lambda: fit.cpuUsed, 4, 0, 9),
("label%sTotalPg", lambda: fit.ship.getModifiedItemAttr("powerOutput"), 4, 0, 9),
("label%sTotalCpu", lambda: fit.ship.getModifiedItemAttr("cpuOutput"), 4, 0, 9),
("label%sUsedDroneBay", lambda: fit.droneBayUsed, 3, 0, 9),
("label%sUsedFighterBay", lambda: fit.fighterBayUsed, 3, 0, 9),
("label%sUsedDroneBandwidth", lambda: fit.droneBandwidthUsed, 3, 0, 9),
("label%sTotalDroneBay", lambda: fit.ship.getModifiedItemAttr("droneCapacity"), 3, 0, 9),
("label%sTotalDroneBandwidth", lambda: fit.ship.getModifiedItemAttr("droneBandwidth"), 3, 0, 9),
("label%sTotalFighterBay", lambda: fit.ship.getModifiedItemAttr("fighterCapacity"), 3, 0, 9),
("label%sUsedCargoBay", lambda: fit.cargoBayUsed, 3, 0, 9),
("label%sTotalCargoBay", lambda: fit.ship.getModifiedItemAttr("capacity"), 3, 0, 9),
)
panel = "Full"
usedTurretHardpoints = 0
labelUTH = ""
totalTurretHardpoints = 0
labelTTH = ""
usedLauncherHardpoints = 0
labelULH = ""
totalLauncherHardPoints = 0
labelTLH = ""
usedDronesActive = 0
labelUDA = ""
totalDronesActive = 0
labelTDA = ""
usedFighterTubes = 0
labelUFT = ""
totalFighterTubes = 0
labelTFT = ""
usedCalibrationPoints = 0
labelUCP = ""
totalCalibrationPoints = 0
labelTCP = ""
for labelName, value, prec, lowest, highest in stats:
label = getattr(self, labelName % panel)
value = value() if fit is not None else 0
value = value if value is not None else 0
if labelName % panel == "label%sUsedTurretHardpoints" % panel:
usedTurretHardpoints = value
labelUTH = label
if labelName % panel == "label%sTotalTurretHardpoints" % panel:
elif labelName % panel == "label%sTotalTurretHardpoints" % panel:
totalTurretHardpoints = value
labelTTH = label
if labelName % panel == "label%sUsedLauncherHardpoints" % panel:
elif labelName % panel == "label%sUsedLauncherHardpoints" % panel:
usedLauncherHardpoints = value
labelULH = label
if labelName % panel == "label%sTotalLauncherHardpoints" % panel:
elif labelName % panel == "label%sTotalLauncherHardpoints" % panel:
totalLauncherHardPoints = value
labelTLH = label
if labelName % panel == "label%sUsedDronesActive" % panel:
elif labelName % panel == "label%sUsedDronesActive" % panel:
usedDronesActive = value
labelUDA = label
if labelName % panel == "label%sTotalDronesActive" % panel:
elif labelName % panel == "label%sTotalDronesActive" % panel:
totalDronesActive = value
labelTDA = label
if labelName % panel == "label%sUsedFighterTubes" % panel:
elif labelName % panel == "label%sUsedFighterTubes" % panel:
usedFighterTubes = value
labelUFT = label
if labelName % panel == "label%sTotalFighterTubes" % panel:
elif labelName % panel == "label%sTotalFighterTubes" % panel:
totalFighterTubes = value
labelTFT = label
if labelName % panel == "label%sUsedCalibrationPoints" % panel:
elif labelName % panel == "label%sUsedCalibrationPoints" % panel:
usedCalibrationPoints = value
labelUCP = label
if labelName % panel == "label%sTotalCalibrationPoints" % panel:
elif labelName % panel == "label%sTotalCalibrationPoints" % panel:
totalCalibrationPoints = value
labelTCP = label
@@ -303,12 +318,16 @@ class ResourcesViewFull(StatsView):
labelTCP.SetForegroundColour(colorC)
if fit is not None:
resMax = (lambda: fit.ship.getModifiedItemAttr("cpuOutput"),
lambda: fit.ship.getModifiedItemAttr("powerOutput"),
lambda: fit.ship.getModifiedItemAttr("droneCapacity"),
lambda: fit.ship.getModifiedItemAttr("fighterCapacity"),
lambda: fit.ship.getModifiedItemAttr("droneBandwidth"),
lambda: fit.ship.getModifiedItemAttr("capacity"))
resMax = (
lambda: fit.ship.getModifiedItemAttr("cpuOutput"),
lambda: fit.ship.getModifiedItemAttr("powerOutput"),
lambda: fit.ship.getModifiedItemAttr("droneCapacity"),
lambda: fit.ship.getModifiedItemAttr("fighterCapacity"),
lambda: fit.ship.getModifiedItemAttr("droneBandwidth"),
lambda: fit.ship.getModifiedItemAttr("capacity"),
)
else:
resMax = None
i = 0
for resourceType in ("cpu", "pg", "droneBay", "fighterBay", "droneBandwidth", "cargoBay"):
@@ -316,11 +335,11 @@ class ResourcesViewFull(StatsView):
capitalizedType = resourceType[0].capitalize() + resourceType[1:]
gauge = getattr(self, "gauge%s%s" % (panel, capitalizedType))
resUsed = getattr(fit,"%sUsed" % resourceType)
resUsed = getattr(fit, "%sUsed" % resourceType)
gauge.SetValueRange(resUsed or 0, resMax[i]() or 0)
i+=1
i += 1
else:
capitalizedType = resourceType[0].capitalize() + resourceType[1:]
@@ -328,9 +347,10 @@ class ResourcesViewFull(StatsView):
gauge.SetValueRange(0, 0)
i+=1
i += 1
self.panel.Layout()
self.headerPanel.Layout()
ResourcesViewFull.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,29 +15,32 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui import builtinStatsViews
from gui.utils.numberFormatter import formatAmount
import locale
try:
from collections import OrderedDict
except ImportError:
from utils.compat import OrderedDict
class TargetingMiscViewFull(StatsView):
name = "targetingmiscViewFull"
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
self._cachedValues = []
def getHeaderText(self, fit):
return "Targeting && Misc"
def getTextExtentW(self, text):
width, height = self.parent.GetTextExtent( text )
width, height = self.parent.GetTextExtent(text)
return width
def populatePanel(self, contentPanel, headerPanel):
@@ -46,7 +49,7 @@ class TargetingMiscViewFull(StatsView):
self.panel = contentPanel
self.headerPanel = headerPanel
gridTargetingMisc = wx.FlexGridSizer(1, 3)
contentSizer.Add( gridTargetingMisc, 0, wx.EXPAND | wx.ALL, 0)
contentSizer.Add(gridTargetingMisc, 0, wx.EXPAND | wx.ALL, 0)
gridTargetingMisc.AddGrowableCol(0)
gridTargetingMisc.AddGrowableCol(2)
# Targeting
@@ -68,17 +71,17 @@ class TargetingMiscViewFull(StatsView):
box = wx.BoxSizer(wx.HORIZONTAL)
gridTargeting.Add(box, 0, wx.ALIGN_LEFT)
lbl = wx.StaticText(contentPanel, wx.ID_ANY, "0 %s" %unit)
lbl = wx.StaticText(contentPanel, wx.ID_ANY, "0 %s" % unit)
setattr(self, "label%s" % labelShort, lbl)
box.Add(lbl, 0, wx.ALIGN_LEFT)
self._cachedValues.append({"main": 0})
# Misc
gridTargetingMisc.Add( wx.StaticLine( contentPanel, wx.ID_ANY, style = wx.VERTICAL),0, wx.EXPAND, 3 )
gridTargetingMisc.Add(wx.StaticLine(contentPanel, wx.ID_ANY, style=wx.VERTICAL), 0, wx.EXPAND, 3)
gridMisc = wx.FlexGridSizer(5, 2)
gridMisc.AddGrowableCol(1)
gridTargetingMisc.Add(gridMisc,0 , wx.ALIGN_LEFT | wx.ALL, 5)
gridTargetingMisc.Add(gridMisc, 0, wx.ALIGN_LEFT | wx.ALL, 5)
labels = (("Speed", "Speed", "m/s"),
("Align time", "AlignTime", "s"),
@@ -98,9 +101,8 @@ class TargetingMiscViewFull(StatsView):
self._cachedValues.append({"main": 0})
def refreshPanel(self, fit):
#If we did anything interesting, we'd update our labels to reflect the new fit's stats here
# If we did anything interesting, we'd update our labels to reflect the new fit's stats here
cargoNamesOrder = OrderedDict((
("fleetHangarCapacity", "Fleet hangar"),
@@ -132,14 +134,17 @@ class TargetingMiscViewFull(StatsView):
"specialSmallShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialSmallShipHoldCapacity"),
"specialMediumShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialMediumShipHoldCapacity"),
"specialLargeShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialLargeShipHoldCapacity"),
"specialIndustrialShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialIndustrialShipHoldCapacity"),
"specialIndustrialShipHoldCapacity": lambda: fit.ship.getModifiedItemAttr(
"specialIndustrialShipHoldCapacity"),
"specialOreHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialOreHoldCapacity"),
"specialMineralHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialMineralHoldCapacity"),
"specialMaterialBayCapacity": lambda: fit.ship.getModifiedItemAttr("specialMaterialBayCapacity"),
"specialGasHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialGasHoldCapacity"),
"specialSalvageHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialSalvageHoldCapacity"),
"specialCommandCenterHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialCommandCenterHoldCapacity"),
"specialPlanetaryCommoditiesHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialPlanetaryCommoditiesHoldCapacity"),
"specialCommandCenterHoldCapacity": lambda: fit.ship.getModifiedItemAttr(
"specialCommandCenterHoldCapacity"),
"specialPlanetaryCommoditiesHoldCapacity": lambda: fit.ship.getModifiedItemAttr(
"specialPlanetaryCommoditiesHoldCapacity"),
"specialQuafeHoldCapacity": lambda: fit.ship.getModifiedItemAttr("specialQuafeHoldCapacity")
}
@@ -155,9 +160,9 @@ class TargetingMiscViewFull(StatsView):
("labelFullCargo", cargoValues, 4, 0, 9, u"m\u00B3"))
counter = 0
RADII = [("Pod",25), ("Interceptor",33), ("Frigate",38),
RADII = [("Pod", 25), ("Interceptor", 33), ("Frigate", 38),
("Destroyer", 83), ("Cruiser", 130),
("Battlecruiser", 265), ("Battleship",420),
("Battlecruiser", 265), ("Battleship", 420),
("Carrier", 3000)]
for labelName, valueDict, prec, lowest, highest, unit in stats:
label = getattr(self, labelName)
@@ -173,13 +178,13 @@ class TargetingMiscViewFull(StatsView):
# Get sum of all cargoholds except for maintenance bay
additionalCargo = sum(otherValues.values())
if additionalCargo > 0:
label.SetLabel("%s+%s %s" %(formatAmount(mainValue, prec, lowest, highest),
formatAmount(additionalCargo, prec, lowest, highest),
unit))
label.SetLabel("%s+%s %s" % (formatAmount(mainValue, prec, lowest, highest),
formatAmount(additionalCargo, prec, lowest, highest),
unit))
else:
label.SetLabel("%s %s" %(formatAmount(mainValue, prec, lowest, highest), unit))
label.SetLabel("%s %s" % (formatAmount(mainValue, prec, lowest, highest), unit))
else:
label.SetLabel("%s %s" %(formatAmount(mainValue, prec, lowest, highest), unit))
label.SetLabel("%s %s" % (formatAmount(mainValue, prec, lowest, highest), unit))
# Tooltip stuff
if fit:
if labelName == "labelScanRes":
@@ -187,25 +192,25 @@ class TargetingMiscViewFull(StatsView):
for size, radius in RADII:
left = "%.1fs" % fit.calculateLockTime(radius)
right = "%s [%d]" % (size, radius)
lockTime += "%5s\t%s\n" % (left,right)
lockTime += "%5s\t%s\n" % (left, right)
label.SetToolTip(wx.ToolTip(lockTime))
elif labelName == "labelFullSigRadius":
label.SetToolTip(wx.ToolTip("Probe Size: %.3f" % (fit.probeSize or 0) ))
label.SetToolTip(wx.ToolTip("Probe Size: %.3f" % (fit.probeSize or 0)))
elif labelName == "labelFullWarpSpeed":
label.SetToolTip(wx.ToolTip("Max Warp Distance: %.1f AU" % fit.maxWarpDistance))
elif labelName == "labelSensorStr":
if fit.jamChance > 0:
label.SetToolTip(wx.ToolTip("Type: %s\n%.1f%% Chance of Jam" % (fit.scanType, fit.jamChance)))
label.SetToolTip(
wx.ToolTip("Type: %s\n%.1f%% Chance of Jam" % (fit.scanType, fit.jamChance)))
else:
label.SetToolTip(wx.ToolTip("Type: %s" % (fit.scanType)))
label.SetToolTip(wx.ToolTip("Type: %s" % fit.scanType))
elif labelName == "labelFullAlignTime":
alignTime = "Align:\t%.3fs"%mainValue
alignTime = "Align:\t%.3fs" % mainValue
mass = 'Mass:\t{:,.0f}kg'.format(fit.ship.getModifiedItemAttr("mass"))
agility = "Agility:\t%.3fx"%(fit.ship.getModifiedItemAttr("agility") or 0)
agility = "Agility:\t%.3fx" % (fit.ship.getModifiedItemAttr("agility") or 0)
label.SetToolTip(wx.ToolTip("%s\n%s\n%s" % (alignTime, mass, agility)))
elif labelName == "labelFullCargo":
tipLines = []
tipLines.append(u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, newValues["main"]))
tipLines = [u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, newValues["main"])]
for attrName, tipAlias in cargoNamesOrder.items():
if newValues[attrName] > 0:
tipLines.append(u"{}: {:,.2f}m\u00B3".format(tipAlias, newValues[attrName]))
@@ -225,7 +230,7 @@ class TargetingMiscViewFull(StatsView):
if fit.jamChance > 0:
label.SetToolTip(wx.ToolTip("Type: %s\n%.1f%% Chance of Jam" % (fit.scanType, fit.jamChance)))
else:
label.SetToolTip(wx.ToolTip("Type: %s" % (fit.scanType)))
label.SetToolTip(wx.ToolTip("Type: %s" % fit.scanType))
else:
label.SetToolTip(wx.ToolTip(""))
elif labelName == "labelFullCargo":
@@ -233,8 +238,7 @@ class TargetingMiscViewFull(StatsView):
cachedCargo = self._cachedValues[counter]
# if you add stuff to cargo, the capacity doesn't change and thus it is still cached
# This assures us that we force refresh of cargo tooltip
tipLines = []
tipLines.append(u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, cachedCargo["main"]))
tipLines = [u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, cachedCargo["main"])]
for attrName, tipAlias in cargoNamesOrder.items():
if cachedCargo[attrName] > 0:
tipLines.append(u"{}: {:,.2f}m\u00B3".format(tipAlias, cachedCargo[attrName]))
@@ -247,4 +251,5 @@ class TargetingMiscViewFull(StatsView):
self.panel.Layout()
self.headerPanel.Layout()
TargetingMiscViewFull.register()

View File

@@ -1,2 +1,2 @@
__all__ = ["ammo", "ammoIcon", "attributeDisplay", "baseIcon", "baseName",
"capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc", "abilities"]
__all__ = ["ammo", "ammoIcon", "attributeDisplay", "baseIcon", "baseName",
"capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc", "abilities"]

View File

@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -16,17 +15,19 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.fighter import Fighter
from gui.viewColumn import ViewColumn
import gui.mainFrame
import wx
from eos.types import Fighter
class Abilities(ViewColumn):
name = "Fighter Abilities"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
@@ -41,4 +42,5 @@ class Abilities(ViewColumn):
return "None"
return ", ".join(active)
Abilities.register()

View File

@@ -1,58 +1,59 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
from gui import builtinViewColumns
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
import wx
from eos.types import Fighter
class Ammo(ViewColumn):
name = "Ammo"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
self.mask = wx.LIST_MASK_IMAGE
self.imageId = fittingView.imageList.GetImageIndex("damagePattern_small", "gui")
self.bitmap = BitmapLoader.getBitmap("damagePattern_small", "gui")
def getText(self, stuff):
if isinstance(stuff, Fighter):
# this is an experiment, not sure I like it. But it saves us from duplicating code.
col = self.columns['Fighter Abilities'](self.fittingView, {})
text = col.getText(stuff)
del col
return text
if getattr(stuff, "charge", None) is not None:
charges = stuff.numCharges
if charges > 0:
cycles = stuff.numShots
if cycles !=0 and charges != cycles:
return "%s (%d, %d cycles)" % (stuff.charge.name, charges, cycles)
else:
return "%s (%d)" % (stuff.charge.name, charges)
else:
return stuff.charge.name
return ""
def getImageId(self, mod):
return -1
Ammo.register()
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.fighter import Fighter
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
class Ammo(ViewColumn):
name = "Ammo"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
self.mask = wx.LIST_MASK_IMAGE
self.imageId = fittingView.imageList.GetImageIndex("damagePattern_small", "gui")
self.bitmap = BitmapLoader.getBitmap("damagePattern_small", "gui")
def getText(self, stuff):
if isinstance(stuff, Fighter):
# this is an experiment, not sure I like it. But it saves us from duplicating code.
col = self.columns['Fighter Abilities'](self.fittingView, {})
text = col.getText(stuff)
del col
return text
if getattr(stuff, "charge", None) is not None:
charges = stuff.numCharges
if charges > 0:
cycles = stuff.numShots
if cycles != 0 and charges != cycles:
return "%s (%d, %d cycles)" % (stuff.charge.name, charges, cycles)
else:
return "%s (%d)" % (stuff.charge.name, charges)
else:
return stuff.charge.name
return ""
def getImageId(self, mod):
return -1
Ammo.register()

View File

@@ -1,55 +1,57 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
from gui import builtinViewColumns
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
import wx
from eos.types import Module
class AmmoIcon(ViewColumn):
name = "Ammo Icon"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
self.size = 24
self.maxsize = self.size
self.mask = wx.LIST_MASK_IMAGE
self.columnText = ""
def getText(self, mod):
return ""
def getImageId(self, stuff):
if not isinstance(stuff, Module):
return -1
if stuff.charge is None:
return -1
else:
iconFile = stuff.charge.icon.iconFile if stuff.charge.icon else ""
if iconFile:
return self.fittingView.imageList.GetImageIndex(iconFile, "icons")
else:
return -1
def getToolTip(self, mod):
if isinstance(mod, Module) and mod.charge is not None:
return mod.charge.name
AmmoIcon.register()
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
from gui.viewColumn import ViewColumn
# noinspection PyPackageRequirements
import wx
from eos.saveddata.module import Module
class AmmoIcon(ViewColumn):
name = "Ammo Icon"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
self.size = 24
self.maxsize = self.size
self.mask = wx.LIST_MASK_IMAGE
self.columnText = ""
def getText(self, mod):
return ""
def getImageId(self, stuff):
if not isinstance(stuff, Module):
return -1
if stuff.charge is None:
return -1
else:
iconFile = stuff.charge.icon.iconFile if stuff.charge.icon else ""
if iconFile:
return self.fittingView.imageList.GetImageIndex(iconFile, "icons")
else:
return -1
def getToolTip(self, mod):
if isinstance(mod, Module) and mod.charge is not None:
return mod.charge.name
AmmoIcon.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,21 +15,25 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui import builtinViewColumns
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
import service
import wx
from service.attribute import Attribute
from service.market import Market
class AttributeDisplay(ViewColumn):
name = "attr"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
sAttr = service.Attribute.getInstance()
sAttr = Attribute.getInstance()
info = sAttr.getAttributeInfo(params["attribute"])
self.info = info
if params["showIcon"]:
@@ -57,9 +61,10 @@ class AttributeDisplay(ViewColumn):
self.direct = True
self.view = fittingView
originalRefresh = fittingView.refresh
sMkt = service.Market.getInstance()
#Hack into our master view and add a callback for ourselves to know when to query
sMkt = Market.getInstance()
def refresh(stuff):
# Hack into our master view and add a callback for ourselves to know when to query
self.directInfo = sMkt.directAttrRequest(stuff, info) if stuff else None
originalRefresh(stuff)
@@ -76,10 +81,10 @@ class AttributeDisplay(ViewColumn):
attr = mod.getAttribute(self.info.name)
if self.info.name == "volume":
str = (formatAmount(attr, 3, 0, 3))
str_ = (formatAmount(attr, 3, 0, 3))
if hasattr(mod, "amount"):
str = str + u"m\u00B3 (%s m\u00B3)"%(formatAmount(attr*mod.amount, 3, 0, 3))
attr = str
str_ += u"m\u00B3 (%s m\u00B3)" % (formatAmount(attr * mod.amount, 3, 0, 3))
attr = str_
if isinstance(attr, (float, int)):
attr = (formatAmount(attr, 3, 0, 3))
@@ -102,4 +107,5 @@ class AttributeDisplay(ViewColumn):
("showIcon", bool, True),
("direct", bool, False))
AttributeDisplay.register()

View File

@@ -1,44 +1,50 @@
from gui import builtinViewColumns
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
import wx
from eos.types import Drone, Fit, Module, Slot, Rack, Implant
class BaseIcon(ViewColumn):
name = "Base Icon"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
self.size = 24
self.maxsize = self.size
self.mask = wx.LIST_MASK_IMAGE
self.columnText = ""
self.shipImage = fittingView.imageList.GetImageIndex("ship_small", "gui")
def getImageId(self, stuff):
if isinstance(stuff, Drone):
return -1
if isinstance(stuff, Fit):
return self.shipImage
if isinstance(stuff, Rack):
return -1
if isinstance(stuff, Implant):
if stuff.character: # if it has a character as it's parent
return self.fittingView.imageList.GetImageIndex("character_small", "gui")
else:
return self.shipImage
if isinstance(stuff, Module):
if stuff.isEmpty:
return self.fittingView.imageList.GetImageIndex("slot_%s_small" % Slot.getName(stuff.slot).lower(), "gui")
else:
return self.loadIconFile(stuff.item.icon.iconFile if stuff.item.icon else "")
item = getattr(stuff, "item", stuff)
return self.loadIconFile(item.icon.iconFile if item.icon else "")
def loadIconFile(self, iconFile):
if iconFile:
return self.fittingView.imageList.GetImageIndex(iconFile, "icons")
else:
return -1
BaseIcon.register()
# noinspection PyPackageRequirements
import wx
from eos.saveddata.implant import Implant
from eos.saveddata.drone import Drone
from eos.saveddata.module import Module, Slot, Rack
from eos.saveddata.fit import Fit
from gui.viewColumn import ViewColumn
class BaseIcon(ViewColumn):
name = "Base Icon"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
self.size = 24
self.maxsize = self.size
self.mask = wx.LIST_MASK_IMAGE
self.columnText = ""
self.shipImage = fittingView.imageList.GetImageIndex("ship_small", "gui")
def getImageId(self, stuff):
if isinstance(stuff, Drone):
return -1
elif isinstance(stuff, Fit):
return self.shipImage
elif isinstance(stuff, Rack):
return -1
elif isinstance(stuff, Implant):
if stuff.character: # if it has a character as it's parent
return self.fittingView.imageList.GetImageIndex("character_small", "gui")
else:
return self.shipImage
elif isinstance(stuff, Module):
if stuff.isEmpty:
return self.fittingView.imageList.GetImageIndex("slot_%s_small" % Slot.getName(stuff.slot).lower(),
"gui")
else:
return self.loadIconFile(stuff.item.icon.iconFile if stuff.item.icon else "")
item = getattr(stuff, "item", stuff)
return self.loadIconFile(item.icon.iconFile if item.icon else "")
def loadIconFile(self, iconFile):
if iconFile:
return self.fittingView.imageList.GetImageIndex(iconFile, "icons")
else:
return -1
BaseIcon.register()

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
#===============================================================================
# coding: utf-8
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -16,17 +16,24 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.cargo import Cargo
from eos.saveddata.implant import Implant
from eos.saveddata.drone import Drone
from eos.saveddata.fighter import Fighter
from eos.saveddata.module import Module, Slot, Rack
from eos.saveddata.fit import Fit
from service.fit import Fit as FitSvc
from gui.viewColumn import ViewColumn
import gui.mainFrame
import wx
from eos.types import Drone, Cargo, Fit, Module, Slot, Rack, Implant, Fighter
import service
class BaseName(ViewColumn):
name = "Base Name"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
@@ -39,8 +46,9 @@ class BaseName(ViewColumn):
def getText(self, stuff):
if isinstance(stuff, Drone):
return "%dx %s" % (stuff.amount, stuff.item.name)
if isinstance(stuff, Fighter):
return "%d/%d %s" % (stuff.amountActive, stuff.getModifiedItemAttr("fighterSquadronMaxSize"), stuff.item.name)
elif isinstance(stuff, Fighter):
return "%d/%d %s" % \
(stuff.amountActive, stuff.getModifiedItemAttr("fighterSquadronMaxSize"), stuff.item.name)
elif isinstance(stuff, Cargo):
return "%dx %s" % (stuff.amount, stuff.item.name)
elif isinstance(stuff, Fit):
@@ -51,7 +59,7 @@ class BaseName(ViewColumn):
else:
return "%s (%s)" % (stuff.name, stuff.ship.item.name)
elif isinstance(stuff, Rack):
if service.Fit.getInstance().serviceFittingOptions["rackLabels"]:
if FitSvc.getInstance().serviceFittingOptions["rackLabels"]:
if stuff.slot == Slot.MODE:
return u'─ Tactical Mode ─'
else:
@@ -68,15 +76,16 @@ class BaseName(ViewColumn):
else:
item = getattr(stuff, "item", stuff)
if service.Fit.getInstance().serviceFittingOptions["showMarketShortcuts"]:
if FitSvc.getInstance().serviceFittingOptions["showMarketShortcuts"]:
marketShortcut = getattr(item, "marketShortcut", None)
if marketShortcut:
# use unicode subscript to display shortcut value
shortcut = unichr(marketShortcut+8320)+u" "
shortcut = unichr(marketShortcut + 8320) + u" "
del item.marketShortcut
return shortcut+item.name
return shortcut + item.name
return item.name
BaseName.register()

View File

@@ -1,56 +1,59 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
import service
from gui.utils.numberFormatter import formatAmount
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
from eos.types import Mode
class CapacitorUse(ViewColumn):
name = "Capacitor Usage"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
self.mask = wx.LIST_MASK_IMAGE
sAttr = service.Attribute.getInstance()
info = sAttr.getAttributeInfo("capacitorNeed")
self.imageId = fittingView.imageList.GetImageIndex("capacitorRecharge_small", "gui")
self.bitmap = BitmapLoader.getBitmap("capacitorRecharge_small", "gui")
def getText(self, mod):
if isinstance(mod, Mode):
return ""
capUse = mod.capUse
if capUse:
return "%s%s" % ("+" if capUse < 0 else "", (formatAmount(-capUse, 3, 0, 3)))
else:
return ""
def getImageId(self, mod):
return -1
def getToolTip(self, mod):
return self.name
CapacitorUse.register()
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.mode import Mode
from service.attribute import Attribute
from gui.utils.numberFormatter import formatAmount
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
class CapacitorUse(ViewColumn):
name = "Capacitor Usage"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
self.mask = wx.LIST_MASK_IMAGE
Attribute.getInstance().getAttributeInfo("capacitorNeed")
self.imageId = fittingView.imageList.GetImageIndex("capacitorRecharge_small", "gui")
self.bitmap = BitmapLoader.getBitmap("capacitorRecharge_small", "gui")
def getText(self, mod):
if isinstance(mod, Mode):
return ""
capUse = mod.capUse
if capUse:
return "%s%s" % ("+" if capUse < 0 else "", (formatAmount(-capUse, 3, 0, 3)))
else:
return ""
def getImageId(self, mod):
return -1
def getToolTip(self, mod):
return self.name
CapacitorUse.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,25 +15,28 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
from gui import builtinViewColumns
# noinspection PyPackageRequirements
import wx
from eos.saveddata.mode import Mode
from service.attribute import Attribute
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
import service
from gui.utils.numberFormatter import formatAmount
import wx
from eos.types import Mode
class MaxRange(ViewColumn):
name = "Max Range"
def __init__(self, fittingView, params = None):
if params == None:
params = {"showIcon": True,
"displayName": False}
def __init__(self, fittingView, params=None):
if params is None:
params = {"showIcon": True, "displayName": False}
ViewColumn.__init__(self, fittingView)
sAttr = service.Attribute.getInstance()
sAttr = Attribute.getInstance()
info = sAttr.getAttributeInfo("maxRange")
self.info = info
if params["showIcon"]:
@@ -71,10 +74,10 @@ class MaxRange(ViewColumn):
return -1
def getParameters(self):
return (("displayName", bool, False),
("showIcon", bool, True))
return ("displayName", bool, False), ("showIcon", bool, True)
def getToolTip(self, mod):
return "Optimal + Falloff"
MaxRange.register()

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos, Lucas Thode
#
# This file is part of pyfa.
@@ -15,17 +15,22 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.cargo import Cargo
from eos.saveddata.drone import Drone
from service.market import Market
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
from eos.types import Drone, Cargo
import wx
import service
class Price(ViewColumn):
name = "Price"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
self.mask = wx.LIST_MASK_IMAGE
@@ -36,7 +41,7 @@ class Price(ViewColumn):
if stuff.item is None or stuff.item.group.name == "Ship Modifiers":
return ""
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
price = sMkt.getPriceNow(stuff.item.ID)
if not price or not price.price or not price.isValid:
@@ -45,21 +50,22 @@ class Price(ViewColumn):
price = price.price # Set new price variable with what we need
if isinstance(stuff, Drone) or isinstance(stuff, Cargo):
price *= stuff.amount
price *= stuff.amount
return formatAmount(price, 3, 3, 9, currency=True)
def delayedText(self, mod, display, colItem):
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
def callback(item):
price = sMkt.getPriceNow(item.ID)
text = formatAmount(price.price, 3, 3, 9, currency=True) if price.price else ""
if price.failed: text += " (!)"
if price.failed:
text += " (!)"
colItem.SetText(text)
display.SetItem(colItem)
sMkt.waitForPrice(mod.item, callback)
def getImageId(self, mod):
@@ -68,4 +74,5 @@ class Price(ViewColumn):
def getToolTip(self, mod):
return self.name
Price.register()

View File

@@ -1,70 +1,71 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
import wx
import service
class PropertyDisplay(ViewColumn):
name = "prop"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
sAttr = service.Attribute.getInstance()
attributeSlave = params["attributeSlave"] or params["property"]
# This function can throw an exception if the database isn't sane
# We need to do a sanity check before this runs
info = sAttr.getAttributeInfo(attributeSlave)
self.mask = 0
self.propertyName = params["property"]
self.info = info
if params["showIcon"]:
if info.name == "power":
iconFile = "pg_small"
iconType = "gui"
else:
iconFile = info.icon.iconFile if info.icon else None
iconType = "icons"
if iconFile:
self.imageId = fittingView.imageList.GetImageIndex(iconFile, iconType)
else:
self.imageId = -1
else:
self.imageId = -1
if params["displayName"] or self.imageId == -1:
self.columnText = info.displayName if info.displayName != "" else info.name
def getText(self, stuff):
attr = getattr(stuff, self.propertyName, None)
if attr:
return (formatAmount(attr, 3, 0, 3))
else:
return ""
@staticmethod
def getParameters():
return (("property", str, None),
("attributeSlave", str, None),
("displayName", bool, False),
("showIcon", bool, True))
PropertyDisplay.register()
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
from gui.viewColumn import ViewColumn
from gui.utils.numberFormatter import formatAmount
from service.attribute import Attribute
class PropertyDisplay(ViewColumn):
name = "prop"
def __init__(self, fittingView, params):
ViewColumn.__init__(self, fittingView)
sAttr = Attribute.getInstance()
attributeSlave = params["attributeSlave"] or params["property"]
# This function can throw an exception if the database isn't sane
# We need to do a sanity check before this runs
info = sAttr.getAttributeInfo(attributeSlave)
self.mask = 0
self.propertyName = params["property"]
self.info = info
if params["showIcon"]:
if info.name == "power":
iconFile = "pg_small"
iconType = "gui"
else:
iconFile = info.icon.iconFile if info.icon else None
iconType = "icons"
if iconFile:
self.imageId = fittingView.imageList.GetImageIndex(iconFile, iconType)
else:
self.imageId = -1
else:
self.imageId = -1
if params["displayName"] or self.imageId == -1:
self.columnText = info.displayName if info.displayName != "" else info.name
def getText(self, stuff):
attr = getattr(stuff, self.propertyName, None)
if attr:
return formatAmount(attr, 3, 0, 3)
else:
return ""
@staticmethod
def getParameters():
return (("property", str, None),
("attributeSlave", str, None),
("displayName", bool, False),
("showIcon", bool, True))
PropertyDisplay.register()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,18 +15,24 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.fit import Fit
from eos.saveddata.implant import Implant
from eos.saveddata.drone import Drone
from eos.saveddata.module import Module, State as State_, Rack
from gui.viewColumn import ViewColumn
from gui.bitmapLoader import BitmapLoader
import gui.mainFrame
import wx
from eos.types import Drone, Module, Rack, Fit, Implant
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()
@@ -44,7 +50,8 @@ class State(ViewColumn):
def getImageId(self, stuff):
generic_active = self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(1).lower(), "gui")
generic_inactive = self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(-1).lower(), "gui")
generic_inactive = self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(-1).lower(),
"gui")
if isinstance(stuff, Drone):
if stuff.amountActive > 0:
@@ -57,7 +64,8 @@ class State(ViewColumn):
if stuff.isEmpty:
return -1
else:
return self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(stuff.state).lower(), "gui")
return self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(stuff.state).lower(),
"gui")
elif isinstance(stuff, Fit):
fitID = self.mainFrame.getActiveFit()
projectionInfo = stuff.getProjectionInfo(fitID)
@@ -78,4 +86,5 @@ class State(ViewColumn):
return generic_active
return generic_inactive
State.register()

View File

@@ -1 +1 @@
__all__ = ["fittingView", "implantEditor"]
__all__ = ["fittingView", "implantEditor"]

View File

@@ -1,8 +1,9 @@
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
import gui.chromeTabs
from gui.chromeTabs import EVT_NOTEBOOK_PAGE_CHANGED
import gui.mainFrame
import service
class BlankPage(wx.Panel):
def __init__(self, parent):
@@ -11,20 +12,20 @@ class BlankPage(wx.Panel):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.parent = parent
self.parent.Bind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
self.parent.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=None))
def Destroy(self):
self.parent.Unbind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged)
self.parent.Unbind(EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged)
wx.Panel.Destroy(self)
def pageChanged(self, event):
if self.parent.IsActive(self):
fitID = None
# sFit = service.Fit.getInstance()
# sFit.switchFit(fitID)
# sFit = Fit.getInstance()
# sFit.switchFit(fitID)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
event.Skip()
event.Skip()

View File

@@ -1,6 +1,7 @@
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
import service
class BaseValidator(wx.PyValidator):
def __init__(self):
@@ -15,6 +16,7 @@ class BaseValidator(wx.PyValidator):
def TransferFromWindow(self):
return True
class TextEntryValidatedDialog(wx.TextEntryDialog):
def __init__(self, parent, validator=None, *args, **kargs):
wx.TextEntryDialog.__init__(self, parent, *args, **kargs)
@@ -24,7 +26,8 @@ class TextEntryValidatedDialog(wx.TextEntryDialog):
if validator:
self.txtctrl.SetValidator(validator())
class EntityEditor (wx.Panel):
class EntityEditor(wx.Panel):
"""
Entity Editor is a panel that takes some sort of list as a source and populates a drop down with options to add/
rename/clone/delete an entity. Comes with dialogs that take user input. Classes that derive this class must override
@@ -52,7 +55,7 @@ class EntityEditor (wx.Panel):
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
if size is None:
size = btn.GetSize()
size = btn.GetSize()
btn.SetMinSize(size)
btn.SetMaxSize(size)
@@ -135,8 +138,9 @@ class EntityEditor (wx.Panel):
def OnDelete(self, event):
dlg = wx.MessageDialog(self,
"Do you really want to delete the {} {}?".format(self.getActiveEntity().name, self.entityName),
"Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
"Do you really want to delete the {} {}?".format(self.getActiveEntity().name,
self.entityName),
"Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
dlg.CenterOnParent()
if dlg.ShowModal() == wx.ID_YES:
@@ -171,4 +175,4 @@ class EntityEditor (wx.Panel):
return False
self.Parent.Show()
return True
return True

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,29 +15,36 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
# noinspection PyPackageRequirements
import wx.lib.newevent
import service
import gui.mainFrame
import gui.marketBrowser
import gui.display as d
from gui.contextMenu import ContextMenu
import gui.shipBrowser
import gui.multiSwitch
from eos.types import Slot, Rack, Module, Mode
from eos.saveddata.mode import Mode
from eos.saveddata.module import Module, Slot, Rack
from gui.builtinViewColumns.state import State
from gui.bitmapLoader import BitmapLoader
import gui.builtinViews.emptyView
from gui.utils.exportHtml import exportHtml
from logging import getLogger, Formatter
from logbook import Logger
from gui.chromeTabs import EVT_NOTEBOOK_PAGE_CHANGED
from service.fit import Fit
from service.market import Market
import gui.globalEvents as GE
logger = getLogger(__name__)
pyfalog = Logger(__name__)
#Tab spawning handler
# Tab spawning handler
class FitSpawner(gui.multiSwitch.TabSpawner):
def __init__(self, multiSwitch):
self.multiSwitch = multiSwitch
@@ -54,11 +61,12 @@ class FitSpawner(gui.multiSwitch.TabSpawner):
self.multiSwitch.SetSelection(index)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=event.fitID))
break
except:
pass
except Exception as e:
pyfalog.critical("Caught exception in fitSelected")
pyfalog.critical(e)
if count < 0:
startup = getattr(event, "startup", False) # see OpenFitsThread in gui.mainFrame
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
openFitInNew = sFit.serviceFittingOptions["openFitInNew"]
mstate = wx.GetMouseState()
@@ -87,22 +95,25 @@ class FitSpawner(gui.multiSwitch.TabSpawner):
self.multiSwitch.AddPage(view)
view.handleDrag(type, fitID)
FitSpawner.register()
#Drag'n'drop handler
class FittingViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
# Drag'n'drop handler
class FittingViewDrop(wx.PyDropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(FittingViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
class FittingView(d.Display):
DEFAULT_COLS = ["State",
@@ -119,7 +130,7 @@ class FittingView(d.Display):
]
def __init__(self, parent):
d.Display.__init__(self, parent, size = (0,0), style = wx.BORDER_NONE)
d.Display.__init__(self, parent, size=(0, 0), style=wx.BORDER_NONE)
self.Show(False)
self.parent = parent
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
@@ -129,7 +140,7 @@ class FittingView(d.Display):
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
if "__WXGTK__" in wx.PlatformInfo:
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
@@ -150,7 +161,7 @@ class FittingView(d.Display):
self.Bind(wx.EVT_SHOW, self.OnShow)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
self.parent.Bind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
self.parent.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
def OnLeaveWindow(self, event):
self.SetToolTip(None)
@@ -178,13 +189,13 @@ class FittingView(d.Display):
event.Skip()
def handleListDrag(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two items:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "fitting":
self.swapItems(x, y, int(data[1]))
@@ -194,12 +205,12 @@ class FittingView(d.Display):
self.addModule(x, y, int(data[1]))
def handleDrag(self, type, fitID):
#Those are drags coming from pyfa sources, NOT builtin wx drags
# Those are drags coming from pyfa sources, NOT builtin wx drags
if type == "fit":
wx.PostEvent(self.mainFrame, gui.shipBrowser.FitSelected(fitID=fitID))
def Destroy(self):
self.parent.Unbind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged)
self.parent.Unbind(EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged)
self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.fitChanged)
self.mainFrame.Unbind(gui.shipBrowser.EVT_FIT_RENAMED, handler=self.fitRenamed)
self.mainFrame.Unbind(gui.shipBrowser.EVT_FIT_REMOVED, handler=self.fitRemoved)
@@ -210,7 +221,7 @@ class FittingView(d.Display):
def pageChanged(self, event):
if self.parent.IsActive(self):
fitID = self.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.switchFit(fitID)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -224,11 +235,11 @@ class FittingView(d.Display):
if row != -1 and row not in self.blanks:
data = wx.PyTextDataObject()
data.SetText("fitting:"+str(self.mods[row].position))
data.SetText("fitting:" + str(self.mods[row].modPosition))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
res = dropSource.DoDragDrop()
dropSource.DoDragDrop()
def getSelectedMods(self):
sel = []
@@ -239,25 +250,24 @@ class FittingView(d.Display):
return sel
def kbEvent(self,event):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
row = self.GetFirstSelected()
firstSel = row
while row != -1:
if row not in self.blanks:
self.removeModule(self.mods[row])
self.Select(row,0)
self.Select(row, 0)
row = self.GetNextSelected(row)
event.Skip()
def fitRemoved(self, event):
'''
"""
If fit is removed and active, the page is deleted.
We also refresh the fit of the new current page in case
delete fit caused change in stats (projected)
'''
"""
fitID = event.fitID
if fitID == self.getActiveFit():
@@ -265,10 +275,11 @@ class FittingView(d.Display):
try:
# Sometimes there is no active page after deletion, hence the try block
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.refreshFit(self.getActiveFit())
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID))
except wx._core.PyDeadObjectError:
pyfalog.warning("Caught dead object")
pass
event.Skip()
@@ -285,7 +296,7 @@ class FittingView(d.Display):
fitID = event.fitID
startup = getattr(event, "startup", False)
self.activeFitID = fitID
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
self.updateTab()
if not startup or startup == 2: # see OpenFitsThread in gui.mainFrame
self.Show(fitID is not None)
@@ -296,7 +307,7 @@ class FittingView(d.Display):
event.Skip()
def updateTab(self):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.getActiveFit(), basic=True)
bitmap = BitmapLoader.getImage("race_%s_small" % fit.ship.item.race, "gui")
@@ -310,8 +321,8 @@ class FittingView(d.Display):
if self.parent.IsActive(self):
itemID = event.itemID
fitID = self.activeFitID
if fitID != None:
sFit = service.Fit.getInstance()
if fitID is not None:
sFit = Fit.getInstance()
if sFit.isAmmo(itemID):
modules = []
sel = self.GetFirstSelected()
@@ -340,7 +351,7 @@ class FittingView(d.Display):
self.click(event)
def removeModule(self, module):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.activeFitID)
populate = sFit.removeModule(self.activeFitID, fit.modules.index(module))
@@ -349,36 +360,36 @@ class FittingView(d.Display):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID))
def addModule(self, x, y, srcIdx):
'''Add a module from the market browser'''
mstate = wx.GetMouseState()
"""Add a module from the market browser"""
dstRow, _ = self.HitTest((x, y))
if dstRow != -1 and dstRow not in self.blanks:
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
moduleChanged = sFit.changeModule(fitID, self.mods[dstRow].position, srcIdx)
moduleChanged = sFit.changeModule(fitID, self.mods[dstRow].modPosition, srcIdx)
if moduleChanged is None:
# the new module doesn't fit in specified slot, try to simply append it
wx.PostEvent(self.mainFrame, gui.marketBrowser.ItemSelected(itemID=srcIdx))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
def swapCargo(self, x, y, srcIdx):
'''Swap a module from cargo to fitting window'''
"""Swap a module from cargo to fitting window"""
mstate = wx.GetMouseState()
dstRow, _ = self.HitTest((x, y))
if dstRow != -1 and dstRow not in self.blanks:
module = self.mods[dstRow]
sFit = service.Fit.getInstance()
sFit.moveCargoToModule(self.mainFrame.getActiveFit(), module.position, srcIdx, mstate.CmdDown() and module.isEmpty)
sFit = Fit.getInstance()
sFit.moveCargoToModule(self.mainFrame.getActiveFit(), module.modPosition, srcIdx,
mstate.CmdDown() and module.isEmpty)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
def swapItems(self, x, y, srcIdx):
'''Swap two modules in fitting window'''
"""Swap two modules in fitting window"""
mstate = wx.GetMouseState()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.activeFitID)
if mstate.CmdDown():
@@ -389,6 +400,7 @@ class FittingView(d.Display):
dstRow, _ = self.HitTest((x, y))
if dstRow != -1 and dstRow not in self.blanks:
mod1 = fit.modules[srcIdx]
mod2 = self.mods[dstRow]
@@ -396,35 +408,38 @@ class FittingView(d.Display):
if mod1.slot != mod2.slot:
return
if clone and mod2.isEmpty:
sFit.cloneModule(self.mainFrame.getActiveFit(), mod1.position, mod2.position)
else:
sFit.swapModules(self.mainFrame.getActiveFit(), mod1.position, mod2.position)
if getattr(mod2, "modPosition"):
if clone and mod2.isEmpty:
sFit.cloneModule(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)
else:
sFit.swapModules(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
else:
pyfalog.error("Missing module position for: {0}", str(getattr(mod2, "ID", "Unknown")))
def generateMods(self):
'''
"""
Generate module list.
This also injects dummy modules to visually separate racks. These modules are only
known to the display, and not the backend, so it's safe.
'''
"""
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.activeFitID)
slotOrder = [Slot.SUBSYSTEM, Slot.HIGH, Slot.MED, Slot.LOW, Slot.RIG, Slot.SERVICE]
if fit is not None:
self.mods = fit.modules[:]
self.mods.sort(key=lambda mod: (slotOrder.index(mod.slot), mod.position))
self.mods.sort(key=lambda _mod: (slotOrder.index(_mod.slot), _mod.position))
# Blanks is a list of indexes that mark non-module positions (such
# as Racks and tactical Modes. This allows us to skip over common
# module operations such as swapping, removing, copying, etc. that
# would otherwise cause complications
self.blanks = [] # preliminary markers where blanks will be inserted
self.blanks = [] # preliminary markers where blanks will be inserted
if sFit.serviceFittingOptions["rackSlots"]:
# flag to know when to add blanks, based on previous slot
@@ -434,12 +449,12 @@ class FittingView(d.Display):
for i, mod in enumerate(self.mods):
if mod.slot != slotDivider:
slotDivider = mod.slot
self.blanks.append((i, slotDivider)) # where and what
self.blanks.append((i, slotDivider)) # where and what
# second loop modifies self.mods, rewrites self.blanks to represent actual index of blanks
for i, (x, slot) in enumerate(self.blanks):
self.blanks[i] = x+i # modify blanks with actual index
self.mods.insert(x+i, Rack.buildRack(slot))
self.blanks[i] = x + i # modify blanks with actual index
self.mods.insert(x + i, Rack.buildRack(slot))
if fit.mode:
# Modes are special snowflakes and need a little manual loving
@@ -470,7 +485,7 @@ class FittingView(d.Display):
self.Show(self.activeFitID is not None and self.activeFitID == event.fitID)
except wx._core.PyDeadObjectError:
pass
pyfalog.warning("Caught dead object")
finally:
event.Skip()
@@ -483,7 +498,7 @@ class FittingView(d.Display):
if self.activeFitID is None:
return
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
selection = []
sel = self.GetFirstSelected()
contexts = []
@@ -497,7 +512,7 @@ class FittingView(d.Display):
itemContext = "Tactical Mode"
fullContext = (srcContext, itemContext)
if not srcContext in tuple(fCtxt[0] for fCtxt in contexts):
if srcContext not in tuple(fCtxt[0] for fCtxt in contexts):
contexts.append(fullContext)
selection.append(mod)
@@ -506,22 +521,21 @@ class FittingView(d.Display):
srcContext = "fittingModule"
itemContext = sMkt.getCategoryByItem(mod.item).name
fullContext = (srcContext, itemContext)
if not srcContext in tuple(fCtxt[0] for fCtxt in contexts):
if srcContext not in tuple(fCtxt[0] for fCtxt in contexts):
contexts.append(fullContext)
if mod.charge is not None:
srcContext = "fittingCharge"
itemContext = sMkt.getCategoryByItem(mod.charge).name
fullContext = (srcContext, itemContext)
if not srcContext in tuple(fCtxt[0] for fCtxt in contexts):
if srcContext not in tuple(fCtxt[0] for fCtxt in contexts):
contexts.append(fullContext)
selection.append(mod)
sel = self.GetNextSelected(sel)
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.activeFitID)
contexts.append(("fittingShip", "Ship" if not fit.isStructure else "Citadel"))
@@ -530,13 +544,13 @@ class FittingView(d.Display):
self.PopupMenu(menu)
def click(self, event):
'''
"""
Handle click event on modules.
This is only useful for the State column. If multiple items are selected,
and we have clicked the State column, iterate through the selections and
change State
'''
"""
row, _, col = self.HitTestSubItem(event.Position)
# only do State column and ignore invalid rows
@@ -544,7 +558,7 @@ class FittingView(d.Display):
sel = []
curr = self.GetFirstSelected()
while curr != -1 and row not in self.blanks :
while curr != -1 and row not in self.blanks:
sel.append(curr)
curr = self.GetNextSelected(curr)
@@ -553,7 +567,7 @@ class FittingView(d.Display):
else:
mods = self.getSelectedMods()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
ctrl = wx.GetMouseState().CmdDown() or wx.GetMouseState().MiddleDown()
click = "ctrl" if ctrl is True else "right" if event.GetButton() == 3 else "left"
@@ -578,16 +592,16 @@ class FittingView(d.Display):
return self.slotColourMap.get(slot) or self.GetBackgroundColour()
def refresh(self, stuff):
'''
"""
Displays fitting
Sends data to d.Display.refresh where the rows and columns are set up, then does a
bit of post-processing (colors)
'''
"""
self.Freeze()
d.Display.refresh(self, stuff)
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.activeFitID)
slotMap = {}
@@ -624,40 +638,44 @@ class FittingView(d.Display):
if 'wxMac' in wx.PlatformInfo:
try:
self.MakeSnapshot()
except:
pass
except Exception as e:
pyfalog.critical("Failed to make snapshot")
pyfalog.critical(e)
def OnShow(self, event):
if event.GetShow():
try:
self.MakeSnapshot()
except:
pass
except Exception as e:
pyfalog.critical("Failed to make snapshot")
pyfalog.critical(e)
event.Skip()
def Snapshot(self):
return self.FVsnapshot
def MakeSnapshot(self, maxColumns = 1337):
# noinspection PyPropertyAccess
def MakeSnapshot(self, maxColumns=1337):
if self.FVsnapshot:
del self.FVsnapshot
tbmp = wx.EmptyBitmap(16,16)
tbmp = wx.EmptyBitmap(16, 16)
tdc = wx.MemoryDC()
tdc.SelectObject(tbmp)
font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
tdc.SetFont(font)
columnsWidths = []
for i in xrange(len(self.DEFAULT_COLS)):
for i in range(len(self.DEFAULT_COLS)):
columnsWidths.append(0)
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
try:
fit = sFit.getFit(self.activeFitID)
except:
return
except Exception as e:
pyfalog.critical("Failed to get fit")
pyfalog.critical(e)
if fit is None:
return
@@ -671,28 +689,27 @@ class FittingView(d.Display):
isize = 16
headerSize = max(isize, tdc.GetTextExtent("W")[0]) + padding * 2
maxWidth = 0
maxRowHeight = isize
rows = 0
for id,st in enumerate(self.mods):
for st in self.mods:
for i, col in enumerate(self.activeColumns):
if i>maxColumns:
if i > maxColumns:
break
name = col.getText(st)
if not isinstance(name, basestring):
name = ""
nx,ny = tdc.GetTextExtent(name)
nx, ny = tdc.GetTextExtent(name)
imgId = col.getImageId(st)
cw = 0
if imgId != -1:
cw += isize + padding
if name != "":
cw += nx + 4*padding
cw += nx + 4 * padding
if imgId == -1 and name == "":
cw += isize +padding
cw += isize + padding
maxRowHeight = max(ny, maxRowHeight)
columnsWidths[i] = max(columnsWidths[i], cw)
@@ -701,7 +718,7 @@ class FittingView(d.Display):
render = wx.RendererNative.Get()
#Fix column widths (use biggest between header or items)
# Fix column widths (use biggest between header or items)
for i, col in enumerate(self.activeColumns):
if i > maxColumns:
@@ -719,26 +736,23 @@ class FittingView(d.Display):
opts.m_labelText = name
if imgId != -1:
opts.m_labelBitmap = wx.EmptyBitmap(isize,isize)
opts.m_labelBitmap = wx.EmptyBitmap(isize, isize)
width = render.DrawHeaderButton(self, tdc, (0, 0, 16, 16),
sortArrow = wx.HDR_SORT_ICON_NONE, params = opts)
width = render.DrawHeaderButton(self, tdc, (0, 0, 16, 16), sortArrow=wx.HDR_SORT_ICON_NONE, params=opts)
columnsWidths[i] = max(columnsWidths[i], width)
tdc.SelectObject(wx.NullBitmap)
maxWidth = padding * 2
for i in xrange(len(self.DEFAULT_COLS)):
for i in range(len(self.DEFAULT_COLS)):
if i > maxColumns:
break
maxWidth += columnsWidths[i]
mdc = wx.MemoryDC()
mbmp = wx.EmptyBitmap(maxWidth, (maxRowHeight) * rows + padding*4 + headerSize)
mbmp = wx.EmptyBitmap(maxWidth, maxRowHeight * rows + padding * 4 + headerSize)
mdc.SelectObject(mbmp)
@@ -768,8 +782,7 @@ class FittingView(d.Display):
bmp = col.bitmap
opts.m_labelBitmap = bmp
width = render.DrawHeaderButton (self, mdc, (cx, padding, columnsWidths[i], headerSize), wx.CONTROL_CURRENT,
sortArrow = wx.HDR_SORT_ICON_NONE, params = opts)
render.DrawHeaderButton(self, mdc, (cx, padding, columnsWidths[i], headerSize), wx.CONTROL_CURRENT, sortArrow=wx.HDR_SORT_ICON_NONE, params=opts)
cx += columnsWidths[i]
@@ -779,15 +792,15 @@ class FittingView(d.Display):
mdc.SetPen(pen)
mdc.SetBrush(brush)
cy = padding*2 + headerSize
for id,st in enumerate(self.mods):
cy = padding * 2 + headerSize
for st in self.mods:
cx = padding
if slotMap[st.slot]:
mdc.DrawRectangle(cx,cy,maxWidth - cx,maxRowHeight)
mdc.DrawRectangle(cx, cy, maxWidth - cx, maxRowHeight)
for i, col in enumerate(self.activeColumns):
if i>maxColumns:
if i > maxColumns:
break
name = col.getText(st)
@@ -798,14 +811,14 @@ class FittingView(d.Display):
tcx = cx
if imgId != -1:
self.imageList.Draw(imgId,mdc,cx,cy,wx.IMAGELIST_DRAW_TRANSPARENT,False)
self.imageList.Draw(imgId, mdc, cx, cy, wx.IMAGELIST_DRAW_TRANSPARENT, False)
tcx += isize + padding
if name != "":
nx,ny = mdc.GetTextExtent(name)
nx, ny = mdc.GetTextExtent(name)
rect = wx.Rect()
rect.top = cy
rect.left = cx + 2*padding
rect.left = cx + 2 * padding
rect.width = nx
rect.height = maxRowHeight + padding
mdc.DrawLabel(name, rect, wx.ALIGN_CENTER_VERTICAL)
@@ -817,4 +830,4 @@ class FittingView(d.Display):
mdc.SelectObject(wx.NullBitmap)
self.FVsnapshot = mbmp
self.FVsnapshot = mbmp

View File

@@ -1,12 +1,16 @@
# noinspection PyPackageRequirements
import wx
import service
import gui.display as d
from gui.bitmapLoader import BitmapLoader
import gui.PFSearchBox as SBox
from gui.marketBrowser import SearchBox
# noinspection PyPackageRequirements
from wx.lib.buttons import GenBitmapButton
class BaseImplantEditorView (wx.Panel):
from service.market import Market
import gui.display as d
import gui.PFSearchBox as SBox
from gui.bitmapLoader import BitmapLoader
from gui.marketBrowser import SearchBox
class BaseImplantEditorView(wx.Panel):
def addMarketViewImage(self, iconFile):
if iconFile is None:
return -1
@@ -17,7 +21,8 @@ class BaseImplantEditorView (wx.Panel):
return self.availableImplantsImageList.Add(bitmap)
def __init__(self, parent):
wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TAB_TRAVERSAL)
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
style=wx.TAB_TRAVERSAL)
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
pmainSizer = wx.BoxSizer(wx.HORIZONTAL)
@@ -46,32 +51,32 @@ class BaseImplantEditorView (wx.Panel):
availableSizer.Add(self.availableImplantsTree, 1, wx.EXPAND)
pmainSizer.Add(availableSizer, 1, wx.ALL | wx.EXPAND, 5)
buttonSizer = wx.BoxSizer(wx.VERTICAL)
buttonSizer.AddSpacer(( 0, 0), 1)
buttonSizer.AddSpacer((0, 0), 1)
self.btnAdd = GenBitmapButton(self, wx.ID_ADD, BitmapLoader.getBitmap("fit_add_small", "gui"), style = wx.BORDER_NONE)
self.btnAdd = GenBitmapButton(self, wx.ID_ADD, BitmapLoader.getBitmap("fit_add_small", "gui"),
style=wx.BORDER_NONE)
buttonSizer.Add(self.btnAdd, 0)
self.btnRemove = GenBitmapButton(self, wx.ID_REMOVE, BitmapLoader.getBitmap("fit_delete_small", "gui"), style = wx.BORDER_NONE)
self.btnRemove = GenBitmapButton(self, wx.ID_REMOVE, BitmapLoader.getBitmap("fit_delete_small", "gui"),
style=wx.BORDER_NONE)
buttonSizer.Add(self.btnRemove, 0)
buttonSizer.AddSpacer(( 0, 0), 1)
buttonSizer.AddSpacer((0, 0), 1)
pmainSizer.Add(buttonSizer, 0, wx.EXPAND, 0)
characterImplantSizer = wx.BoxSizer(wx.VERTICAL)
self.pluggedImplantsTree = AvailableImplantsView(self)
characterImplantSizer.Add(self.pluggedImplantsTree, 1, wx.ALL|wx.EXPAND, 5)
characterImplantSizer.Add(self.pluggedImplantsTree, 1, wx.ALL | wx.EXPAND, 5)
pmainSizer.Add(characterImplantSizer, 1, wx.EXPAND, 5)
self.SetSizer(pmainSizer)
# Populate the market tree
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
for mktGrp in sMkt.getImplantTree():
iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(mktGrp))
childId = self.availableImplantsTree.AppendItem(root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
@@ -80,13 +85,13 @@ class BaseImplantEditorView (wx.Panel):
self.availableImplantsTree.SortChildren(self.availableRoot)
#Bind the event to replace dummies by real data
# Bind the event to replace dummies by real data
self.availableImplantsTree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
self.availableImplantsTree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.itemSelected)
self.itemView.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemSelected)
#Bind add & remove buttons
# Bind add & remove buttons
self.btnAdd.Bind(wx.EVT_BUTTON, self.itemSelected)
self.btnRemove.Bind(wx.EVT_BUTTON, self.removeItem)
@@ -126,7 +131,7 @@ class BaseImplantEditorView (wx.Panel):
def expandLookup(self, event):
tree = self.availableImplantsTree
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
parent = event.Item
child, _ = tree.GetFirstChild(parent)
text = tree.GetItemText(child)
@@ -136,7 +141,7 @@ class BaseImplantEditorView (wx.Panel):
# if the dummy item is a market group, replace with actual market groups
if text == "dummy":
#Add 'real stoof!' instead
# Add 'real stoof!' instead
currentMktGrp = sMkt.getMarketGroup(tree.GetPyData(parent), eager="children")
for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(childMktGrp))
@@ -194,6 +199,7 @@ class BaseImplantEditorView (wx.Panel):
self.removeImplantFromContext(self.implants[pos])
self.update()
class AvailableImplantsView(d.Display):
DEFAULT_COLS = ["attr:implantness",
"Base Icon",
@@ -203,6 +209,7 @@ class AvailableImplantsView(d.Display):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL)
self.Bind(wx.EVT_LEFT_DCLICK, parent.removeItem)
class ItemView(d.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
@@ -235,7 +242,7 @@ class ItemView(d.Display):
self.update(self.items)
def scheduleSearch(self, event=None):
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
search = self.searchBox.GetLineText(0)
# Make sure we do not count wildcard as search symbol
@@ -255,4 +262,4 @@ class ItemView(d.Display):
self.items = sorted(list(items), key=lambda i: i.name)
self.update(self.items)
self.update(self.items)

View File

@@ -1,35 +1,38 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
from gui.bitmapLoader import BitmapLoader
class CachingImageList(wx.ImageList):
def __init__(self, width, height):
wx.ImageList.__init__(self, width, height)
self.map = {}
def GetImageIndex(self, *loaderArgs):
id = self.map.get(loaderArgs)
if id is None:
bitmap = BitmapLoader.getBitmap(*loaderArgs)
if bitmap is None:
return -1
id = self.map[loaderArgs] = wx.ImageList.Add(self,bitmap)
return id
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
class CachingImageList(wx.ImageList):
def __init__(self, width, height):
wx.ImageList.__init__(self, width, height)
self.map = {}
def GetImageIndex(self, *loaderArgs):
id_ = self.map.get(loaderArgs)
if id_ is None:
bitmap = BitmapLoader.getBitmap(*loaderArgs)
if bitmap is None:
return -1
id_ = self.map[loaderArgs] = wx.ImageList.Add(self, bitmap)
return id_

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,31 +15,34 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import service
import gui.display as d
import gui.marketBrowser as mb
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
import globalEvents as GE
from service.fit import Fit
from service.market import Market
class CargoViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def __init__(self, dropFn, *args, **kwargs):
super(CargoViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
# @todo: Was copied form another class and modified. Look through entire file, refine
# @todo: Was copied form another class and modified. Look through entire file, refine
class CargoView(d.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
@@ -58,24 +61,24 @@ class CargoView(d.Display):
self.SetDropTarget(CargoViewDrop(self.handleListDrag))
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
if "__WXGTK__" in wx.PlatformInfo:
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
def handleListDrag(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "fitting":
self.swapModule(x, y, int(data[1]))
elif data[0] == "market":
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.addCargo(self.mainFrame.getActiveFit(), int(data[1]), 1)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
@@ -84,17 +87,17 @@ class CargoView(d.Display):
if row != -1:
data = wx.PyTextDataObject()
data.SetText("cargo:"+str(row))
data.SetText("cargo:" + str(row))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
res = dropSource.DoDragDrop()
dropSource.DoDragDrop()
def kbEvent(self,event):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
row = self.GetFirstSelected()
if row != -1:
sFit.removeCargo(fitID, self.GetItemData(row))
@@ -102,8 +105,8 @@ class CargoView(d.Display):
event.Skip()
def swapModule(self, x, y, modIdx):
'''Swap a module from fitting window with cargo'''
sFit = service.Fit.getInstance()
"""Swap a module from fitting window with cargo"""
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
dstRow, _ = self.HitTest((x, y))
mstate = wx.GetMouseState()
@@ -111,26 +114,26 @@ class CargoView(d.Display):
# Gather module information to get position
module = fit.modules[modIdx]
if dstRow != -1: # we're swapping with cargo
if mstate.CmdDown(): # if copying, append to cargo
if dstRow != -1: # we're swapping with cargo
if mstate.CmdDown(): # if copying, append to cargo
sFit.addCargo(self.mainFrame.getActiveFit(), module.item.ID)
else: # else, move / swap
else: # else, move / swap
sFit.moveCargoToModule(self.mainFrame.getActiveFit(), module.position, dstRow)
else: # dragging to blank spot, append
else: # dragging to blank spot, append
sFit.addCargo(self.mainFrame.getActiveFit(), module.item.ID)
if not mstate.CmdDown(): # if not copying, remove module
sFit.removeModule(self.mainFrame.getActiveFit(), module.position)
if not mstate.CmdDown(): # if not copying, remove module
sFit.removeModule(self.mainFrame.getActiveFit(), module.position)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
#Clear list and get out if current fitId is None
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
@@ -139,7 +142,8 @@ class CargoView(d.Display):
self.original = fit.cargo if fit is not None else None
self.cargo = stuff = fit.cargo if fit is not None else None
if stuff is not None: stuff.sort(key=lambda cargo: cargo.itemID)
if stuff is not None:
stuff.sort(key=lambda cargo: cargo.itemID)
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
@@ -161,7 +165,7 @@ class CargoView(d.Display):
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
cargo = self.cargo[self.GetItemData(row)]
sFit.removeCargo(fitID, self.original.index(cargo))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -174,11 +178,11 @@ class CargoView(d.Display):
def spawnMenu(self):
sel = self.GetFirstSelected()
if sel != -1:
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
cargo = fit.cargo[sel]
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
sourceContext = "cargoItem"
itemContext = sMkt.getCategoryByItem(cargo.item).name

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,18 +15,26 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
# noinspection PyPackageRequirements
import wx.lib.newevent
# noinspection PyPackageRequirements
import wx.gizmos
from gui.bitmapLoader import BitmapLoader
import service
from gui.contextMenu import ContextMenu
import gui.globalEvents as GE
from gui.builtinViews.implantEditor import BaseImplantEditorView
from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
from service.fit import Fit
from service.character import Character
from service.network import AuthenticationError, TimeoutError
from service.market import Market
from logbook import Logger
pyfalog = Logger(__name__)
class CharacterTextValidor(BaseValidator):
@@ -49,6 +57,7 @@ class CharacterTextValidor(BaseValidator):
return True
except ValueError, e:
pyfalog.error(e)
wx.MessageBox(u"{}".format(e), "Error")
textCtrl.SetFocus()
return False
@@ -60,7 +69,7 @@ class CharacterEntityEditor(EntityEditor):
self.SetEditorValidator(CharacterTextValidor)
def getEntitiesFromContext(self):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
charList = sorted(sChar.getCharacterList(), key=lambda c: c.name)
# Do some processing to ensure that we have All 0 and All 5 at the top
@@ -76,35 +85,35 @@ class CharacterEntityEditor(EntityEditor):
return charList
def DoNew(self, name):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
return sChar.new(name)
def DoRename(self, entity, name):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
sChar.rename(entity, name)
def DoCopy(self, entity, name):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
copy = sChar.copy(entity)
sChar.rename(copy, name)
return copy
def DoDelete(self, entity):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
sChar.delete(entity)
class CharacterEditor(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__ (self, parent, id=wx.ID_ANY, title=u"pyfa: Character Editor", pos=wx.DefaultPosition,
size=wx.Size(640, 600), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=u"pyfa: Character Editor", pos=wx.DefaultPosition,
size=wx.Size(640, 600), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
i = wx.IconFromBitmap(BitmapLoader.getBitmap("character_small", "gui"))
self.SetIcon(i)
self.mainFrame = parent
#self.disableWin = wx.WindowDisabler(self)
sFit = service.Fit.getInstance()
# self.disableWin = wx.WindowDisabler(self)
sFit = Fit.getInstance()
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
@@ -158,6 +167,8 @@ class CharacterEditor(wx.Frame):
self.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList)
self.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged)
self.charChanged(None)
def btnRestrict(self):
char = self.entityEditor.getActiveEntity()
@@ -176,12 +187,12 @@ class CharacterEditor(wx.Frame):
event.Skip()
def editingFinished(self, event):
#del self.disableWin
# del self.disableWin
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
self.Destroy()
def saveChar(self, event):
sChr = service.Character.getInstance()
sChr = Character.getInstance()
char = self.entityEditor.getActiveEntity()
sChr.saveCharacter(char.ID)
wx.PostEvent(self, GE.CharListUpdated())
@@ -192,13 +203,13 @@ class CharacterEditor(wx.Frame):
dlg.ShowModal()
def revertChar(self, event):
sChr = service.Character.getInstance()
sChr = Character.getInstance()
char = self.entityEditor.getActiveEntity()
sChr.revertCharacter(char.ID)
wx.PostEvent(self, GE.CharListUpdated())
def closeEvent(self, event):
#del self.disableWin
# del self.disableWin
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
self.Destroy()
@@ -223,7 +234,7 @@ class CharacterEditor(wx.Frame):
event.Skip()
def Destroy(self):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
if fitID is not None:
sFit.clearFit(fitID)
@@ -231,18 +242,35 @@ class CharacterEditor(wx.Frame):
wx.Frame.Destroy(self)
class SkillTreeView (wx.Panel):
class SkillTreeView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TAB_TRAVERSAL)
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
style=wx.TAB_TRAVERSAL)
self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
pmainSizer = wx.BoxSizer(wx.VERTICAL)
self.clonesChoice = wx.Choice(self, wx.ID_ANY, style=0)
i = self.clonesChoice.Append("Omega Clone", None)
self.clonesChoice.SetSelection(i)
pmainSizer.Add(self.clonesChoice, 0, wx.ALL | wx.EXPAND, 5)
sChar = Character.getInstance()
self.alphaClones = sChar.getAlphaCloneList()
char = self.charEditor.entityEditor.getActiveEntity()
for clone in self.alphaClones:
i = self.clonesChoice.Append(clone.alphaCloneName, clone.ID)
if clone.ID == char.alphaCloneID:
self.clonesChoice.SetSelection(i)
self.clonesChoice.Bind(wx.EVT_CHOICE, self.cloneChanged)
tree = self.skillTreeListCtrl = wx.gizmos.TreeListCtrl(self, wx.ID_ANY, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
pmainSizer.Add(tree, 1, wx.EXPAND | wx.ALL, 5)
self.imageList = wx.ImageList(16, 16)
tree.SetImageList(self.imageList)
self.skillBookImageId = self.imageList.Add(BitmapLoader.getBitmap("skill_small", "gui"))
@@ -262,7 +290,7 @@ class SkillTreeView (wx.Panel):
tree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.scheduleMenu)
# bind the Character selection event
self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.populateSkillTree)
self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged)
self.charEditor.Bind(GE.CHAR_LIST_UPDATED, self.populateSkillTree)
srcContext = "skillItem"
@@ -286,7 +314,6 @@ class SkillTreeView (wx.Panel):
self.revertID = wx.NewId()
self.levelChangeMenu.Append(self.revertID, "Revert")
self.saveID = wx.NewId()
self.levelChangeMenu.Append(self.saveID, "Save")
@@ -295,11 +322,30 @@ class SkillTreeView (wx.Panel):
self.Layout()
def cloneChanged(self, event):
sChar = Character.getInstance()
sChar.setAlphaClone(self.charEditor.entityEditor.getActiveEntity(), event.ClientData)
self.populateSkillTree()
def charChanged(self, event=None):
char = self.charEditor.entityEditor.getActiveEntity()
for i in range(self.clonesChoice.GetCount()):
cloneID = self.clonesChoice.GetClientData(i)
if char.alphaCloneID == cloneID:
self.clonesChoice.SetSelection(i)
self.populateSkillTree(event)
def populateSkillTree(self, event=None):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
char = self.charEditor.entityEditor.getActiveEntity()
dirtyGroups = set([skill.item.group.ID for skill in char.dirtySkills])
if char.name in ("All 0", "All 5"):
self.clonesChoice.Disable()
else:
self.clonesChoice.Enable()
groups = sChar.getSkillGroups()
imageId = self.skillBookImageId
root = self.root
@@ -325,8 +371,8 @@ class SkillTreeView (wx.Panel):
if tree.GetItemText(child) == "dummy":
tree.Delete(child)
#Get the real intrestin' stuff
sChar = service.Character.getInstance()
# Get the real intrestin' stuff
sChar = Character.getInstance()
char = self.charEditor.entityEditor.getActiveEntity()
for id, name in sChar.getSkills(tree.GetPyData(root)):
iconId = self.skillBookImageId
@@ -348,7 +394,7 @@ class SkillTreeView (wx.Panel):
return
char = self.charEditor.entityEditor.getActiveEntity()
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
if char.name not in ("All 0", "All 5"):
self.levelChangeMenu.selection = sMkt.getItem(self.skillTreeListCtrl.GetPyData(item))
self.PopupMenu(self.levelChangeMenu)
@@ -359,7 +405,7 @@ class SkillTreeView (wx.Panel):
def changeLevel(self, event):
level = self.levelIds.get(event.Id)
sChar = service.Character.getInstance()
sChar = Character.getInstance()
char = self.charEditor.entityEditor.getActiveEntity()
selection = self.skillTreeListCtrl.GetSelection()
skillID = self.skillTreeListCtrl.GetPyData(selection)
@@ -388,7 +434,7 @@ class SkillTreeView (wx.Panel):
class ImplantEditorView(BaseImplantEditorView):
def __init__(self, parent):
BaseImplantEditorView.__init__ (self, parent)
BaseImplantEditorView.__init__(self, parent)
self.determineEnabled()
@@ -405,19 +451,19 @@ class ImplantEditorView(BaseImplantEditorView):
self.determineEnabled()
def getImplantsFromContext(self):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
char = self.Parent.Parent.entityEditor.getActiveEntity()
return sChar.getImplants(char.ID)
def addImplantToContext(self, item):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
char = self.Parent.Parent.entityEditor.getActiveEntity()
sChar.addImplant(char.ID, item.ID)
def removeImplantFromContext(self, implant):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
char = self.Parent.Parent.entityEditor.getActiveEntity()
sChar.removeImplant(char.ID, implant)
@@ -442,9 +488,10 @@ class ImplantEditorView(BaseImplantEditorView):
self.Enable()
class APIView (wx.Panel):
class APIView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL)
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300),
style=wx.TAB_TRAVERSAL)
self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
@@ -453,17 +500,17 @@ class APIView (wx.Panel):
pmainSizer = wx.BoxSizer(wx.VERTICAL)
hintSizer = wx.BoxSizer( wx.HORIZONTAL )
hintSizer = wx.BoxSizer(wx.HORIZONTAL)
hintSizer.AddStretchSpacer()
self.stDisabledTip = wx.StaticText( self, wx.ID_ANY, u"You cannot add API Details for All 0 and All 5 characters.\n"
u"Please select another character or make a new one.", style=wx.ALIGN_CENTER )
self.stDisabledTip.Wrap( -1 )
hintSizer.Add( self.stDisabledTip, 0, wx.TOP | wx.BOTTOM, 10 )
self.stDisabledTip = wx.StaticText(self, wx.ID_ANY,
u"You cannot add API Details for All 0 and All 5 characters.\n"
u"Please select another character or make a new one.", style=wx.ALIGN_CENTER)
self.stDisabledTip.Wrap(-1)
hintSizer.Add(self.stDisabledTip, 0, wx.TOP | wx.BOTTOM, 10)
self.stDisabledTip.Hide()
hintSizer.AddStretchSpacer()
pmainSizer.Add(hintSizer, 0, wx.EXPAND, 5)
fgSizerInput = wx.FlexGridSizer(3, 2, 0, 0)
fgSizerInput.AddGrowableCol(1)
fgSizerInput.SetFlexibleDirection(wx.BOTH)
@@ -495,39 +542,44 @@ class APIView (wx.Panel):
pmainSizer.Add(fgSizerInput, 0, wx.EXPAND, 5)
btnSizer = wx.BoxSizer( wx.HORIZONTAL )
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.AddStretchSpacer()
self.btnFetchCharList = wx.Button(self, wx.ID_ANY, u"Get Characters")
btnSizer.Add(self.btnFetchCharList, 0, wx.ALL, 2)
self.btnFetchCharList.Bind(wx.EVT_BUTTON, self.fetchCharList)
self.btnFetchSkills = wx.Button(self, wx.ID_ANY, u"Fetch Skills")
btnSizer.Add(self.btnFetchSkills, 0, wx.ALL, 2)
self.btnFetchSkills = wx.Button(self, wx.ID_ANY, u"Fetch Skills")
btnSizer.Add(self.btnFetchSkills, 0, wx.ALL, 2)
self.btnFetchSkills.Bind(wx.EVT_BUTTON, self.fetchSkills)
self.btnFetchSkills.Enable(False)
btnSizer.AddStretchSpacer()
pmainSizer.Add(btnSizer, 0, wx.EXPAND, 5)
self.stStatus = wx.StaticText(self, wx.ID_ANY, wx.EmptyString)
self.stStatus = wx.StaticText(self, wx.ID_ANY, wx.EmptyString)
pmainSizer.Add(self.stStatus, 0, wx.ALL, 5)
pmainSizer.AddStretchSpacer()
self.stAPITip = wx.StaticText( self, wx.ID_ANY, u"You can create a pre-defined key here (only CharacterSheet is required):", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stAPITip.Wrap( -1 )
self.stAPITip = wx.StaticText(self, wx.ID_ANY,
u"You can create a pre-defined key here (only CharacterSheet is required):",
wx.DefaultPosition, wx.DefaultSize, 0)
self.stAPITip.Wrap(-1)
pmainSizer.Add( self.stAPITip, 0, wx.ALL, 2 )
pmainSizer.Add(self.stAPITip, 0, wx.ALL, 2)
self.hlEveAPI = wx.HyperlinkCtrl( self, wx.ID_ANY, self.apiUrlCreatePredefined, self.apiUrlCreatePredefined, wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE )
pmainSizer.Add( self.hlEveAPI, 0, wx.ALL, 2 )
self.hlEveAPI = wx.HyperlinkCtrl(self, wx.ID_ANY, self.apiUrlCreatePredefined, self.apiUrlCreatePredefined,
wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE)
pmainSizer.Add(self.hlEveAPI, 0, wx.ALL, 2)
self.stAPITip2 = wx.StaticText( self, wx.ID_ANY, u"Or, you can choose an existing key from:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stAPITip2.Wrap( -1 )
pmainSizer.Add( self.stAPITip2, 0, wx.ALL, 2 )
self.stAPITip2 = wx.StaticText(self, wx.ID_ANY, u"Or, you can choose an existing key from:", wx.DefaultPosition,
wx.DefaultSize, 0)
self.stAPITip2.Wrap(-1)
pmainSizer.Add(self.stAPITip2, 0, wx.ALL, 2)
self.hlEveAPI2 = wx.HyperlinkCtrl( self, wx.ID_ANY, self.apiUrlKeyList, self.apiUrlKeyList, wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE )
pmainSizer.Add( self.hlEveAPI2, 0, wx.ALL, 2 )
self.hlEveAPI2 = wx.HyperlinkCtrl(self, wx.ID_ANY, self.apiUrlKeyList, self.apiUrlKeyList, wx.DefaultPosition,
wx.DefaultSize, wx.HL_DEFAULT_STYLE)
pmainSizer.Add(self.hlEveAPI2, 0, wx.ALL, 2)
self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged)
@@ -536,7 +588,7 @@ class APIView (wx.Panel):
self.charChanged(None)
def charChanged(self, event):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
activeChar = self.charEditor.entityEditor.getActiveEntity()
ID, key, char, chars = sChar.getApiDetails(activeChar.ID)
@@ -547,7 +599,7 @@ class APIView (wx.Panel):
if chars:
for charName in chars:
i = self.charChoice.Append(charName)
self.charChoice.Append(charName)
self.charChoice.SetStringSelection(char)
self.charChoice.Enable(True)
self.btnFetchSkills.Enable(True)
@@ -575,20 +627,25 @@ class APIView (wx.Panel):
self.stStatus.SetLabel("Invalid keyID or vCode!")
return
sChar = service.Character.getInstance()
sChar = Character.getInstance()
try:
activeChar = self.charEditor.entityEditor.getActiveEntity()
list = sChar.apiCharList(activeChar.ID, self.inputID.GetLineText(0), self.inputKey.GetLineText(0))
except service.network.AuthenticationError, e:
self.stStatus.SetLabel("Authentication failure. Please check keyID and vCode combination.")
except service.network.TimeoutError, e:
self.stStatus.SetLabel("Request timed out. Please check network connectivity and/or proxy settings.")
except AuthenticationError, e:
msg = "Authentication failure. Please check keyID and vCode combination."
pyfalog.info(msg)
self.stStatus.SetLabel(msg)
except TimeoutError, e:
msg = "Request timed out. Please check network connectivity and/or proxy settings."
pyfalog.info(msg)
self.stStatus.SetLabel(msg)
except Exception, e:
self.stStatus.SetLabel("Error:\n%s"%e.message)
pyfalog.error(e)
self.stStatus.SetLabel("Error:\n%s" % e.message)
else:
self.charChoice.Clear()
for charName in list:
i = self.charChoice.Append(charName)
self.charChoice.Append(charName)
self.btnFetchSkills.Enable(True)
self.charChoice.Enable(True)
@@ -601,20 +658,21 @@ class APIView (wx.Panel):
charName = self.charChoice.GetString(self.charChoice.GetSelection())
if charName:
try:
sChar = service.Character.getInstance()
sChar = Character.getInstance()
activeChar = self.charEditor.entityEditor.getActiveEntity()
sChar.apiFetch(activeChar.ID, charName)
self.stStatus.SetLabel("Successfully fetched %s\'s skills from EVE API." % charName)
except Exception, e:
pyfalog.error("Unable to retrieve {0}\'s skills. Error message:\n{1}", charName, e)
self.stStatus.SetLabel("Unable to retrieve %s\'s skills. Error message:\n%s" % (charName, e))
class SaveCharacterAs(wx.Dialog):
class SaveCharacterAs(wx.Dialog):
def __init__(self, parent, charID):
wx.Dialog.__init__(self, parent, title="Save Character As...", size=wx.Size(300, 60))
self.charID = charID
self.parent = parent
sChar = service.Character.getInstance()
sChar = Character.getInstance()
name = sChar.getCharName(charID)
bSizer1 = wx.BoxSizer(wx.HORIZONTAL)
@@ -631,10 +689,9 @@ class SaveCharacterAs(wx.Dialog):
self.button.Bind(wx.EVT_BUTTON, self.change)
def change(self, event):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
sChar.saveCharacterAs(self.charID, self.input.GetLineText(0))
wx.PostEvent(self.parent, GE.CharListUpdated())
event.Skip()
self.Close()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,13 +15,18 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import service
from gui.bitmapLoader import BitmapLoader
import gui.globalEvents as GE
import gui.mainFrame
from service.character import Character
from service.fit import Fit
from logbook import Logger
pyfalog = Logger(__name__)
class CharacterSelection(wx.Panel):
def __init__(self, parent):
@@ -42,9 +47,9 @@ class CharacterSelection(wx.Panel):
self.refreshCharacterList()
self.cleanSkills = BitmapLoader.getBitmap("skill_big", "gui")
self.redSkills = BitmapLoader.getBitmap("skillRed_big", "gui")
self.redSkills = BitmapLoader.getBitmap("skillRed_big", "gui")
self.greenSkills = BitmapLoader.getBitmap("skillGreen_big", "gui")
self.refresh = BitmapLoader.getBitmap("refresh", "gui")
self.refresh = BitmapLoader.getBitmap("refresh", "gui")
self.btnRefresh = wx.BitmapButton(self, wx.ID_ANY, self.refresh)
size = self.btnRefresh.GetSize()
@@ -66,7 +71,7 @@ class CharacterSelection(wx.Panel):
self.mainFrame.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList)
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.SetMinSize(wx.Size(25,-1))
self.SetMinSize(wx.Size(25, -1))
self.charChoice.Enable(False)
@@ -76,7 +81,7 @@ class CharacterSelection(wx.Panel):
def refreshCharacterList(self, event=None):
choice = self.charChoice
sChar = service.Character.getInstance()
sChar = Character.getInstance()
activeChar = self.getActiveCharacter()
choice.Clear()
@@ -94,7 +99,7 @@ class CharacterSelection(wx.Panel):
charID = sChar.all5ID()
self.selectChar(charID)
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.changeChar(fitID, charID)
choice.Append(u"\u2015 Open Character Editor \u2015", -1)
@@ -104,20 +109,21 @@ class CharacterSelection(wx.Panel):
event.Skip()
def refreshApi(self, event):
sChar = service.Character.getInstance()
sChar = Character.getInstance()
ID, key, charName, chars = sChar.getApiDetails(self.getActiveCharacter())
if charName:
try:
sChar.apiFetch(self.getActiveCharacter(), charName)
except:
except Exception as e:
# can we do a popup, notifying user of API error?
pass
pyfalog.error("API fetch error")
pyfalog.error(e)
self.refreshCharacterList()
def charChanged(self, event):
fitID = self.mainFrame.getActiveFit()
charID = self.getActiveCharacter()
sChar = service.Character.getInstance()
sChar = Character.getInstance()
if charID == -1:
# revert to previous character
@@ -129,7 +135,7 @@ class CharacterSelection(wx.Panel):
else:
self.btnRefresh.Enable(False)
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.changeChar(fitID, charID)
self.charCache = self.charChoice.GetCurrentSelection()
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -137,18 +143,18 @@ class CharacterSelection(wx.Panel):
def selectChar(self, charID):
choice = self.charChoice
numItems = len(choice.GetItems())
for i in xrange(numItems):
id = choice.GetClientData(i)
if id == charID:
for i in range(numItems):
id_ = choice.GetClientData(i)
if id_ == charID:
choice.SetSelection(i)
return True
return False
def fitChanged(self, event):
self.charChoice.Enable(event.fitID != None)
self.charChoice.Enable(event.fitID is not None)
choice = self.charChoice
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
currCharID = choice.GetClientData(choice.GetCurrentSelection())
fit = sFit.getFit(event.fitID)
newCharID = fit.character.ID if fit is not None else None
@@ -156,38 +162,37 @@ class CharacterSelection(wx.Panel):
self.skillReqsStaticBitmap.SetBitmap(self.cleanSkills)
self.skillReqsStaticBitmap.SetToolTipString("No active fit")
else:
sCharacter = service.Character.getInstance()
sCharacter = Character.getInstance()
reqs = sCharacter.checkRequirements(fit)
sCharacter.skillReqsDict = {'charname':fit.character.name, 'skills':[]}
sCharacter.skillReqsDict = {'charname': fit.character.name, 'skills': []}
if len(reqs) == 0:
tip = "All skill prerequisites have been met"
self.skillReqsStaticBitmap.SetBitmap(self.greenSkills)
else:
tip = "Skills required:\n"
tip = "Skills required:\n"
condensed = sFit.serviceFittingOptions["compactSkills"]
if condensed:
dict = self._buildSkillsTooltipCondensed(reqs, skillsMap = {})
for key in sorted(dict):
tip += "%s: %d\n" % (key, dict[key])
dict_ = self._buildSkillsTooltipCondensed(reqs, skillsMap={})
for key in sorted(dict_):
tip += "%s: %d\n" % (key, dict_[key])
else:
tip += self._buildSkillsTooltip(reqs)
self.skillReqsStaticBitmap.SetBitmap(self.redSkills)
self.skillReqsStaticBitmap.SetToolTipString(tip.strip())
if newCharID == None:
sChar = service.Character.getInstance()
if newCharID is None:
sChar = Character.getInstance()
self.selectChar(sChar.all5ID())
elif currCharID != newCharID:
self.selectChar(newCharID)
self.charChanged(None)
event.Skip()
def _buildSkillsTooltip(self, reqs, currItem = "", tabulationLevel = 0):
def _buildSkillsTooltip(self, reqs, currItem="", tabulationLevel=0):
tip = ""
sCharacter = service.Character.getInstance()
sCharacter = Character.getInstance()
if tabulationLevel == 0:
for item, subReqs in reqs.iteritems():
@@ -197,11 +202,11 @@ class CharacterSelection(wx.Panel):
for name, info in reqs.iteritems():
level, ID, more = info
sCharacter.skillReqsDict['skills'].append({
'item' : currItem,
'skillID' : ID,
'skill' : name,
'level' : level,
'indent' : tabulationLevel
'item': currItem,
'skillID': ID,
'skill': name,
'level': level,
'indent': tabulationLevel,
})
tip += "%s%s: %d\n" % (" " * tabulationLevel, name, level)
@@ -209,8 +214,11 @@ class CharacterSelection(wx.Panel):
return tip
def _buildSkillsTooltipCondensed(self, reqs, currItem = "", tabulationLevel = 0, skillsMap = {}):
sCharacter = service.Character.getInstance()
def _buildSkillsTooltipCondensed(self, reqs, currItem="", tabulationLevel=0, skillsMap=None):
if skillsMap is None:
skillsMap = {}
sCharacter = Character.getInstance()
if tabulationLevel == 0:
for item, subReqs in reqs.iteritems():
@@ -220,11 +228,11 @@ class CharacterSelection(wx.Panel):
for name, info in reqs.iteritems():
level, ID, more = info
sCharacter.skillReqsDict['skills'].append({
'item' : currItem,
'skillID' : ID,
'skill' : name,
'level' : level,
'indent' : tabulationLevel
'item': currItem,
'skillID': ID,
'skill': name,
'level': level,
'indent': tabulationLevel,
})
if name not in skillsMap:
@@ -232,6 +240,6 @@ class CharacterSelection(wx.Panel):
elif skillsMap[name] < level:
skillsMap[name] = level
skillMap = self._buildSkillsTooltipCondensed(more, currItem, tabulationLevel + 1, skillsMap)
skillsMap = self._buildSkillsTooltipCondensed(more, currItem, tabulationLevel + 1, skillsMap)
return skillsMap

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Darriele
#
# This file is part of pyfa.
@@ -15,17 +15,20 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
# noinspection PyPackageRequirements
import wx.lib.newevent
import gui.utils.colorUtils as colorUtils
import gui.utils.drawUtils as drawUtils
import gui.utils.fonts as fonts
from gui.bitmapLoader import BitmapLoader
import gui.utils.fonts as fonts
from logbook import Logger
from service.fit import Fit
import service
pyfalog = Logger(__name__)
_PageChanging, EVT_NOTEBOOK_PAGE_CHANGING = wx.lib.newevent.NewEvent()
_PageChanged, EVT_NOTEBOOK_PAGE_CHANGED = wx.lib.newevent.NewEvent()
@@ -34,7 +37,8 @@ _PageClosing, EVT_NOTEBOOK_PAGE_CLOSING = wx.lib.newevent.NewEvent()
PageAdded, EVT_NOTEBOOK_PAGE_ADDED = wx.lib.newevent.NewEvent()
PageClosed, EVT_NOTEBOOK_PAGE_CLOSED = wx.lib.newevent.NewEvent()
class VetoAble():
class VetoAble(object):
def __init__(self):
self.__vetoed = False
@@ -45,7 +49,7 @@ class VetoAble():
return self.__vetoed
class NotebookTabChangeEvent():
class NotebookTabChangeEvent(object):
def __init__(self, old, new):
self.__old = old
self.__new = new
@@ -91,7 +95,6 @@ class PageAdding(_PageAdding, VetoAble):
class PFNotebook(wx.Panel):
def __init__(self, parent, canAdd=True):
"""
Instance of Pyfa Notebook. Initializes general layout, includes methods
@@ -100,8 +103,8 @@ class PFNotebook(wx.Panel):
parent - wx parent element
canAdd - True if tabs be deleted and added, passed directly to
PFTabsContainer
"""
wx.Panel.__init__(self, parent, wx.ID_ANY, size=(-1, -1))
self.pages = []
@@ -147,7 +150,8 @@ class PFNotebook(wx.Panel):
if self.activePage == page:
self.ShowActive()
def GetBorders(self):
@staticmethod
def GetBorders():
"""Gets border widths to better determine page size in ShowActive()"""
bx = wx.SystemSettings_GetMetric(wx.SYS_BORDER_X)
@@ -234,7 +238,7 @@ class PFNotebook(wx.Panel):
try:
# Set page to the first non-disabled page
self.SetSelection(next(i for i, _ in enumerate(self.pages) if not self.tabsContainer.tabs[i].disabled))
except StopIteration, ex:
except StopIteration:
self.SetSelection(0)
self.tabsContainer.DisableTab(idx, toggle)
@@ -336,8 +340,8 @@ class PFNotebook(wx.Panel):
event.Skip()
class PFTabRenderer:
def __init__(self, size=(36, 24), text=wx.EmptyString, img=None, inclination=6 , closeButton=True):
class PFTabRenderer(object):
def __init__(self, size=(36, 24), text=wx.EmptyString, img=None, inclination=6, closeButton=True):
"""
Renders a new tab
@@ -432,14 +436,15 @@ class PFTabRenderer:
mdc.SelectObject(ebmp)
mdc.SetFont(self.font)
textSizeX, textSizeY = mdc.GetTextExtent(self.text)
totalSize = self.leftWidth + self.rightWidth + textSizeX + self.closeBtnWidth/2 + 16 + self.padding*2
totalSize = self.leftWidth + self.rightWidth + textSizeX + self.closeBtnWidth / 2 + 16 + self.padding * 2
mdc.SelectObject(wx.NullBitmap)
return totalSize, self.tabHeight
def SetTabImage(self, img):
self.tabImg = img
def CopyRegion(self, region):
@staticmethod
def CopyRegion(region):
rect = region.GetBox()
newRegion = wx.Region(rect.X, rect.Y, rect.Width, rect.Height)
@@ -497,7 +502,7 @@ class PFTabRenderer:
mdc = wx.MemoryDC()
mdc.SelectObject(bkbmp)
#mdc.SetBackground(wx.Brush((0x12, 0x23, 0x32)))
# mdc.SetBackground(wx.Brush((0x12, 0x23, 0x32)))
mdc.Clear()
mdc.DrawBitmap(self.ctabLeftBmp, 0, 0) # set the left bitmap
@@ -506,14 +511,14 @@ class PFTabRenderer:
cm = self.ctabMiddleBmp.ConvertToImage()
mimg = cm.Scale(self.contentWidth, self.ctabMiddle.GetHeight(), wx.IMAGE_QUALITY_NORMAL)
mbmp = wx.BitmapFromImage(mimg)
mdc.DrawBitmap(mbmp, self.leftWidth, 0 ) # set middle bitmap, offset by left
mdc.DrawBitmap(mbmp, self.leftWidth, 0) # set middle bitmap, offset by left
# set right bitmap offset by left + middle
mdc.DrawBitmap(self.ctabRightBmp, self.contentWidth + self.leftWidth, 0)
mdc.SelectObject(wx.NullBitmap)
#bkbmp.SetMaskColour((0x12, 0x23, 0x32))
# bkbmp.SetMaskColour((0x12, 0x23, 0x32))
if self.tabBackBitmap:
del self.tabBackBitmap
@@ -527,7 +532,10 @@ class PFTabRenderer:
"""
self.tabRegion = wx.RegionFromBitmap(self.tabBackBitmap)
self.closeBtnRegion = wx.RegionFromBitmap(self.ctabCloseBmp)
self.closeBtnRegion.Offset(self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth()/2, (self.tabHeight - self.ctabCloseBmp.GetHeight())/2)
self.closeBtnRegion.Offset(
self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2,
(self.tabHeight - self.ctabCloseBmp.GetHeight()) / 2
)
def InitColors(self):
"""Determines colors used for tab, based on system settings"""
@@ -545,33 +553,33 @@ class PFTabRenderer:
height = self.tabHeight
#rect = wx.Rect(0, 0, self.tabWidth, self.tabHeight)
# rect = wx.Rect(0, 0, self.tabWidth, self.tabHeight)
canvas = wx.EmptyBitmap(self.tabWidth, self.tabHeight, 24)
mdc = wx.MemoryDC()
mdc.SelectObject(canvas)
#mdc.SetBackground(wx.Brush ((0x12,0x23,0x32)))
# mdc.SetBackground(wx.Brush ((0x12,0x23,0x32)))
mdc.Clear()
#r = copy.copy(rect)
#r.top = r.left = 0
#r.height = height
# r = copy.copy(rect)
# r.top = r.left = 0
# r.height = height
mdc.DrawBitmap(self.tabBackBitmap, 0, 0, True)
if self.tabImg:
bmp = wx.BitmapFromImage(self.tabImg.ConvertToGreyscale() if self.disabled else self.tabImg)
if self.contentWidth > 16: # @todo: is this conditional relevant anymore?
# Draw tab icon
mdc.DrawBitmap(bmp, self.leftWidth + self.padding - bmp.GetWidth()/2, (height - bmp.GetHeight())/2)
textStart = self.leftWidth + self.padding + bmp.GetWidth()/2
mdc.DrawBitmap(bmp, self.leftWidth + self.padding - bmp.GetWidth() / 2, (height - bmp.GetHeight()) / 2)
textStart = self.leftWidth + self.padding + bmp.GetWidth() / 2
else:
textStart = self.leftWidth
mdc.SetFont(self.font)
maxsize = self.tabWidth - textStart - self.rightWidth - self.padding*4
maxsize = self.tabWidth - textStart - self.rightWidth - self.padding * 4
color = self.selectedColor if self.selected else self.inactiveColor
mdc.SetTextForeground(colorUtils.GetSuitableColor(color, 1))
@@ -589,9 +597,10 @@ class PFTabRenderer:
cbmp = wx.BitmapFromImage(cimg)
mdc.DrawBitmap(
cbmp,
self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth()/2,
(height - self.ctabCloseBmp.GetHeight())/2)
cbmp,
self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2,
(height - self.ctabCloseBmp.GetHeight()) / 2,
)
mdc.SelectObject(wx.NullBitmap)
@@ -606,10 +615,11 @@ class PFTabRenderer:
def __repr__(self):
return "PFTabRenderer(text={}, disabled={}) at {}".format(
self.text, self.disabled, hex(id(self))
self.text, self.disabled, hex(id(self))
)
class PFAddRenderer:
class PFAddRenderer(object):
def __init__(self):
"""Renders the add tab button"""
self.addImg = BitmapLoader.getImage("ctabadd", "gui")
@@ -628,7 +638,7 @@ class PFAddRenderer:
def GetPosition(self):
return self.position
def SetPosition(self,pos):
def SetPosition(self, pos):
self.position = pos
def GetSize(self):
@@ -648,7 +658,8 @@ class PFAddRenderer:
region = wx.RegionFromBitmap(self.tbmp)
return region
def CopyRegion(self, region):
@staticmethod
def CopyRegion(region):
rect = region.GetBox()
newRegion = wx.Region(rect.X, rect.Y, rect.Width, rect.Height)
@@ -689,7 +700,7 @@ class PFTabsContainer(wx.Panel):
"""
wx.Panel.__init__(self, parent, id, pos, size)
if wx.VERSION >= (3,0):
if wx.VERSION >= (3, 0):
self.SetBackgroundStyle(wx.BG_STYLE_PAINT)
self.tabs = []
@@ -699,7 +710,7 @@ class PFTabsContainer(wx.Panel):
self.containerHeight = height
self.startDrag = False
self.dragging = False
self.sFit = service.Fit.getInstance()
self.sFit = Fit.getInstance()
self.inclination = 7
if canAdd:
@@ -865,7 +876,8 @@ class PFTabsContainer(wx.Panel):
return True
if self.TabHitTest(tab, x, y):
if tab.disabled: return
if tab.disabled:
return
tab.SetSelected(True)
oldSelTab.SetSelected(False)
@@ -942,7 +954,7 @@ class PFTabsContainer(wx.Panel):
closeBtnReg = tab.GetCloseButtonRegion()
tabPos = tab.GetPosition()
tabPosX, tabPosY = tabPos
closeBtnReg.Offset(tabPosX,tabPosY)
closeBtnReg.Offset(tabPosX, tabPosY)
if closeBtnReg.Contains(x, y):
if not tab.GetCloseButtonHoverStatus():
@@ -968,7 +980,8 @@ class PFTabsContainer(wx.Panel):
return tab
return None
def TabHitTest(self, tab, x, y):
@staticmethod
def TabHitTest(tab, x, y):
tabRegion = tab.GetTabRegion()
tabPos = tab.GetPosition()
tabPosX, tabPosY = tabPos
@@ -985,7 +998,6 @@ class PFTabsContainer(wx.Panel):
def GetTabAtRight(self, tabIndex):
return self.tabs[tabIndex + 1] if tabIndex < self.GetTabsCount() - 1 else None
def SwitchTabs(self, src, dest, draggedTab=None):
self.tabs[src], self.tabs[dest] = self.tabs[dest], self.tabs[src]
self.UpdateTabsPosition(draggedTab)
@@ -1083,8 +1095,9 @@ class PFTabsContainer(wx.Panel):
self.previewTab = tab
self.previewTimer.Start(500, True)
break
except:
pass
except Exception as e:
pyfalog.critical("Exception caught in CheckTabPreview.")
pyfalog.critical(e)
def CheckAddHighlighted(self, x, y):
"""
@@ -1110,25 +1123,23 @@ class PFTabsContainer(wx.Panel):
def OnPaint(self, event):
if "wxGTK" in wx.PlatformInfo:
mdc = wx.AutoBufferedPaintDC(self)
else:
rect = self.GetRect()
mdc = wx.BufferedPaintDC(self)
selected = 0
if 'wxMac' in wx.PlatformInfo and wx.VERSION < (3,0):
if 'wxMac' in wx.PlatformInfo and wx.VERSION < (3, 0):
color = wx.Colour(0, 0, 0)
brush = wx.Brush(color)
# noinspection PyPackageRequirements,PyUnresolvedReferences,PyUnresolvedReferences,PyUnresolvedReferences
from Carbon.Appearance import kThemeBrushDialogBackgroundActive
# noinspection PyUnresolvedReferences
brush.MacSetTheme(kThemeBrushDialogBackgroundActive)
else:
color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
brush = wx.Brush(color)
if "wxGTK" not in wx.PlatformInfo:
mdc.SetBackground (brush)
mdc.SetBackground(brush)
mdc.Clear()
selected = None
@@ -1136,21 +1147,18 @@ class PFTabsContainer(wx.Panel):
tabsWidth = 0
for tab in self.tabs:
tabsWidth += tab.tabWidth - self.inclination*2
pos = tabsWidth
tabsWidth += tab.tabWidth - self.inclination * 2
if self.showAddButton:
ax,ay = self.addButton.GetPosition()
ax, ay = self.addButton.GetPosition()
mdc.DrawBitmap(self.addButton.Render(), ax, ay, True)
for i in xrange(len(self.tabs) - 1, -1, -1):
for i in range(len(self.tabs) - 1, -1, -1):
tab = self.tabs[i]
width = tab.tabWidth - 6
posx, posy = tab.GetPosition()
if not tab.IsSelected():
mdc.DrawBitmap(self.efxBmp, posx, posy, True )
mdc.DrawBitmap(self.efxBmp, posx, posy, True)
bmp = tab.Render()
img = bmp.ConvertToImage()
img = img.AdjustChannels(1, 1, 1, 0.85)
@@ -1254,7 +1262,7 @@ class PFTabsContainer(wx.Panel):
if self.tabMinWidth < 1:
self.tabMinWidth = 1
for tab in self.tabs:
w, h = tab.GetSize()
tab.GetSize()
tab.SetSize((self.tabMinWidth, self.height))
if self.GetTabsCount() > 0:
@@ -1265,13 +1273,14 @@ class PFTabsContainer(wx.Panel):
def UpdateTabsPosition(self, skipTab=None):
tabsWidth = 0
for tab in self.tabs:
tabsWidth += tab.tabWidth - self.inclination*2
tabsWidth += tab.tabWidth - self.inclination * 2
pos = tabsWidth
selected = None
for i in xrange(len(self.tabs) - 1, -1, -1):
selpos = None
for i in range(len(self.tabs) - 1, -1, -1):
tab = self.tabs[i]
width = tab.tabWidth - self.inclination*2
width = tab.tabWidth - self.inclination * 2
pos -= width
if not tab.IsSelected():
tab.SetPosition((pos, self.containerHeight - self.height))
@@ -1280,7 +1289,12 @@ class PFTabsContainer(wx.Panel):
selpos = pos
if selected is not skipTab:
selected.SetPosition((selpos, self.containerHeight - self.height))
self.addButton.SetPosition((round(tabsWidth) + self.inclination*2, self.containerHeight - self.height/2 - self.addButton.GetHeight()/3))
self.addButton.SetPosition(
(
round(tabsWidth) + self.inclination * 2,
self.containerHeight - self.height / 2 - self.addButton.GetHeight() / 3
)
)
def OnLeaveWindow(self, event):
@@ -1305,17 +1319,28 @@ class PFTabsContainer(wx.Panel):
if not self.previewTab.GetSelected():
page = self.Parent.GetPage(self.GetTabIndex(self.previewTab))
if page.Snapshot():
self.previewWnd = PFNotebookPagePreview(self, (mposx+3, mposy+3), page.Snapshot(), self.previewTab.text)
self.previewWnd = PFNotebookPagePreview(
self,
(mposx + 3, mposy + 3),
page.Snapshot(),
self.previewTab.text
)
self.previewWnd.Show()
event.Skip()
class PFNotebookPagePreview(wx.Frame):
def __init__ (self,parent, pos, bitmap, title):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=pos, size=wx.DefaultSize, style=
wx.NO_BORDER
| wx.FRAME_NO_TASKBAR
| wx.STAY_ON_TOP)
def __init__(self, parent, pos, bitmap, title):
wx.Frame.__init__(
self,
parent,
id=wx.ID_ANY,
title=wx.EmptyString,
pos=pos,
size=wx.DefaultSize,
style=wx.NO_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP
)
self.title = title
self.bitmap = bitmap
@@ -1342,13 +1367,13 @@ class PFNotebookPagePreview(wx.Frame):
else:
width = bitmap.GetWidth()
self.SetSize((width, bitmap.GetHeight()+16))
self.SetSize((width, bitmap.GetHeight() + 16))
self.SetTransparent(0)
self.Refresh()
def OnTimer(self, event):
self.transp += 20*self.direction
self.transp += 20 * self.direction
if self.transp > 220:
self.transp = 220
@@ -1357,7 +1382,7 @@ class PFNotebookPagePreview(wx.Frame):
if self.transp < 0:
self.transp = 0
self.timer.Stop()
wx.Frame.Show(self,False)
wx.Frame.Show(self, False)
self.Destroy()
return
self.SetTransparent(self.transp)
@@ -1381,8 +1406,7 @@ class PFNotebookPagePreview(wx.Frame):
self.direction = -1
self.timer.Start(10)
def OnWindowEraseBk(self,event):
def OnWindowEraseBk(self, event):
pass
def OnWindowPaint(self, event):
@@ -1394,17 +1418,17 @@ class PFNotebookPagePreview(wx.Frame):
mdc.SetBackground(wx.Brush(color))
mdc.Clear()
font = wx.Font(fonts.NORMAL, wx.SWISS, wx.NORMAL,wx.NORMAL, False)
font = wx.Font(fonts.NORMAL, wx.SWISS, wx.NORMAL, wx.NORMAL, False)
mdc.SetFont(font)
x,y = mdc.GetTextExtent(self.title)
x, y = mdc.GetTextExtent(self.title)
mdc.SetBrush(wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)))
mdc.DrawRectangle(0, 0, rect.width, 16)
mdc.SetTextForeground(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
mdc.DrawText(self.title, (rect.width - x)/2, (16 - y)/2)
mdc.DrawText(self.title, (rect.width - x) / 2, (16 - y) / 2)
mdc.DrawBitmap(self.bitmap, 0, 16)

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,46 +15,51 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.display as d
import gui.globalEvents as GE
import service
import gui.droneView
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
import eos.types
from service.fit import Fit
from eos.saveddata.drone import Drone as es_Drone
class DummyItem:
class DummyItem(object):
def __init__(self, txt):
self.name = txt
self.icon = None
class DummyEntry:
class DummyEntry(object):
def __init__(self, txt):
self.item = DummyItem(txt)
class CommandViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
class CommandViewDrop(wx.PyDropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(CommandViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
class CommandView(d.Display):
DEFAULT_COLS = ["Base Name",]
DEFAULT_COLS = ["Base Name"]
def __init__(self, parent):
d.Display.__init__(self, parent, style = wx.LC_SINGLE_SEL | wx.BORDER_NONE)
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
@@ -66,7 +71,7 @@ class CommandView(d.Display):
self.droneView = gui.droneView.DroneView
if "__WXGTK__" in wx.PlatformInfo:
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
@@ -74,56 +79,58 @@ class CommandView(d.Display):
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
self.SetDropTarget(CommandViewDrop(self.handleListDrag))
def handleListDrag(self, x, y, data):
'''
@staticmethod
def handleListDrag(x, y, data):
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
pass
def kbEvent(self,event):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
row = self.GetFirstSelected()
if row != -1:
sFit.removeCommand(fitID, self.get(row))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def handleDrag(self, type, fitID):
#Those are drags coming from pyfa sources, NOT builtin wx drags
# Those are drags coming from pyfa sources, NOT builtin wx drags
if type == "fit":
activeFit = self.mainFrame.getActiveFit()
if activeFit:
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
draggedFit = sFit.getFit(fitID)
sFit.addCommandFit(activeFit, draggedFit)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFit))
def startDrag(self, event):
row = event.GetIndex()
if row != -1 and isinstance(self.get(row), eos.types.Drone):
if row != -1 and isinstance(self.get(row), es_Drone):
data = wx.PyTextDataObject()
data.SetText("command:"+str(self.GetItemData(row)))
data.SetText("command:" + str(self.GetItemData(row)))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
dropSource.DoDragDrop()
def fitSort(self, fit):
@staticmethod
def fitSort(fit):
return fit.name
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
#Clear list and get out if current fitId is None
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
@@ -147,7 +154,7 @@ class CommandView(d.Display):
self.deselectItems()
# todo: verify
if stuff == []:
if not stuff:
stuff = [DummyEntry("Drag a fit to this area")]
self.update(stuff)
@@ -155,7 +162,7 @@ class CommandView(d.Display):
def get(self, row):
numFits = len(self.fits)
if (numFits) == 0:
if numFits == 0:
return None
return self.fits[row]
@@ -168,7 +175,7 @@ class CommandView(d.Display):
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.toggleCommandFit(fitID, item)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -182,12 +189,12 @@ class CommandView(d.Display):
menu = None
if sel != -1:
item = self.get(sel)
if item is None: return
sMkt = service.Market.getInstance()
if item is None:
return
fitSrcContext = "commandFit"
fitItemContext = item.name
context = ((fitSrcContext,fitItemContext),)
context = context + (("command",),)
context = ((fitSrcContext, fitItemContext),)
context += ("command",),
menu = ContextMenu.getMenu((item,), *context)
elif sel == -1:
fitID = self.mainFrame.getActiveFit()
@@ -204,6 +211,6 @@ class CommandView(d.Display):
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.removeCommand(fitID, self.get(row))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))

View File

@@ -1,179 +1,206 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
import logging
logger = logging.getLogger(__name__)
class ContextMenu(object):
menus = []
_ids = [] #[wx.NewId() for x in xrange(200)] # init with decent amount
_idxid = -1
@classmethod
def register(cls):
ContextMenu.menus.append(cls)
@classmethod
def getMenu(cls, selection, *fullContexts):
"""
getMenu returns a menu that is used with wx.PopupMenu.
selection: provides a list of what was selected. If only 1 item was
selected, it's is a 1-item list or tuple. Can also be None for
contexts without selection, such as statsPane or projected view
fullContexts: a number of tuples of the following tuple:
srcContext - context were menu was spawned, eg: projectedFit,
cargoItem, etc
itemContext - usually the name of the item's category
eg:
(('fittingModule', 'Module'), ('fittingShip', 'Ship'))
(('marketItemGroup', 'Implant'),)
(('fittingShip', 'Ship'),)
"""
cls._idxid = -1
debug_start = len(cls._ids)
rootMenu = wx.Menu()
rootMenu.info = {}
rootMenu.selection = (selection,) if not hasattr(selection, "__iter__") else selection
empty = True
for i, fullContext in enumerate(fullContexts):
amount = 0
srcContext = fullContext[0]
try:
itemContext = fullContext[1]
except IndexError:
itemContext = None
for menuHandler in cls.menus:
# loop through registered menus
m = menuHandler()
if m.display(srcContext, selection):
amount += 1
texts = m.getText(itemContext, selection)
if isinstance(texts, basestring):
texts = (texts,)
bitmap = m.getBitmap(srcContext, selection)
multiple = not isinstance(bitmap, wx.Bitmap)
for it, text in enumerate(texts):
id = cls.nextID()
rootItem = wx.MenuItem(rootMenu, id, text)
rootMenu.info[id] = (m, fullContext, it)
sub = m.getSubMenu(srcContext, selection, rootMenu, it, rootItem)
if sub is None:
# if there is no sub menu, bind the handler to the rootItem
rootMenu.Bind(wx.EVT_MENU, cls.handler, rootItem)
elif sub:
# If sub exists and is not False, set submenu.
# Sub might return False when we have a mix of
# single menu items and submenus (see: damage profile
# context menu)
#
# If there is a submenu, it is expected that the sub
# logic take care of it's own bindings, including for
# any single root items. No binding is done here
#
# It is important to remember that when binding sub
# menu items, the menu to bind to depends on platform.
# Windows should bind to rootMenu, and all other
# platforms should bind to sub menu. See existing
# implementations for examples.
rootItem.SetSubMenu(sub)
if bitmap is not None:
if multiple:
bp = bitmap[it]
if bp:
rootItem.SetBitmap(bp)
else:
rootItem.SetBitmap(bitmap)
rootMenu.AppendItem(rootItem)
empty = False
if amount > 0 and i != len(fullContexts) - 1:
rootMenu.AppendSeparator()
debug_end = len(cls._ids)
if (debug_end - debug_start):
logger.debug("%d new IDs created for this menu" % (debug_end - debug_start))
return rootMenu if empty is False else None
@classmethod
def handler(cls, event):
menu = event.EventObject
stuff = menu.info.get(event.Id)
if stuff is not None:
menuHandler, context, i = stuff
selection = menu.selection
if not hasattr(selection, "__iter__"):
selection = (selection,)
menuHandler.activate(context, selection, i)
else:
event.Skip()
def display(self, context, selection):
raise NotImplementedError()
def activate(self, fullContext, selection, i):
return None
def getSubMenu(self, context, selection, rootMenu, i, pitem):
return None
@classmethod
def nextID(cls):
"""
Fetches an ID from the pool of IDs allocated to Context Menu.
If we don't have enough ID's to fulfill request, create new
ID and add it to the pool.
See GH Issue #589
"""
cls._idxid += 1
if cls._idxid >= len(cls._ids): # We don't ahve an ID for this index, create one
cls._ids.append(wx.NewId())
return cls._ids[cls._idxid]
def getText(self, context, selection):
"""
getText should be implemented in child classes, and should return either
a string that will make up a menu item label or a list of strings which
will make numerous menu items.
These menu items will be added to the root menu
"""
raise NotImplementedError()
def getBitmap(self, context, selection):
return None
from gui.builtinContextMenus import *
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from logbook import Logger
pyfalog = Logger(__name__)
class ContextMenu(object):
menus = []
_ids = [] # [wx.NewId() for x in xrange(200)] # init with decent amount
_idxid = -1
@classmethod
def register(cls):
ContextMenu.menus.append(cls)
@classmethod
def getMenu(cls, selection, *fullContexts):
"""
getMenu returns a menu that is used with wx.PopupMenu.
selection: provides a list of what was selected. If only 1 item was
selected, it's is a 1-item list or tuple. Can also be None for
contexts without selection, such as statsPane or projected view
fullContexts: a number of tuples of the following tuple:
srcContext - context were menu was spawned, eg: projectedFit,
cargoItem, etc
itemContext - usually the name of the item's category
eg:
(('fittingModule', 'Module'), ('fittingShip', 'Ship'))
(('marketItemGroup', 'Implant'),)
(('fittingShip', 'Ship'),)
"""
cls._idxid = -1
debug_start = len(cls._ids)
rootMenu = wx.Menu()
rootMenu.info = {}
rootMenu.selection = (selection,) if not hasattr(selection, "__iter__") else selection
empty = True
for i, fullContext in enumerate(fullContexts):
display_amount = 0
srcContext = fullContext[0]
try:
itemContext = fullContext[1]
except IndexError:
itemContext = None
for menuHandler in cls.menus:
# loop through registered menus
m = menuHandler()
if m.display(srcContext, selection):
display_amount += 1
texts = m.getText(itemContext, selection)
if isinstance(texts, basestring):
texts = (texts,)
bitmap = m.getBitmap(srcContext, selection)
multiple = not isinstance(bitmap, wx.Bitmap)
for it, text in enumerate(texts):
id = cls.nextID()
rootItem = wx.MenuItem(rootMenu, id, text)
rootMenu.info[id] = (m, fullContext, it)
sub = m.getSubMenu(srcContext, selection, rootMenu, it, rootItem)
if sub is None:
# if there is no sub menu, bind the handler to the rootItem
rootMenu.Bind(wx.EVT_MENU, cls.handler, rootItem)
elif sub:
# If sub exists and is not False, set submenu.
# Sub might return False when we have a mix of
# single menu items and submenus (see: damage profile
# context menu)
#
# If there is a submenu, it is expected that the sub
# logic take care of it's own bindings, including for
# any single root items. No binding is done here
#
# It is important to remember that when binding sub
# menu items, the menu to bind to depends on platform.
# Windows should bind to rootMenu, and all other
# platforms should bind to sub menu. See existing
# implementations for examples.
rootItem.SetSubMenu(sub)
if bitmap is not None:
if multiple:
bp = bitmap[it]
if bp:
rootItem.SetBitmap(bp)
else:
rootItem.SetBitmap(bitmap)
rootMenu.AppendItem(rootItem)
empty = False
if display_amount > 0 and i != len(fullContexts) - 1:
rootMenu.AppendSeparator()
debug_end = len(cls._ids)
if debug_end - debug_start:
pyfalog.debug("{0} new IDs created for this menu", (debug_end - debug_start))
return rootMenu if empty is False else None
@classmethod
def handler(cls, event):
menu = event.EventObject
stuff = menu.info.get(event.Id)
if stuff is not None:
menuHandler, context, i = stuff
selection = menu.selection
if not hasattr(selection, "__iter__"):
selection = (selection,)
menuHandler.activate(context, selection, i)
else:
event.Skip()
def display(self, context, selection):
raise NotImplementedError()
def activate(self, fullContext, selection, i):
return None
def getSubMenu(self, context, selection, rootMenu, i, pitem):
return None
@classmethod
def nextID(cls):
"""
Fetches an ID from the pool of IDs allocated to Context Menu.
If we don't have enough ID's to fulfill request, create new
ID and add it to the pool.
See GH Issue #589
"""
cls._idxid += 1
if cls._idxid >= len(cls._ids): # We don't ahve an ID for this index, create one
cls._ids.append(wx.NewId())
return cls._ids[cls._idxid]
def getText(self, context, selection):
"""
getText should be implemented in child classes, and should return either
a string that will make up a menu item label or a list of strings which
will make numerous menu items.
These menu items will be added to the root menu
"""
raise NotImplementedError()
def getBitmap(self, context, selection):
return None
# noinspection PyUnresolvedReferences
from gui.builtinContextMenus import ( # noqa: E402,F401
openFit,
# moduleGlobalAmmoPicker,
moduleAmmoPicker,
itemStats,
damagePattern,
marketJump,
droneSplit,
itemRemove,
droneRemoveStack,
ammoPattern,
project,
factorReload,
whProjector,
cargo,
shipJump,
changeAffectingSkills,
tacticalMode,
targetResists,
priceClear,
amount,
metaSwap,
implantSets,
fighterAbilities,
)

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Lucas Thode
#
# This file is part of pyfa.
@@ -15,11 +15,13 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
class CopySelectDialog(wx.Dialog):
copyFormatEft = 0
copyFormatEftImps = 1
@@ -29,7 +31,8 @@ class CopySelectDialog(wx.Dialog):
copyFormatMultiBuy = 5
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id = wx.ID_ANY, title = u"Select a format", size = (-1,-1), style = wx.DEFAULT_DIALOG_STYLE)
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=u"Select a format", size=(-1, -1),
style=wx.DEFAULT_DIALOG_STYLE)
mainSizer = wx.BoxSizer(wx.VERTICAL)
copyFormats = [u"EFT", u"EFT (Implants)", u"XML", u"DNA", u"CREST", u"MultiBuy"]
@@ -39,7 +42,8 @@ class CopySelectDialog(wx.Dialog):
CopySelectDialog.copyFormatDna: u"A one-line text format",
CopySelectDialog.copyFormatCrest: u"A JSON format used for EVE CREST",
CopySelectDialog.copyFormatMultiBuy: u"MultiBuy text format"}
selector = wx.RadioBox(self, wx.ID_ANY, label = u"Copy to the clipboard using:", choices = copyFormats, style = wx.RA_SPECIFY_ROWS)
selector = wx.RadioBox(self, wx.ID_ANY, label=u"Copy to the clipboard using:", choices=copyFormats,
style=wx.RA_SPECIFY_ROWS)
selector.Bind(wx.EVT_RADIOBOX, self.Selected)
for format, tooltip in copyFormatTooltips.iteritems():
selector.SetItemToolTip(format, tooltip)
@@ -47,21 +51,18 @@ class CopySelectDialog(wx.Dialog):
self.copyFormat = CopySelectDialog.copyFormatEft
selector.SetSelection(self.copyFormat)
mainSizer.Add(selector,0,wx.EXPAND | wx.ALL, 5)
mainSizer.Add(selector, 0, wx.EXPAND | wx.ALL, 5)
buttonSizer = self.CreateButtonSizer(wx.OK | wx.CANCEL)
if (buttonSizer):
mainSizer.Add(buttonSizer,0, wx.EXPAND | wx.ALL, 5)
if buttonSizer:
mainSizer.Add(buttonSizer, 0, wx.EXPAND | wx.ALL, 5)
self.SetSizer(mainSizer)
self.Fit()
self.Center()
def Selected(self, event):
self.copyFormat = event.GetSelection()
def GetSelected(self):
return self.copyFormat

View File

@@ -1,66 +1,74 @@
import time
import webbrowser
import json
# noinspection PyPackageRequirements
import wx
import requests
import service
from service.crest import CrestModes
from service.port import Port
from service.fit import Fit
from eos.types import Cargo
from eos.saveddata.cargo import Cargo
from eos.db import getItem
import gui.display as d
from gui.display import Display
import gui.globalEvents as GE
from logbook import Logger
pyfalog = Logger(__name__)
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
from service.crest import Crest, CrestModes
class CrestFittings(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Browse EVE Fittings", pos=wx.DefaultPosition, size=wx.Size( 550,450 ), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Browse EVE Fittings", pos=wx.DefaultPosition,
size=wx.Size(550, 450), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
self.mainFrame = parent
mainSizer = wx.BoxSizer(wx.VERTICAL)
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
characterSelectSizer = wx.BoxSizer( wx.HORIZONTAL )
characterSelectSizer = wx.BoxSizer(wx.HORIZONTAL)
if sCrest.settings.get('mode') == CrestModes.IMPLICIT:
self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s"%sCrest.implicitCharacter.name, wx.DefaultPosition, wx.DefaultSize)
self.stLogged.Wrap( -1 )
self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s" % sCrest.implicitCharacter.name,
wx.DefaultPosition, wx.DefaultSize)
self.stLogged.Wrap(-1)
characterSelectSizer.Add( self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
characterSelectSizer.Add(self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
else:
self.charChoice = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [])
characterSelectSizer.Add( self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
characterSelectSizer.Add(self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
self.updateCharList()
self.fetchBtn = wx.Button( self, wx.ID_ANY, u"Fetch Fits", wx.DefaultPosition, wx.DefaultSize, 5 )
characterSelectSizer.Add( self.fetchBtn, 0, wx.ALL, 5 )
mainSizer.Add( characterSelectSizer, 0, wx.EXPAND, 5 )
self.fetchBtn = wx.Button(self, wx.ID_ANY, u"Fetch Fits", wx.DefaultPosition, wx.DefaultSize, 5)
characterSelectSizer.Add(self.fetchBtn, 0, wx.ALL, 5)
mainSizer.Add(characterSelectSizer, 0, wx.EXPAND, 5)
self.sl = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.sl, 0, wx.EXPAND |wx.ALL, 5 )
self.sl = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.sl, 0, wx.EXPAND | wx.ALL, 5)
contentSizer = wx.BoxSizer( wx.HORIZONTAL )
browserSizer = wx.BoxSizer( wx.VERTICAL )
contentSizer = wx.BoxSizer(wx.HORIZONTAL)
browserSizer = wx.BoxSizer(wx.VERTICAL)
self.fitTree = FittingsTreeView(self)
browserSizer.Add( self.fitTree, 1, wx.ALL|wx.EXPAND, 5 )
contentSizer.Add( browserSizer, 1, wx.EXPAND, 0 )
fitSizer = wx.BoxSizer( wx.VERTICAL )
browserSizer.Add(self.fitTree, 1, wx.ALL | wx.EXPAND, 5)
contentSizer.Add(browserSizer, 1, wx.EXPAND, 0)
fitSizer = wx.BoxSizer(wx.VERTICAL)
self.fitView = FitView(self)
fitSizer.Add( self.fitView, 1, wx.ALL|wx.EXPAND, 5 )
fitSizer.Add(self.fitView, 1, wx.ALL | wx.EXPAND, 5)
btnSizer = wx.BoxSizer( wx.HORIZONTAL )
self.importBtn = wx.Button( self, wx.ID_ANY, u"Import to pyfa", wx.DefaultPosition, wx.DefaultSize, 5 )
self.deleteBtn = wx.Button( self, wx.ID_ANY, u"Delete from EVE", wx.DefaultPosition, wx.DefaultSize, 5 )
btnSizer.Add( self.importBtn, 1, wx.ALL, 5 )
btnSizer.Add( self.deleteBtn, 1, wx.ALL, 5 )
fitSizer.Add( btnSizer, 0, wx.EXPAND )
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
self.importBtn = wx.Button(self, wx.ID_ANY, u"Import to pyfa", wx.DefaultPosition, wx.DefaultSize, 5)
self.deleteBtn = wx.Button(self, wx.ID_ANY, u"Delete from EVE", wx.DefaultPosition, wx.DefaultSize, 5)
btnSizer.Add(self.importBtn, 1, wx.ALL, 5)
btnSizer.Add(self.deleteBtn, 1, wx.ALL, 5)
fitSizer.Add(btnSizer, 0, wx.EXPAND)
contentSizer.Add(fitSizer, 1, wx.EXPAND, 0)
mainSizer.Add(contentSizer, 1, wx.EXPAND, 5)
@@ -90,7 +98,7 @@ class CrestFittings(wx.Frame):
event.Skip()
def updateCharList(self):
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
chars = sCrest.getCrestCharacters()
if len(chars) == 0:
@@ -103,12 +111,12 @@ class CrestFittings(wx.Frame):
self.charChoice.SetSelection(0)
def updateCacheStatus(self, event):
t = time.gmtime(self.cacheTime-time.time())
t = time.gmtime(self.cacheTime - time.time())
if t < 0:
self.cacheTimer.Stop()
else:
sTime = time.strftime("%H:%M:%S", t)
self.statusbar.SetStatusText("Cached for %s"%sTime, 0)
self.statusbar.SetStatusText("Cached for %s" % sTime, 0)
def ssoLogout(self, event):
if event.type == CrestModes.IMPLICIT:
@@ -123,7 +131,7 @@ class CrestFittings(wx.Frame):
event.Skip()
def getActiveCharacter(self):
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
if sCrest.settings.get('mode') == CrestModes.IMPLICIT:
return sCrest.implicitCharacter.ID
@@ -132,7 +140,7 @@ class CrestFittings(wx.Frame):
return self.charChoice.GetClientData(selection) if selection is not None else None
def fetchFittings(self, event):
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
try:
waitDialog = wx.BusyInfo("Fetching fits, please wait...", parent=self)
fittings = sCrest.getFittings(self.getActiveCharacter())
@@ -140,65 +148,69 @@ class CrestFittings(wx.Frame):
self.updateCacheStatus(None)
self.cacheTimer.Start(1000)
self.fitTree.populateSkillTree(fittings)
except requests.exceptions.ConnectionError:
self.statusbar.SetStatusText("Connection error, please check your internet connection")
finally:
del waitDialog
except requests.exceptions.ConnectionError:
msg = "Connection error, please check your internet connection"
pyfalog.error(msg)
self.statusbar.SetStatusText(msg)
def importFitting(self, event):
selection = self.fitView.fitSelection
if not selection:
return
data = self.fitTree.fittingsTreeCtrl.GetPyData(selection)
sFit = service.Fit.getInstance()
fits = sFit.importFitFromBuffer(data)
sPort = Port.getInstance()
fits = sPort.importFitFromBuffer(data)
self.mainFrame._openAfterImport(fits)
def deleteFitting(self, event):
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
selection = self.fitView.fitSelection
if not selection:
return
data = json.loads(self.fitTree.fittingsTreeCtrl.GetPyData(selection))
dlg = wx.MessageDialog(self,
"Do you really want to delete %s (%s) from EVE?"%(data['name'], data['ship']['name']),
"Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
"Do you really want to delete %s (%s) from EVE?" % (data['name'], data['ship']['name']),
"Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
if dlg.ShowModal() == wx.ID_YES:
try:
sCrest.delFitting(self.getActiveCharacter(), data['fittingID'])
except requests.exceptions.ConnectionError:
self.statusbar.SetStatusText("Connection error, please check your internet connection")
msg = "Connection error, please check your internet connection"
pyfalog.error(msg)
self.statusbar.SetStatusText(msg)
class ExportToEve(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Export fit to EVE", pos=wx.DefaultPosition, size=(wx.Size(350,100)), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Export fit to EVE", pos=wx.DefaultPosition,
size=(wx.Size(350, 100)), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
self.mainFrame = parent
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
mainSizer = wx.BoxSizer(wx.VERTICAL)
hSizer = wx.BoxSizer(wx.HORIZONTAL)
if sCrest.settings.get('mode') == CrestModes.IMPLICIT:
self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s"%sCrest.implicitCharacter.name, wx.DefaultPosition, wx.DefaultSize)
self.stLogged.Wrap( -1 )
self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s" % sCrest.implicitCharacter.name,
wx.DefaultPosition, wx.DefaultSize)
self.stLogged.Wrap(-1)
hSizer.Add( self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
hSizer.Add(self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
else:
self.charChoice = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [])
hSizer.Add( self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
hSizer.Add(self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
self.updateCharList()
self.charChoice.SetSelection(0)
self.exportBtn = wx.Button( self, wx.ID_ANY, u"Export Fit", wx.DefaultPosition, wx.DefaultSize, 5 )
hSizer.Add( self.exportBtn, 0, wx.ALL, 5 )
self.exportBtn = wx.Button(self, wx.ID_ANY, u"Export Fit", wx.DefaultPosition, wx.DefaultSize, 5)
hSizer.Add(self.exportBtn, 0, wx.ALL, 5)
mainSizer.Add( hSizer, 0, wx.EXPAND, 5 )
mainSizer.Add(hSizer, 0, wx.EXPAND, 5)
self.exportBtn.Bind(wx.EVT_BUTTON, self.exportFitting)
@@ -217,7 +229,7 @@ class ExportToEve(wx.Frame):
self.Centre(wx.BOTH)
def updateCharList(self):
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
chars = sCrest.getCrestCharacters()
if len(chars) == 0:
@@ -245,7 +257,7 @@ class ExportToEve(wx.Frame):
event.Skip()
def getActiveCharacter(self):
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
if sCrest.settings.get('mode') == CrestModes.IMPLICIT:
return sCrest.implicitCharacter.ID
@@ -254,7 +266,7 @@ class ExportToEve(wx.Frame):
return self.charChoice.GetClientData(selection) if selection is not None else None
def exportFitting(self, event):
sFit = service.Fit.getInstance()
sPort = Port.getInstance()
fitID = self.mainFrame.getActiveFit()
self.statusbar.SetStatusText("", 0)
@@ -264,64 +276,68 @@ class ExportToEve(wx.Frame):
return
self.statusbar.SetStatusText("Sending request and awaiting response", 1)
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
try:
data = sFit.exportCrest(fitID)
sFit = Fit.getInstance()
data = sPort.exportCrest(sFit.getFit(fitID))
res = sCrest.postFitting(self.getActiveCharacter(), data)
self.statusbar.SetStatusText("%d: %s"%(res.status_code, res.reason), 0)
self.statusbar.SetStatusText("%d: %s" % (res.status_code, res.reason), 0)
try:
text = json.loads(res.text)
self.statusbar.SetStatusText(text['message'], 1)
except ValueError:
pyfalog.warning("Value error on loading JSON.")
self.statusbar.SetStatusText("", 1)
except requests.exceptions.ConnectionError:
self.statusbar.SetStatusText("Connection error, please check your internet connection", 1)
msg = "Connection error, please check your internet connection"
pyfalog.error(msg)
self.statusbar.SetStatusText(msg)
class CrestMgmt(wx.Dialog):
def __init__( self, parent ):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = "CREST Character Management", pos = wx.DefaultPosition, size = wx.Size( 550,250 ), style = wx.DEFAULT_DIALOG_STYLE )
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="CREST Character Management", pos=wx.DefaultPosition,
size=wx.Size(550, 250), style=wx.DEFAULT_DIALOG_STYLE)
self.mainFrame = parent
mainSizer = wx.BoxSizer( wx.HORIZONTAL )
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
self.lcCharacters = wx.ListCtrl( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT)
self.lcCharacters = wx.ListCtrl(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT)
self.lcCharacters.InsertColumn(0, heading='Character')
self.lcCharacters.InsertColumn(1, heading='Refresh Token')
self.popCharList()
mainSizer.Add( self.lcCharacters, 1, wx.ALL|wx.EXPAND, 5 )
mainSizer.Add(self.lcCharacters, 1, wx.ALL | wx.EXPAND, 5)
btnSizer = wx.BoxSizer( wx.VERTICAL )
btnSizer = wx.BoxSizer(wx.VERTICAL)
self.addBtn = wx.Button( self, wx.ID_ANY, u"Add Character", wx.DefaultPosition, wx.DefaultSize, 0 )
btnSizer.Add( self.addBtn, 0, wx.ALL | wx.EXPAND, 5 )
self.addBtn = wx.Button(self, wx.ID_ANY, u"Add Character", wx.DefaultPosition, wx.DefaultSize, 0)
btnSizer.Add(self.addBtn, 0, wx.ALL | wx.EXPAND, 5)
self.deleteBtn = wx.Button( self, wx.ID_ANY, u"Revoke Character", wx.DefaultPosition, wx.DefaultSize, 0 )
btnSizer.Add( self.deleteBtn, 0, wx.ALL | wx.EXPAND, 5 )
self.deleteBtn = wx.Button(self, wx.ID_ANY, u"Revoke Character", wx.DefaultPosition, wx.DefaultSize, 0)
btnSizer.Add(self.deleteBtn, 0, wx.ALL | wx.EXPAND, 5)
mainSizer.Add( btnSizer, 0, wx.EXPAND, 5 )
mainSizer.Add(btnSizer, 0, wx.EXPAND, 5)
self.addBtn.Bind(wx.EVT_BUTTON, self.addChar)
self.deleteBtn.Bind(wx.EVT_BUTTON, self.delChar)
self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.ssoLogin)
self.SetSizer( mainSizer )
self.SetSizer(mainSizer)
self.Layout()
self.Centre( wx.BOTH )
self.Centre(wx.BOTH)
def ssoLogin(self, event):
self.popCharList()
event.Skip()
def popCharList(self):
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
chars = sCrest.getCrestCharacters()
self.lcCharacters.DeleteAllItems()
@@ -334,8 +350,9 @@ class CrestMgmt(wx.Dialog):
self.lcCharacters.SetColumnWidth(0, wx.LIST_AUTOSIZE)
self.lcCharacters.SetColumnWidth(1, wx.LIST_AUTOSIZE)
def addChar(self, event):
sCrest = service.Crest.getInstance()
@staticmethod
def addChar(event):
sCrest = Crest.getInstance()
uri = sCrest.startServer()
webbrowser.open(uri)
@@ -343,7 +360,7 @@ class CrestMgmt(wx.Dialog):
item = self.lcCharacters.GetFirstSelected()
if item > -1:
charID = self.lcCharacters.GetItemData(item)
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
sCrest.delCrestCharacter(charID)
self.popCharList()
@@ -398,17 +415,18 @@ class FittingsTreeView(wx.Panel):
cargo = Cargo(getItem(item['type']['id']))
cargo.amount = item['quantity']
list.append(cargo)
except:
pass
except Exception as e:
pyfalog.critical("Exception caught in displayFit")
pyfalog.critical(e)
self.parent.fitView.fitSelection = selection
self.parent.fitView.update(list)
class FitView(d.Display):
class FitView(Display):
DEFAULT_COLS = ["Base Icon",
"Base Name"]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL)
Display.__init__(self, parent, style=wx.LC_SINGLE_SEL)
self.fitSelection = None

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,19 +15,22 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
import sys
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from gui.viewColumn import ViewColumn
from gui.cachingImageList import CachingImageList
class Display(wx.ListCtrl):
def __init__(self, parent, size = wx.DefaultSize, style = 0):
wx.ListCtrl.__init__(self, parent,size = size, style=wx.LC_REPORT | style )
class Display(wx.ListCtrl):
DEFAULT_COLS = None
def __init__(self, parent, size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, size=size, style=wx.LC_REPORT | style)
self.imageList = CachingImageList(16, 16)
self.SetImageList(self.imageList, wx.IMAGE_LIST_SMALL)
self.activeColumns = []
@@ -64,15 +67,15 @@ class Display(wx.ListCtrl):
i += 1
info = wx.ListItem()
# noinspection PyPropertyAccess
info.m_mask = wx.LIST_MASK_WIDTH
self.InsertColumnInfo(i, info)
self.SetColumnWidth(i, 0)
self.imageListBase = self.imageList.ImageCount
# Override native HitTestSubItem (doesn't work as it should on GTK)
# Source: ObjectListView
# Override native HitTestSubItem (doesn't work as it should on GTK)
# Source: ObjectListView
def HitTestSubItem(self, pt):
"""
@@ -89,11 +92,11 @@ class Display(wx.ListCtrl):
# Did the point hit any item?
if (flags & wx.LIST_HITTEST_ONITEM) == 0:
return (-1, 0, -1)
return -1, 0, -1
# If it did hit an item and we are not in report mode, it must be the primary cell
if not self.InReportView():
return (rowIndex, wx.LIST_HITTEST_ONITEM, 0)
return rowIndex, wx.LIST_HITTEST_ONITEM, 0
# Find which subitem is hit
right = 0
@@ -106,19 +109,18 @@ class Display(wx.ListCtrl):
flag = wx.LIST_HITTEST_ONITEMICON
else:
flag = wx.LIST_HITTEST_ONITEMLABEL
return (rowIndex, flag, i)
return rowIndex, flag, i
return (rowIndex, 0, -1)
return rowIndex, 0, -1
def OnEraseBk(self,event):
if self.GetItemCount() >0:
def OnEraseBk(self, event):
if self.GetItemCount() > 0:
width, height = self.GetClientSize()
dc = event.GetDC()
dc.DestroyClippingRegion()
dc.SetClippingRegion(0, 0, width, height)
x,y,w,h = dc.GetClippingBox()
x, y, w, h = dc.GetClippingBox()
topItem = self.GetTopItem()
bottomItem = topItem + self.GetCountPerPage()
@@ -129,10 +131,9 @@ class Display(wx.ListCtrl):
topRect = self.GetItemRect(topItem, wx.LIST_RECT_LABEL)
bottomRect = self.GetItemRect(bottomItem, wx.LIST_RECT_BOUNDS)
items_rect = wx.Rect(topRect.left, 0, bottomRect.right - topRect.left, bottomRect.bottom)
items_rect = wx.Rect(topRect.left, 0, bottomRect.right - topRect.left, bottomRect.bottom )
updateRegion = wx.Region(x,y,w,h)
updateRegion = wx.Region(x, y, w, h)
updateRegion.SubtractRect(items_rect)
dc.DestroyClippingRegion()
@@ -146,6 +147,7 @@ class Display(wx.ListCtrl):
else:
event.Skip()
# noinspection PyPropertyAccess
def addColumn(self, i, col):
self.activeColumns.append(col)
info = wx.ListItem()
@@ -171,41 +173,37 @@ class Display(wx.ListCtrl):
# we veto header cell resize by default till we find a way
# to assure a minimal size for the resized header cell
column = event.GetColumn()
wx.CallAfter(self.checkColumnSize,column)
wx.CallAfter(self.checkColumnSize, column)
event.Skip()
def resizeSkip(self, event):
column = event.GetColumn()
if column > len (self.activeColumns)-1:
if column > len(self.activeColumns) - 1:
self.SetColumnWidth(column, 0)
event.Veto()
return
colItem = self.activeColumns[column]
# colItem = self.activeColumns[column]
if self.activeColumns[column].maxsize != -1:
event.Veto()
else:
event.Skip()
def checkColumnSize(self,column):
def checkColumnSize(self, column):
colItem = self.activeColumns[column]
if self.GetColumnWidth(column) < self.columnsMinWidth[column]:
self.SetColumnWidth(column,self.columnsMinWidth[column])
self.SetColumnWidth(column, self.columnsMinWidth[column])
colItem.resized = True
def getLastItem( self, state = wx.LIST_STATE_DONTCARE):
lastFound = -1
while True:
index = self.GetNextItem(
lastFound,
wx.LIST_NEXT_ALL,
state,
)
if index == -1:
break
else:
lastFound = index
def getLastItem(self, state=wx.LIST_STATE_DONTCARE):
lastFound = -1
while True:
index = self.GetNextItem(lastFound, wx.LIST_NEXT_ALL, state)
if index == -1:
break
else:
lastFound = index
return lastFound
return lastFound
def deselectItems(self):
sel = self.GetFirstSelected()
@@ -220,26 +218,25 @@ class Display(wx.ListCtrl):
stuffItemCount = len(stuff)
if listItemCount < stuffItemCount:
for i in xrange(stuffItemCount - listItemCount):
index = self.InsertStringItem(sys.maxint, "")
for i in range(stuffItemCount - listItemCount):
self.InsertStringItem(sys.maxint, "")
if listItemCount > stuffItemCount:
if listItemCount - stuffItemCount > 20 and stuffItemCount < 20:
if listItemCount - stuffItemCount > 20 > stuffItemCount:
self.DeleteAllItems()
for i in xrange(stuffItemCount):
index = self.InsertStringItem(sys.maxint, "")
for i in range(stuffItemCount):
self.InsertStringItem(sys.maxint, "")
else:
for i in xrange(listItemCount - stuffItemCount):
for i in range(listItemCount - stuffItemCount):
self.DeleteItem(self.getLastItem())
self.Refresh()
def refresh(self, stuff):
if stuff == None:
if stuff is None:
return
item = -1
for id, st in enumerate(stuff):
for id_, st in enumerate(stuff):
item = self.GetNextItem(item)
@@ -270,11 +267,11 @@ class Display(wx.ListCtrl):
colItem.SetMask(mask)
self.SetItem(colItem)
self.SetItemData(item, id)
self.SetItemData(item, id_)
# self.Freeze()
# self.Freeze()
if 'wxMSW' in wx.PlatformInfo:
for i,col in enumerate(self.activeColumns):
for i, col in enumerate(self.activeColumns):
if not col.resized:
self.SetColumnWidth(i, col.size)
else:
@@ -289,9 +286,7 @@ class Display(wx.ListCtrl):
self.SetColumnWidth(i, headerWidth)
else:
self.SetColumnWidth(i, col.size)
# self.Thaw()
# self.Thaw()
def update(self, stuff):
self.populate(stuff)

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,43 +15,49 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import service
import gui.globalEvents as GE
import gui.marketBrowser as mb
import gui.display as d
from gui.marketBrowser import ITEM_SELECTED, ItemSelected
from gui.display import Display
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
from service.fit import Fit
from service.market import Market
class DroneViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def __init__(self, dropFn, *args, **kwargs):
super(DroneViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
class DroneView(d.Display):
DEFAULT_COLS = ["State",
#"Base Icon",
"Base Name",
# "prop:droneDps,droneBandwidth",
"Max Range",
"Miscellanea",
"attr:maxVelocity",
"Price",]
class DroneView(Display):
DEFAULT_COLS = [
"State",
# "Base Icon",
"Base Name",
# "prop:droneDps,droneBandwidth",
"Max Range",
"Miscellanea",
"attr:maxVelocity",
"Price",
]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
@@ -59,19 +65,18 @@ class DroneView(d.Display):
self.hoveredColumn = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem)
self.mainFrame.Bind(ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
if "__WXGTK__" in wx.PlatformInfo:
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
self.SetDropTarget(DroneViewDrop(self.handleDragDrop))
@@ -107,7 +112,6 @@ class DroneView(d.Display):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
row = self.GetFirstSelected()
firstSel = row
if row != -1:
drone = self.drones[self.GetItemData(row)]
self.removeDrone(drone)
@@ -118,31 +122,32 @@ class DroneView(d.Display):
row = event.GetIndex()
if row != -1:
data = wx.PyTextDataObject()
data.SetText("drone:"+str(row))
data.SetText("drone:" + str(row))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
res = dropSource.DoDragDrop()
dropSource.DoDragDrop()
def handleDragDrop(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "drone": # we want to merge drones
srcRow = int(data[1])
dstRow, _ = self.HitTest((x, y))
if srcRow != -1 and dstRow != -1:
self._merge(srcRow, dstRow)
elif data[0] == "market":
wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1])))
wx.PostEvent(self.mainFrame, ItemSelected(itemID=int(data[1])))
def _merge(self, src, dst):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
if sFit.mergeDrones(fitID, self.drones[src], self.drones[dst]):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -150,8 +155,9 @@ class DroneView(d.Display):
'Heavy Attack Drones', 'Sentry Drones', 'Fighters',
'Fighter Bombers', 'Combat Utility Drones',
'Electronic Warfare Drones', 'Logistic Drones', 'Mining Drones', 'Salvage Drones')
def droneKey(self, drone):
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
groupName = sMkt.getMarketGroupByItem(drone.item).name
@@ -159,12 +165,12 @@ class DroneView(d.Display):
drone.item.name)
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
#Clear list and get out if current fitId is None
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
@@ -177,7 +183,6 @@ class DroneView(d.Display):
if stuff is not None:
stuff.sort(key=self.droneKey)
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
@@ -191,9 +196,8 @@ class DroneView(d.Display):
self.update(stuff)
event.Skip()
def addItem(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
@@ -218,7 +222,7 @@ class DroneView(d.Display):
def removeDrone(self, drone):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.removeDrone(fitID, self.original.index(drone))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -229,7 +233,7 @@ class DroneView(d.Display):
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
drone = self.drones[row]
sFit.toggleDrone(fitID, self.original.index(drone))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -244,7 +248,7 @@ class DroneView(d.Display):
if sel != -1:
drone = self.drones[sel]
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
sourceContext = "droneItem"
itemContext = sMkt.getCategoryByItem(drone.item).name
menu = ContextMenu.getMenu((drone,), (sourceContext, itemContext))

94
gui/errorDialog.py Normal file
View File

@@ -0,0 +1,94 @@
# ===============================================================================
# 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 <http://www.gnu.org/licenses/>.
# ===============================================================================
import wx
import sys
import gui.utils.fonts as fonts
import config
class ErrorFrame(wx.Frame):
def __init__(self, exception, tb):
wx.Frame.__init__(self, None, id=wx.ID_ANY, title="pyfa error", pos=wx.DefaultPosition, size=wx.Size(500, 400),
style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER | wx.STAY_ON_TOP)
desc = "pyfa has experienced an unexpected error. Below is the " \
"Traceback that contains crucial information about how this " \
"error was triggered. Please contact the developers with " \
"the information provided through the EVE Online forums " \
"or file a GitHub issue."
self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
if 'wxMSW' in wx.PlatformInfo:
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
mainSizer = wx.BoxSizer(wx.VERTICAL)
headSizer = wx.BoxSizer(wx.HORIZONTAL)
self.headingText = wx.StaticText(self, wx.ID_ANY, "Error!", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTRE)
self.headingText.SetFont(wx.Font(14, 74, 90, 92, False))
headSizer.Add(self.headingText, 1, wx.ALL, 5)
mainSizer.Add(headSizer, 0, wx.EXPAND, 5)
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND | wx.ALL, 5)
descSizer = wx.BoxSizer(wx.HORIZONTAL)
self.descText = wx.TextCtrl(self, wx.ID_ANY, desc, wx.DefaultPosition, wx.DefaultSize,
wx.TE_AUTO_URL | wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE | wx.TRANSPARENT_WINDOW)
self.descText.SetFont(wx.Font(fonts.BIG, wx.SWISS, wx.NORMAL, wx.NORMAL))
descSizer.Add(self.descText, 1, wx.ALL, 5)
mainSizer.Add(descSizer, 1, wx.EXPAND, 5)
self.eveForums = wx.HyperlinkCtrl(self, wx.ID_ANY, "EVE Forums Thread", "https://forums.eveonline.com/default.aspx?g=posts&t=466425",
wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE)
mainSizer.Add(self.eveForums, 0, wx.ALL, 2)
self.eveForums = wx.HyperlinkCtrl(self, wx.ID_ANY, "Github Issues", "https://github.com/pyfa-org/Pyfa/issues",
wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE)
mainSizer.Add(self.eveForums, 0, wx.ALL, 2)
# mainSizer.AddSpacer((0, 5), 0, wx.EXPAND, 5)
self.errorTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2 | wx.TE_DONTWRAP)
self.errorTextCtrl.SetFont(wx.Font(8, wx.FONTFAMILY_TELETYPE, wx.NORMAL, wx.NORMAL))
mainSizer.Add(self.errorTextCtrl, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5)
self.errorTextCtrl.AppendText("pyfa root: ")
self.errorTextCtrl.AppendText(config.pyfaPath or "Unknown")
self.errorTextCtrl.AppendText('\n')
self.errorTextCtrl.AppendText("save path: ")
self.errorTextCtrl.AppendText(config.savePath or "Unknown")
self.errorTextCtrl.AppendText('\n')
self.errorTextCtrl.AppendText("fs encoding: ")
self.errorTextCtrl.AppendText(sys.getfilesystemencoding())
self.errorTextCtrl.AppendText('\n\n')
self.errorTextCtrl.AppendText(tb)
self.SetSizer(mainSizer)
mainSizer.Layout()
self.Layout()
self.Centre(wx.BOTH)
self.Show()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,37 +15,40 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import service
import gui.globalEvents as GE
import gui.marketBrowser as mb
import gui.marketBrowser as marketBrowser
import gui.mainFrame
import gui.display as d
from gui.builtinViewColumns.state import State
from eos.types import Slot
from eos.saveddata.module import Slot
from gui.contextMenu import ContextMenu
from service.fit import Fit
from service.market import Market
class FighterViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def __init__(self, dropFn, *args, **kwargs):
super(FighterViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
class FighterView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, style=wx.TAB_TRAVERSAL )
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, style=wx.TAB_TRAVERSAL)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.labels = ["Light", "Heavy", "Support"]
@@ -55,7 +58,7 @@ class FighterView(wx.Panel):
mainSizer.Add(self.fighterDisplay, 1, wx.EXPAND, 0)
textSizer = wx.BoxSizer(wx.HORIZONTAL)
textSizer.AddSpacer(( 0, 0), 1, wx.EXPAND, 5)
textSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
for x in self.labels:
lbl = wx.StaticText(self, wx.ID_ANY, x.capitalize())
@@ -74,14 +77,13 @@ class FighterView(wx.Panel):
mainSizer.Add(textSizer, 0, wx.EXPAND, 5)
self.SetSizer( mainSizer )
self.SetSizer(mainSizer)
self.SetAutoLayout(True)
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
activeFitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(activeFitID)
@@ -90,7 +92,8 @@ class FighterView(wx.Panel):
slot = getattr(Slot, "F_{}".format(x.upper()))
used = fit.getSlotsUsed(slot)
total = fit.getNumSlots(slot)
color = wx.Colour(204, 51, 51) if used > total else wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
color = wx.Colour(204, 51, 51) if used > total else wx.SystemSettings_GetColour(
wx.SYS_COLOUR_WINDOWTEXT)
lbl = getattr(self, "label%sUsed" % x.capitalize())
lbl.SetLabel(str(int(used)))
@@ -105,15 +108,15 @@ class FighterView(wx.Panel):
class FighterDisplay(d.Display):
DEFAULT_COLS = ["State",
#"Base Icon",
# "Base Icon",
"Base Name",
# "prop:droneDps,droneBandwidth",
#"Max Range",
#"Miscellanea",
# "Max Range",
# "Miscellanea",
"attr:maxVelocity",
"Fighter Abilities"
#"Price",
]
# "Price",
]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
@@ -124,19 +127,18 @@ class FighterDisplay(d.Display):
self.hoveredColumn = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem)
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
if "__WXGTK__" in wx.PlatformInfo:
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
self.SetDropTarget(FighterViewDrop(self.handleDragDrop))
@@ -172,7 +174,6 @@ class FighterDisplay(d.Display):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
row = self.GetFirstSelected()
firstSel = row
if row != -1:
fighter = self.fighters[self.GetItemData(row)]
self.removeFighter(fighter)
@@ -183,29 +184,30 @@ class FighterDisplay(d.Display):
row = event.GetIndex()
if row != -1:
data = wx.PyTextDataObject()
data.SetText("fighter:"+str(row))
data.SetText("fighter:" + str(row))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
res = dropSource.DoDragDrop()
dropSource.DoDragDrop()
def handleDragDrop(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "fighter": # we want to merge fighters
srcRow = int(data[1])
dstRow, _ = self.HitTest((x, y))
if srcRow != -1 and dstRow != -1:
self._merge(srcRow, dstRow)
elif data[0] == "market":
wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1])))
wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1])))
def _merge(self, src, dst):
@staticmethod
def _merge(src, dst):
return
'''
@@ -215,7 +217,7 @@ class FighterDisplay(d.Display):
'Electronic Warfare Drones', 'Logistic Drones', 'Mining Drones', 'Salvage Drones',
'Light Fighters', 'Heavy Fighters', 'Support Fighters')
def droneKey(self, drone):
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
groupName = sMkt.getMarketGroupByItem(drone.item).name
print groupName
@@ -224,12 +226,12 @@ class FighterDisplay(d.Display):
'''
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.Parent.DisablePage(self.Parent, not fit)
#Clear list and get out if current fitId is None
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
@@ -257,9 +259,8 @@ class FighterDisplay(d.Display):
self.update(stuff)
event.Skip()
def addItem(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
trigger = sFit.addFighter(fitID, event.itemID)
if trigger:
@@ -278,7 +279,7 @@ class FighterDisplay(d.Display):
def removeFighter(self, fighter):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.removeFighter(fitID, self.original.index(fighter))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -289,7 +290,7 @@ class FighterDisplay(d.Display):
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fighter = self.fighters[row]
sFit.toggleFighter(fitID, self.original.index(fighter))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -304,7 +305,7 @@ class FighterDisplay(d.Display):
if sel != -1:
fighter = self.fighters[sel]
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
sourceContext = "fighterItem"
itemContext = sMkt.getCategoryByItem(fighter.item).name
menu = ContextMenu.getMenu((fighter,), (sourceContext, itemContext))

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx.lib.newevent
FitChanged, FIT_CHANGED = wx.lib.newevent.NewEvent()

View File

@@ -1,36 +1,39 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
class Graph(object):
views = []
@classmethod
def register(cls):
Graph.views.append(cls)
def __init__(self):
self.name = ""
def getFields(self, fit, fields):
raise NotImplementedError()
def getIcons(self):
return None
from gui.builtinGraphs import *
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
class Graph(object):
views = []
@classmethod
def register(cls):
Graph.views.append(cls)
def __init__(self):
self.name = ""
def getFields(self, fit, fields):
raise NotImplementedError()
def getIcons(self):
return None
# noinspection PyUnresolvedReferences
from gui.builtinGraphs import fitDps # noqa: E402, F401

View File

@@ -1,278 +1,349 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
import os
from gui.bitmapLoader import BitmapLoader
import gui.display
import gui.globalEvents as GE
from gui.graph import Graph
import service
import gui.mainFrame
enabled = True
mplImported = False
class GraphFrame(wx.Frame):
def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):
global enabled
global mplImported
self.legendFix = False
if not enabled:
return
try:
import matplotlib as mpl
try:
cache_dir = mpl._get_cachedir()
except:
cache_dir = unicode(os.path.expanduser(os.path.join("~", ".matplotlib")))
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
from matplotlib.figure import Figure
enabled = True
if mpl.__version__[0] != "1":
print "pyfa: Found matplotlib version ",mpl.__version__, " - activating OVER9000 workarounds"
print "pyfa: Recommended minimum matplotlib version is 1.0.0"
self.legendFix = True
except:
print "Problems importing matplotlib; continuing without graphs"
enabled = False
return
mplImported = True
wx.Frame.__init__(self, parent, title=u"pyfa: Graph Generator", style=style, size=(520, 390))
i = wx.IconFromBitmap(BitmapLoader.getBitmap("graphs_small", "gui"))
self.SetIcon(i)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.CreateStatusBar()
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.mainSizer)
sFit = service.Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
self.fits = [fit] if fit is not None else []
self.fitList = FitList(self)
self.fitList.SetMinSize((270, -1))
self.fitList.fitList.update(self.fits)
self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)
self.figure = Figure(figsize=(4, 3))
rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
clr = [c/255. for c in rgbtuple]
self.figure.set_facecolor( clr )
self.figure.set_edgecolor( clr )
self.canvas = Canvas(self, -1, self.figure)
self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )
self.subplot = self.figure.add_subplot(111)
self.subplot.grid(True)
self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
self.mainSizer.Add(wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ), 0 , wx.EXPAND)
self.gridPanel = wx.Panel(self)
self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND)
dummyBox = wx.BoxSizer(wx.VERTICAL)
self.gridPanel.SetSizer(dummyBox)
self.gridSizer = wx.FlexGridSizer(0, 4)
self.gridSizer.AddGrowableCol(1)
dummyBox.Add(self.gridSizer, 0, wx.EXPAND)
for view in Graph.views:
view = view()
self.graphSelection.Append(view.name, view)
self.graphSelection.SetSelection(0)
self.fields = {}
self.select(0)
self.sl1 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
self.mainSizer.Add(self.sl1,0, wx.EXPAND)
self.mainSizer.Add(self.fitList, 0, wx.EXPAND)
self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.mainFrame.Bind(GE.FIT_CHANGED, self.draw)
self.Bind(wx.EVT_CLOSE, self.close)
self.Fit()
self.SetMinSize(self.GetSize())
def handleDrag(self, type, fitID):
if type == "fit":
self.AppendFitToList(fitID)
def close(self, event):
self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem)
self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
event.Skip()
def getView(self):
return self.graphSelection.GetClientData(self.graphSelection.GetSelection())
def getValues(self):
values = {}
for fieldName, field in self.fields.iteritems():
values[fieldName] = field.GetValue()
return values
def select(self, index):
view = self.getView()
icons = view.getIcons()
labels = view.getLabels()
sizer = self.gridSizer
self.gridPanel.DestroyChildren()
self.fields.clear()
#Setup textboxes
for field, defaultVal in view.getFields().iteritems():
textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
self.fields[field] = textBox
textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)
if defaultVal is not None:
if not isinstance(defaultVal, basestring):
defaultVal = ("%f" % defaultVal).rstrip("0")
if defaultVal[-1:] == ".":
defaultVal = defaultVal + "0"
textBox.ChangeValue(defaultVal)
imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
if icons:
icon = icons.get(field)
if icon is not None:
static = wx.StaticBitmap(self.gridPanel)
static.SetBitmap(icon)
imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
if labels:
label = labels.get(field)
label = label if label is not None else field
else:
label = field
imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
self.draw()
def draw(self, event=None):
values = self.getValues()
view = self.getView()
self.subplot.clear()
self.subplot.grid(True)
legend = []
for fit in self.fits:
try:
success, status = view.getPoints(fit, values)
if not success:
#TODO: Add a pwetty statys bar to report errors with
self.SetStatusText(status)
return
x, y = success, status
self.subplot.plot(x, y)
legend.append(fit.name)
except:
self.SetStatusText("Invalid values in '%s'" % fit.name)
self.canvas.draw()
return
if self.legendFix and len(legend) > 0:
leg = self.subplot.legend(tuple(legend), "upper right" , shadow = False)
for t in leg.get_texts():
t.set_fontsize('small')
for l in leg.get_lines():
l.set_linewidth(1)
elif not self.legendFix and len(legend) >0:
leg = self.subplot.legend(tuple(legend), "upper right" , shadow = False, frameon = False)
for t in leg.get_texts():
t.set_fontsize('small')
for l in leg.get_lines():
l.set_linewidth(1)
self.canvas.draw()
self.SetStatusText("")
if event is not None:
event.Skip()
def onFieldChanged(self, event):
self.draw()
def AppendFitToList(self, fitID):
sFit = service.Fit.getInstance()
fit = sFit.getFit(fitID)
if fit not in self.fits:
self.fits.append(fit)
self.fitList.fitList.update(self.fits)
self.draw()
def removeItem(self, event):
row, _ = self.fitList.fitList.HitTest(event.Position)
if row != -1:
del self.fits[row]
self.fitList.fitList.update(self.fits)
self.draw()
class FitList(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.mainSizer)
self.fitList = FitDisplay(self)
self.mainSizer.Add(self.fitList, 1, wx.EXPAND)
fitToolTip = wx.ToolTip("Drag a fit into this list to graph it")
self.fitList.SetToolTip(fitToolTip)
class FitDisplay(gui.display.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name"]
def __init__(self, parent):
gui.display.Display.__init__(self, parent)
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
import os
from logbook import Logger
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
import gui.display
import gui.mainFrame
import gui.globalEvents as GE
from gui.graph import Graph
from gui.bitmapLoader import BitmapLoader
pyfalog = Logger(__name__)
try:
import matplotlib as mpl
mpl_version = int(mpl.__version__[0])
if mpl_version >= 2:
mpl.use('wxagg')
mplImported = True
else:
mplImported = False
from matplotlib.patches import Patch
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
from matplotlib.figure import Figure
graphFrame_enabled = True
mplImported = True
except ImportError:
Patch = mpl = Canvas = Figure = None
graphFrame_enabled = False
mplImported = False
pyfalog = Logger(__name__)
class GraphFrame(wx.Frame):
def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):
global graphFrame_enabled
global mplImported
self.Patch = None
self.mpl_version = -1
try:
import matplotlib as mpl
self.mpl_version = int(mpl.__version__[0])
if self.mpl_version >= 2:
mpl.use('wxagg')
mplImported = True
else:
mplImported = False
from matplotlib.patches import Patch
self.Patch = Patch
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
from matplotlib.figure import Figure
graphFrame_enabled = True
except ImportError:
Patch = mpl = Canvas = Figure = None
graphFrame_enabled = False
self.legendFix = False
if not graphFrame_enabled:
pyfalog.info("Problems importing matplotlib; continuing without graphs")
return
try:
cache_dir = mpl._get_cachedir()
except:
cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib"))
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')
graphFrame_enabled = True
if int(mpl.__version__[0]) < 1:
print("pyfa: Found matplotlib version ", mpl.__version__, " - activating OVER9000 workarounds")
print("pyfa: Recommended minimum matplotlib version is 1.0.0")
self.legendFix = True
mplImported = True
wx.Frame.__init__(self, parent, title=u"pyfa: Graph Generator", style=style, size=(520, 390))
i = wx.IconFromBitmap(BitmapLoader.getBitmap("graphs_small", "gui"))
self.SetIcon(i)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.CreateStatusBar()
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.mainSizer)
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
self.fits = [fit] if fit is not None else []
self.fitList = FitList(self)
self.fitList.SetMinSize((270, -1))
self.fitList.fitList.update(self.fits)
self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)
self.figure = Figure(figsize=(4, 3))
rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
clr = [c / 255. for c in rgbtuple]
self.figure.set_facecolor(clr)
self.figure.set_edgecolor(clr)
self.canvas = Canvas(self, -1, self.figure)
self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))
self.subplot = self.figure.add_subplot(111)
self.subplot.grid(True)
self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
wx.EXPAND)
self.gridPanel = wx.Panel(self)
self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND)
dummyBox = wx.BoxSizer(wx.VERTICAL)
self.gridPanel.SetSizer(dummyBox)
self.gridSizer = wx.FlexGridSizer(0, 4)
self.gridSizer.AddGrowableCol(1)
dummyBox.Add(self.gridSizer, 0, wx.EXPAND)
for view in Graph.views:
view = view()
self.graphSelection.Append(view.name, view)
self.graphSelection.SetSelection(0)
self.fields = {}
self.select(0)
self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
self.mainSizer.Add(self.sl1, 0, wx.EXPAND)
self.mainSizer.Add(self.fitList, 0, wx.EXPAND)
self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.mainFrame.Bind(GE.FIT_CHANGED, self.draw)
self.Bind(wx.EVT_CLOSE, self.close)
self.Fit()
self.SetMinSize(self.GetSize())
def handleDrag(self, type, fitID):
if type == "fit":
self.AppendFitToList(fitID)
def close(self, event):
self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem)
self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
event.Skip()
def getView(self):
return self.graphSelection.GetClientData(self.graphSelection.GetSelection())
def getValues(self):
values = {}
for fieldName, field in self.fields.iteritems():
values[fieldName] = field.GetValue()
return values
def select(self, index):
view = self.getView()
icons = view.getIcons()
labels = view.getLabels()
sizer = self.gridSizer
self.gridPanel.DestroyChildren()
self.fields.clear()
# Setup textboxes
for field, defaultVal in view.getFields().iteritems():
textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
self.fields[field] = textBox
textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)
if defaultVal is not None:
if not isinstance(defaultVal, basestring):
defaultVal = ("%f" % defaultVal).rstrip("0")
if defaultVal[-1:] == ".":
defaultVal += "0"
textBox.ChangeValue(defaultVal)
imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
if icons:
icon = icons.get(field)
if icon is not None:
static = wx.StaticBitmap(self.gridPanel)
static.SetBitmap(icon)
imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
if labels:
label = labels.get(field)
label = label if label is not None else field
else:
label = field
imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0,
wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
self.draw()
def draw(self, event=None):
values = self.getValues()
view = self.getView()
self.subplot.clear()
self.subplot.grid(True)
legend = []
for fit in self.fits:
try:
success, status = view.getPoints(fit, values)
if not success:
# TODO: Add a pwetty statys bar to report errors with
self.SetStatusText(status)
return
x, y = success, status
self.subplot.plot(x, y)
legend.append(fit.name)
except:
pyfalog.warning("Invalid values in '{0}'", fit.name)
self.SetStatusText("Invalid values in '%s'" % fit.name)
self.canvas.draw()
return
if self.mpl_version < 2:
if self.legendFix and len(legend) > 0:
leg = self.subplot.legend(tuple(legend), "upper right", shadow=False)
for t in leg.get_texts():
t.set_fontsize('small')
for l in leg.get_lines():
l.set_linewidth(1)
elif not self.legendFix and len(legend) > 0:
leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False)
for t in leg.get_texts():
t.set_fontsize('small')
for l in leg.get_lines():
l.set_linewidth(1)
elif self.mpl_version >= 2:
legend2 = []
legend_colors = {
0: "blue",
1: "orange",
2: "green",
3: "red",
4: "purple",
5: "brown",
6: "pink",
7: "grey",
}
for i, i_name in enumerate(legend):
try:
selected_color = legend_colors[i]
except:
selected_color = None
legend2.append(Patch(color=selected_color, label=i_name), )
if len(legend2) > 0:
leg = self.subplot.legend(handles=legend2)
for t in leg.get_texts():
t.set_fontsize('small')
for l in leg.get_lines():
l.set_linewidth(1)
self.canvas.draw()
self.SetStatusText("")
if event is not None:
event.Skip()
def onFieldChanged(self, event):
self.draw()
def AppendFitToList(self, fitID):
sFit = Fit.getInstance()
fit = sFit.getFit(fitID)
if fit not in self.fits:
self.fits.append(fit)
self.fitList.fitList.update(self.fits)
self.draw()
def removeItem(self, event):
row, _ = self.fitList.fitList.HitTest(event.Position)
if row != -1:
del self.fits[row]
self.fitList.fitList.update(self.fits)
self.draw()
class FitList(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.mainSizer)
self.fitList = FitDisplay(self)
self.mainSizer.Add(self.fitList, 1, wx.EXPAND)
fitToolTip = wx.ToolTip("Drag a fit into this list to graph it")
self.fitList.SetToolTip(fitToolTip)
class FitDisplay(gui.display.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name"]
def __init__(self, parent):
gui.display.Display.__init__(self, parent)

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,31 +15,33 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import service
import gui.display as d
import gui.marketBrowser as mb
import gui.marketBrowser as marketBrowser
import gui.mainFrame
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
import globalEvents as GE
from eos.types import ImplantLocation
from eos.saveddata.fit import ImplantLocation
from service.fit import Fit
from service.market import Market
class ImplantView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, style=wx.TAB_TRAVERSAL )
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, style=wx.TAB_TRAVERSAL)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.implantDisplay = ImplantDisplay(self)
mainSizer.Add(self.implantDisplay, 1, wx.EXPAND, 0 )
mainSizer.Add(self.implantDisplay, 1, wx.EXPAND, 0)
radioSizer = wx.BoxSizer(wx.HORIZONTAL)
radioSizer.AddSpacer(( 0, 0), 1, wx.EXPAND, 5)
radioSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
self.rbFit = wx.RadioButton(self, id=wx.ID_ANY, label="Use Fit-specific Implants", style=wx.RB_GROUP)
self.rbChar = wx.RadioButton(self, id=wx.ID_ANY, label="Use Character Implants")
radioSizer.Add(self.rbFit, 0, wx.ALL, 5)
@@ -48,7 +50,7 @@ class ImplantView(wx.Panel):
mainSizer.Add(radioSizer, 0, wx.EXPAND, 5)
self.SetSizer( mainSizer )
self.SetSizer(mainSizer)
self.SetAutoLayout(True)
self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioSelect, self.rbFit)
@@ -56,7 +58,7 @@ class ImplantView(wx.Panel):
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
activeFitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(activeFitID)
if fit:
@@ -70,7 +72,7 @@ class ImplantView(wx.Panel):
def OnRadioSelect(self, event):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.toggleImplantSource(fitID, ImplantLocation.FIT if self.rbFit.GetValue() else ImplantLocation.CHARACTER)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -88,17 +90,17 @@ class ImplantDisplay(d.Display):
self.lastFitId = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem)
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
if "__WXGTK__" in wx.PlatformInfo:
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
def kbEvent(self,event):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
row = self.GetFirstSelected()
@@ -107,12 +109,12 @@ class ImplantDisplay(d.Display):
event.Skip()
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.Parent.DisablePage(self.Parent, not fit or fit.isStructure)
#Clear list and get out if current fitId is None
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
@@ -121,7 +123,8 @@ class ImplantDisplay(d.Display):
self.original = fit.implants if fit is not None else None
self.implants = stuff = fit.appliedImplants if fit is not None else None
if stuff is not None: stuff.sort(key=lambda implant: implant.slot)
if stuff is not None:
stuff.sort(key=lambda implant: implant.slot)
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
@@ -137,7 +140,7 @@ class ImplantDisplay(d.Display):
event.Skip()
def addItem(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
@@ -161,7 +164,7 @@ class ImplantDisplay(d.Display):
def removeImplant(self, implant):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.removeImplant(fitID, self.original.index(implant))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -172,7 +175,7 @@ class ImplantDisplay(d.Display):
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.toggleImplant(fitID, row)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -185,7 +188,7 @@ class ImplantDisplay(d.Display):
sel = self.GetFirstSelected()
menu = None
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
if not fit:
@@ -194,7 +197,7 @@ class ImplantDisplay(d.Display):
if sel != -1:
implant = fit.appliedImplants[sel]
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
sourceContext = "implantItem" if fit.implantSource == ImplantLocation.FIT else "implantItemChar"
itemContext = sMkt.getCategoryByItem(implant.item).name

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,28 +15,31 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
import sys
import os.path
from logbook import Logger
import sqlalchemy
# noinspection PyPackageRequirements
import wx
# noinspection PyPackageRequirements
from wx._core import PyDeadObjectError
# noinspection PyPackageRequirements
from wx.lib.wordwrap import wordwrap
# noinspection PyPackageRequirements
from wx.lib.inspection import InspectionTool
import time
from codecs import open
from wx._core import PyDeadObjectError
from wx.lib.wordwrap import wordwrap
import service
import config
import threading
import webbrowser
from eos.config import gamedata_version
import gui.aboutData
import gui.chromeTabs
import gui.utils.animUtils as animUtils
from gui.chromeTabs import PFNotebook
import gui.globalEvents as GE
from gui.bitmapLoader import BitmapLoader
@@ -56,40 +59,62 @@ from gui.graphFrame import GraphFrame
from gui.copySelectDialog import CopySelectDialog
from gui.utils.clipboard import toClipboard, fromClipboard
from gui.updateDialog import UpdateDialog
from gui.builtinViews import *
# noinspection PyUnresolvedReferences
from gui.builtinViews import emptyView, entityEditor, fittingView, implantEditor # noqa: F401
from gui import graphFrame
from service.settings import SettingsProvider
from service.fit import Fit
from service.character import Character
from service.update import Update
# import this to access override setting
from eos.modifiedAttributeDict import ModifiedAttributeDict
from eos.db.saveddata.loadDefaultDatabaseValues import DefaultDatabaseValues
from eos.db.saveddata.queries import getFit as db_getFit
from service.port import Port
from service.settings import HTMLExportSettings
from time import gmtime, strftime
if not 'wxMac' in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3,0)):
import threading
import webbrowser
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
from service.crest import Crest
from service.crest import CrestModes
from gui.crestFittings import CrestFittings, ExportToEve, CrestMgmt
try:
from gui.propertyEditor import AttributeEditor
disableOverrideEditor = False
except ImportError, e:
print "Error loading Attribute Editor: %s.\nAccess to Attribute Editor is disabled."%e.message
disableOverrideEditor = True
disableOverrideEditor = False
#dummy panel(no paint no erasebk)
try:
from gui.propertyEditor import AttributeEditor
except ImportError as e:
AttributeEditor = None
print("Error loading Attribute Editor: %s.\nAccess to Attribute Editor is disabled." % e.message)
disableOverrideEditor = True
pyfalog = Logger(__name__)
# dummy panel(no paint no erasebk)
class PFPanel(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent)
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnBkErase)
def OnPaint(self, event):
event.Skip()
def OnBkErase(self, event):
pass
class OpenFitsThread(threading.Thread):
def __init__(self, fits, callback):
threading.Thread.__init__(self)
self.name = "LoadingOpenFits"
self.mainFrame = MainFrame.getInstance()
self.callback = callback
self.fits = fits
@@ -111,51 +136,56 @@ class OpenFitsThread(threading.Thread):
wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fits[-1], startup=2))
wx.CallAfter(self.callback)
class MainFrame(wx.Frame):
__instance = None
@classmethod
def getInstance(cls):
return cls.__instance if cls.__instance is not None else MainFrame()
def __init__(self, title):
self.title=title
def __init__(self, title="pyfa"):
pyfalog.debug("Initialize MainFrame")
self.title = title
wx.Frame.__init__(self, None, wx.ID_ANY, self.title)
MainFrame.__instance = self
#Load stored settings (width/height/maximized..)
# Load stored settings (width/height/maximized..)
self.LoadMainFrameAttribs()
#Fix for msw (have the frame background color match panel color
if 'wxMSW' in wx.PlatformInfo:
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
self.disableOverrideEditor = disableOverrideEditor
#Load and set the icon for pyfa main window
# Fix for msw (have the frame background color match panel color
if 'wxMSW' in wx.PlatformInfo:
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
# Load and set the icon for pyfa main window
i = wx.IconFromBitmap(BitmapLoader.getBitmap("pyfa", "gui"))
self.SetIcon(i)
#Create the layout and windows
# Create the layout and windows
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
self.browser_fitting_split = wx.SplitterWindow(self, style = wx.SP_LIVE_UPDATE)
self.fitting_additions_split = wx.SplitterWindow(self.browser_fitting_split, style = wx.SP_LIVE_UPDATE)
self.browser_fitting_split = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
self.fitting_additions_split = wx.SplitterWindow(self.browser_fitting_split, style=wx.SP_LIVE_UPDATE)
mainSizer.Add(self.browser_fitting_split, 1, wx.EXPAND | wx.LEFT, 2)
self.fitMultiSwitch = MultiSwitch(self.fitting_additions_split)
self.additionsPane = AdditionsPane(self.fitting_additions_split)
self.notebookBrowsers = gui.chromeTabs.PFNotebook(self.browser_fitting_split, False)
self.notebookBrowsers = PFNotebook(self.browser_fitting_split, False)
marketImg = BitmapLoader.getImage("market_small", "gui")
shipBrowserImg = BitmapLoader.getImage("ship_small", "gui")
self.marketBrowser = MarketBrowser(self.notebookBrowsers)
self.notebookBrowsers.AddPage(self.marketBrowser, "Market", tabImage = marketImg, showClose = False)
self.notebookBrowsers.AddPage(self.marketBrowser, "Market", tabImage=marketImg, showClose=False)
self.marketBrowser.splitter.SetSashPosition(self.marketHeight)
self.shipBrowser = ShipBrowser(self.notebookBrowsers)
self.notebookBrowsers.AddPage(self.shipBrowser, "Fittings", tabImage = shipBrowserImg, showClose = False)
self.notebookBrowsers.AddPage(self.shipBrowser, "Fittings", tabImage=shipBrowserImg, showClose=False)
self.notebookBrowsers.SetSelection(1)
@@ -180,31 +210,31 @@ class MainFrame(wx.Frame):
self.SetSizer(mainSizer)
#Add menu
# Add menu
self.addPageId = wx.NewId()
self.closePageId = wx.NewId()
self.widgetInspectMenuID = wx.NewId()
self.SetMenuBar(MainMenuBar())
self.SetMenuBar(MainMenuBar(self))
self.registerMenu()
#Internal vars to keep track of other windows (graphing/stats)
# Internal vars to keep track of other windows (graphing/stats)
self.graphFrame = None
self.statsWnds = []
self.activeStatsWnd = None
self.Bind(wx.EVT_CLOSE, self.OnClose)
#Show ourselves
# Show ourselves
self.Show()
self.LoadPreviousOpenFits()
#Check for updates
self.sUpdate = service.Update.getInstance()
# Check for updates
self.sUpdate = Update.getInstance()
self.sUpdate.CheckUpdate(self.ShowUpdateBox)
if not 'wxMac' in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3,0)):
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
self.Bind(GE.EVT_SSO_LOGIN, self.onSSOLogin)
self.Bind(GE.EVT_SSO_LOGOUT, self.onSSOLogout)
@@ -216,9 +246,10 @@ class MainFrame(wx.Frame):
dlg.ShowModal()
def LoadPreviousOpenFits(self):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
self.prevOpenFits = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []})
self.prevOpenFits = SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits",
{"enabled": False, "pyfaOpenFits": []})
fits = self.prevOpenFits['pyfaOpenFits']
# Remove any fits that cause exception when fetching (non-existent fits)
@@ -237,8 +268,10 @@ class MainFrame(wx.Frame):
OpenFitsThread(fits, self.closeWaitDialog)
def LoadMainFrameAttribs(self):
mainFrameDefaultAttribs = {"wnd_width": 1000, "wnd_height": 700, "wnd_maximized": False, "browser_width": 300, "market_height": 0, "fitting_height": -200}
self.mainFrameAttribs = service.SettingsProvider.getInstance().getSettings("pyfaMainWindowAttribs", mainFrameDefaultAttribs)
mainFrameDefaultAttribs = {"wnd_width": 1000, "wnd_height": 700, "wnd_maximized": False, "browser_width": 300,
"market_height": 0, "fitting_height": -200}
self.mainFrameAttribs = SettingsProvider.getInstance().getSettings("pyfaMainWindowAttribs",
mainFrameDefaultAttribs)
if self.mainFrameAttribs["wnd_maximized"]:
width = mainFrameDefaultAttribs["wnd_width"]
@@ -258,7 +291,7 @@ class MainFrame(wx.Frame):
def UpdateMainFrameAttribs(self):
if self.IsIconized():
return
width,height = self.GetSize()
width, height = self.GetSize()
self.mainFrameAttribs["wnd_width"] = width
self.mainFrameAttribs["wnd_height"] = height
@@ -292,7 +325,7 @@ class MainFrame(wx.Frame):
return m() if m is not None else None
def getActiveView(self):
sel = self.fitMultiSwitch.GetSelectedPage()
self.fitMultiSwitch.GetSelectedPage()
def CloseCurrentPage(self, evt):
ms = self.fitMultiSwitch
@@ -305,14 +338,14 @@ class MainFrame(wx.Frame):
self.UpdateMainFrameAttribs()
# save open fits
self.prevOpenFits['pyfaOpenFits'] = [] # clear old list
self.prevOpenFits['pyfaOpenFits'] = [] # clear old list
for page in self.fitMultiSwitch.pages:
m = getattr(page, "getActiveFit", None)
if m is not None:
self.prevOpenFits['pyfaOpenFits'].append(m())
self.prevOpenFits['pyfaOpenFits'].append(m())
# save all teh settingz
service.SettingsProvider.getInstance().saveAll()
SettingsProvider.getInstance().saveAll()
event.Skip()
def ExitApp(self, event):
@@ -320,86 +353,107 @@ class MainFrame(wx.Frame):
event.Skip()
def ShowAboutBox(self, evt):
import eos.config
v = sys.version_info
info = wx.AboutDialogInfo()
info.Name = "pyfa"
info.Version = gui.aboutData.versionString
try:
import matplotlib
matplotlib_version = matplotlib.__version__
except:
matplotlib_version = None
info.Description = wordwrap(gui.aboutData.description + "\n\nDevelopers:\n\t" +
"\n\t".join(gui.aboutData.developers) +
"\n\nAdditional credits:\n\t" +
"\n\t".join(gui.aboutData.credits) +
"\n\nLicenses:\n\t" +
"\n\t".join(gui.aboutData.licenses) +
"\n\nEVE Data: \t" + eos.config.gamedata_version +
"\nPython: \t\t" + '{}.{}.{}'.format(v.major, v.minor, v.micro) +
"\nwxPython: \t" + wx.__version__ +
"\nSQLAlchemy: \t" + sqlalchemy.__version__,
500, wx.ClientDC(self))
if "__WXGTK__" in wx.PlatformInfo:
"\n\t".join(gui.aboutData.developers) +
"\n\nAdditional credits:\n\t" +
"\n\t".join(gui.aboutData.credits) +
"\n\nLicenses:\n\t" +
"\n\t".join(gui.aboutData.licenses) +
"\n\nEVE Data: \t" + gamedata_version +
"\nPython: \t\t" + '{}.{}.{}'.format(v.major, v.minor, v.micro) +
"\nwxPython: \t" + wx.__version__ +
"\nSQLAlchemy: \t" + sqlalchemy.__version__ +
"\nmatplotlib: \t {}".format(matplotlib_version if matplotlib_version else "Not Installed"),
500, wx.ClientDC(self))
if "__WXGTK__" in wx.PlatformInfo:
forumUrl = "http://forums.eveonline.com/default.aspx?g=posts&amp;t=466425"
else:
forumUrl = "http://forums.eveonline.com/default.aspx?g=posts&t=466425"
info.WebSite = (forumUrl, "pyfa thread at EVE Online forum")
wx.AboutBox(info)
def showCharacterEditor(self, event):
dlg=CharacterEditor(self)
dlg = CharacterEditor(self)
dlg.Show()
def showAttrEditor(self, event):
dlg=AttributeEditor(self)
dlg = AttributeEditor(self)
dlg.Show()
def showTargetResistsEditor(self, event):
ResistsEditorDlg(self)
def showDamagePatternEditor(self, event):
dlg=DmgPatternEditorDlg(self)
dlg = DmgPatternEditorDlg(self)
dlg.ShowModal()
dlg.Destroy()
try:
dlg.Destroy()
except PyDeadObjectError:
pyfalog.error("Tried to destroy an object that doesn't exist in <showDamagePatternEditor>.")
def showImplantSetEditor(self, event):
ImplantSetEditorDlg(self)
def showExportDialog(self, event):
""" Export active fit """
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.getActiveFit())
defaultFile = "%s - %s.xml"%(fit.ship.item.name, fit.name) if fit else None
defaultFile = "%s - %s.xml" % (fit.ship.item.name, fit.name) if fit else None
dlg = wx.FileDialog(self, "Save Fitting As...",
wildcard = "EVE XML fitting files (*.xml)|*.xml",
style = wx.FD_SAVE,
wildcard="EVE XML fitting files (*.xml)|*.xml",
style=wx.FD_SAVE,
defaultFile=defaultFile)
if dlg.ShowModal() == wx.ID_OK:
format = dlg.GetFilterIndex()
format_ = dlg.GetFilterIndex()
path = dlg.GetPath()
if format == 0:
output = sFit.exportXml(None, self.getActiveFit())
if format_ == 0:
sPort = Port.getInstance()
output = sPort.exportXml(None, fit)
if '.' not in os.path.basename(path):
path += ".xml"
else:
print "oops, invalid fit format %d" % format
dlg.Destroy()
print("oops, invalid fit format %d" % format_)
try:
dlg.Destroy()
except PyDeadObjectError:
pyfalog.error("Tried to destroy an object that doesn't exist in <showExportDialog>.")
return
file = open(path, "w", encoding="utf-8")
file.write(output)
file.close()
dlg.Destroy()
with open(path, "w", encoding="utf-8") as openfile:
openfile.write(output)
openfile.close()
try:
dlg.Destroy()
except PyDeadObjectError:
pyfalog.error("Tried to destroy an object that doesn't exist in <showExportDialog>.")
def showPreferenceDialog(self, event):
dlg = PreferenceDialog(self)
dlg.ShowModal()
def goWiki(self, event):
@staticmethod
def goWiki(event):
webbrowser.open('https://github.com/pyfa-org/Pyfa/wiki')
def goForums(self, event):
@staticmethod
def goForums(event):
webbrowser.open('https://forums.eveonline.com/default.aspx?g=posts&t=466425')
def loadDatabaseDefaults(self, event):
@staticmethod
def loadDatabaseDefaults(event):
# Import values that must exist otherwise Pyfa breaks
DefaultDatabaseValues.importRequiredDefaults()
# Import default values for damage profiles
@@ -415,7 +469,7 @@ class MainFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.loadDatabaseDefaults, id=menuBar.importDatabaseDefaultsId)
# Widgets Inspector
if config.debug:
self.Bind(wx.EVT_MENU, self.openWXInspectTool, id = self.widgetInspectMenuID)
self.Bind(wx.EVT_MENU, self.openWXInspectTool, id=self.widgetInspectMenuID)
# About
self.Bind(wx.EVT_MENU, self.ShowAboutBox, id=wx.ID_ABOUT)
# Char editor
@@ -443,32 +497,32 @@ class MainFrame(wx.Frame):
# Preference dialog
self.Bind(wx.EVT_MENU, self.showPreferenceDialog, id=wx.ID_PREFERENCES)
# User guide
self.Bind(wx.EVT_MENU, self.goWiki, id = menuBar.wikiId)
self.Bind(wx.EVT_MENU, self.goWiki, id=menuBar.wikiId)
# EVE Forums
self.Bind(wx.EVT_MENU, self.goForums, id = menuBar.forumId)
self.Bind(wx.EVT_MENU, self.goForums, id=menuBar.forumId)
# Save current character
self.Bind(wx.EVT_MENU, self.saveChar, id = menuBar.saveCharId)
self.Bind(wx.EVT_MENU, self.saveChar, id=menuBar.saveCharId)
# Save current character as another character
self.Bind(wx.EVT_MENU, self.saveCharAs, id = menuBar.saveCharAsId)
self.Bind(wx.EVT_MENU, self.saveCharAs, id=menuBar.saveCharAsId)
# Save current character
self.Bind(wx.EVT_MENU, self.revertChar, id = menuBar.revertCharId)
self.Bind(wx.EVT_MENU, self.revertChar, id=menuBar.revertCharId)
# Browse fittings
self.Bind(wx.EVT_MENU, self.eveFittings, id = menuBar.eveFittingsId)
self.Bind(wx.EVT_MENU, self.eveFittings, id=menuBar.eveFittingsId)
# Export to EVE
self.Bind(wx.EVT_MENU, self.exportToEve, id = menuBar.exportToEveId)
self.Bind(wx.EVT_MENU, self.exportToEve, id=menuBar.exportToEveId)
# Handle SSO event (login/logout/manage characters, depending on mode and current state)
self.Bind(wx.EVT_MENU, self.ssoHandler, id = menuBar.ssoLoginId)
self.Bind(wx.EVT_MENU, self.ssoHandler, id=menuBar.ssoLoginId)
# Open attribute editor
self.Bind(wx.EVT_MENU, self.showAttrEditor, id = menuBar.attrEditorId)
self.Bind(wx.EVT_MENU, self.showAttrEditor, id=menuBar.attrEditorId)
# Toggle Overrides
self.Bind(wx.EVT_MENU, self.toggleOverrides, id = menuBar.toggleOverridesId)
self.Bind(wx.EVT_MENU, self.toggleOverrides, id=menuBar.toggleOverridesId)
#Clipboard exports
# Clipboard exports
self.Bind(wx.EVT_MENU, self.exportToClipboard, id=wx.ID_COPY)
#Graphs
# Graphs
self.Bind(wx.EVT_MENU, self.openGraphFrame, id=menuBar.graphFrameId)
toggleSearchBoxId = wx.NewId()
@@ -478,11 +532,11 @@ class MainFrame(wx.Frame):
# Close Page
self.Bind(wx.EVT_MENU, self.CloseCurrentPage, id=self.closePageId)
self.Bind(wx.EVT_MENU, self.HAddPage, id = self.addPageId)
self.Bind(wx.EVT_MENU, self.toggleSearchBox, id = toggleSearchBoxId)
self.Bind(wx.EVT_MENU, self.toggleShipMarket, id = toggleShipMarketId)
self.Bind(wx.EVT_MENU, self.CTabNext, id = ctabnext)
self.Bind(wx.EVT_MENU, self.CTabPrev, id = ctabprev)
self.Bind(wx.EVT_MENU, self.HAddPage, id=self.addPageId)
self.Bind(wx.EVT_MENU, self.toggleSearchBox, id=toggleSearchBoxId)
self.Bind(wx.EVT_MENU, self.toggleShipMarket, id=toggleShipMarketId)
self.Bind(wx.EVT_MENU, self.CTabNext, id=ctabnext)
self.Bind(wx.EVT_MENU, self.CTabPrev, id=ctabprev)
actb = [(wx.ACCEL_CTRL, ord('T'), self.addPageId),
(wx.ACCEL_CMD, ord('T'), self.addPageId),
@@ -515,30 +569,30 @@ class MainFrame(wx.Frame):
for i in range(0, self.additionsPane.notebook.GetPageCount()):
self.additionsSelect.append(wx.NewId())
self.Bind(wx.EVT_MENU, self.AdditionsTabSelect, id=self.additionsSelect[i])
actb.append((wx.ACCEL_CMD, i+49, self.additionsSelect[i]))
actb.append((wx.ACCEL_CTRL, i+49, self.additionsSelect[i]))
actb.append((wx.ACCEL_CMD, i + 49, self.additionsSelect[i]))
actb.append((wx.ACCEL_CTRL, i + 49, self.additionsSelect[i]))
# Alt+1-9 for market item selection
self.itemSelect = []
for i in range(0, 9):
self.itemSelect.append(wx.NewId())
self.Bind(wx.EVT_MENU, self.ItemSelect, id = self.itemSelect[i])
self.Bind(wx.EVT_MENU, self.ItemSelect, id=self.itemSelect[i])
actb.append((wx.ACCEL_ALT, i + 49, self.itemSelect[i]))
atable = wx.AcceleratorTable(actb)
self.SetAcceleratorTable(atable)
def eveFittings(self, event):
dlg=CrestFittings(self)
dlg = CrestFittings(self)
dlg.Show()
def updateTitle(self, event):
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
char = sCrest.implicitCharacter
if char:
t = time.gmtime(char.eve.expires-time.time())
t = time.gmtime(char.eve.expires - time.time())
sTime = time.strftime("%H:%M:%S", t if t >= 0 else 0)
newTitle = "%s | %s - %s"%(self.title, char.name, sTime)
newTitle = "%s | %s - %s" % (self.title, char.name, sTime)
self.SetTitle(newTitle)
def onSSOLogin(self, event):
@@ -568,7 +622,7 @@ class MainFrame(wx.Frame):
self.SetTitle(self.title)
menu = self.GetMenuBar()
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
if type == CrestModes.IMPLICIT:
menu.SetLabel(menu.ssoLoginId, "Login to EVE")
@@ -581,7 +635,7 @@ class MainFrame(wx.Frame):
menu.Enable(menu.exportToEveId, not enable)
def ssoHandler(self, event):
sCrest = service.Crest.getInstance()
sCrest = Crest.getInstance()
if sCrest.settings.get('mode') == CrestModes.IMPLICIT:
if sCrest.implicitCharacter is not None:
sCrest.logout()
@@ -589,21 +643,22 @@ class MainFrame(wx.Frame):
uri = sCrest.startServer()
webbrowser.open(uri)
else:
dlg=CrestMgmt(self)
dlg = CrestMgmt(self)
dlg.Show()
def exportToEve(self, event):
dlg=ExportToEve(self)
dlg = ExportToEve(self)
dlg.Show()
def toggleOverrides(self, event):
ModifiedAttributeDict.OVERRIDES = not ModifiedAttributeDict.OVERRIDES
wx.PostEvent(self, GE.FitChanged(fitID=self.getActiveFit()))
menu = self.GetMenuBar()
menu.SetLabel(menu.toggleOverridesId, "Turn Overrides Off" if ModifiedAttributeDict.OVERRIDES else "Turn Overrides On")
menu.SetLabel(menu.toggleOverridesId,
"Turn Overrides Off" if ModifiedAttributeDict.OVERRIDES else "Turn Overrides On")
def saveChar(self, event):
sChr = service.Character.getInstance()
sChr = Character.getInstance()
charID = self.charSelection.getActiveCharacter()
sChr.saveCharacter(charID)
wx.PostEvent(self, GE.CharListUpdated())
@@ -614,7 +669,7 @@ class MainFrame(wx.Frame):
dlg.ShowModal()
def revertChar(self, event):
sChr = service.Character.getInstance()
sChr = Character.getInstance()
charID = self.charSelection.getActiveCharacter()
sChr.revertCharacter(charID)
wx.PostEvent(self, GE.CharListUpdated())
@@ -637,7 +692,7 @@ class MainFrame(wx.Frame):
def CTabPrev(self, event):
self.fitMultiSwitch.PrevPage()
def HAddPage(self,event):
def HAddPage(self, event):
self.fitMultiSwitch.AddPage()
def toggleShipMarket(self, event):
@@ -652,35 +707,35 @@ class MainFrame(wx.Frame):
self.marketBrowser.search.Focus()
def clipboardEft(self):
sFit = service.Fit.getInstance()
toClipboard(sFit.exportFit(self.getActiveFit()))
fit = db_getFit(self.getActiveFit())
toClipboard(Port.exportEft(fit))
def clipboardEftImps(self):
sFit = service.Fit.getInstance()
toClipboard(sFit.exportEftImps(self.getActiveFit()))
fit = db_getFit(self.getActiveFit())
toClipboard(Port.exportEftImps(fit))
def clipboardDna(self):
sFit = service.Fit.getInstance()
toClipboard(sFit.exportDna(self.getActiveFit()))
fit = db_getFit(self.getActiveFit())
toClipboard(Port.exportDna(fit))
def clipboardCrest(self):
sFit = service.Fit.getInstance()
toClipboard(sFit.exportCrest(self.getActiveFit()))
fit = db_getFit(self.getActiveFit())
toClipboard(Port.exportCrest(fit))
def clipboardXml(self):
sFit = service.Fit.getInstance()
toClipboard(sFit.exportXml(None, self.getActiveFit()))
fit = db_getFit(self.getActiveFit())
toClipboard(Port.exportXml(None, fit))
def clipboardMultiBuy(self):
sFit = service.Fit.getInstance()
toClipboard(sFit.exportMultiBuy(self.getActiveFit()))
fit = db_getFit(self.getActiveFit())
toClipboard(Port.exportMultiBuy(fit))
def importFromClipboard(self, event):
sFit = service.Fit.getInstance()
clipboard = fromClipboard()
try:
fits = sFit.importFitFromBuffer(fromClipboard(), self.getActiveFit())
fits = Port().importFitFromBuffer(clipboard, self.getActiveFit())
except:
pass
pyfalog.error("Attempt to import failed:\n{0}", clipboard)
else:
self._openAfterImport(fits)
@@ -697,17 +752,22 @@ class MainFrame(wx.Frame):
CopySelectDict[selected]()
dlg.Destroy()
try:
dlg.Destroy()
except PyDeadObjectError:
pyfalog.error("Tried to destroy an object that doesn't exist in <exportToClipboard>.")
def exportSkillsNeeded(self, event):
""" Exports skills needed for active fit and active character """
sCharacter = service.Character.getInstance()
saveDialog = wx.FileDialog(self, "Export Skills Needed As...",
wildcard = "EVEMon skills training file (*.emp)|*.emp|" \
"EVEMon skills training XML file (*.xml)|*.xml|" \
"Text skills training file (*.txt)|*.txt",
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
sCharacter = Character.getInstance()
saveDialog = wx.FileDialog(
self,
"Export Skills Needed As...",
wildcard=("EVEMon skills training file (*.emp)|*.emp|"
"EVEMon skills training XML file (*.xml)|*.xml|"
"Text skills training file (*.txt)|*.txt"),
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT,
)
if saveDialog.ShowModal() == wx.ID_OK:
saveFmtInt = saveDialog.GetFilterIndex()
@@ -730,66 +790,85 @@ class MainFrame(wx.Frame):
def fileImportDialog(self, event):
"""Handles importing single/multiple EVE XML / EFT cfg fit files"""
sFit = service.Fit.getInstance()
dlg = wx.FileDialog(self, "Open One Or More Fitting Files",
wildcard = "EVE XML fitting files (*.xml)|*.xml|" \
"EFT text fitting files (*.cfg)|*.cfg|" \
"All Files (*)|*",
style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE)
if (dlg.ShowModal() == wx.ID_OK):
sPort = Port.getInstance()
dlg = wx.FileDialog(
self,
"Open One Or More Fitting Files",
wildcard=("EVE XML fitting files (*.xml)|*.xml|"
"EFT text fitting files (*.cfg)|*.cfg|"
"All Files (*)|*"),
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE
)
if dlg.ShowModal() == wx.ID_OK:
self.progressDialog = wx.ProgressDialog(
"Importing fits",
" "*100, # set some arbitrary spacing to create width in window
parent=self, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME)
"Importing fits",
" " * 100, # set some arbitrary spacing to create width in window
parent=self,
style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME
)
self.progressDialog.message = None
sFit.importFitsThreaded(dlg.GetPaths(), self.fileImportCallback)
sPort.importFitsThreaded(dlg.GetPaths(), self.fileImportCallback)
self.progressDialog.ShowModal()
dlg.Destroy()
try:
dlg.Destroy()
except PyDeadObjectError:
pyfalog.error("Tried to destroy an object that doesn't exist in <fileImportDialog>.")
def backupToXml(self, event):
""" Back up all fits to EVE XML file """
defaultFile = "pyfa-fits-%s.xml"%strftime("%Y%m%d_%H%M%S", gmtime())
defaultFile = "pyfa-fits-%s.xml" % strftime("%Y%m%d_%H%M%S", gmtime())
saveDialog = wx.FileDialog(self, "Save Backup As...",
wildcard = "EVE XML fitting file (*.xml)|*.xml",
style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT,
defaultFile=defaultFile)
saveDialog = wx.FileDialog(
self,
"Save Backup As...",
wildcard="EVE XML fitting file (*.xml)|*.xml",
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT,
defaultFile=defaultFile,
)
if saveDialog.ShowModal() == wx.ID_OK:
filePath = saveDialog.GetPath()
if '.' not in os.path.basename(filePath):
filePath += ".xml"
sFit = service.Fit.getInstance()
max = sFit.countAllFits()
sFit = Fit.getInstance()
max_ = sFit.countAllFits()
self.progressDialog = wx.ProgressDialog("Backup fits",
"Backing up %d fits to: %s"%(max, filePath),
maximum=max, parent=self,
style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME)
sFit.backupFits(filePath, self.backupCallback)
self.progressDialog = wx.ProgressDialog(
"Backup fits",
"Backing up %d fits to: %s" % (max_, filePath),
maximum=max_,
parent=self,
style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME,
)
Port().backupFits(filePath, self.backupCallback)
self.progressDialog.ShowModal()
def exportHtml(self, event):
from gui.utils.exportHtml import exportHtml
sFit = service.Fit.getInstance()
settings = service.settings.HTMLExportSettings.getInstance()
sFit = Fit.getInstance()
settings = HTMLExportSettings.getInstance()
max = sFit.countAllFits()
max_ = sFit.countAllFits()
path = settings.getPath()
if not os.path.isdir(os.path.dirname(path)):
dlg = wx.MessageDialog(self,
"Invalid Path\n\nThe following path is invalid or does not exist: \n%s\n\nPlease verify path location pyfa's preferences."%path,
"Error", wx.OK | wx.ICON_ERROR)
dlg = wx.MessageDialog(
self,
"Invalid Path\n\nThe following path is invalid or does not exist: \n%s\n\nPlease verify path location pyfa's preferences." % path,
"Error",
wx.OK | wx.ICON_ERROR
)
if dlg.ShowModal() == wx.ID_OK:
return
self.progressDialog = wx.ProgressDialog("Backup fits",
"Generating HTML file at: %s"%path,
maximum=max, parent=self,
style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME)
self.progressDialog = wx.ProgressDialog(
"Backup fits",
"Generating HTML file at: %s" % path,
maximum=max_, parent=self,
style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME
)
exportHtml.getInstance().refreshFittingHtml(True, self.backupCallback)
self.progressDialog.ShowModal()
@@ -826,7 +905,7 @@ class MainFrame(wx.Frame):
self._openAfterImport(data)
elif action == -2:
dlg = wx.MessageDialog(self,
"The following error was generated\n\n%s\n\nBe aware that already processed fits were not saved"%data,
"The following error was generated\n\n%s\n\nBe aware that already processed fits were not saved" % data,
"Import Error", wx.OK | wx.ICON_ERROR)
if dlg.ShowModal() == wx.ID_OK:
return
@@ -851,14 +930,16 @@ class MainFrame(wx.Frame):
def importCharacter(self, event):
""" Imports character XML file from EVE API """
dlg = wx.FileDialog(self, "Open One Or More Character Files",
wildcard="EVE API XML character files (*.xml)|*.xml|" \
"All Files (*)|*",
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE)
dlg = wx.FileDialog(
self,
"Open One Or More Character Files",
wildcard="EVE API XML character files (*.xml)|*.xml|All Files (*)|*",
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE
)
if dlg.ShowModal() == wx.ID_OK:
self.waitDialog = wx.BusyInfo("Importing Character...")
sCharacter = service.Character.getInstance()
sCharacter = Character.getInstance()
sCharacter.importCharacter(dlg.GetPaths(), self.importCharacterCallback)
def importCharacterCallback(self):
@@ -871,13 +952,13 @@ class MainFrame(wx.Frame):
def openGraphFrame(self, event):
if not self.graphFrame:
self.graphFrame = GraphFrame(self)
if gui.graphFrame.enabled:
if graphFrame.graphFrame_enabled:
self.graphFrame.Show()
else:
elif graphFrame.graphFrame_enabled:
self.graphFrame.SetFocus()
def openWXInspectTool(self, event):
from wx.lib.inspection import InspectionTool
if not InspectionTool().initialized:
InspectionTool().Init()
@@ -887,4 +968,3 @@ class MainFrame(wx.Frame):
if not wnd:
wnd = self
InspectionTool().Show(wnd, True)

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,21 +15,28 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import config
from gui.bitmapLoader import BitmapLoader
import gui.mainFrame
from service.character import Character
import gui.graphFrame
import gui.globalEvents as GE
import service
from gui.bitmapLoader import BitmapLoader
if not 'wxMac' in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3,0)):
from logbook import Logger
pyfalog = Logger(__name__)
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
from service.crest import Crest
from service.crest import CrestModes
class MainMenuBar(wx.MenuBar):
def __init__(self):
def __init__(self, mainFrame):
pyfalog.debug("Initialize MainMenuBar")
self.characterEditorId = wx.NewId()
self.damagePatternEditorId = wx.NewId()
self.targetResistsEditorId = wx.NewId()
@@ -51,11 +58,11 @@ class MainMenuBar(wx.MenuBar):
self.toggleOverridesId = wx.NewId()
self.importDatabaseDefaultsId = wx.NewId()
if 'wxMac' in wx.PlatformInfo and wx.VERSION >= (3,0):
if 'wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0):
wx.ID_COPY = wx.NewId()
wx.ID_PASTE = wx.NewId()
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.mainFrame = mainFrame
wx.MenuBar.__init__(self)
# File menu
@@ -80,8 +87,8 @@ class MainMenuBar(wx.MenuBar):
editMenu = wx.Menu()
self.Append(editMenu, "&Edit")
#editMenu.Append(wx.ID_UNDO)
#editMenu.Append(wx.ID_REDO)
# editMenu.Append(wx.ID_UNDO)
# editMenu.Append(wx.ID_REDO)
editMenu.Append(wx.ID_COPY, "To Clipboard\tCTRL+C", "Export a fit to the clipboard")
editMenu.Append(wx.ID_PASTE, "From Clipboard\tCTRL+V", "Import a fit from the clipboard")
@@ -114,13 +121,16 @@ class MainMenuBar(wx.MenuBar):
graphFrameItem.SetBitmap(BitmapLoader.getBitmap("graphs_small", "gui"))
windowMenu.AppendItem(graphFrameItem)
if not gui.graphFrame.graphFrame_enabled:
self.Enable(self.graphFrameId, False)
preferencesShortCut = "CTRL+," if 'wxMac' in wx.PlatformInfo else "CTRL+P"
preferencesItem = wx.MenuItem(windowMenu, wx.ID_PREFERENCES, "Preferences\t"+preferencesShortCut)
preferencesItem = wx.MenuItem(windowMenu, wx.ID_PREFERENCES, "Preferences\t" + preferencesShortCut)
preferencesItem.SetBitmap(BitmapLoader.getBitmap("preferences_small", "gui"))
windowMenu.AppendItem(preferencesItem)
if not 'wxMac' in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3,0)):
self.sCrest = service.Crest.getInstance()
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
self.sCrest = Crest.getInstance()
# CREST Menu
crestMenu = wx.Menu()
@@ -136,7 +146,7 @@ class MainMenuBar(wx.MenuBar):
self.Enable(self.eveFittingsId, False)
self.Enable(self.exportToEveId, False)
if not gui.mainFrame.disableOverrideEditor:
if not self.mainFrame.disableOverrideEditor:
windowMenu.AppendSeparator()
attrItem = wx.MenuItem(windowMenu, self.attrEditorId, "Attribute Overrides\tCTRL+B")
attrItem.SetBitmap(BitmapLoader.getBitmap("fit_rename_small", "gui"))
@@ -154,17 +164,19 @@ class MainMenuBar(wx.MenuBar):
helpMenu.Append(wx.ID_ABOUT)
if config.debug:
helpMenu.Append( self.mainFrame.widgetInspectMenuID, "Open Widgets Inspect tool", "Open Widgets Inspect tool")
helpMenu.Append(self.mainFrame.widgetInspectMenuID, "Open Widgets Inspect tool",
"Open Widgets Inspect tool")
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
def fitChanged(self, event):
pyfalog.debug("fitChanged triggered")
enable = event.fitID is not None
self.Enable(wx.ID_SAVEAS, enable)
self.Enable(wx.ID_COPY, enable)
self.Enable(self.exportSkillsNeededId, enable)
sChar = service.Character.getInstance()
sChar = Character.getInstance()
charID = self.mainFrame.charSelection.getActiveCharacter()
char = sChar.getCharacter(charID)
@@ -174,5 +186,3 @@ class MainMenuBar(wx.MenuBar):
self.Enable(self.revertCharId, char.isDirty)
event.Skip()

View File

@@ -1,456 +1,471 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
import service
import gui.display as d
from gui.cachingImageList import CachingImageList
from gui.contextMenu import ContextMenu
import gui.PFSearchBox as SBox
from gui.bitmapLoader import BitmapLoader
ItemSelected, ITEM_SELECTED = wx.lib.newevent.NewEvent()
RECENTLY_USED_MODULES = -2
MAX_RECENTLY_USED_MODULES = 20
class MetaButton(wx.ToggleButton):
def __init__(self, *args, **kwargs):
super(MetaButton, self).__init__(*args, **kwargs)
self.setUserSelection(True)
def setUserSelection(self, isSelected):
self.userSelected = isSelected
self.SetValue(isSelected)
def setMetaAvailable(self, isAvailable):
self.Enable(isAvailable)
# need to also SetValue(False) for windows because Enabled=False AND SetValue(True) looks enabled.
if not isAvailable:
self.SetValue(False)
def reset(self):
self.Enable(True)
self.SetValue(self.userSelected)
class MarketBrowser(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
vbox = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(vbox)
# Add a search box on top
self.search = SearchBox(self)
vbox.Add(self.search, 0, wx.EXPAND)
self.splitter = wx.SplitterWindow(self, style = wx.SP_LIVE_UPDATE)
vbox.Add(self.splitter, 1, wx.EXPAND)
# Grab market service instance and create child objects
self.sMkt = service.Market.getInstance()
self.searchMode = False
self.marketView = MarketTree(self.splitter, self)
self.itemView = ItemView(self.splitter, self)
self.splitter.SplitHorizontally(self.marketView, self.itemView)
self.splitter.SetMinimumPaneSize(250)
# Setup our buttons for metaGroup selection
# Same fix as for search box on macs,
# need some pixels of extra space or everything clips and is ugly
p = wx.Panel(self)
box = wx.BoxSizer(wx.HORIZONTAL)
p.SetSizer(box)
vbox.Add(p, 0, wx.EXPAND)
self.metaButtons = []
for name in self.sMkt.META_MAP.keys():
btn = MetaButton(p, wx.ID_ANY, name.capitalize(), style=wx.BU_EXACTFIT)
setattr(self, name, btn)
box.Add(btn, 1, wx.ALIGN_CENTER)
btn.Bind(wx.EVT_TOGGLEBUTTON, self.toggleMetaButton)
btn.metaName = name
self.metaButtons.append(btn)
# Make itemview to set toggles according to list contents
self.itemView.setToggles()
p.SetMinSize((wx.SIZE_AUTO_WIDTH, btn.GetSize()[1] + 5))
def toggleMetaButton(self, event):
"""Process clicks on toggle buttons"""
appendMeta = wx.GetMouseState().CmdDown()
clickedBtn = event.EventObject
if appendMeta:
activeBtns = [btn for btn in self.metaButtons if btn.GetValue()]
if activeBtns:
clickedBtn.setUserSelection(clickedBtn.GetValue())
self.itemView.filterItemStore()
else:
# Do 'nothing' if we're trying to turn last active button off
# Keep button in the same state
clickedBtn.setUserSelection(True)
else:
for btn in self.metaButtons:
btn.setUserSelection(btn == clickedBtn)
self.itemView.filterItemStore()
def jump(self, item):
self.marketView.jump(item)
class SearchBox(SBox.PFSearchBox):
def __init__(self, parent, **kwargs):
SBox.PFSearchBox.__init__(self, parent, **kwargs)
cancelBitmap = BitmapLoader.getBitmap("fit_delete_small","gui")
searchBitmap = BitmapLoader.getBitmap("fsearch_small","gui")
self.SetSearchBitmap(searchBitmap)
self.SetCancelBitmap(cancelBitmap)
self.ShowSearchButton()
self.ShowCancelButton()
class MarketTree(wx.TreeCtrl):
def __init__(self, parent, marketBrowser):
wx.TreeCtrl.__init__(self, parent, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
self.root = self.AddRoot("root")
self.imageList = CachingImageList(16, 16)
self.SetImageList(self.imageList)
self.sMkt = marketBrowser.sMkt
self.marketBrowser = marketBrowser
# Form market tree root
sMkt = self.sMkt
for mktGrp in sMkt.getMarketRoot():
iconId = self.addImage(sMkt.getIconByMarketGroup(mktGrp))
childId = self.AppendItem(self.root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
# All market groups which were never expanded are dummies, here we assume
# that all root market groups are expandable
self.AppendItem(childId, "dummy")
self.SortChildren(self.root)
# Add recently used modules node
rumIconId = self.addImage("market_small", "gui")
self.AppendItem(self.root, "Recently Used Modules", rumIconId, data = wx.TreeItemData(RECENTLY_USED_MODULES))
# Bind our lookup method to when the tree gets expanded
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
def addImage(self, iconFile, location="icons"):
if iconFile is None:
return -1
return self.imageList.GetImageIndex(iconFile, location)
def expandLookup(self, event):
"""Process market tree expands"""
root = event.Item
child = self.GetFirstChild(root)[0]
# If child of given market group is a dummy
if self.GetItemText(child) == "dummy":
# Delete it
self.Delete(child)
# And add real market group contents
sMkt = self.sMkt
currentMktGrp = sMkt.getMarketGroup(self.GetPyData(root), eager="children")
for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
# If market should have items but it doesn't, do not show it
if sMkt.marketGroupValidityCheck(childMktGrp) is False:
continue
iconId = self.addImage(sMkt.getIconByMarketGroup(childMktGrp))
try:
childId = self.AppendItem(root, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID))
except:
continue
if sMkt.marketGroupHasTypesCheck(childMktGrp) is False:
self.AppendItem(childId, "dummy")
self.SortChildren(root)
def jump(self, item):
"""Open market group and meta tab of given item"""
self.marketBrowser.searchMode = False
sMkt = self.sMkt
mg = sMkt.getMarketGroupByItem(item)
jumpList = []
while mg is not None:
jumpList.append(mg.ID)
mg = mg.parent
for id in sMkt.ROOT_MARKET_GROUPS:
if id in jumpList:
jumpList = jumpList[:jumpList.index(id)+1]
item = self.root
for i in range(len(jumpList) -1, -1, -1):
target = jumpList[i]
child, cookie = self.GetFirstChild(item)
while self.GetItemPyData(child) != target:
child, cookie = self.GetNextChild(item, cookie)
item = child
self.Expand(item)
self.SelectItem(item)
self.marketBrowser.itemView.selectionMade()
class ItemView(d.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
"attr:power,,,True",
"attr:cpu,,,True"]
def __init__(self, parent, marketBrowser):
d.Display.__init__(self, parent)
marketBrowser.Bind(wx.EVT_TREE_SEL_CHANGED, self.selectionMade)
self.unfilteredStore = set()
self.filteredStore = set()
self.recentlyUsedModules = set()
self.sMkt = marketBrowser.sMkt
self.searchMode = marketBrowser.searchMode
self.marketBrowser = marketBrowser
self.marketView = marketBrowser.marketView
# Make sure our search actually does interesting stuff
self.marketBrowser.search.Bind(SBox.EVT_TEXT_ENTER, self.scheduleSearch)
self.marketBrowser.search.Bind(SBox.EVT_SEARCH_BTN, self.scheduleSearch)
self.marketBrowser.search.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
self.marketBrowser.search.Bind(SBox.EVT_TEXT, self.scheduleSearch)
# Make sure WE do interesting stuff too
self.Bind(wx.EVT_CONTEXT_MENU, self.contextMenu)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
# Make reverse map, used by sorter
self.metaMap = self.makeReverseMetaMap()
# Fill up recently used modules set
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
def startDrag(self, event):
row = self.GetFirstSelected()
if row != -1:
data = wx.PyTextDataObject()
data.SetText("market:"+str(self.active[row].ID))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
res = dropSource.DoDragDrop()
def itemActivated(self, event=None):
# Check if something is selected, if so, spawn the menu for it
sel = self.GetFirstSelected()
if sel == -1:
return
if self.mainFrame.getActiveFit():
self.storeRecentlyUsedMarketItem(self.active[sel].ID)
self.recentlyUsedModules = set()
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
wx.PostEvent(self.mainFrame, ItemSelected(itemID=self.active[sel].ID))
def storeRecentlyUsedMarketItem(self, itemID):
if len(self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]) > MAX_RECENTLY_USED_MODULES:
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].pop(0)
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].append(itemID)
def selectionMade(self, event=None):
self.marketBrowser.searchMode = False
# Grab the threeview selection and check if it's fine
sel = self.marketView.GetSelection()
if sel.IsOk():
# Get data field of the selected item (which is a marketGroup ID if anything was selected)
seldata = self.marketView.GetPyData(sel)
if seldata is not None and seldata != RECENTLY_USED_MODULES:
# If market group treeview item doesn't have children (other market groups or dummies),
# then it should have items in it and we want to request them
if self.marketView.ItemHasChildren(sel) is False:
sMkt = self.sMkt
# Get current market group
mg = sMkt.getMarketGroup(seldata, eager=("items", "items.metaGroup"))
# Get all its items
items = sMkt.getItemsByMarketGroup(mg)
else:
items = set()
else:
# If method was called but selection wasn't actually made or we have a hit on recently used modules
if seldata == RECENTLY_USED_MODULES:
items = self.recentlyUsedModules
else:
items = set()
# Fill store
self.updateItemStore(items)
# Set toggle buttons / use search mode flag if recently used modules category is selected (in order to have all modules listed and not filtered)
if seldata is not RECENTLY_USED_MODULES:
self.setToggles()
else:
self.marketBrowser.searchMode = True
self.setToggles()
# Update filtered items
self.filterItemStore()
def updateItemStore(self, items):
self.unfilteredStore = items
def filterItemStore(self):
sMkt = self.sMkt
selectedMetas = set()
for btn in self.marketBrowser.metaButtons:
if btn.GetValue():
selectedMetas.update(sMkt.META_MAP[btn.metaName])
self.filteredStore = sMkt.filterItemsByMeta(self.unfilteredStore, selectedMetas)
self.update(list(self.filteredStore))
def setToggles(self):
metaIDs = set()
sMkt = self.sMkt
for item in self.unfilteredStore:
metaIDs.add(sMkt.getMetaGroupIdByItem(item))
for btn in self.marketBrowser.metaButtons:
btn.reset()
btnMetas = sMkt.META_MAP[btn.metaName]
if len(metaIDs.intersection(btnMetas)) > 0:
btn.setMetaAvailable(True)
else:
btn.setMetaAvailable(False)
def scheduleSearch(self, event=None):
search = self.marketBrowser.search.GetLineText(0)
# Make sure we do not count wildcard as search symbol
realsearch = search.replace("*", "")
# Re-select market group if search query has zero length
if len(realsearch) == 0:
self.selectionMade()
return
# Show nothing if query is too short
elif len(realsearch) < 3:
self.clearSearch()
return
self.marketBrowser.searchMode = True
self.sMkt.searchItems(search, self.populateSearch)
def clearSearch(self, event=None):
# Wipe item store and update everything to accomodate with it
# If clearSearch was generated by SearchCtrl's Cancel button, clear the content also
if event:
self.marketBrowser.search.Clear()
self.marketBrowser.searchMode = False
self.updateItemStore(set())
self.setToggles()
self.filterItemStore()
def populateSearch(self, items):
# If we're no longer searching, dump the results
if self.marketBrowser.searchMode is False:
return
self.updateItemStore(items)
self.setToggles()
self.filterItemStore()
def itemSort(self, item):
sMkt = self.sMkt
catname = sMkt.getCategoryByItem(item).name
try:
mktgrpid = sMkt.getMarketGroupByItem(item).ID
except AttributeError:
mktgrpid = None
print "unable to find market group for", item.name
parentname = sMkt.getParentItemByItem(item).name
# Get position of market group
metagrpid = sMkt.getMetaGroupIdByItem(item)
metatab = self.metaMap.get(metagrpid)
metalvl = self.metalvls.get(item.ID, 0)
return (catname, mktgrpid, parentname, metatab, metalvl, item.name)
def contextMenu(self, event):
# Check if something is selected, if so, spawn the menu for it
sel = self.GetFirstSelected()
if sel == -1:
return
item = self.active[sel]
sMkt = self.sMkt
sourceContext = "marketItemGroup" if self.marketBrowser.searchMode is False else "marketItemMisc"
itemContext = sMkt.getCategoryByItem(item).name
menu = ContextMenu.getMenu((item,), (sourceContext, itemContext))
self.PopupMenu(menu)
def populate(self, items):
if len(items) > 0:
# Get dictionary with meta level attribute
sAttr = service.Attribute.getInstance()
attrs = sAttr.getAttributeInfo("metaLevel")
sMkt = self.sMkt
self.metalvls = sMkt.directAttrRequest(items, attrs)
# Clear selection
self.deselectItems()
# Perform sorting, using item's meta levels besides other stuff
items.sort(key=self.itemSort)
# Mark current item list as active
self.active = items
# Show them
d.Display.populate(self, items)
def refresh(self, items):
if len(items) > 1:
# Get dictionary with meta level attribute
sAttr = service.Attribute.getInstance()
attrs = sAttr.getAttributeInfo("metaLevel")
sMkt = self.sMkt
self.metalvls = sMkt.directAttrRequest(items, attrs)
# Re-sort stuff
items.sort(key=self.itemSort)
for i, item in enumerate(items[:9]):
# set shortcut info for first 9 modules
item.marketShortcut = i+1
d.Display.refresh(self, items)
def makeReverseMetaMap(self):
"""
Form map which tells in which tab items of given metagroup are located
"""
revmap = {}
i = 0
for mgids in self.sMkt.META_MAP.itervalues():
for mgid in mgids:
revmap[mgid] = i
i += 1
return revmap
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from service.market import Market
from service.attribute import Attribute
from gui.display import Display
import gui.PFSearchBox as SBox
from gui.cachingImageList import CachingImageList
from gui.contextMenu import ContextMenu
from gui.bitmapLoader import BitmapLoader
from logbook import Logger
pyfalog = Logger(__name__)
ItemSelected, ITEM_SELECTED = wx.lib.newevent.NewEvent()
RECENTLY_USED_MODULES = -2
MAX_RECENTLY_USED_MODULES = 20
class MetaButton(wx.ToggleButton):
def __init__(self, *args, **kwargs):
super(MetaButton, self).__init__(*args, **kwargs)
self.setUserSelection(True)
def setUserSelection(self, isSelected):
self.userSelected = isSelected
self.SetValue(isSelected)
def setMetaAvailable(self, isAvailable):
self.Enable(isAvailable)
# need to also SetValue(False) for windows because Enabled=False AND SetValue(True) looks enabled.
if not isAvailable:
self.SetValue(False)
def reset(self):
self.Enable(True)
self.SetValue(self.userSelected)
class MarketBrowser(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
pyfalog.debug("Initialize marketBrowser")
vbox = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(vbox)
# Add a search box on top
self.search = SearchBox(self)
vbox.Add(self.search, 0, wx.EXPAND)
self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
vbox.Add(self.splitter, 1, wx.EXPAND)
# Grab market service instance and create child objects
self.sMkt = Market.getInstance()
self.searchMode = False
self.marketView = MarketTree(self.splitter, self)
self.itemView = ItemView(self.splitter, self)
self.splitter.SplitHorizontally(self.marketView, self.itemView)
self.splitter.SetMinimumPaneSize(250)
# Setup our buttons for metaGroup selection
# Same fix as for search box on macs,
# need some pixels of extra space or everything clips and is ugly
p = wx.Panel(self)
box = wx.BoxSizer(wx.HORIZONTAL)
p.SetSizer(box)
vbox.Add(p, 0, wx.EXPAND)
self.metaButtons = []
btn = None
for name in self.sMkt.META_MAP.keys():
btn = MetaButton(p, wx.ID_ANY, name.capitalize(), style=wx.BU_EXACTFIT)
setattr(self, name, btn)
box.Add(btn, 1, wx.ALIGN_CENTER)
btn.Bind(wx.EVT_TOGGLEBUTTON, self.toggleMetaButton)
btn.metaName = name
self.metaButtons.append(btn)
# Make itemview to set toggles according to list contents
self.itemView.setToggles()
p.SetMinSize((wx.SIZE_AUTO_WIDTH, btn.GetSize()[1] + 5))
def toggleMetaButton(self, event):
"""Process clicks on toggle buttons"""
appendMeta = wx.GetMouseState().CmdDown()
clickedBtn = event.EventObject
if appendMeta:
activeBtns = [btn for btn in self.metaButtons if btn.GetValue()]
if activeBtns:
clickedBtn.setUserSelection(clickedBtn.GetValue())
self.itemView.filterItemStore()
else:
# Do 'nothing' if we're trying to turn last active button off
# Keep button in the same state
clickedBtn.setUserSelection(True)
else:
for btn in self.metaButtons:
btn.setUserSelection(btn == clickedBtn)
self.itemView.filterItemStore()
def jump(self, item):
self.marketView.jump(item)
class SearchBox(SBox.PFSearchBox):
def __init__(self, parent, **kwargs):
SBox.PFSearchBox.__init__(self, parent, **kwargs)
cancelBitmap = BitmapLoader.getBitmap("fit_delete_small", "gui")
searchBitmap = BitmapLoader.getBitmap("fsearch_small", "gui")
self.SetSearchBitmap(searchBitmap)
self.SetCancelBitmap(cancelBitmap)
self.ShowSearchButton()
self.ShowCancelButton()
class MarketTree(wx.TreeCtrl):
def __init__(self, parent, marketBrowser):
wx.TreeCtrl.__init__(self, parent, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
pyfalog.debug("Initialize marketTree")
self.root = self.AddRoot("root")
self.imageList = CachingImageList(16, 16)
self.SetImageList(self.imageList)
self.sMkt = marketBrowser.sMkt
self.marketBrowser = marketBrowser
# Form market tree root
sMkt = self.sMkt
for mktGrp in sMkt.getMarketRoot():
iconId = self.addImage(sMkt.getIconByMarketGroup(mktGrp))
childId = self.AppendItem(self.root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
# All market groups which were never expanded are dummies, here we assume
# that all root market groups are expandable
self.AppendItem(childId, "dummy")
self.SortChildren(self.root)
# Add recently used modules node
rumIconId = self.addImage("market_small", "gui")
self.AppendItem(self.root, "Recently Used Modules", rumIconId, data=wx.TreeItemData(RECENTLY_USED_MODULES))
# Bind our lookup method to when the tree gets expanded
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
def addImage(self, iconFile, location="icons"):
if iconFile is None:
return -1
return self.imageList.GetImageIndex(iconFile, location)
def expandLookup(self, event):
"""Process market tree expands"""
root = event.Item
child = self.GetFirstChild(root)[0]
# If child of given market group is a dummy
if self.GetItemText(child) == "dummy":
# Delete it
self.Delete(child)
# And add real market group contents
sMkt = self.sMkt
currentMktGrp = sMkt.getMarketGroup(self.GetPyData(root), eager="children")
for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
# If market should have items but it doesn't, do not show it
if sMkt.marketGroupValidityCheck(childMktGrp) is False:
continue
iconId = self.addImage(sMkt.getIconByMarketGroup(childMktGrp))
try:
childId = self.AppendItem(root, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID))
except Exception as e:
pyfalog.debug("Error appending item.")
pyfalog.debug(e)
continue
if sMkt.marketGroupHasTypesCheck(childMktGrp) is False:
self.AppendItem(childId, "dummy")
self.SortChildren(root)
def jump(self, item):
"""Open market group and meta tab of given item"""
self.marketBrowser.searchMode = False
sMkt = self.sMkt
mg = sMkt.getMarketGroupByItem(item)
jumpList = []
while mg is not None:
jumpList.append(mg.ID)
mg = mg.parent
for id in sMkt.ROOT_MARKET_GROUPS:
if id in jumpList:
jumpList = jumpList[:jumpList.index(id) + 1]
item = self.root
for i in range(len(jumpList) - 1, -1, -1):
target = jumpList[i]
child, cookie = self.GetFirstChild(item)
while self.GetItemPyData(child) != target:
child, cookie = self.GetNextChild(item, cookie)
item = child
self.Expand(item)
self.SelectItem(item)
self.marketBrowser.itemView.selectionMade()
class ItemView(Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
"attr:power,,,True",
"attr:cpu,,,True"]
def __init__(self, parent, marketBrowser):
Display.__init__(self, parent)
pyfalog.debug("Initialize ItemView")
marketBrowser.Bind(wx.EVT_TREE_SEL_CHANGED, self.selectionMade)
self.unfilteredStore = set()
self.filteredStore = set()
self.recentlyUsedModules = set()
self.sMkt = marketBrowser.sMkt
self.searchMode = marketBrowser.searchMode
self.marketBrowser = marketBrowser
self.marketView = marketBrowser.marketView
# Make sure our search actually does interesting stuff
self.marketBrowser.search.Bind(SBox.EVT_TEXT_ENTER, self.scheduleSearch)
self.marketBrowser.search.Bind(SBox.EVT_SEARCH_BTN, self.scheduleSearch)
self.marketBrowser.search.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
self.marketBrowser.search.Bind(SBox.EVT_TEXT, self.scheduleSearch)
# Make sure WE do interesting stuff too
self.Bind(wx.EVT_CONTEXT_MENU, self.contextMenu)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
# Make reverse map, used by sorter
self.metaMap = self.makeReverseMetaMap()
# Fill up recently used modules set
pyfalog.debug("Fill up recently used modules set")
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
def startDrag(self, event):
row = self.GetFirstSelected()
if row != -1:
data = wx.PyTextDataObject()
data.SetText("market:" + str(self.active[row].ID))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
dropSource.DoDragDrop()
def itemActivated(self, event=None):
# Check if something is selected, if so, spawn the menu for it
sel = self.GetFirstSelected()
if sel == -1:
return
if self.mainFrame.getActiveFit():
self.storeRecentlyUsedMarketItem(self.active[sel].ID)
self.recentlyUsedModules = set()
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
wx.PostEvent(self.mainFrame, ItemSelected(itemID=self.active[sel].ID))
def storeRecentlyUsedMarketItem(self, itemID):
if len(self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]) > MAX_RECENTLY_USED_MODULES:
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].pop(0)
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].append(itemID)
def selectionMade(self, event=None):
self.marketBrowser.searchMode = False
# Grab the threeview selection and check if it's fine
sel = self.marketView.GetSelection()
if sel.IsOk():
# Get data field of the selected item (which is a marketGroup ID if anything was selected)
seldata = self.marketView.GetPyData(sel)
if seldata is not None and seldata != RECENTLY_USED_MODULES:
# If market group treeview item doesn't have children (other market groups or dummies),
# then it should have items in it and we want to request them
if self.marketView.ItemHasChildren(sel) is False:
sMkt = self.sMkt
# Get current market group
mg = sMkt.getMarketGroup(seldata, eager=("items", "items.metaGroup"))
# Get all its items
items = sMkt.getItemsByMarketGroup(mg)
else:
items = set()
else:
# If method was called but selection wasn't actually made or we have a hit on recently used modules
if seldata == RECENTLY_USED_MODULES:
items = self.recentlyUsedModules
else:
items = set()
# Fill store
self.updateItemStore(items)
# Set toggle buttons / use search mode flag if recently used modules category is selected (in order to have all modules listed and not filtered)
if seldata is not RECENTLY_USED_MODULES:
self.setToggles()
else:
self.marketBrowser.searchMode = True
self.setToggles()
# Update filtered items
self.filterItemStore()
def updateItemStore(self, items):
self.unfilteredStore = items
def filterItemStore(self):
sMkt = self.sMkt
selectedMetas = set()
for btn in self.marketBrowser.metaButtons:
if btn.GetValue():
selectedMetas.update(sMkt.META_MAP[btn.metaName])
self.filteredStore = sMkt.filterItemsByMeta(self.unfilteredStore, selectedMetas)
self.update(list(self.filteredStore))
def setToggles(self):
metaIDs = set()
sMkt = self.sMkt
for item in self.unfilteredStore:
metaIDs.add(sMkt.getMetaGroupIdByItem(item))
for btn in self.marketBrowser.metaButtons:
btn.reset()
btnMetas = sMkt.META_MAP[btn.metaName]
if len(metaIDs.intersection(btnMetas)) > 0:
btn.setMetaAvailable(True)
else:
btn.setMetaAvailable(False)
def scheduleSearch(self, event=None):
search = self.marketBrowser.search.GetLineText(0)
# Make sure we do not count wildcard as search symbol
realsearch = search.replace("*", "")
# Re-select market group if search query has zero length
if len(realsearch) == 0:
self.selectionMade()
return
# Show nothing if query is too short
elif len(realsearch) < 3:
self.clearSearch()
return
self.marketBrowser.searchMode = True
self.sMkt.searchItems(search, self.populateSearch)
def clearSearch(self, event=None):
# Wipe item store and update everything to accomodate with it
# If clearSearch was generated by SearchCtrl's Cancel button, clear the content also
if event:
self.marketBrowser.search.Clear()
self.marketBrowser.searchMode = False
self.updateItemStore(set())
self.setToggles()
self.filterItemStore()
def populateSearch(self, items):
# If we're no longer searching, dump the results
if self.marketBrowser.searchMode is False:
return
self.updateItemStore(items)
self.setToggles()
self.filterItemStore()
def itemSort(self, item):
sMkt = self.sMkt
catname = sMkt.getCategoryByItem(item).name
try:
mktgrpid = sMkt.getMarketGroupByItem(item).ID
except AttributeError:
mktgrpid = None
print("unable to find market group for", item.name)
parentname = sMkt.getParentItemByItem(item).name
# Get position of market group
metagrpid = sMkt.getMetaGroupIdByItem(item)
metatab = self.metaMap.get(metagrpid)
metalvl = self.metalvls.get(item.ID, 0)
return catname, mktgrpid, parentname, metatab, metalvl, item.name
def contextMenu(self, event):
# Check if something is selected, if so, spawn the menu for it
sel = self.GetFirstSelected()
if sel == -1:
return
item = self.active[sel]
sMkt = self.sMkt
sourceContext = "marketItemGroup" if self.marketBrowser.searchMode is False else "marketItemMisc"
itemContext = sMkt.getCategoryByItem(item).name
menu = ContextMenu.getMenu((item,), (sourceContext, itemContext))
self.PopupMenu(menu)
def populate(self, items):
if len(items) > 0:
# Get dictionary with meta level attribute
sAttr = Attribute.getInstance()
attrs = sAttr.getAttributeInfo("metaLevel")
sMkt = self.sMkt
self.metalvls = sMkt.directAttrRequest(items, attrs)
# Clear selection
self.deselectItems()
# Perform sorting, using item's meta levels besides other stuff
items.sort(key=self.itemSort)
# Mark current item list as active
self.active = items
# Show them
Display.populate(self, items)
def refresh(self, items):
if len(items) > 1:
# Get dictionary with meta level attribute
sAttr = Attribute.getInstance()
attrs = sAttr.getAttributeInfo("metaLevel")
sMkt = self.sMkt
self.metalvls = sMkt.directAttrRequest(items, attrs)
# Re-sort stuff
items.sort(key=self.itemSort)
for i, item in enumerate(items[:9]):
# set shortcut info for first 9 modules
item.marketShortcut = i + 1
Display.refresh(self, items)
def makeReverseMetaMap(self):
"""
Form map which tells in which tab items of given metagroup are located
"""
revmap = {}
i = 0
for mgids in self.sMkt.META_MAP.itervalues():
for mgid in mgids:
revmap[mgid] = i
i += 1
return revmap

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,16 +15,16 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
import gui.chromeTabs
from gui.chromeTabs import PFNotebook
import gui.builtinViews.emptyView
class MultiSwitch(gui.chromeTabs.PFNotebook):
class MultiSwitch(PFNotebook):
def __init__(self, parent):
gui.chromeTabs.PFNotebook.__init__(self, parent)
#self.AddPage() # now handled by mainFrame
PFNotebook.__init__(self, parent)
# self.AddPage() # now handled by mainFrame
self.handlers = handlers = []
for type in TabSpawner.tabTypes:
handlers.append(type(self))
@@ -40,10 +40,10 @@ class MultiSwitch(gui.chromeTabs.PFNotebook):
tabWnd = gui.builtinViews.emptyView.BlankPage(self)
tabWnd.handleDrag = lambda type, info: self.handleDrag(type, info)
gui.chromeTabs.PFNotebook.AddPage(self, tabWnd, tabTitle, tabImage, True)
PFNotebook.AddPage(self, tabWnd, tabTitle, tabImage, True)
def DeletePage(self, n, *args, **kwargs):
gui.chromeTabs.PFNotebook.DeletePage(self, n, *args, **kwargs)
PFNotebook.DeletePage(self, n, *args, **kwargs)
if self.GetPageCount() == 0:
self.AddPage()

View File

@@ -1,9 +1,11 @@
# noinspection PyPackageRequirements
import wx
import service
from service.fit import Fit
import gui.globalEvents as GE
import gui.mainFrame
class NotesView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
@@ -19,7 +21,7 @@ class NotesView(wx.Panel):
self.Bind(wx.EVT_TIMER, self.delayedSave, self.saveTimer)
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
@@ -34,11 +36,11 @@ class NotesView(wx.Panel):
def onText(self, event):
# delay the save so we're not writing to sqlite on every keystroke
self.saveTimer.Stop() # cancel the existing timer
self.saveTimer.Stop() # cancel the existing timer
self.saveTimer.Start(1000, True)
def delayedSave(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(self.lastFitId)
newNotes = self.editNotes.GetValue()
fit.notes = newNotes

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,18 +15,20 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
import service
# noinspection PyPackageRequirements
from wx.lib.intctrl import IntCtrl
from gui.utils.clipboard import toClipboard, fromClipboard
from service.damagePattern import ImportError
from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
###########################################################################
## Class DmgPatternEditorDlg
###########################################################################
from service.damagePattern import DamagePattern, ImportError
from logbook import Logger
pyfalog = Logger(__name__)
class DmgPatternTextValidor(BaseValidator):
def __init__(self):
@@ -47,7 +49,8 @@ class DmgPatternTextValidor(BaseValidator):
raise ValueError("Damage Profile name already in use, please choose another.")
return True
except ValueError, e:
except ValueError as e:
pyfalog.error(e)
wx.MessageBox(u"{}".format(e), "Error")
textCtrl.SetFocus()
return False
@@ -59,33 +62,34 @@ class DmgPatternEntityEditor(EntityEditor):
self.SetEditorValidator(DmgPatternTextValidor)
def getEntitiesFromContext(self):
sDP = service.DamagePattern.getInstance()
sDP = DamagePattern.getInstance()
choices = sorted(sDP.getDamagePatternList(), key=lambda p: p.name)
return [c for c in choices if c.name != "Selected Ammo"]
def DoNew(self, name):
sDP = service.DamagePattern.getInstance()
sDP = DamagePattern.getInstance()
return sDP.newPattern(name)
def DoRename(self, entity, name):
sDP = service.DamagePattern.getInstance()
sDP = DamagePattern.getInstance()
sDP.renamePattern(entity, name)
def DoCopy(self, entity, name):
sDP = service.DamagePattern.getInstance()
sDP = DamagePattern.getInstance()
copy = sDP.copyPattern(entity)
sDP.renamePattern(copy, name)
return copy
def DoDelete(self, entity):
sDP = service.DamagePattern.getInstance()
sDP = DamagePattern.getInstance()
sDP.deletePattern(entity)
class DmgPatternEditorDlg(wx.Dialog):
DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive")
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id = wx.ID_ANY, title = u"Damage Pattern Editor", size = wx.Size( 400,240 ))
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=u"Damage Pattern Editor", size=wx.Size(400, 240))
self.block = False
self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
@@ -111,11 +115,11 @@ class DmgPatternEditorDlg(wx.Dialog):
dmgeditSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
width = -1
defSize = wx.Size(width,-1)
defSize = wx.Size(width, -1)
for i, type in enumerate(self.DAMAGE_TYPES):
bmp = wx.StaticBitmap(self, wx.ID_ANY, BitmapLoader.getBitmap("%s_big"%type, "gui"))
if i%2:
for i, type_ in enumerate(self.DAMAGE_TYPES):
bmp = wx.StaticBitmap(self, wx.ID_ANY, BitmapLoader.getBitmap("%s_big" % type_, "gui"))
if i % 2:
style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT
border = 20
else:
@@ -123,13 +127,13 @@ class DmgPatternEditorDlg(wx.Dialog):
border = 5
# set text edit
setattr(self, "%sEdit"%type, IntCtrl(self, wx.ID_ANY, 0, wx.DefaultPosition, defSize))
setattr(self, "%sPerc"%type, wx.StaticText(self, wx.ID_ANY, u"0%"))
editObj = getattr(self, "%sEdit"%type)
setattr(self, "%sEdit" % type_, IntCtrl(self, wx.ID_ANY, 0, wx.DefaultPosition, defSize))
setattr(self, "%sPerc" % type_, wx.StaticText(self, wx.ID_ANY, u"0%"))
editObj = getattr(self, "%sEdit" % type_)
dmgeditSizer.Add(bmp, 0, style, border)
dmgeditSizer.Add(editObj, 0, wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER_VERTICAL, 5)
dmgeditSizer.Add(getattr(self, "%sPerc"%type), 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
dmgeditSizer.Add(getattr(self, "%sPerc" % type_), 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
editObj.Bind(wx.EVT_TEXT, self.ValuesUpdated)
editObj.SetLimited(True)
@@ -147,7 +151,7 @@ class DmgPatternEditorDlg(wx.Dialog):
self.stNotice.Wrap(-1)
perSizer.Add(self.stNotice, 0, wx.BOTTOM | wx.TOP | wx.LEFT, 5)
footerSizer.Add(perSizer, 1, wx.ALIGN_CENTER_VERTICAL, 5)
footerSizer.Add(perSizer, 1, wx.ALIGN_CENTER_VERTICAL, 5)
self.totSizer = wx.BoxSizer(wx.VERTICAL)
@@ -156,8 +160,8 @@ class DmgPatternEditorDlg(wx.Dialog):
mainSizer.Add(contentSizer, 1, wx.EXPAND, 0)
if "wxGTK" in wx.PlatformInfo:
self.closeBtn = wx.Button( self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.closeBtn, 0, wx.ALL|wx.ALIGN_RIGHT, 5 )
self.closeBtn = wx.Button(self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.closeBtn, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
self.closeBtn.Bind(wx.EVT_BUTTON, self.closeEvent)
self.SetSizer(mainSizer)
@@ -166,18 +170,18 @@ class DmgPatternEditorDlg(wx.Dialog):
("Export", wx.ART_FILE_SAVE_AS, "to"))
for name, art, direction in importExport:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
btn.SetMinSize( btn.GetSize() )
btn.SetMaxSize( btn.GetSize() )
btn.SetMinSize(btn.GetSize())
btn.SetMaxSize(btn.GetSize())
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s patterns %s clipboard" % (name, direction) )
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
btn.Bind(wx.EVT_BUTTON, getattr(self, "{}Patterns".format(name.lower())))
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s patterns %s clipboard" % (name, direction))
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
btn.Bind(wx.EVT_BUTTON, getattr(self, "{}Patterns".format(name.lower())))
self.Layout()
bsize = self.GetBestSize()
@@ -196,30 +200,30 @@ class DmgPatternEditorDlg(wx.Dialog):
return
p = self.entityEditor.getActiveEntity()
total = sum(map(lambda attr: getattr(self, "%sEdit"%attr).GetValue(), self.DAMAGE_TYPES))
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
percObj = getattr(self, "%sPerc"%type)
setattr(p, "%sAmount"%type, editObj.GetValue())
percObj.SetLabel("%.1f%%"%(float(editObj.GetValue())*100/total if total > 0 else 0))
total = sum(map(lambda attr: getattr(self, "%sEdit" % attr).GetValue(), self.DAMAGE_TYPES))
for type_ in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit" % type_)
percObj = getattr(self, "%sPerc" % type_)
setattr(p, "%sAmount" % type_, editObj.GetValue())
percObj.SetLabel("%.1f%%" % (float(editObj.GetValue()) * 100 / total if total > 0 else 0))
self.totSizer.Layout()
if event is not None:
event.Skip()
service.DamagePattern.getInstance().saveChanges(p)
DamagePattern.getInstance().saveChanges(p)
def restrict(self):
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
for type_ in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit" % type_)
editObj.Enable(False)
self.entityEditor.btnRename.Enable(False)
self.entityEditor.btnDelete.Enable(False)
def unrestrict(self):
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
for type_ in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit" % type_)
editObj.Enable()
self.entityEditor.btnRename.Enable()
self.entityEditor.btnDelete.Enable()
@@ -251,20 +255,24 @@ class DmgPatternEditorDlg(wx.Dialog):
def importPatterns(self, event):
text = fromClipboard()
if text:
sDP = service.DamagePattern.getInstance()
sDP = DamagePattern.getInstance()
try:
sDP.importPatterns(text)
self.stNotice.SetLabel("Patterns successfully imported from clipboard")
except service.damagePattern.ImportError, e:
except ImportError as e:
pyfalog.error(e)
self.stNotice.SetLabel(str(e))
except Exception, e:
self.stNotice.SetLabel("Could not import from clipboard: unknown errors")
except Exception as e:
msg = "Could not import from clipboard: unknown errors"
pyfalog.warning(msg)
pyfalog.error(e)
self.stNotice.SetLabel(msg)
finally:
self.entityEditor.refreshEntityList()
else:
self.stNotice.SetLabel("Could not import from clipboard")
def exportPatterns(self, event):
sDP = service.DamagePattern.getInstance()
toClipboard( sDP.exportPatterns() )
sDP = DamagePattern.getInstance()
toClipboard(sDP.exportPatterns())
self.stNotice.SetLabel("Patterns exported to clipboard")

View File

@@ -1,80 +1,81 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
from gui.preferenceView import PreferenceView
from gui.bitmapLoader import BitmapLoader
class PreferenceDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE)
self.SetTitle("pyfa - Preferences")
i = wx.IconFromBitmap(BitmapLoader.getBitmap("preferences_small", "gui"))
self.SetIcon(i)
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.listbook = wx.Listbook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LB_DEFAULT)
self.listview = self.listbook.GetListView()
#self.listview.SetMinSize((500, -1))
#self.listview.SetSize((500, -1))
self.imageList = wx.ImageList(32,32)
self.listbook.SetImageList(self.imageList)
mainSizer.Add(self.listbook, 1, wx.EXPAND | wx.TOP|wx.BOTTOM|wx.LEFT, 5)
self.m_staticline2 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.m_staticline2, 0, wx.EXPAND, 5 )
btnSizer = wx.BoxSizer( wx.HORIZONTAL )
btnSizer.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 )
self.btnOK = wx.Button( self, wx.ID_ANY, u"OK", wx.DefaultPosition, wx.DefaultSize, 0 )
btnSizer.Add( self.btnOK, 0, wx.ALL, 5 )
mainSizer.Add(btnSizer,0 , wx.EXPAND, 5)
self.SetSizer(mainSizer)
self.Centre(wx.BOTH)
for prefView in PreferenceView.views:
page = wx.Panel(self.listbook)
bmp = prefView.getImage()
if bmp:
imgID = self.imageList.Add(bmp)
else:
imgID = -1
prefView.populatePanel(page)
self.listbook.AddPage(page, prefView.title, imageId = imgID)
# Set the height based on a condition. Can all the panels fit in the current height?
# If not, use the .GetBestVirtualSize() to ensure that all content is available.
minHeight = 360
bestFit = self.GetBestVirtualSize()
if minHeight > bestFit[1]:
self.SetSizeWH(450, minHeight)
else:
self.SetSizeWH(450, bestFit[1])
self.Layout()
self.btnOK.Bind(wx.EVT_BUTTON, self.OnBtnOK)
def OnBtnOK(self, event):
self.Close()
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView
from gui.bitmapLoader import BitmapLoader
class PreferenceDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE)
self.SetTitle("pyfa - Preferences")
i = wx.IconFromBitmap(BitmapLoader.getBitmap("preferences_small", "gui"))
self.SetIcon(i)
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.listbook = wx.Listbook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LB_DEFAULT)
self.listview = self.listbook.GetListView()
# self.listview.SetMinSize((500, -1))
# self.listview.SetSize((500, -1))
self.imageList = wx.ImageList(32, 32)
self.listbook.SetImageList(self.imageList)
mainSizer.Add(self.listbook, 1, wx.EXPAND | wx.TOP | wx.BOTTOM | wx.LEFT, 5)
self.m_staticline2 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_staticline2, 0, wx.EXPAND, 5)
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
self.btnOK = wx.Button(self, wx.ID_ANY, u"OK", wx.DefaultPosition, wx.DefaultSize, 0)
btnSizer.Add(self.btnOK, 0, wx.ALL, 5)
mainSizer.Add(btnSizer, 0, wx.EXPAND, 5)
self.SetSizer(mainSizer)
self.Centre(wx.BOTH)
for prefView in PreferenceView.views:
page = wx.Panel(self.listbook)
bmp = prefView.getImage()
if bmp:
imgID = self.imageList.Add(bmp)
else:
imgID = -1
prefView.populatePanel(page)
self.listbook.AddPage(page, prefView.title, imageId=imgID)
# Set the height based on a condition. Can all the panels fit in the current height?
# If not, use the .GetBestVirtualSize() to ensure that all content is available.
minHeight = 360
bestFit = self.GetBestVirtualSize()
if minHeight > bestFit[1]:
self.SetSizeWH(450, minHeight)
else:
self.SetSizeWH(450, bestFit[1])
self.Layout()
self.btnOK.Bind(wx.EVT_BUTTON, self.OnBtnOK)
def OnBtnOK(self, event):
self.Close()

View File

@@ -1,41 +1,48 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
class PreferenceView(object):
views = []
def __init__(self):
pass
@classmethod
def register(cls):
PreferenceView.views.append(cls())
def populatePanel(self, panel):
raise NotImplementedError()
def refreshPanel(self, fit):
raise NotImplementedError()
def getImage(self):
return wx.NullBitmap
from gui.builtinPreferenceViews import *
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
class PreferenceView(object):
views = []
@classmethod
def register(cls):
PreferenceView.views.append(cls())
def populatePanel(self, panel):
raise NotImplementedError()
def refreshPanel(self, fit):
raise NotImplementedError()
def getImage(self):
return wx.NullBitmap
# noinspection PyUnresolvedReferences
from gui.builtinPreferenceViews import ( # noqa: E402, F401
pyfaGeneralPreferences,
pyfaNetworkPreferences,
pyfaHTMLExportPreferences,
pyfaCrestPreferences,
pyfaUpdatePreferences
)

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,40 +15,47 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.display as d
import gui.globalEvents as GE
import service
import gui.droneView
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
import eos.types
from service.fit import Fit
from service.market import Market
from eos.saveddata.drone import Drone as es_Drone
from eos.saveddata.fighter import Fighter as es_Fighter
from eos.saveddata.module import Module as es_Module
class DummyItem:
class DummyItem(object):
def __init__(self, txt):
self.name = txt
self.icon = None
class DummyEntry:
class DummyEntry(object):
def __init__(self, txt):
self.item = DummyItem(txt)
class ProjectedViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
class ProjectedViewDrop(wx.PyDropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(ProjectedViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
class ProjectedView(d.Display):
DEFAULT_COLS = ["State",
@@ -58,7 +65,7 @@ class ProjectedView(d.Display):
"Ammo"]
def __init__(self, parent):
d.Display.__init__(self, parent, style = wx.LC_SINGLE_SEL | wx.BORDER_NONE)
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
@@ -70,7 +77,7 @@ class ProjectedView(d.Display):
self.droneView = gui.droneView.DroneView
if "__WXGTK__" in wx.PlatformInfo:
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
@@ -79,72 +86,73 @@ class ProjectedView(d.Display):
self.SetDropTarget(ProjectedViewDrop(self.handleListDrag))
def handleListDrag(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "projected":
# if source is coming from projected, we are trying to combine drones.
self.mergeDrones(x, y, int(data[1]))
elif data[0] == "market":
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.project(fitID, int(data[1]))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
def kbEvent(self,event):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
row = self.GetFirstSelected()
if row != -1:
sFit.removeProjected(fitID, self.get(row))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def handleDrag(self, type, fitID):
#Those are drags coming from pyfa sources, NOT builtin wx drags
# Those are drags coming from pyfa sources, NOT builtin wx drags
if type == "fit":
activeFit = self.mainFrame.getActiveFit()
if activeFit:
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
draggedFit = sFit.getFit(fitID)
sFit.project(activeFit, draggedFit)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFit))
def startDrag(self, event):
row = event.GetIndex()
if row != -1 and isinstance(self.get(row), eos.types.Drone):
if row != -1 and isinstance(self.get(row), es_Drone):
data = wx.PyTextDataObject()
data.SetText("projected:"+str(self.GetItemData(row)))
data.SetText("projected:" + str(self.GetItemData(row)))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
dropSource.DoDragDrop()
def mergeDrones(self, x, y, itemID):
srcRow = self.FindItemData(-1,itemID)
srcRow = self.FindItemData(-1, itemID)
dstRow, _ = self.HitTest((x, y))
if srcRow != -1 and dstRow != -1:
self._merge(srcRow, dstRow)
def _merge(self, src, dst):
dstDrone = self.get(dst)
if isinstance(dstDrone, eos.types.Drone):
sFit = service.Fit.getInstance()
if isinstance(dstDrone, es_Drone):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
if sFit.mergeDrones(fitID, self.get(src), dstDrone, True):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def moduleSort(self, module):
@staticmethod
def moduleSort(module):
return module.item.name
def fighterSort(self, fighter):
@staticmethod
def fighterSort(fighter):
return fighter.item.name
def droneSort(self, drone):
@@ -155,16 +163,17 @@ class ProjectedView(d.Display):
return (self.droneView.DRONE_ORDER.index(item.marketGroup.name),
drone.item.name)
def fitSort(self, fit):
@staticmethod
def fitSort(fit):
return fit.name
def fitChanged(self, event):
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
#Clear list and get out if current fitId is None
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
@@ -198,7 +207,7 @@ class ProjectedView(d.Display):
self.deselectItems()
if stuff == []:
if not stuff:
stuff = [DummyEntry("Drag an item or fit, or use right-click menu for system effects")]
self.update(stuff)
@@ -231,7 +240,7 @@ class ProjectedView(d.Display):
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.toggleProjected(fitID, item, "right" if event.Button == 3 else "left")
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@@ -245,17 +254,18 @@ class ProjectedView(d.Display):
menu = None
if sel != -1:
item = self.get(sel)
if item is None: return
sMkt = service.Market.getInstance()
if isinstance(item, eos.types.Drone):
if item is None:
return
sMkt = Market.getInstance()
if isinstance(item, es_Drone):
srcContext = "projectedDrone"
itemContext = sMkt.getCategoryByItem(item.item).name
context = ((srcContext, itemContext),)
elif isinstance(item, eos.types.Fighter):
elif isinstance(item, es_Fighter):
srcContext = "projectedFighter"
itemContext = sMkt.getCategoryByItem(item.item).name
context = ((srcContext, itemContext),)
elif isinstance(item, eos.types.Module):
elif isinstance(item, es_Module):
modSrcContext = "projectedModule"
modItemContext = sMkt.getCategoryByItem(item.item).name
modFullContext = (modSrcContext, modItemContext)
@@ -269,8 +279,8 @@ class ProjectedView(d.Display):
else:
fitSrcContext = "projectedFit"
fitItemContext = item.name
context = ((fitSrcContext,fitItemContext),)
context = context + (("projected",),)
context = ((fitSrcContext, fitItemContext),)
context += ("projected",),
menu = ContextMenu.getMenu((item,), *context)
elif sel == -1:
fitID = self.mainFrame.getActiveFit()
@@ -287,6 +297,6 @@ class ProjectedView(d.Display):
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = service.Fit.getInstance()
sFit = Fit.getInstance()
sFit.removeProjected(fitID, self.get(row))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))

View File

@@ -1,6 +1,11 @@
import csv
from logbook import Logger
# noinspection PyPackageRequirements
import wx
try:
# noinspection PyPackageRequirements
import wx.propgrid as wxpg
except:
if wx.VERSION < (2, 9):
@@ -8,24 +13,22 @@ except:
else:
raise
import gui.PFSearchBox as SBox
from gui.marketBrowser import SearchBox
from eos.db.gamedata.queries import getItem, getAttributeInfo
from service.market import Market
import gui.display as d
import gui.globalEvents as GE
import gui.PFSearchBox as SBox
from gui.marketBrowser import SearchBox
from gui.bitmapLoader import BitmapLoader
import service
import csv
import eos.db
import logging
pyfalog = Logger(__name__)
logger = logging.getLogger(__name__)
class AttributeEditor( wx.Frame ):
def __init__( self, parent ):
class AttributeEditor(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, wx.ID_ANY, title="Attribute Editor", pos=wx.DefaultPosition,
size=wx.Size(650, 600), style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.TAB_TRAVERSAL)
size=wx.Size(650, 600),
style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT | wx.TAB_TRAVERSAL)
i = wx.IconFromBitmap(BitmapLoader.getBitmap("fit_rename_small", "gui"))
self.SetIcon(i)
@@ -45,7 +48,6 @@ class AttributeEditor( wx.Frame ):
self.Bind(wx.EVT_MENU, self.OnExport, fileExport)
self.Bind(wx.EVT_MENU, self.OnClear, fileClear)
i = wx.IconFromBitmap(BitmapLoader.getBitmap("fit_rename_small", "gui"))
self.SetIcon(i)
@@ -55,7 +57,8 @@ class AttributeEditor( wx.Frame ):
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
leftSizer = wx.BoxSizer(wx.VERTICAL)
leftPanel = wx.Panel(panel, wx.ID_ANY, style=wx.DOUBLE_BORDER if 'wxMSW' in wx.PlatformInfo else wx.SIMPLE_BORDER)
leftPanel = wx.Panel(panel, wx.ID_ANY,
style=wx.DOUBLE_BORDER if 'wxMSW' in wx.PlatformInfo else wx.SIMPLE_BORDER)
self.searchBox = SearchBox(leftPanel)
self.itemView = ItemView(leftPanel)
@@ -67,10 +70,11 @@ class AttributeEditor( wx.Frame ):
mainSizer.Add(leftPanel, 1, wx.ALL | wx.EXPAND, 5)
rightSizer = wx.BoxSizer(wx.VERTICAL)
self.btnRemoveOverrides = wx.Button( panel, wx.ID_ANY, u"Remove Overides for Item", wx.DefaultPosition, wx.DefaultSize, 0 )
self.btnRemoveOverrides = wx.Button(panel, wx.ID_ANY, u"Remove Overides for Item", wx.DefaultPosition,
wx.DefaultSize, 0)
self.pg = AttributeGrid(panel)
rightSizer.Add(self.pg, 1, wx.ALL|wx.EXPAND, 5)
rightSizer.Add(self.btnRemoveOverrides, 0, wx.ALL | wx.EXPAND, 5 )
rightSizer.Add(self.pg, 1, wx.ALL | wx.EXPAND, 5)
rightSizer.Add(self.btnRemoveOverrides, 0, wx.ALL | wx.EXPAND, 5)
self.btnRemoveOverrides.Bind(wx.EVT_BUTTON, self.pg.removeOverrides)
self.btnRemoveOverrides.Enable(False)
@@ -94,27 +98,27 @@ class AttributeEditor( wx.Frame ):
def OnImport(self, event):
dlg = wx.FileDialog(self, "Import pyfa override file",
wildcard = "pyfa override file (*.csv)|*.csv",
style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
if (dlg.ShowModal() == wx.ID_OK):
wildcard="pyfa override file (*.csv)|*.csv",
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
with open(path, 'rb') as csvfile:
spamreader = csv.reader(csvfile)
for row in spamreader:
itemID, attrID, value = row
item = eos.db.getItem(int(itemID))
attr = eos.db.getAttributeInfo(int(attrID))
item = getItem(int(itemID))
attr = getAttributeInfo(int(attrID))
item.setOverride(attr, float(value))
self.itemView.updateItems(True)
def OnExport(self, event):
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
items = sMkt.getItemsWithOverrides()
defaultFile = "pyfa_overrides.csv"
dlg = wx.FileDialog(self, "Save Overrides As...",
wildcard = "pyfa overrides (*.csv)|*.csv",
style = wx.FD_SAVE,
wildcard="pyfa overrides (*.csv)|*.csv",
style=wx.FD_SAVE,
defaultFile=defaultFile)
if dlg.ShowModal() == wx.ID_OK:
@@ -126,12 +130,15 @@ class AttributeEditor( wx.Frame ):
writer.writerow([item.ID, override.attrID, override.value])
def OnClear(self, event):
dlg = wx.MessageDialog(self,
"Are you sure you want to delete all overrides?",
"Confirm Delete", wx.YES | wx.NO | wx.ICON_EXCLAMATION)
dlg = wx.MessageDialog(
self,
"Are you sure you want to delete all overrides?",
"Confirm Delete",
wx.YES | wx.NO | wx.ICON_EXCLAMATION
)
if dlg.ShowModal() == wx.ID_YES:
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
items = sMkt.getItemsWithOverrides()
# We can't just delete overrides, as loaded items will still have
# them assigned. Deleting them from the database won't propagate
@@ -143,6 +150,7 @@ class AttributeEditor( wx.Frame ):
self.itemView.updateItems(True)
self.pg.Clear()
# This is literally a stripped down version of the market.
class ItemView(d.Display):
DEFAULT_COLS = ["Base Icon",
@@ -152,7 +160,7 @@ class ItemView(d.Display):
def __init__(self, parent):
d.Display.__init__(self, parent)
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
self.things = sMkt.getItemsWithOverrides()
self.items = self.things
@@ -173,14 +181,14 @@ class ItemView(d.Display):
self.update(self.items)
def updateItems(self, updateDisplay=False):
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
self.things = sMkt.getItemsWithOverrides()
self.items = self.things
if updateDisplay:
self.update(self.things)
def scheduleSearch(self, event=None):
sMkt = service.Market.getInstance()
sMkt = Market.getInstance()
search = self.searchBox.GetLineText(0)
# Make sure we do not count wildcard as search symbol
@@ -198,9 +206,9 @@ class ItemView(d.Display):
class AttributeGrid(wxpg.PropertyGrid):
def __init__(self, parent):
wxpg.PropertyGrid.__init__(self, parent, style=wxpg.PG_HIDE_MARGIN|wxpg.PG_HIDE_CATEGORIES|wxpg.PG_BOLD_MODIFIED|wxpg.PG_TOOLTIPS)
wxpg.PropertyGrid.__init__(self, parent,
style=wxpg.PG_HIDE_MARGIN | wxpg.PG_HIDE_CATEGORIES | wxpg.PG_BOLD_MODIFIED | wxpg.PG_TOOLTIPS)
self.SetExtraStyle(wxpg.PG_EX_HELP_AS_TOOLTIPS)
self.item = None
@@ -209,9 +217,9 @@ class AttributeGrid(wxpg.PropertyGrid):
self.btn = parent.Parent.btnRemoveOverrides
self.Bind( wxpg.EVT_PG_CHANGED, self.OnPropGridChange )
self.Bind( wxpg.EVT_PG_SELECTED, self.OnPropGridSelect )
self.Bind( wxpg.EVT_PG_RIGHT_CLICK, self.OnPropGridRightClick )
self.Bind(wxpg.EVT_PG_CHANGED, self.OnPropGridChange)
self.Bind(wxpg.EVT_PG_SELECTED, self.OnPropGridSelect)
self.Bind(wxpg.EVT_PG_RIGHT_CLICK, self.OnPropGridRightClick)
self.itemView.Bind(wx.EVT_LIST_ITEM_SELECTED, self.itemActivated)
self.itemView.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
@@ -232,14 +240,14 @@ class AttributeGrid(wxpg.PropertyGrid):
prop = wxpg.FloatProperty(key, value=default)
prop.SetClientData(item.attributes[key]) # set this so that we may access it later
prop.SetHelpString("%s\n%s"%(item.attributes[key].displayName or key, "Default Value: %0.3f"%default))
prop.SetHelpString("%s\n%s" % (item.attributes[key].displayName or key, "Default Value: %0.3f" % default))
self.Append(prop)
def removeOverrides(self, event):
if self.item is None:
return
for _, x in self.item.overrides.items():
for x in self.item.overrides.values():
self.item.deleteOverride(x.attr)
self.itemView.updateItems(True)
self.ClearModifiedStatus()
@@ -262,7 +270,7 @@ class AttributeGrid(wxpg.PropertyGrid):
self.itemView.updateItems()
logger.debug('%s changed to "%s"' % (p.GetName(), p.GetValueAsString()))
pyfalog.debug('{0} changed to "{1}"', p.GetName(), p.GetValueAsString())
def OnPropGridSelect(self, event):
pass

View File

@@ -1,65 +1,56 @@
# -*- coding: utf-8 -*-
###########################################################################
## pyfatogllepanel.py
##
## Author: Darriele - HomeWorld
##
## Project home: https://github.com/pyfa-org/Pyfa - pyfa project
## Some portions of code are based on
## AGW:pycollapsiblepane generic implementation of wx.CollapsiblePane
## AGW:pycollapsiblepane credits ( from the original source file used ):
## Andrea Gavana, @ 09 Aug 2007
## Latest Revision: 12 Apr 2010, 12.00 GMT
##
## Module description:
## TogglePanel class is a wx.collipsablepane like implementation that uses
## some optimization from awg::pycollipsablepane to provide certain
## features tailored for PYFA needs.
##
## This module is part of PYFA (PYthon Fitting Assitant) and it shares the same
## licence ( read PYFA licence notice: gpl.txt )
##
## Notes: leave the commented code as it is, those line will be removed someday
# pyfatogllepanel.py
#
# Author: Darriele - HomeWorld
#
# Project home: https://github.com/pyfa-org/Pyfa - pyfa project
# Some portions of code are based on
# AGW:pycollapsiblepane generic implementation of wx.CollapsiblePane
# AGW:pycollapsiblepane credits ( from the original source file used ):
# Andrea Gavana, @ 09 Aug 2007
# Latest Revision: 12 Apr 2010, 12.00 GMT
#
# Module description:
# TogglePanel class is a wx.collipsablepane like implementation that uses
# some optimization from awg::pycollipsablepane to provide certain
# features tailored for PYFA needs.
#
# This module is part of PYFA (PYthon Fitting Assitant) and it shares the same
# licence ( read PYFA licence notice: gpl.txt )
#
# Notes: leave the commented code as it is, those line will be removed someday
###########################################################################
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
###########################################################################
## Class TogglePanel
###########################################################################
class TogglePanel ( wx.Panel ):
def __init__( self, parent , forceLayout = -1):
wx.Panel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( -1,-1 ), style = wx.TAB_TRAVERSAL )
class TogglePanel(wx.Panel):
def __init__(self, parent, forceLayout=-1):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(-1, -1),
style=wx.TAB_TRAVERSAL)
self._toggle = 1
self.parent = parent
self.forceLayout = forceLayout
self.bkColour = self.GetBackgroundColour()
# Create the main sizer of this panel
self.mainSizer = wx.BoxSizer( wx.VERTICAL )
self.SetSizer( self.mainSizer )
parentSize = parent.GetMinSize()
# Create the header panel
# Create the main sizer of this panel
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.mainSizer)
# parentSize = parent.GetMinSize()
# Create the header panel
self.headerPanel = wx.Panel(self)
self.mainSizer.Add(self.headerPanel, 0, wx.EXPAND | wx.TOP | wx.BOTTOM | wx.RIGHT, 1)
self.mainSizer.Add(self.headerPanel,0,wx.EXPAND | wx.TOP|wx.BOTTOM|wx.RIGHT, 1)
# Load expanded/collapsed bitmaps from the icons folder
self.bmpExpanded = BitmapLoader.getBitmap("down-arrow2", "gui")
self.bmpCollapsed = BitmapLoader.getBitmap("up-arrow2", "gui")
# Load expanded/collapsed bitmaps from the icons folder
self.bmpExpanded = BitmapLoader.getBitmap("down-arrow2","gui")
self.bmpCollapsed = BitmapLoader.getBitmap("up-arrow2","gui")
# Make the bitmaps have the same color as window text
sysTextColour = wx.SystemSettings.GetColour( wx.SYS_COLOUR_WINDOWTEXT )
# Make the bitmaps have the same color as window text
sysTextColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
img = self.bmpExpanded.ConvertToImage()
img.Replace(0, 0, 0, sysTextColour[0], sysTextColour[1], sysTextColour[2])
@@ -69,55 +60,53 @@ class TogglePanel ( wx.Panel ):
img.Replace(0, 0, 0, sysTextColour[0], sysTextColour[1], sysTextColour[2])
self.bmpCollapsed = wx.BitmapFromImage(img)
self.headerBmp = wx.StaticBitmap(self.headerPanel )
self.headerBmp.SetBitmap( self.bmpExpanded)
self.headerBmp = wx.StaticBitmap(self.headerPanel)
self.headerBmp.SetBitmap(self.bmpExpanded)
# Create the header sizer and add static bitmap and static text controls to it
# Create the header sizer and add static bitmap and static text controls to it
headerSizer = wx.BoxSizer( wx.HORIZONTAL )
self.headerPanel.SetSizer( headerSizer)
headerSizer = wx.BoxSizer(wx.HORIZONTAL)
self.headerPanel.SetSizer(headerSizer)
hbmpSizer = wx.BoxSizer( wx.HORIZONTAL )
hlblSizer = wx.BoxSizer( wx.HORIZONTAL )
self.hcntSizer = wx.BoxSizer( wx.HORIZONTAL)
hbmpSizer = wx.BoxSizer(wx.HORIZONTAL)
hlblSizer = wx.BoxSizer(wx.HORIZONTAL)
self.hcntSizer = wx.BoxSizer(wx.HORIZONTAL)
hbmpSizer.Add( self.headerBmp, 0,0, 5 )
hbmpSizer.Add(self.headerBmp, 0, 0, 5)
self.headerLabel = wx.StaticText( self.headerPanel, wx.ID_ANY, u"PYFA", wx.DefaultPosition, wx.DefaultSize, 0 )
hlblSizer.Add( self.headerLabel, 0, wx.EXPAND , 5 )
self.headerLabel = wx.StaticText(self.headerPanel, wx.ID_ANY, u"PYFA", wx.DefaultPosition, wx.DefaultSize, 0)
hlblSizer.Add(self.headerLabel, 0, wx.EXPAND, 5)
headerSizer.Add( hbmpSizer, 0, wx.RIGHT, 5 )
headerSizer.Add( hlblSizer, 0, wx.RIGHT, 5 )
headerSizer.Add( self.hcntSizer, 0, wx.RIGHT, 5)
headerSizer.Add(hbmpSizer, 0, wx.RIGHT, 5)
headerSizer.Add(hlblSizer, 0, wx.RIGHT, 5)
headerSizer.Add(self.hcntSizer, 0, wx.RIGHT, 5)
# Set the static text font weight to BOLD
# Set the static text font weight to BOLD
headerFont=parent.GetFont()
headerFont = parent.GetFont()
headerFont.SetWeight(wx.BOLD)
self.headerLabel.SetFont(headerFont)
# Create the content panel and its main sizer
# Create the content panel and its main sizer
self.contentSizer = wx.BoxSizer( wx.VERTICAL )
self.contentSizer = wx.BoxSizer(wx.VERTICAL)
self.contentPanel = wx.Panel(self)
self.contentPanel.SetSizer(self.contentSizer)
self.mainSizer.Add( self.contentPanel, 0, wx.EXPAND | wx.RIGHT | wx.LEFT , 5)
self.mainSizer.Add(self.contentPanel, 0, wx.EXPAND | wx.RIGHT | wx.LEFT, 5)
self.Layout()
# Connect Events
# Connect Events
self.headerLabel.Bind(wx.EVT_LEFT_UP, self.toggleContent)
self.headerBmp.Bind(wx.EVT_LEFT_UP, self.toggleContent)
self.headerPanel.Bind(wx.EVT_LEFT_UP, self.toggleContent)
self.headerLabel.Bind( wx.EVT_LEFT_UP, self.toggleContent )
self.headerBmp.Bind( wx.EVT_LEFT_UP, self.toggleContent )
self.headerPanel.Bind( wx.EVT_LEFT_UP, self.toggleContent )
def __del__( self ):
def __del__(self):
pass
def AddToggleItem(self, hitem):
hitem.Bind( wx.EVT_LEFT_UP, self.toggleContent )
hitem.Bind(wx.EVT_LEFT_UP, self.toggleContent)
def GetHeaderContentSizer(self):
return self.hcntSizer
@@ -126,7 +115,7 @@ class TogglePanel ( wx.Panel ):
return self.headerPanel
def InsertItemInHeader(self, item):
self.hcntSizer.Add(item,0,0,0)
self.hcntSizer.Add(item, 0, 0, 0)
self.Layout()
def AddSizer(self, sizer):
@@ -157,7 +146,7 @@ class TogglePanel ( wx.Panel ):
"""
Handles the status changes (collapsing/expanding).
:param `sz`: an instance of `wx.Size`.
:param sz: an instance of `wx.Size`.
"""
# minimal size has priority over the best size so set here our min size

View File

@@ -11,16 +11,17 @@ PyfaGauge is a generic Gauge implementation tailored for PYFA (Python Fitting As
It uses the easeOutQuad equation from caurina.transitions.Tweener to do the animation stuff
"""
# noinspection PyPackageRequirements
import wx
import copy
import math
from gui.utils import colorUtils
import gui.utils.drawUtils as drawUtils
import gui.utils.animEffects as animEffects
import gui.utils.fonts as fonts
from service import fit
from service.fit import Fit
class PyGauge(wx.PyWindow):
"""
@@ -29,7 +30,7 @@ class PyGauge(wx.PyWindow):
"""
def __init__(self, parent, id=wx.ID_ANY, range=100, pos=wx.DefaultPosition,
size=(-1,30), style=0):
size=(-1, 30), style=0):
"""
Default class constructor.
@@ -46,8 +47,8 @@ class PyGauge(wx.PyWindow):
self._size = size
self._border_colour = wx.BLACK
self._barColour = self._barColourSorted = [wx.Colour(212,228,255)]
self._barGradient = self._barGradientSorted = None
self._barColour = self._barColourSorted = [wx.Colour(212, 228, 255)]
self._barGradient = self._barGradientSorted = None
self._border_padding = 0
self._range = range
@@ -67,10 +68,10 @@ class PyGauge(wx.PyWindow):
self._animDirection = 0
self.animEffect = animEffects.OUT_QUAD
self.transitionsColors = [( wx.Colour(191, 191, 191, 255) , wx.Colour(96, 191, 0, 255) ),
( wx.Colour(191, 167, 96, 255) , wx.Colour(255, 191, 0, 255) ),
( wx.Colour(255, 191, 0, 255) , wx.Colour(255, 128, 0, 255) ),
( wx.Colour(255, 128, 0, 255) , wx.Colour(255, 0, 0, 255) )]
self.transitionsColors = [(wx.Colour(191, 191, 191, 255), wx.Colour(96, 191, 0, 255)),
(wx.Colour(191, 167, 96, 255), wx.Colour(255, 191, 0, 255)),
(wx.Colour(255, 191, 0, 255), wx.Colour(255, 128, 0, 255)),
(wx.Colour(255, 128, 0, 255), wx.Colour(255, 0, 0, 255))]
self.gradientEffect = -35
self._percentage = 0
@@ -79,8 +80,8 @@ class PyGauge(wx.PyWindow):
self.font = wx.Font(fonts.NORMAL, wx.SWISS, wx.NORMAL, wx.NORMAL, False)
self.SetBarGradient((wx.Colour(119,119,119),wx.Colour(153,153,153)))
self.SetBackgroundColour(wx.Colour(51,51,51))
self.SetBarGradient((wx.Colour(119, 119, 119), wx.Colour(153, 153, 153)))
self.SetBackgroundColour(wx.Colour(51, 51, 51))
self._tooltip = wx.ToolTip("")
self.SetToolTip(self._tooltip)
self._tooltip.SetTip("0.00/100.00")
@@ -107,7 +108,6 @@ class PyGauge(wx.PyWindow):
return wx.Size(self._size[0], self._size[1])
def GetBorderColour(self):
return self._border_colour
@@ -121,7 +121,7 @@ class PyGauge(wx.PyWindow):
return self._barColour[0]
def SetBarColour(self, colour):
if type(colour) != type([]):
if not isinstance(colour, list):
self._barColour = [colour]
else:
self._barColour = list(colour)
@@ -130,31 +130,30 @@ class PyGauge(wx.PyWindow):
GetBarColor = GetBarColour
def SetFractionDigits(self, digits):
self._fractionDigits=digits
self._fractionDigits = digits
def GetBarGradient(self):
""" Returns a tuple containing the gradient start and end colours. """
if self._barGradient == None:
if self._barGradient is None:
return None
return self._barGradient[0]
def SetBarGradient(self, gradient = None):
def SetBarGradient(self, gradient=None):
"""
Sets the bar gradient. This overrides the BarColour.
:param `gradient`: a tuple containing the gradient start and end colours.
:param gradient: a tuple containing the gradient start and end colours.
"""
if gradient == None:
if gradient is None:
self._barGradient = None
else:
if type(gradient) != type([]):
if not isinstance(gradient, list):
self._barGradient = [gradient]
else:
self._barGradient = list(gradient)
def GetBorderPadding(self):
""" Gets the border padding. """
@@ -164,19 +163,18 @@ class PyGauge(wx.PyWindow):
"""
Sets the border padding.
:param `padding`: pixels between the border and the progress bar.
:param padding: pixels between the border and the progress bar.
"""
self._border_padding = padding
def GetRange(self):
""" Returns the maximum value of the gauge. """
return self._range
def Animate(self):
sFit = fit.Fit.getInstance()
sFit = Fit.getInstance()
if sFit.serviceFittingOptions["enableGaugeAnimation"]:
if not self._timer:
self._timer = wx.Timer(self, self._timerId)
@@ -186,27 +184,28 @@ class PyGauge(wx.PyWindow):
self._animValue = self._percentage
self.Refresh()
def SetRange(self, range, reinit = False):
def SetRange(self, range, reinit=False):
"""
Sets the range of the gauge. The gauge length is its
value as a proportion of the range.
:param `range`: The maximum value of the gauge.
:param reinit:
:param range: The maximum value of the gauge.
"""
if self._range == range:
return
range = float(range)
range_ = float(range)
if range <= 0:
if range_ <= 0:
self._range = 0.01
else:
self._range = range
self._range = range_
if reinit is False:
self._oldPercentage = self._percentage
self._percentage = (self._value/self._range) * 100
self._percentage = (self._value / self._range) * 100
else:
self._oldPercentage = self._percentage
self._percentage = 0
@@ -214,9 +213,7 @@ class PyGauge(wx.PyWindow):
self.Animate()
self._tooltip.SetTip("%.2f/%.2f" % (self._value, self._range if self._range >0.01 else 0))
self._tooltip.SetTip("%.2f/%.2f" % (self._value, self._range if self._range > 0.01 else 0))
def GetValue(self):
""" Returns the current position of the gauge. """
@@ -233,22 +230,22 @@ class PyGauge(wx.PyWindow):
self._value = value
if value < 0:
self._value = 0
self._percentage = (self._value/self._range) * 100
self._percentage = (self._value / self._range) * 100
self.Animate()
self._tooltip.SetTip("%.2f/%.2f" % (self._value, self._range))
def SetValueRange(self, value, range, reinit = False):
def SetValueRange(self, value, range, reinit=False):
if self._value == value and self._range == range:
return
range = float(range)
range_ = float(range)
if range <= 0:
if range_ <= 0:
self._range = 0.01
else:
self._range = range
self._range = range_
value = float(value)
@@ -258,21 +255,21 @@ class PyGauge(wx.PyWindow):
if reinit is False:
self._oldPercentage = self._percentage
self._percentage = (self._value/self._range) * 100
self._percentage = (self._value / self._range) * 100
else:
self._oldPercentage = self._percentage
self._percentage = 0
self.Animate()
self._tooltip.SetTip("%.2f/%.2f" % (self._value, self._range if self._range >0.01 else 0))
self._tooltip.SetTip("%.2f/%.2f" % (self._value, self._range if self._range > 0.01 else 0))
def OnEraseBackground(self, event):
@staticmethod
def OnEraseBackground(event):
"""
Handles the ``wx.EVT_ERASE_BACKGROUND`` event for L{PyGauge}.
:param `event`: a `wx.EraseEvent` event to be processed.
:param event: a `wx.EraseEvent` event to be processed.
:note: This method is intentionally empty to reduce flicker.
"""
@@ -283,7 +280,7 @@ class PyGauge(wx.PyWindow):
"""
Handles the ``wx.EVT_PAINT`` event for L{PyGauge}.
:param `event`: a `wx.PaintEvent` event to be processed.
:param event: a `wx.PaintEvent` event to be processed.
"""
dc = wx.BufferedPaintDC(self)
@@ -308,7 +305,7 @@ class PyGauge(wx.PyWindow):
dc.SetPen(wx.Pen(self.GetBorderColour()))
dc.DrawRectangleRect(rect)
pad = 1 + self.GetBorderPadding()
rect.Deflate(pad,pad)
rect.Deflate(pad, pad)
if self.GetBarGradient():
@@ -326,48 +323,46 @@ class PyGauge(wx.PyWindow):
# time on them if not needed. See GH issue #282
pv = value
xv=1
transition = 0
if pv <= 100:
xv = pv/100
xv = pv / 100
transition = 0
elif pv <=101:
xv = pv -100
elif pv <= 101:
xv = pv - 100
transition = 1
elif pv <= 103:
xv = (pv -101)/2
xv = (pv - 101) / 2
transition = 2
elif pv <= 105:
xv = (pv -103)/2
xv = (pv - 103) / 2
transition = 3
else:
pv = 106
xv = pv -100
xv = pv - 100
transition = -1
if transition != -1:
colorS,colorE = self.transitionsColors[transition]
colorS, colorE = self.transitionsColors[transition]
color = colorUtils.CalculateTransitionColor(colorS, colorE, xv)
else:
color = wx.Colour(191,48,48)
color = wx.Colour(191, 48, 48)
if self.gradientEffect > 0:
gcolor = colorUtils.BrightenColor(color, float(self.gradientEffect) / 100)
gMid = colorUtils.BrightenColor(color, float(self.gradientEffect/2) / 100)
gcolor = colorUtils.BrightenColor(color, float(self.gradientEffect) / 100)
gMid = colorUtils.BrightenColor(color, float(self.gradientEffect / 2) / 100)
else:
gcolor = colorUtils.DarkenColor(color, float(-self.gradientEffect) / 100)
gMid = colorUtils.DarkenColor(color, float(-self.gradientEffect/2) / 100)
gcolor = colorUtils.DarkenColor(color, float(-self.gradientEffect) / 100)
gMid = colorUtils.DarkenColor(color, float(-self.gradientEffect / 2) / 100)
gBmp = drawUtils.DrawGradientBar(r.width, r.height, gMid, color, gcolor)
dc.DrawBitmap(gBmp, r.left, r.top)
else:
colour=self.GetBarColour()
colour = self.GetBarColour()
dc.SetBrush(wx.Brush(colour))
dc.SetPen(wx.Pen(colour))
if value > 100:
@@ -381,14 +376,14 @@ class PyGauge(wx.PyWindow):
dc.SetFont(self.font)
r = copy.copy(rect)
r.left +=1
r.top +=1
r.left += 1
r.top += 1
if self._range == 0.01 and self._value > 0:
formatStr = u'\u221e'
dc.SetTextForeground(wx.Colour(80,80,80))
formatStr = u'\u221e'
dc.SetTextForeground(wx.Colour(80, 80, 80))
dc.DrawLabel(formatStr, r, wx.ALIGN_CENTER)
dc.SetTextForeground(wx.Colour(255,255,255))
dc.SetTextForeground(wx.Colour(255, 255, 255))
dc.DrawLabel(formatStr, rect, wx.ALIGN_CENTER)
else:
if self.GetBarGradient() and self._showRemaining:
@@ -404,20 +399,20 @@ class PyGauge(wx.PyWindow):
else:
formatStr = "{0:." + str(self._fractionDigits) + "f}%"
dc.SetTextForeground(wx.Colour(80,80,80))
dc.SetTextForeground(wx.Colour(80, 80, 80))
dc.DrawLabel(formatStr.format(value), r, wx.ALIGN_CENTER)
dc.SetTextForeground(wx.Colour(255,255,255))
dc.SetTextForeground(wx.Colour(255, 255, 255))
dc.DrawLabel(formatStr.format(value), rect, wx.ALIGN_CENTER)
def OnTimer(self,event):
def OnTimer(self, event):
"""
Handles the ``wx.EVT_TIMER`` event for L{PyfaGauge}.
:param `event`: a timer event
:param event: a timer event
"""
oldValue=self._oldPercentage
value=self._percentage
oldValue = self._oldPercentage
value = self._percentage
start = 0
direction = 1 if oldValue < value else -1
@@ -436,13 +431,13 @@ class PyGauge(wx.PyWindow):
stop_timer = True
if direction == 1:
if (oldValue+step) < value:
self._animValue = oldValue+step
if (oldValue + step) < value:
self._animValue = oldValue + step
else:
stop_timer = True
else:
if (oldValue-step) > value:
self._animValue = oldValue-step
if (oldValue - step) > value:
self._animValue = oldValue - step
else:
stop_timer = True
@@ -451,4 +446,3 @@ class PyGauge(wx.PyWindow):
self._timer.Stop()
self.Refresh()

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2014 Ryan Holmes
#
# This file is part of pyfa.
@@ -15,14 +15,17 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
# noinspection PyPackageRequirements
import wx
from service.targetResists import TargetResists
from gui.bitmapLoader import BitmapLoader
import service
from gui.utils.clipboard import toClipboard, fromClipboard
from service.targetResists import ImportError
from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
from logbook import Logger
pyfalog = Logger(__name__)
class TargetResistsTextValidor(BaseValidator):
@@ -44,7 +47,8 @@ class TargetResistsTextValidor(BaseValidator):
raise ValueError("Target Resist Profile name already in use, please choose another.")
return True
except ValueError, e:
except ValueError as e:
pyfalog.error(e)
wx.MessageBox(u"{}".format(e), "Error")
textCtrl.SetFocus()
return False
@@ -56,34 +60,34 @@ class TargetResistsEntityEditor(EntityEditor):
self.SetEditorValidator(TargetResistsTextValidor)
def getEntitiesFromContext(self):
sTR = service.TargetResists.getInstance()
sTR = TargetResists.getInstance()
choices = sorted(sTR.getTargetResistsList(), key=lambda p: p.name)
return choices
def DoNew(self, name):
sTR = service.TargetResists.getInstance()
sTR = TargetResists.getInstance()
return sTR.newPattern(name)
def DoRename(self, entity, name):
sTR = service.TargetResists.getInstance()
sTR = TargetResists.getInstance()
sTR.renamePattern(entity, name)
def DoCopy(self, entity, name):
sTR = service.TargetResists.getInstance()
sTR = TargetResists.getInstance()
copy = sTR.copyPattern(entity)
sTR.renamePattern(copy, name)
return copy
def DoDelete(self, entity):
sTR = service.TargetResists.getInstance()
sTR = TargetResists.getInstance()
sTR.deletePattern(entity)
class ResistsEditorDlg(wx.Dialog):
class ResistsEditorDlg(wx.Dialog):
DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive")
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id = wx.ID_ANY, title = u"Target Resists Editor", size = wx.Size( 350,240 ))
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=u"Target Resists Editor", size=wx.Size(350, 240))
self.block = False
self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
@@ -104,24 +108,24 @@ class ResistsEditorDlg(wx.Dialog):
resistEditSizer.SetFlexibleDirection(wx.BOTH)
resistEditSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
width = -1
defSize = wx.Size(50,-1)
defSize = wx.Size(50, -1)
for i, type in enumerate(self.DAMAGE_TYPES):
if i%2:
for i, type_ in enumerate(self.DAMAGE_TYPES):
if i % 2:
style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT
border = 25
else:
style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT
border = 5
bmp = wx.StaticBitmap(self, wx.ID_ANY, BitmapLoader.getBitmap("%s_big"%type, "gui"))
bmp = wx.StaticBitmap(self, wx.ID_ANY, BitmapLoader.getBitmap("%s_big" % type_, "gui"))
resistEditSizer.Add(bmp, 0, style, border)
# set text edit
setattr(self, "%sEdit"%type, wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, defSize))
editObj = getattr(self, "%sEdit"%type)
setattr(self, "%sEdit" % type_, wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, defSize))
editObj = getattr(self, "%sEdit" % type_)
resistEditSizer.Add(editObj, 0, wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER_VERTICAL, 5)
resistEditSizer.Add(wx.StaticText( self, wx.ID_ANY, u"%", wx.DefaultPosition, wx.DefaultSize, 0 ), 0, wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER_VERTICAL, 5)
resistEditSizer.Add(wx.StaticText(self, wx.ID_ANY, u"%", wx.DefaultPosition, wx.DefaultSize, 0), 0,
wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER_VERTICAL, 5)
editObj.Bind(wx.EVT_TEXT, self.ValuesUpdated)
# Color we use to reset invalid value color
@@ -138,7 +142,7 @@ class ResistsEditorDlg(wx.Dialog):
self.stNotice.Wrap(-1)
perSizer.Add(self.stNotice, 0, wx.BOTTOM | wx.TOP | wx.LEFT, 5)
footerSizer.Add(perSizer, 1, wx.ALIGN_CENTER_VERTICAL, 5)
footerSizer.Add(perSizer, 1, wx.ALIGN_CENTER_VERTICAL, 5)
self.totSizer = wx.BoxSizer(wx.VERTICAL)
@@ -147,8 +151,8 @@ class ResistsEditorDlg(wx.Dialog):
mainSizer.Add(contentSizer, 1, wx.EXPAND, 0)
if "wxGTK" in wx.PlatformInfo:
self.closeBtn = wx.Button( self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.closeBtn, 0, wx.ALL|wx.ALIGN_RIGHT, 5 )
self.closeBtn = wx.Button(self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.closeBtn, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
self.closeBtn.Bind(wx.EVT_BUTTON, self.closeEvent)
self.SetSizer(mainSizer)
@@ -160,13 +164,13 @@ class ResistsEditorDlg(wx.Dialog):
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
btn.SetMinSize( btn.GetSize() )
btn.SetMaxSize( btn.GetSize() )
btn.SetMinSize(btn.GetSize())
btn.SetMaxSize(btn.GetSize())
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s patterns %s clipboard" % (name, direction) )
btn.SetToolTipString("%s patterns %s clipboard" % (name, direction))
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
btn.Bind(wx.EVT_BUTTON, getattr(self, "{}Patterns".format(name.lower())))
@@ -189,20 +193,22 @@ class ResistsEditorDlg(wx.Dialog):
self.Destroy()
def ValuesUpdated(self, event=None):
'''
"""
Event that is fired when resists values change. Iterates through all
resist edit fields. If blank, sets it to 0.0. If it is not a proper
decimal value, sets text color to red and refuses to save changes until
issue is resolved
'''
"""
if self.block:
return
editObj = None
try:
p = self.entityEditor.getActiveEntity()
for type in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit"%type)
for type_ in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit" % type_)
if editObj.GetValue() == "":
# if we are blank, overwrite with 0
@@ -215,7 +221,7 @@ class ResistsEditorDlg(wx.Dialog):
assert 0 <= value <= 100
# if everything checks out, set resist attribute
setattr(p, "%sAmount"%type, value/100)
setattr(p, "%sAmount" % type_, value / 100)
editObj.SetForegroundColour(self.colorReset)
self.stNotice.SetLabel("")
@@ -224,19 +230,23 @@ class ResistsEditorDlg(wx.Dialog):
if event is not None:
event.Skip()
service.TargetResists.getInstance().saveChanges(p)
TargetResists.getInstance().saveChanges(p)
except ValueError:
editObj.SetForegroundColour(wx.RED)
self.stNotice.SetLabel("Incorrect Formatting (decimals only)")
msg = "Incorrect Formatting (decimals only)"
pyfalog.warning(msg)
self.stNotice.SetLabel(msg)
except AssertionError:
editObj.SetForegroundColour(wx.RED)
self.stNotice.SetLabel("Incorrect Range (must be 0-100)")
msg = "Incorrect Range (must be 0-100)"
pyfalog.warning(msg)
self.stNotice.SetLabel(msg)
finally: # Refresh for color changes to take effect immediately
self.Refresh()
def patternChanged(self, event=None):
"Event fired when user selects pattern. Can also be called from script"
"""Event fired when user selects pattern. Can also be called from script"""
if not self.entityEditor.checkEntitiesExist():
self.Destroy()
@@ -250,35 +260,39 @@ class ResistsEditorDlg(wx.Dialog):
# Set new values
for field in self.DAMAGE_TYPES:
edit = getattr(self, "%sEdit" % field)
amount = getattr(p, "%sAmount" % field)*100
amount = getattr(p, "%sAmount" % field) * 100
edit.ChangeValue(str(amount))
self.block = False
self.ValuesUpdated()
def __del__( self ):
def __del__(self):
pass
def importPatterns(self, event):
"Event fired when import from clipboard button is clicked"
"""Event fired when import from clipboard button is clicked"""
text = fromClipboard()
if text:
sTR = service.TargetResists.getInstance()
sTR = TargetResists.getInstance()
try:
sTR.importPatterns(text)
self.stNotice.SetLabel("Patterns successfully imported from clipboard")
except service.targetResists.ImportError, e:
except ImportError as e:
pyfalog.error(e)
self.stNotice.SetLabel(str(e))
except Exception, e:
self.stNotice.SetLabel("Could not import from clipboard: unknown errors")
except Exception as e:
msg = "Could not import from clipboard:"
pyfalog.warning(msg)
pyfalog.error(e)
self.stNotice.SetLabel(msg)
finally:
self.entityEditor.refreshEntityList()
else:
self.stNotice.SetLabel("Could not import from clipboard")
def exportPatterns(self, event):
"Event fired when export to clipboard button is clicked"
sTR = service.TargetResists.getInstance()
toClipboard( sTR.exportPatterns() )
"""Event fired when export to clipboard button is clicked"""
sTR = TargetResists.getInstance()
toClipboard(sTR.exportPatterns())
self.stNotice.SetLabel("Patterns exported to clipboard")

View File

@@ -1,4 +1,4 @@
#===============================================================================
# =============================================================================
# Copyright (C) 2016 Ryan Holmes
#
# This file is part of pyfa.
@@ -15,18 +15,19 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# =============================================================================
from logbook import Logger
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from service.implantSet import ImplantSets
from gui.builtinViews.implantEditor import BaseImplantEditorView
import service
from gui.utils.clipboard import toClipboard, fromClipboard
from service.implantSet import ImportError
import logging
from gui.builtinViews.entityEditor import EntityEditor, BaseValidator
logger = logging.getLogger(__name__)
pyfalog = Logger(__name__)
class ImplantTextValidor(BaseValidator):
def __init__(self):
@@ -47,7 +48,8 @@ class ImplantTextValidor(BaseValidator):
raise ValueError("Imlplant Set name already in use, please choose another.")
return True
except ValueError, e:
except ValueError as e:
pyfalog.error(e)
wx.MessageBox(u"{}".format(e), "Error")
textCtrl.SetFocus()
return False
@@ -59,25 +61,25 @@ class ImplantSetEntityEditor(EntityEditor):
self.SetEditorValidator(ImplantTextValidor)
def getEntitiesFromContext(self):
sIS = service.ImplantSets.getInstance()
sIS = ImplantSets.getInstance()
return sorted(sIS.getImplantSetList(), key=lambda c: c.name)
def DoNew(self, name):
sIS = service.ImplantSets.getInstance()
sIS = ImplantSets.getInstance()
return sIS.newSet(name)
def DoRename(self, entity, name):
sIS = service.ImplantSets.getInstance()
sIS = ImplantSets.getInstance()
sIS.renameSet(entity, name)
def DoCopy(self, entity, name):
sIS = service.ImplantSets.getInstance()
sIS = ImplantSets.getInstance()
copy = sIS.copySet(entity)
sIS.renameSet(copy, name)
return copy
def DoDelete(self, entity):
sIS = service.ImplantSets.getInstance()
sIS = ImplantSets.getInstance()
sIS.deleteSet(entity)
@@ -91,28 +93,28 @@ class ImplantSetEditor(BaseImplantEditorView):
self.Parent.entityEditor.Bind(wx.EVT_CHOICE, self.contextChanged)
def getImplantsFromContext(self):
sIS = service.ImplantSets.getInstance()
set = self.Parent.entityEditor.getActiveEntity()
if set:
return sIS.getImplants(set.ID)
sIS = ImplantSets.getInstance()
set_ = self.Parent.entityEditor.getActiveEntity()
if set_:
return sIS.getImplants(set_.ID)
return []
def addImplantToContext(self, item):
sIS = service.ImplantSets.getInstance()
set = self.Parent.entityEditor.getActiveEntity()
sIS = ImplantSets.getInstance()
set_ = self.Parent.entityEditor.getActiveEntity()
sIS.addImplant(set.ID, item.ID)
sIS.addImplant(set_.ID, item.ID)
def removeImplantFromContext(self, implant):
sIS = service.ImplantSets.getInstance()
set = self.Parent.entityEditor.getActiveEntity()
sIS = ImplantSets.getInstance()
set_ = self.Parent.entityEditor.getActiveEntity()
sIS.removeImplant(set_.ID, implant)
sIS.removeImplant(set.ID, implant)
class ImplantSetEditorDlg(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id = wx.ID_ANY, title = u"Implant Set Editor", size = wx.Size(640, 600))
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=u"Implant Set Editor", size=wx.Size(640, 600))
self.block = False
self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
@@ -138,25 +140,25 @@ class ImplantSetEditorDlg(wx.Dialog):
footerSizer.Add(self.stNotice, 1, wx.BOTTOM | wx.TOP | wx.LEFT, 5)
if "wxGTK" in wx.PlatformInfo:
self.closeBtn = wx.Button( self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.closeBtn, 0, wx.ALL|wx.ALIGN_RIGHT, 5 )
self.closeBtn = wx.Button(self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.closeBtn, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
self.closeBtn.Bind(wx.EVT_BUTTON, self.closeEvent)
importExport = (("Import", wx.ART_FILE_OPEN, "from"),
("Export", wx.ART_FILE_SAVE_AS, "to"))
for name, art, direction in importExport:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
btn.SetMinSize( btn.GetSize() )
btn.SetMaxSize( btn.GetSize() )
btn.SetMinSize(btn.GetSize())
btn.SetMaxSize(btn.GetSize())
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s implant sets %s clipboard" % (name, direction) )
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s implant sets %s clipboard" % (name, direction))
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
mainSizer.Add(footerSizer, 0, wx.ALL | wx.EXPAND, 5)
@@ -183,23 +185,24 @@ class ImplantSetEditorDlg(wx.Dialog):
def closeEvent(self, event):
self.Destroy()
def __del__( self ):
def __del__(self):
pass
def importPatterns(self, event):
"Event fired when import from clipboard button is clicked"
"""Event fired when import from clipboard button is clicked"""
text = fromClipboard()
if text:
sIS = service.ImplantSets.getInstance()
sIS = ImplantSets.getInstance()
try:
sIS.importSets(text)
self.stNotice.SetLabel("Patterns successfully imported from clipboard")
self.showInput(False)
except ImportError, e:
except ImportError as e:
pyfalog.error(e)
self.stNotice.SetLabel(str(e))
except Exception, e:
logging.exception("Unhandled Exception")
except Exception as e:
pyfalog.error(e)
self.stNotice.SetLabel("Could not import from clipboard: unknown errors")
finally:
self.updateChoices()
@@ -207,8 +210,8 @@ class ImplantSetEditorDlg(wx.Dialog):
self.stNotice.SetLabel("Could not import from clipboard")
def exportPatterns(self, event):
"Event fired when export to clipboard button is clicked"
"""Event fired when export to clipboard button is clicked"""
sIS = service.ImplantSets.getInstance()
sIS = ImplantSets.getInstance()
toClipboard(sIS.exportSets())
self.stNotice.SetLabel("Sets exported to clipboard")

View File

@@ -1,5 +1,5 @@
# noinspection PyPackageRequirements
import wx
import gui.utils.colorUtils as colorUtils
import gui.utils.drawUtils as drawUtils
SB_ITEM_NORMAL = 0
@@ -7,14 +7,15 @@ SB_ITEM_SELECTED = 1
SB_ITEM_HIGHLIGHTED = 2
SB_ITEM_DISABLED = 4
BTN_NORMAL = 1
BTN_PRESSED = 2
BTN_HOVER = 4
BTN_NORMAL = 1
BTN_PRESSED = 2
BTN_HOVER = 4
BTN_DISABLED = 8
class PFBaseButton(object):
def __init__(self, normalBitmap = wx.NullBitmap,label = "", callback = None, hoverBitmap = None, disabledBitmap = None, show = True):
def __init__(self, normalBitmap=wx.NullBitmap, label="", callback=None, hoverBitmap=None, disabledBitmap=None,
show=True):
self.normalBmp = normalBitmap
self.dropShadowOpacity = 0.2
@@ -48,7 +49,7 @@ class PFBaseButton(object):
if self.callback:
self.callback()
def SetState(self, state = BTN_NORMAL):
def SetState(self, state=BTN_NORMAL):
self.state = state
def GetState(self):
@@ -57,7 +58,7 @@ class PFBaseButton(object):
def GetSize(self):
w = self.normalBmp.GetWidth()
h = self.normalBmp.GetHeight()
return (w,h)
return w, h
def GetBitmap(self):
return self.normalBmp
@@ -70,22 +71,23 @@ class PFBaseButton(object):
return self.label
def GetHoverBitmap(self):
if self.hoverBmp == None:
if self.hoverBmp is None:
return self.normalBmp
return self.hoverBmp
def GetDisabledBitmap(self):
if self.disabledBmp == None:
if self.disabledBmp is None:
return self.normalBmp
return self.disabledBmp
def GetDropShadowBitmap(self):
return self.dropShadowBmp
class PFToolbar(object):
def __init__(self, parent):
self.Parent = parent
self.buttons =[]
self.buttons = []
self.toolbarX = 0
self.toolbarY = 0
self.padding = 2
@@ -94,7 +96,7 @@ class PFToolbar(object):
def SetPosition(self, pos):
self.toolbarX, self.toolbarY = pos
def AddButton(self, btnBitmap, label = "", clickCallback = None, hoverBitmap = None, disabledBitmap = None, show = True):
def AddButton(self, btnBitmap, label="", clickCallback=None, hoverBitmap=None, disabledBitmap=None, show=True):
btn = PFBaseButton(btnBitmap, label, clickCallback, hoverBitmap, disabledBitmap, show)
self.buttons.append(btn)
return btn
@@ -115,7 +117,7 @@ class PFToolbar(object):
continue
state = button.GetState()
if self.HitTest( (bx, self.toolbarY), event.GetPosition(), button.GetSize()):
if self.HitTest((bx, self.toolbarY), event.GetPosition(), button.GetSize()):
changeCursor = True
if not state & BTN_HOVER:
button.SetState(state | BTN_HOVER)
@@ -135,7 +137,6 @@ class PFToolbar(object):
return doRefresh
def MouseClick(self, event):
mx,my = event.GetPosition()
bx = self.toolbarX
for button in self.buttons:
if not button.IsVisible():
@@ -143,8 +144,8 @@ class PFToolbar(object):
state = button.GetState()
if state & BTN_PRESSED:
button.SetState(state ^ BTN_PRESSED )
if self.HitTest( (bx, self.toolbarY), event.GetPosition(), button.GetSize()):
button.SetState(state ^ BTN_PRESSED)
if self.HitTest((bx, self.toolbarY), event.GetPosition(), button.GetSize()):
return button
else:
return False
@@ -158,7 +159,7 @@ class PFToolbar(object):
state = button.GetState()
if self.HitTest( (bx, self.toolbarY), event.GetPosition(), button.GetSize()):
if self.HitTest((bx, self.toolbarY), event.GetPosition(), button.GetSize()):
if event.LeftDown() or event.LeftDClick():
button.SetState(state | BTN_PRESSED)
@@ -195,11 +196,12 @@ class PFToolbar(object):
return height
def HitTest(self, target, position, area):
@staticmethod
def HitTest(target, position, area):
x, y = target
px, py = position
aX, aY = area
if (px > x and px < x + aX) and (py > y and py < y + aY):
if (x < px < x + aX) and (y < py < y + aY):
return True
return False
@@ -230,14 +232,14 @@ class PFToolbar(object):
bmpWidth = bmp.GetWidth()
pdc.DrawBitmap(dropShadowBmp,bx + self.padding / 2, self.toolbarY + self.padding / 2)
pdc.DrawBitmap(dropShadowBmp, bx + self.padding / 2, self.toolbarY + self.padding / 2)
pdc.DrawBitmap(bmp, tbx, by)
bx += bmpWidth + self.padding
class SFBrowserItem(wx.Window):
def __init__(self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = (0,16), style = 0):
def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=(0, 16), style=0):
wx.Window.__init__(self, parent, id, pos, size, style)
self.highlighted = False
@@ -248,7 +250,6 @@ class SFBrowserItem(wx.Window):
self.toolbar = PFToolbar(self)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
@@ -256,8 +257,7 @@ class SFBrowserItem(wx.Window):
if "wxMSW" in wx.PlatformInfo:
self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_DOWN,self.OnLeftDown)
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
self.Bind(wx.EVT_MOTION, self.OnMotion)
@@ -271,7 +271,7 @@ class SFBrowserItem(wx.Window):
self.RenderBackground()
mdc.DrawBitmap(self.bkBitmap, 0,0)
mdc.DrawBitmap(self.bkBitmap, 0, 0)
self.DrawItem(mdc)
self.toolbar.Render(mdc)
@@ -291,7 +291,7 @@ class SFBrowserItem(wx.Window):
def MouseMove(self, event):
pass
def SetDraggable(self, mode = True):
def SetDraggable(self, mode=True):
self.canBeDragged = mode
def OnLeftUp(self, event):
@@ -302,14 +302,13 @@ class SFBrowserItem(wx.Window):
mposx, mposy = wx.GetMousePosition()
rect = self.GetRect()
rect.top = rect.left = 0
cx,cy = self.ScreenToClient((mposx,mposy))
if not rect.Contains((cx,cy)):
cx, cy = self.ScreenToClient((mposx, mposy))
if not rect.Contains((cx, cy)):
self.SetHighlighted(False)
self.toolbar.ClearState()
self.Refresh()
return
btn = self.toolbar.MouseClick(event)
if btn is not None:
@@ -323,7 +322,6 @@ class SFBrowserItem(wx.Window):
self.MouseLeftUp(event)
def OnLeftDown(self, event):
if not self.HasCapture():
self.CaptureMouse()
@@ -357,13 +355,14 @@ class SFBrowserItem(wx.Window):
event.Skip()
def GetType(self):
@staticmethod
def GetType():
return -1
def SetSelected(self, select = True):
def SetSelected(self, select=True):
self.selected = select
def SetHighlighted(self, highlight = True):
def SetHighlighted(self, highlight=True):
self.highlighted = highlight
def GetState(self):
@@ -373,7 +372,7 @@ class SFBrowserItem(wx.Window):
elif self.selected:
if self.highlighted:
state = SB_ITEM_SELECTED | SB_ITEM_HIGHLIGHTED
state = SB_ITEM_SELECTED | SB_ITEM_HIGHLIGHTED
else:
state = SB_ITEM_SELECTED
else:
@@ -396,7 +395,7 @@ class SFBrowserItem(wx.Window):
mFactor = 0.45
eFactor = 0.30
elif state == SB_ITEM_SELECTED | SB_ITEM_HIGHLIGHTED:
elif state == SB_ITEM_SELECTED | SB_ITEM_HIGHLIGHTED:
eFactor = 0.3
elif state == SB_ITEM_SELECTED:
eFactor = 0.15
@@ -405,7 +404,7 @@ class SFBrowserItem(wx.Window):
if self.bkBitmap:
if self.bkBitmap.eFactor == eFactor and self.bkBitmap.sFactor == sFactor and self.bkBitmap.mFactor == mFactor \
and rect.width == self.bkBitmap.GetWidth() and rect.height == self.bkBitmap.GetHeight() :
and rect.width == self.bkBitmap.GetWidth() and rect.height == self.bkBitmap.GetHeight():
return
else:
del self.bkBitmap

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More