diff --git a/gui/PFListPane.py b/gui/PFListPane.py
index 9803f6873..556b97638 100644
--- a/gui/PFListPane.py
+++ b/gui/PFListPane.py
@@ -22,7 +22,8 @@ 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
diff --git a/gui/PFSearchBox.py b/gui/PFSearchBox.py
index 452bdbf09..ece5cef5f 100644
--- a/gui/PFSearchBox.py
+++ b/gui/PFSearchBox.py
@@ -2,7 +2,6 @@ import wx
import gui.utils.colorUtils as colorUtils
import gui.utils.drawUtils as drawUtils
-
SearchButton, EVT_SEARCH_BTN = wx.lib.newevent.NewEvent()
CancelButton, EVT_CANCEL_BTN = wx.lib.newevent.NewEvent()
TextEnter, EVT_TEXT_ENTER = wx.lib.newevent.NewEvent()
@@ -40,7 +39,9 @@ class PFSearchBox(wx.Window):
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))
+ 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)
diff --git a/gui/aboutData.py b/gui/aboutData.py
index 98e4c12f7..6e8ce07bc 100644
--- a/gui/aboutData.py
+++ b/gui/aboutData.py
@@ -19,7 +19,6 @@
import config
-
versionString = "{0} {1} - {2} {3}".format(config.version, config.tag, config.expansionName, config.expansionVersion)
licenses = (
"pyfa is released under GNU GPLv3 - see included LICENSE file",
diff --git a/gui/additionsPane.py b/gui/additionsPane.py
index 2e7e459e3..c0616f597 100644
--- a/gui/additionsPane.py
+++ b/gui/additionsPane.py
@@ -35,7 +35,6 @@ import gui.chromeTabs
class AdditionsPane(TogglePanel):
-
def __init__(self, parent):
TogglePanel.__init__(self, parent, forceLayout=1)
diff --git a/gui/bitmapLoader.py b/gui/bitmapLoader.py
index fb8be8a02..307a11267 100644
--- a/gui/bitmapLoader.py
+++ b/gui/bitmapLoader.py
@@ -30,7 +30,6 @@ except ImportError:
class BitmapLoader(object):
-
try:
archive = zipfile.ZipFile(os.path.join(config.pyfaPath, 'imgs.zip'), 'r')
except IOError:
diff --git a/gui/cargoView.py b/gui/cargoView.py
index 527b41691..6fe9e3c9e 100644
--- a/gui/cargoView.py
+++ b/gui/cargoView.py
@@ -27,21 +27,21 @@ 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):
+ 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
+ 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",
diff --git a/gui/characterEditor.py b/gui/characterEditor.py
index e9d512a74..2d9e63277 100644
--- a/gui/characterEditor.py
+++ b/gui/characterEditor.py
@@ -99,14 +99,14 @@ class CharacterEntityEditor(EntityEditor):
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)
+ # self.disableWin = wx.WindowDisabler(self)
sFit = Fit.getInstance()
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
@@ -179,7 +179,7 @@ class CharacterEditor(wx.Frame):
event.Skip()
def editingFinished(self, event):
- #del self.disableWin
+ # del self.disableWin
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
self.Destroy()
@@ -201,7 +201,7 @@ class CharacterEditor(wx.Frame):
wx.PostEvent(self, GE.CharListUpdated())
def closeEvent(self, event):
- #del self.disableWin
+ # del self.disableWin
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
self.Destroy()
@@ -234,18 +234,20 @@ 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)
- tree = self.skillTreeListCtrl = wx.gizmos.TreeListCtrl(self, wx.ID_ANY, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
+ 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"))
@@ -289,7 +291,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")
@@ -328,7 +329,7 @@ class SkillTreeView (wx.Panel):
if tree.GetItemText(child) == "dummy":
tree.Delete(child)
- #Get the real intrestin' stuff
+ # Get the real intrestin' stuff
sChar = Character.getInstance()
char = self.charEditor.entityEditor.getActiveEntity()
for id, name in sChar.getSkills(tree.GetPyData(root)):
@@ -391,7 +392,7 @@ class SkillTreeView (wx.Panel):
class ImplantEditorView(BaseImplantEditorView):
def __init__(self, parent):
- BaseImplantEditorView.__init__ (self, parent)
+ BaseImplantEditorView.__init__(self, parent)
self.determineEnabled()
@@ -445,9 +446,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))
@@ -456,17 +458,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)
@@ -498,39 +500,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)
@@ -587,7 +594,7 @@ class APIView (wx.Panel):
except TimeoutError, e:
self.stStatus.SetLabel("Request timed out. Please check network connectivity and/or proxy settings.")
except Exception, e:
- self.stStatus.SetLabel("Error:\n%s"%e.message)
+ self.stStatus.SetLabel("Error:\n%s" % e.message)
else:
self.charChoice.Clear()
for charName in list:
@@ -611,8 +618,8 @@ class APIView (wx.Panel):
except Exception, 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
@@ -640,4 +647,3 @@ class SaveCharacterAs(wx.Dialog):
event.Skip()
self.Close()
-
\ No newline at end of file
diff --git a/gui/chromeTabs.py b/gui/chromeTabs.py
index be2342622..00998eb87 100644
--- a/gui/chromeTabs.py
+++ b/gui/chromeTabs.py
@@ -26,7 +26,6 @@ from gui.bitmapLoader import BitmapLoader
from service.fit import Fit
-
_PageChanging, EVT_NOTEBOOK_PAGE_CHANGING = wx.lib.newevent.NewEvent()
_PageChanged, EVT_NOTEBOOK_PAGE_CHANGED = wx.lib.newevent.NewEvent()
_PageAdding, EVT_NOTEBOOK_PAGE_ADDING = wx.lib.newevent.NewEvent()
@@ -527,7 +526,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"""
@@ -1277,7 +1279,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):
@@ -1302,7 +1309,12 @@ 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()
@@ -1310,7 +1322,15 @@ class PFTabsContainer(wx.Panel):
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)
+ 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
diff --git a/gui/contextMenu.py b/gui/contextMenu.py
index 2a8033b44..5e8839cac 100644
--- a/gui/contextMenu.py
+++ b/gui/contextMenu.py
@@ -1,180 +1,179 @@
-# =============================================================================
-# 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 .
-# =============================================================================
-
-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 * # noqa
+# =============================================================================
+# 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 .
+# =============================================================================
+
+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 * # noqa
diff --git a/gui/copySelectDialog.py b/gui/copySelectDialog.py
index 659e01b5a..bb5a6e601 100644
--- a/gui/copySelectDialog.py
+++ b/gui/copySelectDialog.py
@@ -30,7 +30,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"]
@@ -40,7 +41,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)
diff --git a/gui/crestFittings.py b/gui/crestFittings.py
index 585e0f7ec..aa1fdc595 100644
--- a/gui/crestFittings.py
+++ b/gui/crestFittings.py
@@ -16,9 +16,9 @@ import gui.globalEvents as GE
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))
@@ -26,42 +26,43 @@ class CrestFittings(wx.Frame):
mainSizer = wx.BoxSizer(wx.VERTICAL)
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)
@@ -104,12 +105,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:
@@ -163,8 +164,8 @@ class CrestFittings(wx.Frame):
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:
@@ -174,9 +175,9 @@ class CrestFittings(wx.Frame):
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))
@@ -186,20 +187,21 @@ class ExportToEve(wx.Frame):
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)
@@ -271,7 +273,7 @@ class ExportToEve(wx.Frame):
data = sFit.exportCrest(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)
@@ -282,40 +284,40 @@ class ExportToEve(wx.Frame):
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()
diff --git a/gui/display.py b/gui/display.py
index 2aebc1db7..0d9e0308f 100644
--- a/gui/display.py
+++ b/gui/display.py
@@ -70,9 +70,8 @@ class Display(wx.ListCtrl):
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):
"""
@@ -282,7 +281,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)
diff --git a/gui/fighterView.py b/gui/fighterView.py
index 56aeb73b1..524c07976 100644
--- a/gui/fighterView.py
+++ b/gui/fighterView.py
@@ -28,24 +28,25 @@ from eos.types import Slot
from gui.contextMenu import ContextMenu
from service.fit import Fit
-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 OnData(self, x, y, t):
- if self.GetData():
- data = self.dropData.GetText().split(':')
- self.dropFn(x, y, data)
- return t
+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 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 +56,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,10 +75,9 @@ 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):
@@ -90,7 +90,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 +106,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)
@@ -131,12 +132,11 @@ class FighterDisplay(d.Display):
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))
@@ -183,7 +183,7 @@ 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)
@@ -229,7 +229,7 @@ class FighterDisplay(d.Display):
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,7 +257,6 @@ class FighterDisplay(d.Display):
self.update(stuff)
event.Skip()
-
def addItem(self, event):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
diff --git a/gui/fleetBrowser.py b/gui/fleetBrowser.py
index 1d3c6b38c..ab50e58ca 100644
--- a/gui/fleetBrowser.py
+++ b/gui/fleetBrowser.py
@@ -1,448 +1,449 @@
-import wx
-from wx.lib.buttons import GenBitmapButton
-
-import service.fleet
-import gui.mainFrame
-import gui.utils.colorUtils as colorUtils
-import gui.sfBrowserItem as SFItem
-from gui.bitmapLoader import BitmapLoader
-from gui.PFListPane import PFListPane
-from gui.utils.drawUtils import GetPartialText
-
-
-FleetSelected, EVT_FLEET_SELECTED = wx.lib.newevent.NewEvent()
-FleetRenamed, EVT_FLEET_RENAMED = wx.lib.newevent.NewEvent()
-FleetRemoved, EVT_FLEET_REMOVED = wx.lib.newevent.NewEvent()
-FleetItemSelect, EVT_FLEET_ITEM_SELECT = wx.lib.newevent.NewEvent()
-FleetItemDelete, EVT_FLEET_ITEM_DELETE = wx.lib.newevent.NewEvent()
-FleetItemNew, EVT_FLEET_ITEM_NEW = wx.lib.newevent.NewEvent()
-FleetItemCopy, EVT_FLEET_ITEM_COPY = wx.lib.newevent.NewEvent()
-FleetItemRename, EVT_FLEET_ITEM_RENAME = wx.lib.newevent.NewEvent()
-
-
-class FleetBrowser(wx.Panel):
- def __init__(self, parent):
- wx.Panel.__init__(self, parent)
-
- self.sFleet = service.fleet.Fleet.getInstance()
- self.mainFrame = gui.mainFrame.MainFrame.getInstance()
-
- mainSizer = wx.BoxSizer(wx.VERTICAL)
-
- self.hpane = FleetBrowserHeader(self)
- mainSizer.Add(self.hpane, 0, wx.EXPAND)
-
- self.m_sl2 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
- mainSizer.Add(self.m_sl2, 0, wx.EXPAND, 0)
-
- self.fleetItemContainer = PFFleetItemContainer(self)
-
- mainSizer.Add(self.fleetItemContainer, 1, wx.EXPAND)
-
- self.SetSizer(mainSizer)
- self.Layout()
-
- self.filter = ""
- self.fleetIDMustEditName = -1
-
- self.Bind(wx.EVT_SIZE, self.SizeRefreshList)
-
- self.Bind(EVT_FLEET_ITEM_NEW, self.AddNewFleetItem)
- self.Bind(EVT_FLEET_ITEM_SELECT, self.SelectFleetItem)
- self.Bind(EVT_FLEET_ITEM_DELETE, self.DeleteFleetItem)
- self.Bind(EVT_FLEET_ITEM_COPY, self.CopyFleetItem)
- self.Bind(EVT_FLEET_ITEM_RENAME, self.RenameFleetItem)
-
- self.PopulateFleetList()
-
- def AddNewFleetItem(self, event):
- fleetName = event.fleetName
- newFleet = self.sFleet.addFleet()
- self.sFleet.renameFleet(newFleet, fleetName)
-
- self.fleetIDMustEditName = newFleet.ID
- self.AddItem(newFleet.ID, newFleet.name, newFleet.count())
-
- def SelectFleetItem(self, event):
- fleetID = event.fleetID
- self.fleetItemContainer.SelectWidgetByFleetID(fleetID)
- wx.PostEvent(self.mainFrame, FleetSelected(fleetID=fleetID))
-
- def CopyFleetItem(self, event):
- fleetID = event.fleetID
- fleet = self.sFleet.copyFleetByID(fleetID)
-
- fleetName = fleet.name + " Copy"
- self.sFleet.renameFleet(fleet, fleetName)
-
- self.fleetIDMustEditName = fleet.ID
- self.AddItem(fleet.ID, fleet.name, fleet.count())
-
- self.fleetItemContainer.SelectWidgetByFleetID(fleet.ID)
- wx.PostEvent(self.mainFrame, FleetSelected(fleetID=fleet.ID))
-
- def RenameFleetItem(self, event):
- fleetID = event.fleetID
- fleet = self.sFleet.getFleetByID(fleetID)
-
- newFleetName = event.fleetName
-
- self.sFleet.renameFleet(fleet, newFleetName)
- wx.PostEvent(self.mainFrame, FleetRenamed(fleetID=fleet.ID))
-
- def DeleteFleetItem(self, event):
- self.sFleet.deleteFleetByID(event.fleetID)
- self.PopulateFleetList()
- wx.PostEvent(self.mainFrame, FleetRemoved(fleetID=event.fleetID))
-
- def AddItem(self, ID, name, count):
- self.fleetItemContainer.AddWidget(FleetItem(self, ID, name, count))
- widget = self.fleetItemContainer.GetWidgetByFleetID(ID)
- self.fleetItemContainer.RefreshList(True)
- self.fleetItemContainer.ScrollChildIntoView(widget)
- wx.PostEvent(self, FleetItemSelect(fleetID=ID))
-
- def PopulateFleetList(self):
- self.Freeze()
- filter_ = self.filter
- self.fleetItemContainer.RemoveAllChildren()
- fleetList = self.sFleet.getFleetList()
- for fleetID, fleetName, fleetCount in fleetList:
- if fleetName.lower().find(filter_.lower()) != -1:
- self.fleetItemContainer.AddWidget(FleetItem(self, fleetID, fleetName, fleetCount))
- self.fleetItemContainer.RefreshList()
- self.Thaw()
-
- def SetFilter(self, filter):
- self.filter = filter
-
- def SizeRefreshList(self, event):
- ewidth, eheight = event.GetSize()
- self.Layout()
- self.fleetItemContainer.Layout()
- self.fleetItemContainer.RefreshList(True)
- event.Skip()
-
-
-class FleetBrowserHeader(wx.Panel):
- def __init__(self, parent):
- wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 24), style=wx.TAB_TRAVERSAL)
- self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
-
- self.newBmp = BitmapLoader.getBitmap("fit_add_small", "gui")
- bmpSize = (16, 16)
-
- mainSizer = wx.BoxSizer(wx.HORIZONTAL)
-
- if 'wxMac' in wx.PlatformInfo:
- bgcolour = wx.Colour(0, 0, 0, 0)
- else:
- bgcolour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
-
- self.fbNewFleet = PFGenBitmapButton(self, wx.ID_ANY, self.newBmp, wx.DefaultPosition, bmpSize, wx.BORDER_NONE)
- mainSizer.Add(self.fbNewFleet, 0, wx.LEFT | wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 5)
- self.fbNewFleet.SetBackgroundColour(bgcolour)
-
- self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_VERTICAL)
- mainSizer.Add(self.sl1, 0, wx.EXPAND | wx.LEFT, 5)
-
- self.tcFilter = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
- mainSizer.Add(self.tcFilter, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
-
- self.stStatus = wx.StaticText(self, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0)
- self.stStatus.Wrap(-1)
- mainSizer.Add(self.stStatus, 1, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
-
- self.SetSizer(mainSizer)
- self.Layout()
-
- self.fbNewFleet.Bind(wx.EVT_ENTER_WINDOW, self.fbNewEnterWindow)
- self.fbNewFleet.Bind(wx.EVT_LEAVE_WINDOW, self.fbHItemLeaveWindow)
- self.fbNewFleet.Bind(wx.EVT_BUTTON, self.OnNewFleetItem)
-
- self.tcFilter.Bind(wx.EVT_TEXT, self.OnFilterText)
-
- self.tcFilter.Bind(wx.EVT_ENTER_WINDOW, self.fbFilterEnterWindow)
- self.tcFilter.Bind(wx.EVT_LEAVE_WINDOW, self.fbHItemLeaveWindow)
-
- def OnFilterText(self, event):
- filter = self.tcFilter.GetValue()
- self.Parent.SetFilter(filter)
- self.Parent.PopulateFleetList()
- event.Skip()
-
- def OnNewFleetItem(self, event):
- wx.PostEvent(self.Parent, FleetItemNew(fleetName="New Fleet"))
-
- def fbNewEnterWindow(self, event):
- self.stStatus.SetLabel("New fleet")
- self.Parent.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
- event.Skip()
-
- def fbHItemLeaveWindow(self, event):
- self.stStatus.SetLabel("")
- self.Parent.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
- event.Skip()
-
- def fbFilterEnterWindow(self, event):
- self.stStatus.SetLabel("Filter list")
- event.Skip()
-
-
-class PFFleetItemContainer(PFListPane):
- def __init__(self, parent):
- PFListPane.__init__(self, parent)
- self.selectedWidget = -1
- self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
-
- def IsWidgetSelectedByContext(self, widget):
- if self.GetWidgetList()[widget].IsSelected():
- return True
- return False
-
- def GetWidgetIndex(self, widgetWnd):
- return self.GetWidgetList().index(widgetWnd)
-
- def GetWidgetByFleetID(self, fleetID):
- for widget in self.GetWidgetList():
- if widget.fleetID == fleetID:
- return widget
- return None
-
- def SelectWidget(self, widgetWnd):
- wlist = self.GetWidgetList()
- if self.selectedWidget != -1:
- wlist[self.selectedWidget].SetSelected(False)
- wlist[self.selectedWidget].Refresh()
- windex = self.GetWidgetIndex(widgetWnd)
- wlist[windex].SetSelected(True)
- wlist[windex].Refresh()
- self.selectedWidget = windex
-
- def SelectWidgetByFleetID(self, fleetID):
- widgetWnd = self.GetWidgetByFleetID(fleetID)
- if widgetWnd:
- self.SelectWidget(widgetWnd)
-
- def RemoveWidget(self, child):
- child.Destroy()
- self.selectedWidget = -1
- self._wList.remove(child)
-
- def RemoveAllChildren(self):
- for widget in self._wList:
- widget.Destroy()
-
- self.selectedWidget = -1
- self._wList = []
-
- def OnLeftUp(self, event):
- event.Skip()
-
-
-class FleetItem(SFItem.SFBrowserItem):
- def __init__(self, parent, fleetID, fleetName, fleetCount,
- id=wx.ID_ANY, pos=wx.DefaultPosition,
- size=(0, 40), style=0):
- SFItem.SFBrowserItem.__init__(self, parent, size=size)
-
- self.fleetBrowser = self.Parent
- self.fleetID = fleetID
- self.fleetName = fleetName
- self.fleetCount = fleetCount
-
- self.padding = 4
-
- self.fontBig = wx.FontFromPixelSize((0, 15), wx.SWISS, wx.NORMAL, wx.BOLD, False)
- self.fontNormal = wx.FontFromPixelSize((0, 14), wx.SWISS, wx.NORMAL, wx.NORMAL, False)
- self.fontSmall = wx.FontFromPixelSize((0, 12), wx.SWISS, wx.NORMAL, wx.NORMAL, False)
-
- self.copyBmp = BitmapLoader.getBitmap("fit_add_small", "gui")
- self.renameBmp = BitmapLoader.getBitmap("fit_rename_small", "gui")
- self.deleteBmp = BitmapLoader.getBitmap("fit_delete_small", "gui")
- self.acceptBmp = BitmapLoader.getBitmap("faccept_small", "gui")
- self.fleetBmp = BitmapLoader.getBitmap("fleet_item_big", "gui")
-
- fleetImg = self.fleetBmp.ConvertToImage()
- fleetImg = fleetImg.Blur(2)
-
- if not fleetImg.HasAlpha():
- fleetImg.InitAlpha()
-
- fleetImg = fleetImg.AdjustChannels(1, 1, 1, 0.5)
- self.fleetEffBmp = wx.BitmapFromImage(fleetImg)
-
- self.toolbar.AddButton(self.copyBmp, "Copy", self.CopyFleetCB)
- self.renameBtn = self.toolbar.AddButton(self.renameBmp, "Rename", self.RenameFleetCB)
- self.toolbar.AddButton(self.deleteBmp, "Delete", self.DeleteFleetCB)
-
- self.editWidth = 150
- self.tcFleetName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fleetName, wx.DefaultPosition, (self.editWidth, -1), wx.TE_PROCESS_ENTER)
-
- if self.fleetBrowser.fleetIDMustEditName != self.fleetID:
- self.tcFleetName.Show(False)
- else:
- self.tcFleetName.SetFocus()
- self.tcFleetName.SelectAll()
- self.fleetBrowser.fleetIDMustEditName = -1
- self.renameBtn.SetBitmap(self.acceptBmp)
- self.selected = True
-
- self.tcFleetName.Bind(wx.EVT_KILL_FOCUS, self.OnEditLostFocus)
- self.tcFleetName.Bind(wx.EVT_TEXT_ENTER, self.RenameFleet)
- self.tcFleetName.Bind(wx.EVT_KEY_DOWN, self.EditCheckEsc)
-
- self.animCount = 0
-
- def MouseLeftUp(self, event):
- if self.tcFleetName.IsShown():
- self.RestoreEditButton()
- else:
- wx.PostEvent(self.fleetBrowser, FleetItemSelect(fleetID=self.fleetID))
-
- def CopyFleetCB(self):
- if self.tcFleetName.IsShown():
- self.RestoreEditButton()
- return
-
- wx.PostEvent(self.fleetBrowser, FleetItemCopy(fleetID=self.fleetID))
-
- def RenameFleetCB(self):
-
- if self.tcFleetName.IsShown():
-
- self.RenameFleet(None)
- self.RestoreEditButton()
-
- else:
- self.tcFleetName.SetValue(self.fleetName)
- self.tcFleetName.Show()
-
- self.renameBtn.SetBitmap(self.acceptBmp)
- self.Refresh()
-
- self.tcFleetName.SetFocus()
- self.tcFleetName.SelectAll()
-
- self.Refresh()
-
- def RenameFleet(self, event):
-
- newFleetName = self.tcFleetName.GetValue()
- self.fleetName = newFleetName
-
- self.tcFleetName.Show(False)
-
- wx.PostEvent(self.fleetBrowser, FleetItemRename(fleetID=self.fleetID, fleetName=self.fleetName))
- self.Refresh()
-
- def DeleteFleetCB(self):
- if self.tcFleetName.IsShown():
- self.RestoreEditButton()
- return
- wx.PostEvent(self.fleetBrowser, FleetItemDelete(fleetID=self.fleetID))
-
- def RestoreEditButton(self):
- self.tcFleetName.Show(False)
- self.renameBtn.SetBitmap(self.renameBmp)
- self.Refresh()
-
- def OnEditLostFocus(self, event):
- self.RestoreEditButton()
- self.Refresh()
-
- def EditCheckEsc(self, event):
- if event.GetKeyCode() == wx.WXK_ESCAPE:
- self.RestoreEditButton()
- else:
- event.Skip()
-
- def IsSelected(self):
- return self.selected
-
- def UpdateElementsPos(self, mdc):
- rect = self.GetRect()
-
- self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding
- self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2
-
- self.toolbarx = self.toolbarx + self.animCount
-
- self.fleetBmpx = self.padding + (rect.height - self.fleetBmp.GetWidth()) / 2
- self.fleetBmpy = (rect.height - self.fleetBmp.GetHeight()) / 2
-
- self.fleetBmpx -= self.animCount
-
- self.textStartx = self.fleetBmpx + self.fleetBmp.GetWidth() + self.padding
-
- self.fleetNamey = (rect.height - self.fleetBmp.GetHeight()) / 2
-
- mdc.SetFont(self.fontBig)
- wtext, htext = mdc.GetTextExtent(self.fleetName)
-
- self.fleetCounty = self.fleetNamey + htext
-
- mdc.SetFont(self.fontSmall)
-
- wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel)
-
- self.thoverx = self.toolbarx - self.padding - wlabel
- self.thovery = (rect.height - hlabel) / 2
- self.thoverw = wlabel
-
- def DrawItem(self, mdc):
- # rect = self.GetRect()
-
- windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
- textColor = colorUtils.GetSuitableColor(windowColor, 1)
-
- mdc.SetTextForeground(textColor)
-
- self.UpdateElementsPos(mdc)
-
- self.toolbar.SetPosition((self.toolbarx, self.toolbary))
- mdc.DrawBitmap(self.fleetEffBmp, self.fleetBmpx + 3, self.fleetBmpy + 2)
- mdc.DrawBitmap(self.fleetBmp, self.fleetBmpx, self.fleetBmpy)
-
- mdc.SetFont(self.fontNormal)
-
- suffix = "%d ships" % self.fleetCount if self.fleetCount > 1 else "%d ship" % self.fleetCount if self.fleetCount == 1 else "No ships"
- fleetCount = "Fleet size: %s" % suffix
- fleetCount = GetPartialText(mdc, fleetCount, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
-
- mdc.DrawText(fleetCount, self.textStartx, self.fleetCounty)
-
- mdc.SetFont(self.fontSmall)
- mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
-
- mdc.SetFont(self.fontBig)
-
- pfname = GetPartialText(mdc, self.fleetName, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
- mdc.DrawText(pfname, self.textStartx, self.fleetNamey)
-
- if self.tcFleetName.IsShown():
- self.AdjustControlSizePos(self.tcFleetName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
-
- def AdjustControlSizePos(self, editCtl, start, end):
- fnEditSize = editCtl.GetSize()
- wSize = self.GetSize()
- fnEditPosX = end
- fnEditPosY = (wSize.height - fnEditSize.height) / 2
- if fnEditPosX < start:
- editCtl.SetSize((self.editWidth + fnEditPosX - start, -1))
- editCtl.SetPosition((start, fnEditPosY))
- else:
- editCtl.SetSize((self.editWidth, -1))
- editCtl.SetPosition((fnEditPosX, fnEditPosY))
-
-
-class PFGenBitmapButton(GenBitmapButton):
- def __init__(self, parent, id, bitmap, pos, size, style):
- GenBitmapButton.__init__(self, parent, id, bitmap, pos, size, style)
- self.bgcolor = wx.Brush(wx.WHITE)
-
- def SetBackgroundColour(self, color):
- self.bgcolor = wx.Brush(color)
-
- def GetBackgroundBrush(self, dc):
- return self.bgcolor
+import wx
+from wx.lib.buttons import GenBitmapButton
+
+import service.fleet
+import gui.mainFrame
+import gui.utils.colorUtils as colorUtils
+import gui.sfBrowserItem as SFItem
+from gui.bitmapLoader import BitmapLoader
+from gui.PFListPane import PFListPane
+from gui.utils.drawUtils import GetPartialText
+
+FleetSelected, EVT_FLEET_SELECTED = wx.lib.newevent.NewEvent()
+FleetRenamed, EVT_FLEET_RENAMED = wx.lib.newevent.NewEvent()
+FleetRemoved, EVT_FLEET_REMOVED = wx.lib.newevent.NewEvent()
+FleetItemSelect, EVT_FLEET_ITEM_SELECT = wx.lib.newevent.NewEvent()
+FleetItemDelete, EVT_FLEET_ITEM_DELETE = wx.lib.newevent.NewEvent()
+FleetItemNew, EVT_FLEET_ITEM_NEW = wx.lib.newevent.NewEvent()
+FleetItemCopy, EVT_FLEET_ITEM_COPY = wx.lib.newevent.NewEvent()
+FleetItemRename, EVT_FLEET_ITEM_RENAME = wx.lib.newevent.NewEvent()
+
+
+class FleetBrowser(wx.Panel):
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent)
+
+ self.sFleet = service.fleet.Fleet.getInstance()
+ self.mainFrame = gui.mainFrame.MainFrame.getInstance()
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+ self.hpane = FleetBrowserHeader(self)
+ mainSizer.Add(self.hpane, 0, wx.EXPAND)
+
+ self.m_sl2 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
+ mainSizer.Add(self.m_sl2, 0, wx.EXPAND, 0)
+
+ self.fleetItemContainer = PFFleetItemContainer(self)
+
+ mainSizer.Add(self.fleetItemContainer, 1, wx.EXPAND)
+
+ self.SetSizer(mainSizer)
+ self.Layout()
+
+ self.filter = ""
+ self.fleetIDMustEditName = -1
+
+ self.Bind(wx.EVT_SIZE, self.SizeRefreshList)
+
+ self.Bind(EVT_FLEET_ITEM_NEW, self.AddNewFleetItem)
+ self.Bind(EVT_FLEET_ITEM_SELECT, self.SelectFleetItem)
+ self.Bind(EVT_FLEET_ITEM_DELETE, self.DeleteFleetItem)
+ self.Bind(EVT_FLEET_ITEM_COPY, self.CopyFleetItem)
+ self.Bind(EVT_FLEET_ITEM_RENAME, self.RenameFleetItem)
+
+ self.PopulateFleetList()
+
+ def AddNewFleetItem(self, event):
+ fleetName = event.fleetName
+ newFleet = self.sFleet.addFleet()
+ self.sFleet.renameFleet(newFleet, fleetName)
+
+ self.fleetIDMustEditName = newFleet.ID
+ self.AddItem(newFleet.ID, newFleet.name, newFleet.count())
+
+ def SelectFleetItem(self, event):
+ fleetID = event.fleetID
+ self.fleetItemContainer.SelectWidgetByFleetID(fleetID)
+ wx.PostEvent(self.mainFrame, FleetSelected(fleetID=fleetID))
+
+ def CopyFleetItem(self, event):
+ fleetID = event.fleetID
+ fleet = self.sFleet.copyFleetByID(fleetID)
+
+ fleetName = fleet.name + " Copy"
+ self.sFleet.renameFleet(fleet, fleetName)
+
+ self.fleetIDMustEditName = fleet.ID
+ self.AddItem(fleet.ID, fleet.name, fleet.count())
+
+ self.fleetItemContainer.SelectWidgetByFleetID(fleet.ID)
+ wx.PostEvent(self.mainFrame, FleetSelected(fleetID=fleet.ID))
+
+ def RenameFleetItem(self, event):
+ fleetID = event.fleetID
+ fleet = self.sFleet.getFleetByID(fleetID)
+
+ newFleetName = event.fleetName
+
+ self.sFleet.renameFleet(fleet, newFleetName)
+ wx.PostEvent(self.mainFrame, FleetRenamed(fleetID=fleet.ID))
+
+ def DeleteFleetItem(self, event):
+ self.sFleet.deleteFleetByID(event.fleetID)
+ self.PopulateFleetList()
+ wx.PostEvent(self.mainFrame, FleetRemoved(fleetID=event.fleetID))
+
+ def AddItem(self, ID, name, count):
+ self.fleetItemContainer.AddWidget(FleetItem(self, ID, name, count))
+ widget = self.fleetItemContainer.GetWidgetByFleetID(ID)
+ self.fleetItemContainer.RefreshList(True)
+ self.fleetItemContainer.ScrollChildIntoView(widget)
+ wx.PostEvent(self, FleetItemSelect(fleetID=ID))
+
+ def PopulateFleetList(self):
+ self.Freeze()
+ filter_ = self.filter
+ self.fleetItemContainer.RemoveAllChildren()
+ fleetList = self.sFleet.getFleetList()
+ for fleetID, fleetName, fleetCount in fleetList:
+ if fleetName.lower().find(filter_.lower()) != -1:
+ self.fleetItemContainer.AddWidget(FleetItem(self, fleetID, fleetName, fleetCount))
+ self.fleetItemContainer.RefreshList()
+ self.Thaw()
+
+ def SetFilter(self, filter):
+ self.filter = filter
+
+ def SizeRefreshList(self, event):
+ ewidth, eheight = event.GetSize()
+ self.Layout()
+ self.fleetItemContainer.Layout()
+ self.fleetItemContainer.RefreshList(True)
+ event.Skip()
+
+
+class FleetBrowserHeader(wx.Panel):
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 24),
+ style=wx.TAB_TRAVERSAL)
+ self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
+
+ self.newBmp = BitmapLoader.getBitmap("fit_add_small", "gui")
+ bmpSize = (16, 16)
+
+ mainSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ if 'wxMac' in wx.PlatformInfo:
+ bgcolour = wx.Colour(0, 0, 0, 0)
+ else:
+ bgcolour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
+
+ self.fbNewFleet = PFGenBitmapButton(self, wx.ID_ANY, self.newBmp, wx.DefaultPosition, bmpSize, wx.BORDER_NONE)
+ mainSizer.Add(self.fbNewFleet, 0, wx.LEFT | wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 5)
+ self.fbNewFleet.SetBackgroundColour(bgcolour)
+
+ self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_VERTICAL)
+ mainSizer.Add(self.sl1, 0, wx.EXPAND | wx.LEFT, 5)
+
+ self.tcFilter = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
+ mainSizer.Add(self.tcFilter, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
+
+ self.stStatus = wx.StaticText(self, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0)
+ self.stStatus.Wrap(-1)
+ mainSizer.Add(self.stStatus, 1, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
+
+ self.SetSizer(mainSizer)
+ self.Layout()
+
+ self.fbNewFleet.Bind(wx.EVT_ENTER_WINDOW, self.fbNewEnterWindow)
+ self.fbNewFleet.Bind(wx.EVT_LEAVE_WINDOW, self.fbHItemLeaveWindow)
+ self.fbNewFleet.Bind(wx.EVT_BUTTON, self.OnNewFleetItem)
+
+ self.tcFilter.Bind(wx.EVT_TEXT, self.OnFilterText)
+
+ self.tcFilter.Bind(wx.EVT_ENTER_WINDOW, self.fbFilterEnterWindow)
+ self.tcFilter.Bind(wx.EVT_LEAVE_WINDOW, self.fbHItemLeaveWindow)
+
+ def OnFilterText(self, event):
+ filter = self.tcFilter.GetValue()
+ self.Parent.SetFilter(filter)
+ self.Parent.PopulateFleetList()
+ event.Skip()
+
+ def OnNewFleetItem(self, event):
+ wx.PostEvent(self.Parent, FleetItemNew(fleetName="New Fleet"))
+
+ def fbNewEnterWindow(self, event):
+ self.stStatus.SetLabel("New fleet")
+ self.Parent.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
+ event.Skip()
+
+ def fbHItemLeaveWindow(self, event):
+ self.stStatus.SetLabel("")
+ self.Parent.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+ event.Skip()
+
+ def fbFilterEnterWindow(self, event):
+ self.stStatus.SetLabel("Filter list")
+ event.Skip()
+
+
+class PFFleetItemContainer(PFListPane):
+ def __init__(self, parent):
+ PFListPane.__init__(self, parent)
+ self.selectedWidget = -1
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+
+ def IsWidgetSelectedByContext(self, widget):
+ if self.GetWidgetList()[widget].IsSelected():
+ return True
+ return False
+
+ def GetWidgetIndex(self, widgetWnd):
+ return self.GetWidgetList().index(widgetWnd)
+
+ def GetWidgetByFleetID(self, fleetID):
+ for widget in self.GetWidgetList():
+ if widget.fleetID == fleetID:
+ return widget
+ return None
+
+ def SelectWidget(self, widgetWnd):
+ wlist = self.GetWidgetList()
+ if self.selectedWidget != -1:
+ wlist[self.selectedWidget].SetSelected(False)
+ wlist[self.selectedWidget].Refresh()
+ windex = self.GetWidgetIndex(widgetWnd)
+ wlist[windex].SetSelected(True)
+ wlist[windex].Refresh()
+ self.selectedWidget = windex
+
+ def SelectWidgetByFleetID(self, fleetID):
+ widgetWnd = self.GetWidgetByFleetID(fleetID)
+ if widgetWnd:
+ self.SelectWidget(widgetWnd)
+
+ def RemoveWidget(self, child):
+ child.Destroy()
+ self.selectedWidget = -1
+ self._wList.remove(child)
+
+ def RemoveAllChildren(self):
+ for widget in self._wList:
+ widget.Destroy()
+
+ self.selectedWidget = -1
+ self._wList = []
+
+ def OnLeftUp(self, event):
+ event.Skip()
+
+
+class FleetItem(SFItem.SFBrowserItem):
+ def __init__(self, parent, fleetID, fleetName, fleetCount,
+ id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=(0, 40), style=0):
+ SFItem.SFBrowserItem.__init__(self, parent, size=size)
+
+ self.fleetBrowser = self.Parent
+ self.fleetID = fleetID
+ self.fleetName = fleetName
+ self.fleetCount = fleetCount
+
+ self.padding = 4
+
+ self.fontBig = wx.FontFromPixelSize((0, 15), wx.SWISS, wx.NORMAL, wx.BOLD, False)
+ self.fontNormal = wx.FontFromPixelSize((0, 14), wx.SWISS, wx.NORMAL, wx.NORMAL, False)
+ self.fontSmall = wx.FontFromPixelSize((0, 12), wx.SWISS, wx.NORMAL, wx.NORMAL, False)
+
+ self.copyBmp = BitmapLoader.getBitmap("fit_add_small", "gui")
+ self.renameBmp = BitmapLoader.getBitmap("fit_rename_small", "gui")
+ self.deleteBmp = BitmapLoader.getBitmap("fit_delete_small", "gui")
+ self.acceptBmp = BitmapLoader.getBitmap("faccept_small", "gui")
+ self.fleetBmp = BitmapLoader.getBitmap("fleet_item_big", "gui")
+
+ fleetImg = self.fleetBmp.ConvertToImage()
+ fleetImg = fleetImg.Blur(2)
+
+ if not fleetImg.HasAlpha():
+ fleetImg.InitAlpha()
+
+ fleetImg = fleetImg.AdjustChannels(1, 1, 1, 0.5)
+ self.fleetEffBmp = wx.BitmapFromImage(fleetImg)
+
+ self.toolbar.AddButton(self.copyBmp, "Copy", self.CopyFleetCB)
+ self.renameBtn = self.toolbar.AddButton(self.renameBmp, "Rename", self.RenameFleetCB)
+ self.toolbar.AddButton(self.deleteBmp, "Delete", self.DeleteFleetCB)
+
+ self.editWidth = 150
+ self.tcFleetName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fleetName, wx.DefaultPosition, (self.editWidth, -1),
+ wx.TE_PROCESS_ENTER)
+
+ if self.fleetBrowser.fleetIDMustEditName != self.fleetID:
+ self.tcFleetName.Show(False)
+ else:
+ self.tcFleetName.SetFocus()
+ self.tcFleetName.SelectAll()
+ self.fleetBrowser.fleetIDMustEditName = -1
+ self.renameBtn.SetBitmap(self.acceptBmp)
+ self.selected = True
+
+ self.tcFleetName.Bind(wx.EVT_KILL_FOCUS, self.OnEditLostFocus)
+ self.tcFleetName.Bind(wx.EVT_TEXT_ENTER, self.RenameFleet)
+ self.tcFleetName.Bind(wx.EVT_KEY_DOWN, self.EditCheckEsc)
+
+ self.animCount = 0
+
+ def MouseLeftUp(self, event):
+ if self.tcFleetName.IsShown():
+ self.RestoreEditButton()
+ else:
+ wx.PostEvent(self.fleetBrowser, FleetItemSelect(fleetID=self.fleetID))
+
+ def CopyFleetCB(self):
+ if self.tcFleetName.IsShown():
+ self.RestoreEditButton()
+ return
+
+ wx.PostEvent(self.fleetBrowser, FleetItemCopy(fleetID=self.fleetID))
+
+ def RenameFleetCB(self):
+
+ if self.tcFleetName.IsShown():
+
+ self.RenameFleet(None)
+ self.RestoreEditButton()
+
+ else:
+ self.tcFleetName.SetValue(self.fleetName)
+ self.tcFleetName.Show()
+
+ self.renameBtn.SetBitmap(self.acceptBmp)
+ self.Refresh()
+
+ self.tcFleetName.SetFocus()
+ self.tcFleetName.SelectAll()
+
+ self.Refresh()
+
+ def RenameFleet(self, event):
+
+ newFleetName = self.tcFleetName.GetValue()
+ self.fleetName = newFleetName
+
+ self.tcFleetName.Show(False)
+
+ wx.PostEvent(self.fleetBrowser, FleetItemRename(fleetID=self.fleetID, fleetName=self.fleetName))
+ self.Refresh()
+
+ def DeleteFleetCB(self):
+ if self.tcFleetName.IsShown():
+ self.RestoreEditButton()
+ return
+ wx.PostEvent(self.fleetBrowser, FleetItemDelete(fleetID=self.fleetID))
+
+ def RestoreEditButton(self):
+ self.tcFleetName.Show(False)
+ self.renameBtn.SetBitmap(self.renameBmp)
+ self.Refresh()
+
+ def OnEditLostFocus(self, event):
+ self.RestoreEditButton()
+ self.Refresh()
+
+ def EditCheckEsc(self, event):
+ if event.GetKeyCode() == wx.WXK_ESCAPE:
+ self.RestoreEditButton()
+ else:
+ event.Skip()
+
+ def IsSelected(self):
+ return self.selected
+
+ def UpdateElementsPos(self, mdc):
+ rect = self.GetRect()
+
+ self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding
+ self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2
+
+ self.toolbarx = self.toolbarx + self.animCount
+
+ self.fleetBmpx = self.padding + (rect.height - self.fleetBmp.GetWidth()) / 2
+ self.fleetBmpy = (rect.height - self.fleetBmp.GetHeight()) / 2
+
+ self.fleetBmpx -= self.animCount
+
+ self.textStartx = self.fleetBmpx + self.fleetBmp.GetWidth() + self.padding
+
+ self.fleetNamey = (rect.height - self.fleetBmp.GetHeight()) / 2
+
+ mdc.SetFont(self.fontBig)
+ wtext, htext = mdc.GetTextExtent(self.fleetName)
+
+ self.fleetCounty = self.fleetNamey + htext
+
+ mdc.SetFont(self.fontSmall)
+
+ wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel)
+
+ self.thoverx = self.toolbarx - self.padding - wlabel
+ self.thovery = (rect.height - hlabel) / 2
+ self.thoverw = wlabel
+
+ def DrawItem(self, mdc):
+ # rect = self.GetRect()
+
+ windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
+ textColor = colorUtils.GetSuitableColor(windowColor, 1)
+
+ mdc.SetTextForeground(textColor)
+
+ self.UpdateElementsPos(mdc)
+
+ self.toolbar.SetPosition((self.toolbarx, self.toolbary))
+ mdc.DrawBitmap(self.fleetEffBmp, self.fleetBmpx + 3, self.fleetBmpy + 2)
+ mdc.DrawBitmap(self.fleetBmp, self.fleetBmpx, self.fleetBmpy)
+
+ mdc.SetFont(self.fontNormal)
+
+ suffix = "%d ships" % self.fleetCount if self.fleetCount > 1 else "%d ship" % self.fleetCount if self.fleetCount == 1 else "No ships"
+ fleetCount = "Fleet size: %s" % suffix
+ fleetCount = GetPartialText(mdc, fleetCount, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
+
+ mdc.DrawText(fleetCount, self.textStartx, self.fleetCounty)
+
+ mdc.SetFont(self.fontSmall)
+ mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
+
+ mdc.SetFont(self.fontBig)
+
+ pfname = GetPartialText(mdc, self.fleetName, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
+ mdc.DrawText(pfname, self.textStartx, self.fleetNamey)
+
+ if self.tcFleetName.IsShown():
+ self.AdjustControlSizePos(self.tcFleetName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
+
+ def AdjustControlSizePos(self, editCtl, start, end):
+ fnEditSize = editCtl.GetSize()
+ wSize = self.GetSize()
+ fnEditPosX = end
+ fnEditPosY = (wSize.height - fnEditSize.height) / 2
+ if fnEditPosX < start:
+ editCtl.SetSize((self.editWidth + fnEditPosX - start, -1))
+ editCtl.SetPosition((start, fnEditPosY))
+ else:
+ editCtl.SetSize((self.editWidth, -1))
+ editCtl.SetPosition((fnEditPosX, fnEditPosY))
+
+
+class PFGenBitmapButton(GenBitmapButton):
+ def __init__(self, parent, id, bitmap, pos, size, style):
+ GenBitmapButton.__init__(self, parent, id, bitmap, pos, size, style)
+ self.bgcolor = wx.Brush(wx.WHITE)
+
+ def SetBackgroundColour(self, color):
+ self.bgcolor = wx.Brush(color)
+
+ def GetBackgroundBrush(self, dc):
+ return self.bgcolor
diff --git a/gui/gangView.py b/gui/gangView.py
index ea422bc83..93e48c117 100644
--- a/gui/gangView.py
+++ b/gui/gangView.py
@@ -32,7 +32,8 @@ import gui.globalEvents as GE
class GangView(ScrolledPanel):
def __init__(self, parent):
- ScrolledPanel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(100, 20), style=wx.TAB_TRAVERSAL | wx.HSCROLL | wx.VSCROLL)
+ ScrolledPanel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(100, 20),
+ style=wx.TAB_TRAVERSAL | wx.HSCROLL | wx.VSCROLL)
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
@@ -49,10 +50,10 @@ class GangView(ScrolledPanel):
self.fleet = {}
for id_, option in enumerate(self.options):
-
# set content for each commander
self.fleet[id_] = {}
- self.fleet[id_]['stLabel'] = wx.StaticText(self, wx.ID_ANY, self.options[id_] + ':', wx.DefaultPosition, wx.DefaultSize, 0)
+ self.fleet[id_]['stLabel'] = wx.StaticText(self, wx.ID_ANY, self.options[id_] + ':', wx.DefaultPosition,
+ wx.DefaultSize, 0)
self.fleet[id_]['stText'] = wx.StaticText(self, wx.ID_ANY, 'None', wx.DefaultPosition, wx.DefaultSize, 0)
self.fleet[id_]['chFit'] = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [])
self.fleet[id_]['chChar'] = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [])
@@ -94,7 +95,8 @@ class GangView(ScrolledPanel):
for id_ in self.fleet:
# set various properties
self.fleet[id_]['stLabel'].Wrap(-1)
- self.fleet[id_]['stLabel'].SetFont(wx.Font(wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString))
+ self.fleet[id_]['stLabel'].SetFont(
+ wx.Font(wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString))
self.fleet[id_]['stText'].Wrap(-1)
# bind text and choice events
@@ -107,7 +109,8 @@ class GangView(ScrolledPanel):
# add fit text and choice to the fit sizer
self.fleet[id_]['fitSizer'].Add(self.fleet[id_]['stText'], 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
- self.fleet[id_]['fitSizer'].Add(self.fleet[id_]['chFit'], 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND, 1)
+ self.fleet[id_]['fitSizer'].Add(self.fleet[id_]['chFit'], 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND,
+ 1)
# add everything to the content sizer
contentFGSizer.Add(self.fleet[id_]['stLabel'], 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
@@ -271,7 +274,8 @@ class GangView(ScrolledPanel):
raise Exception()
self.fleet[id_]['stText'].SetLabel(commander.ship.item.name + ": " + commander.name)
- self.fleet[id_]['chChar'].SetStringSelection(commander.character.name if commander.character is not None else "All 0")
+ self.fleet[id_]['chChar'].SetStringSelection(
+ commander.character.name if commander.character is not None else "All 0")
self.fleet[id_]['chChar'].Enable()
self.fleet[id_]['chFit'].Hide()
self.fleet[id_]['stText'].Show()
diff --git a/gui/globalEvents.py b/gui/globalEvents.py
index 7b81b3218..18f91d348 100644
--- a/gui/globalEvents.py
+++ b/gui/globalEvents.py
@@ -1,6 +1,5 @@
import wx.lib.newevent
-
FitChanged, FIT_CHANGED = wx.lib.newevent.NewEvent()
CharListUpdated, CHAR_LIST_UPDATED = wx.lib.newevent.NewEvent()
CharChanged, CHAR_CHANGED = wx.lib.newevent.NewEvent()
diff --git a/gui/graphFrame.py b/gui/graphFrame.py
index dc286af1b..993998d10 100644
--- a/gui/graphFrame.py
+++ b/gui/graphFrame.py
@@ -1,281 +1,282 @@
-# =============================================================================
-# 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 .
-# =============================================================================
-
-import os
-
-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
-
-
-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 = 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 = 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 .
+# =============================================================================
+
+import os
+
+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
+
+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 = 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 = 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)
diff --git a/gui/itemStats.py b/gui/itemStats.py
index fe56f3a09..a7c008b12 100644
--- a/gui/itemStats.py
+++ b/gui/itemStats.py
@@ -64,7 +64,8 @@ class ItemStatsDialog(wx.Dialog):
itmContext = fullContext[1]
except IndexError:
itmContext = None
- item = getattr(victim, "item", None) if srcContext.lower() not in ("projectedcharge", "fittingcharge") else getattr(victim, "charge", None)
+ item = getattr(victim, "item", None) if srcContext.lower() not in (
+ "projectedcharge", "fittingcharge") else getattr(victim, "charge", None)
if item is None:
sMkt = Market.getInstance()
item = sMkt.getItem(victim.ID)
@@ -76,7 +77,8 @@ class ItemStatsDialog(wx.Dialog):
itemImg = BitmapLoader.getBitmap(iconFile, "icons")
if itemImg is not None:
self.SetIcon(wx.IconFromBitmap(itemImg))
- self.SetTitle("%s: %s%s" % ("%s Stats" % itmContext if itmContext is not None else "Stats", item.name, " (%d)" % item.ID if config.debug else ""))
+ self.SetTitle("%s: %s%s" % ("%s Stats" % itmContext if itmContext is not None else "Stats", item.name,
+ " (%d)" % item.ID if config.debug else ""))
self.SetMinSize((300, 200))
if "wxGTK" in wx.PlatformInfo: # GTK has huge tab widgets, give it a bit more room
@@ -232,7 +234,8 @@ class ItemDescription(wx.Panel):
desc = re.sub("<( *)font( *)color( *)=(.*?)>(?P.*?)<( *)/( *)font( *)>", "\g", desc)
# Strip URLs
desc = re.sub("<( *)a(.*?)>(?P.*?)<( *)/( *)a( *)>", "\g", desc)
- desc = "" + desc + ""
+ desc = "" + desc + ""
self.description.SetPage(desc)
@@ -240,12 +243,13 @@ class ItemDescription(wx.Panel):
self.Layout()
-class ItemParams (wx.Panel):
+class ItemParams(wx.Panel):
def __init__(self, parent, stuff, item, context=None):
wx.Panel.__init__(self, parent)
mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.paramList = AutoListCtrl(self, wx.ID_ANY, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
+ self.paramList = AutoListCtrl(self, wx.ID_ANY,
+ style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
mainSizer.Add(self.paramList, 1, wx.ALL | wx.EXPAND, 0)
self.SetSizer(mainSizer)
@@ -263,10 +267,12 @@ class ItemParams (wx.Panel):
self.totalAttrsLabel = wx.StaticText(self, wx.ID_ANY, u" ", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add(self.totalAttrsLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT)
- self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle view mode", wx.DefaultPosition, wx.DefaultSize, 0)
+ self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle view mode", wx.DefaultPosition, wx.DefaultSize,
+ 0)
bSizer.Add(self.toggleViewBtn, 0, wx.ALIGN_CENTER_VERTICAL)
- self.exportStatsBtn = wx.ToggleButton(self, wx.ID_ANY, u"Export Item Stats", wx.DefaultPosition, wx.DefaultSize, 0)
+ self.exportStatsBtn = wx.ToggleButton(self, wx.ID_ANY, u"Export Item Stats", wx.DefaultPosition, wx.DefaultSize,
+ 0)
bSizer.Add(self.exportStatsBtn, 0, wx.ALIGN_CENTER_VERTICAL)
if stuff is not None:
@@ -470,7 +476,8 @@ class ItemParams (wx.Panel):
trans = {"Inverse Absolute Percent": (lambda: (1 - value) * 100, unitName),
"Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName),
- "Modifier Percent": (lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
+ "Modifier Percent": (
+ lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
"Volume": (lambda: value, u"m\u00B3"),
"Sizeclass": (lambda: value, ""),
"Absolute Percent": (lambda: (value * 100), unitName),
@@ -508,7 +515,8 @@ class ItemCompare(wx.Panel):
self.currentSort = None
self.sortReverse = False
self.item = item
- self.items = sorted(items, key=lambda x: x.attributes['metaLevel'].value if 'metaLevel' in x.attributes else None)
+ self.items = sorted(items,
+ key=lambda x: x.attributes['metaLevel'].value if 'metaLevel' in x.attributes else None)
self.attrs = {}
# get a dict of attrName: attrInfo of all unique attributes across all items
@@ -661,7 +669,7 @@ class ItemCompare(wx.Panel):
trans = {"Inverse Absolute Percent": (lambda: (1 - value) * 100, unitName),
"Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName),
"Modifier Percent": (
- lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
+ lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
"Volume": (lambda: value, u"m\u00B3"),
"Sizeclass": (lambda: value, ""),
"Absolute Percent": (lambda: (value * 100), unitName),
@@ -719,14 +727,15 @@ class ItemRequirements(wx.Panel):
self.skillIdHistory.append(skill.ID)
-class ItemEffects (wx.Panel):
+class ItemEffects(wx.Panel):
def __init__(self, parent, stuff, item):
wx.Panel.__init__(self, parent)
self.item = item
mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.effectList = AutoListCtrl(self, wx.ID_ANY, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
+ self.effectList = AutoListCtrl(self, wx.ID_ANY,
+ style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
mainSizer.Add(self.effectList, 1, wx.ALL | wx.EXPAND, 0)
self.SetSizer(mainSizer)
@@ -1033,7 +1042,8 @@ class ItemAffectedBy(wx.Panel):
else:
item = afflictor.item
- items[attrName].append((type(afflictor), afflictor, item, modifier, amount, getattr(afflictor, "projected", False)))
+ items[attrName].append(
+ (type(afflictor), afflictor, item, modifier, amount, getattr(afflictor, "projected", False)))
# Make sure projected fits are on top
rootOrder = container.keys()
@@ -1234,7 +1244,8 @@ class ItemAffectedBy(wx.Panel):
else:
penalized = ""
- attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized, attrIcon))
+ attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier,
+ attrAmount, penalized, attrIcon))
attrSorted = sorted(attributes, key=lambda attribName: attribName[0])
for attr in attrSorted:
@@ -1242,9 +1253,11 @@ class ItemAffectedBy(wx.Panel):
if self.showRealNames:
display = "%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized)
- saved = "%s %s %.2f %s" % ((displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
+ saved = "%s %s %.2f %s" % (
+ (displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
else:
- display = "%s %s %.2f %s" % ((displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
+ display = "%s %s %.2f %s" % (
+ (displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
saved = "%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized)
treeitem = self.affectedBy.AppendItem(child, display, attrIcon)
diff --git a/gui/mainFrame.py b/gui/mainFrame.py
index 69bdbe3e7..8f2cf73e7 100644
--- a/gui/mainFrame.py
+++ b/gui/mainFrame.py
@@ -81,6 +81,7 @@ if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION
try:
from gui.propertyEditor import AttributeEditor
+
disableOverrideEditor = False
except ImportError as e:
print("Error loading Attribute Editor: %s.\nAccess to Attribute Editor is disabled." % e.message)
@@ -240,7 +241,8 @@ class MainFrame(wx.Frame):
def LoadPreviousOpenFits(self):
sFit = Fit.getInstance()
- self.prevOpenFits = 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)
@@ -259,8 +261,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 = 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"]
@@ -623,7 +627,8 @@ class MainFrame(wx.Frame):
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 = Character.getInstance()
diff --git a/gui/mainMenuBar.py b/gui/mainMenuBar.py
index 2de7f4b80..527f701b1 100644
--- a/gui/mainMenuBar.py
+++ b/gui/mainMenuBar.py
@@ -27,7 +27,6 @@ import gui.graphFrame
import gui.globalEvents as GE
from gui.bitmapLoader import BitmapLoader
-
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
from service.crest import CrestModes
@@ -158,7 +157,8 @@ 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)
diff --git a/gui/marketBrowser.py b/gui/marketBrowser.py
index 33db5d501..7efefb7a5 100644
--- a/gui/marketBrowser.py
+++ b/gui/marketBrowser.py
@@ -1,462 +1,461 @@
-# =============================================================================
-# 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 .
-# =============================================================================
-
-import wx
-from service.market import Market
-from service.attribute import Attribute
-import gui.display as d
-import gui.PFSearchBox as SBox
-from gui.cachingImageList import CachingImageList
-from gui.contextMenu import ContextMenu
-from gui.bitmapLoader import BitmapLoader
-
-
-ItemSelected, ITEM_SELECTED = wx.lib.newevent.NewEvent()
-
-RECENTLY_USED_MODULES = -2
-MAX_RECENTLY_USED_MODULES = 20
-
-
-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 = 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 = wx.ToggleButton(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"""
- ctrl = wx.GetMouseState().CmdDown()
- ebtn = event.EventObject
- if not ctrl:
- for btn in self.metaButtons:
- if btn.Enabled:
- if btn == ebtn:
- btn.SetValue(True)
- else:
- btn.SetValue(False)
- else:
- # Note: using the 'wrong' value for clicked button might seem weird,
- # But the button is toggled by wx and we should deal with it
- activeBtns = set()
- for btn in self.metaButtons:
- if (btn.GetValue() is True and btn != ebtn) or (btn.GetValue() is False and btn == ebtn):
- activeBtns.add(btn)
- # Do 'nothing' if we're trying to turn last active button off
- if len(activeBtns) == 1 and activeBtns.pop() == ebtn:
- # Keep button in the same state
- ebtn.SetValue(True)
- return
- # Leave old unfiltered list contents, just re-filter them and show
- 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)
- metaId = sMkt.getMetaGroupIdByItem(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(forcedMetaSelect=metaId)
-
-
-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)
- 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, forcedMetaSelect=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(forcedMetaSelect=forcedMetaSelect)
- 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, forcedMetaSelect=None):
- metaIDs = set()
- sMkt = self.sMkt
- for item in self.unfilteredStore:
- metaIDs.add(sMkt.getMetaGroupIdByItem(item))
- anySelection = False
- for btn in self.marketBrowser.metaButtons:
- btnMetas = sMkt.META_MAP[btn.metaName]
- if len(metaIDs.intersection(btnMetas)) > 0:
- btn.Enable(True)
- # Select all available buttons if we're searching
- if self.marketBrowser.searchMode is True:
- btn.SetValue(True)
- # Select explicitly requested button
- if forcedMetaSelect is not None:
- btn.SetValue(True if forcedMetaSelect in btnMetas else False)
- else:
- btn.Enable(False)
- btn.SetValue(False)
- if btn.GetValue():
- anySelection = True
- # If no buttons are pressed, press first active
- if anySelection is False:
- for btn in self.marketBrowser.metaButtons:
- if btn.Enabled:
- btn.SetValue(True)
- break
-
- 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
- d.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
-
- 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 .
+# =============================================================================
+
+import wx
+from service.market import Market
+from service.attribute import Attribute
+import gui.display as d
+import gui.PFSearchBox as SBox
+from gui.cachingImageList import CachingImageList
+from gui.contextMenu import ContextMenu
+from gui.bitmapLoader import BitmapLoader
+
+ItemSelected, ITEM_SELECTED = wx.lib.newevent.NewEvent()
+
+RECENTLY_USED_MODULES = -2
+MAX_RECENTLY_USED_MODULES = 20
+
+
+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 = 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 = wx.ToggleButton(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"""
+ ctrl = wx.GetMouseState().CmdDown()
+ ebtn = event.EventObject
+ if not ctrl:
+ for btn in self.metaButtons:
+ if btn.Enabled:
+ if btn == ebtn:
+ btn.SetValue(True)
+ else:
+ btn.SetValue(False)
+ else:
+ # Note: using the 'wrong' value for clicked button might seem weird,
+ # But the button is toggled by wx and we should deal with it
+ activeBtns = set()
+ for btn in self.metaButtons:
+ if (btn.GetValue() is True and btn != ebtn) or (btn.GetValue() is False and btn == ebtn):
+ activeBtns.add(btn)
+ # Do 'nothing' if we're trying to turn last active button off
+ if len(activeBtns) == 1 and activeBtns.pop() == ebtn:
+ # Keep button in the same state
+ ebtn.SetValue(True)
+ return
+ # Leave old unfiltered list contents, just re-filter them and show
+ 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)
+ metaId = sMkt.getMetaGroupIdByItem(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(forcedMetaSelect=metaId)
+
+
+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)
+ 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, forcedMetaSelect=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(forcedMetaSelect=forcedMetaSelect)
+ 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, forcedMetaSelect=None):
+ metaIDs = set()
+ sMkt = self.sMkt
+ for item in self.unfilteredStore:
+ metaIDs.add(sMkt.getMetaGroupIdByItem(item))
+ anySelection = False
+ for btn in self.marketBrowser.metaButtons:
+ btnMetas = sMkt.META_MAP[btn.metaName]
+ if len(metaIDs.intersection(btnMetas)) > 0:
+ btn.Enable(True)
+ # Select all available buttons if we're searching
+ if self.marketBrowser.searchMode is True:
+ btn.SetValue(True)
+ # Select explicitly requested button
+ if forcedMetaSelect is not None:
+ btn.SetValue(True if forcedMetaSelect in btnMetas else False)
+ else:
+ btn.Enable(False)
+ btn.SetValue(False)
+ if btn.GetValue():
+ anySelection = True
+ # If no buttons are pressed, press first active
+ if anySelection is False:
+ for btn in self.marketBrowser.metaButtons:
+ if btn.Enabled:
+ btn.SetValue(True)
+ break
+
+ 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
+ d.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
+
+ 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
diff --git a/gui/patternEditor.py b/gui/patternEditor.py
index 8005d19aa..9d11a5ab9 100644
--- a/gui/patternEditor.py
+++ b/gui/patternEditor.py
@@ -164,18 +164,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,10 +196,10 @@ class DmgPatternEditorDlg(wx.Dialog):
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))
+ 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()
diff --git a/gui/propertyEditor.py b/gui/propertyEditor.py
index dd257302d..1129545a6 100644
--- a/gui/propertyEditor.py
+++ b/gui/propertyEditor.py
@@ -25,7 +25,8 @@ logger = logging.getLogger(__name__)
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)
@@ -54,7 +55,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)
@@ -66,7 +68,8 @@ 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)
@@ -202,7 +205,8 @@ 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
diff --git a/gui/pyfatogglepanel.py b/gui/pyfatogglepanel.py
index d34985115..db37216ba 100644
--- a/gui/pyfatogglepanel.py
+++ b/gui/pyfatogglepanel.py
@@ -27,7 +27,8 @@ from gui.bitmapLoader import BitmapLoader
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)
+ 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
diff --git a/gui/resistsEditor.py b/gui/resistsEditor.py
index 83fb4327d..84f7bf98b 100644
--- a/gui/resistsEditor.py
+++ b/gui/resistsEditor.py
@@ -79,7 +79,6 @@ class TargetResistsEntityEditor(EntityEditor):
class ResistsEditorDlg(wx.Dialog):
-
DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive")
def __init__(self, parent):
@@ -120,7 +119,8 @@ class ResistsEditorDlg(wx.Dialog):
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
diff --git a/gui/setEditor.py b/gui/setEditor.py
index 380c7986a..0118fbe03 100644
--- a/gui/setEditor.py
+++ b/gui/setEditor.py
@@ -146,17 +146,17 @@ class ImplantSetEditorDlg(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 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)
diff --git a/gui/sfBrowserItem.py b/gui/sfBrowserItem.py
index 9b12fcf01..047c04bc6 100644
--- a/gui/sfBrowserItem.py
+++ b/gui/sfBrowserItem.py
@@ -13,7 +13,8 @@ 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
diff --git a/gui/shipBrowser.py b/gui/shipBrowser.py
index 8c27965b9..6a15678e2 100644
--- a/gui/shipBrowser.py
+++ b/gui/shipBrowser.py
@@ -20,7 +20,6 @@ from gui.PFListPane import PFListPane
from gui.contextMenu import ContextMenu
from gui.bitmapLoader import BitmapLoader
-
FitRenamed, EVT_FIT_RENAMED = wx.lib.newevent.NewEvent()
FitSelected, EVT_FIT_SELECTED = wx.lib.newevent.NewEvent()
FitRemoved, EVT_FIT_REMOVED = wx.lib.newevent.NewEvent()
@@ -67,7 +66,8 @@ class PFWidgetsContainer(PFListPane):
class RaceSelector(wx.Window):
- def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, layout=wx.VERTICAL, animate=False):
+ def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0,
+ layout=wx.VERTICAL, animate=False):
wx.Window.__init__(self, parent, id, pos=pos, size=size, style=style)
self.animTimerID = wx.NewId()
@@ -344,11 +344,16 @@ class NavigationPanel(SFItem.SFBrowserItem):
self.switchBmp = self.AdjustChannels(self.switchBmpH)
self.newBmp = self.AdjustChannels(self.newBmpH)
- self.toolbar.AddButton(self.resetBmp, "Ship groups", clickCallback=self.OnHistoryReset, hoverBitmap=self.resetBmpH)
+ self.toolbar.AddButton(self.resetBmp, "Ship groups", clickCallback=self.OnHistoryReset,
+ hoverBitmap=self.resetBmpH)
self.toolbar.AddButton(self.rewBmp, "Back", clickCallback=self.OnHistoryBack, hoverBitmap=self.rewBmpH)
- self.btnNew = self.toolbar.AddButton(self.newBmp, "New fitting", clickCallback=self.OnNewFitting, hoverBitmap=self.newBmpH, show=False)
- self.btnSwitch = self.toolbar.AddButton(self.switchBmpD, "Hide empty ship groups", clickCallback=self.ToggleEmptyGroupsView, hoverBitmap=self.switchBmpH, show=False)
- self.toolbar.AddButton(self.searchBmp, "Search fittings", clickCallback=self.ToggleSearchBox, hoverBitmap=self.searchBmpH)
+ self.btnNew = self.toolbar.AddButton(self.newBmp, "New fitting", clickCallback=self.OnNewFitting,
+ hoverBitmap=self.newBmpH, show=False)
+ self.btnSwitch = self.toolbar.AddButton(self.switchBmpD, "Hide empty ship groups",
+ clickCallback=self.ToggleEmptyGroupsView, hoverBitmap=self.switchBmpH,
+ show=False)
+ self.toolbar.AddButton(self.searchBmp, "Search fittings", clickCallback=self.ToggleSearchBox,
+ hoverBitmap=self.searchBmpH)
self.padding = 4
self.lastSearch = ""
@@ -357,7 +362,9 @@ class NavigationPanel(SFItem.SFBrowserItem):
self.fontSmall = wx.Font(fonts.SMALL, wx.SWISS, wx.NORMAL, wx.NORMAL)
w, h = size
- self.BrowserSearchBox = 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.BrowserSearchBox = 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.BrowserSearchBox.Show(False)
self.BrowserSearchBox.Bind(wx.EVT_TEXT_ENTER, self.OnBrowserSearchBoxEnter)
@@ -882,7 +889,9 @@ class ShipBrowser(wx.Panel):
for ship in ships:
shipTrait = ship.traits.traitText if (ship.traits is not None) else "" # empty string if no traits
- self.lpane.AddWidget(ShipItem(self.lpane, ship.ID, (ship.name, shipTrait, len(sFit.getFitsWithShip(ship.ID))), ship.race))
+ self.lpane.AddWidget(
+ ShipItem(self.lpane, ship.ID, (ship.name, shipTrait, len(sFit.getFitsWithShip(ship.ID))),
+ ship.race))
for ID, name, shipID, shipName, booster, timestamp in fitList:
ship = sMkt.getItem(shipID)
@@ -923,7 +932,8 @@ class ShipBrowser(wx.Panel):
if fits:
for fit in fits:
- shipTrait = fit.ship.traits.traitText if (fit.ship.traits is not None) else "" # empty string if no traits
+ shipTrait = fit.ship.traits.traitText if (
+ fit.ship.traits is not None) else "" # empty string if no traits
self.lpane.AddWidget(FitItem(
self.lpane,
@@ -1067,6 +1077,7 @@ class CategoryItem(SFItem.SFBrowserItem):
mdc.DrawText(categoryName, self.catx, self.caty)
+
# =============================================================================
# Waiting for total #fits impl in eos/service
#
@@ -1140,7 +1151,8 @@ class ShipItem(SFItem.SFBrowserItem):
self.editWidth = 150
self.padding = 4
- self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s fit" % self.shipName, wx.DefaultPosition, (120, -1), wx.TE_PROCESS_ENTER)
+ self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s fit" % self.shipName, wx.DefaultPosition, (120, -1),
+ wx.TE_PROCESS_ENTER)
self.tcFitName.Show(False)
self.newBtn = self.toolbar.AddButton(self.newBmp, "New", self.newBtnCB)
@@ -1331,7 +1343,8 @@ class ShipItem(SFItem.SFBrowserItem):
mdc.SetFont(self.fontBig)
- psname = drawUtils.GetPartialText(mdc, shipName, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
+ psname = drawUtils.GetPartialText(mdc, shipName,
+ self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(psname, self.textStartx, self.shipNamey)
@@ -1353,7 +1366,8 @@ class ShipItem(SFItem.SFBrowserItem):
class PFBitmapFrame(wx.Frame):
def __init__(self, parent, pos, bitmap):
- 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)
+ 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)
img = bitmap.ConvertToImage()
img = img.ConvertToGreyscale()
bitmap = wx.BitmapFromImage(img)
@@ -1409,7 +1423,8 @@ class PFBitmapFrame(wx.Frame):
class FitItem(SFItem.SFBrowserItem):
- def __init__(self, parent, fitID=None, shipFittingInfo=("Test", "TestTrait", "cnc's avatar", 0, 0), shipID=None, itemData=None,
+ def __init__(self, parent, fitID=None, shipFittingInfo=("Test", "TestTrait", "cnc's avatar", 0, 0), shipID=None,
+ itemData=None,
id=wx.ID_ANY, pos=wx.DefaultPosition,
size=(0, 40), style=0):
@@ -1487,7 +1502,8 @@ class FitItem(SFItem.SFBrowserItem):
self.renameBtn = self.toolbar.AddButton(self.renameBmp, "Rename", self.renameBtnCB)
self.toolbar.AddButton(self.deleteBmp, "Delete", self.deleteBtnCB)
- self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fitName, wx.DefaultPosition, (self.editWidth, -1), wx.TE_PROCESS_ENTER)
+ self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fitName, wx.DefaultPosition, (self.editWidth, -1),
+ wx.TE_PROCESS_ENTER)
if self.shipBrowser.fitIDMustEditName != self.fitID:
self.tcFitName.Show(False)
@@ -1852,7 +1868,8 @@ class FitItem(SFItem.SFBrowserItem):
fitDate = time.localtime(self.timestamp)
fitLocalDate = "%d/%02d/%02d %02d:%02d" % (fitDate[0], fitDate[1], fitDate[2], fitDate[3], fitDate[4])
- pfdate = drawUtils.GetPartialText(mdc, fitLocalDate, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
+ pfdate = drawUtils.GetPartialText(mdc, fitLocalDate,
+ self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(pfdate, self.textStartx, self.timestampy)
@@ -1861,7 +1878,8 @@ class FitItem(SFItem.SFBrowserItem):
mdc.SetFont(self.fontBig)
- psname = drawUtils.GetPartialText(mdc, self.fitName, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
+ psname = drawUtils.GetPartialText(mdc, self.fitName,
+ self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(psname, self.textStartx, self.fitNamey)
diff --git a/gui/statsPane.py b/gui/statsPane.py
index 9645f06dd..5d20f22ef 100644
--- a/gui/statsPane.py
+++ b/gui/statsPane.py
@@ -81,7 +81,8 @@ class StatsPane(wx.Panel):
mainSizer.Add(tp, 0, wx.EXPAND | wx.LEFT, 3)
if i < maxviews - 1:
- mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, style=wx.HORIZONTAL), 0, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 2)
+ mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, style=wx.HORIZONTAL), 0,
+ wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 2)
i += 1
tp.OnStateChange(tp.GetBestSize())
diff --git a/gui/updateDialog.py b/gui/updateDialog.py
index 7b148c546..8a88f9e17 100644
--- a/gui/updateDialog.py
+++ b/gui/updateDialog.py
@@ -23,79 +23,89 @@ import config
import dateutil.parser
from service import settings
-class UpdateDialog(wx.Dialog):
+class UpdateDialog(wx.Dialog):
def __init__(self, parent, release):
- wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = "Pyfa Update", pos = wx.DefaultPosition, size = wx.Size( 400,300 ), style = wx.DEFAULT_DIALOG_STYLE )
+ wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Pyfa Update", pos=wx.DefaultPosition,
+ size=wx.Size(400, 300), style=wx.DEFAULT_DIALOG_STYLE)
self.UpdateSettings = settings.UpdateSettings.getInstance()
self.releaseInfo = release
- self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
+ self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
- mainSizer = wx.BoxSizer( wx.VERTICAL )
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
- headSizer = wx.BoxSizer( wx.HORIZONTAL )
+ headSizer = wx.BoxSizer(wx.HORIZONTAL)
- self.headingText = wx.StaticText( self, wx.ID_ANY, "Pyfa Update Available!", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTRE )
- self.headingText.Wrap( -1 )
- self.headingText.SetFont( wx.Font( 14, 74, 90, 92, False) )
+ self.headingText = wx.StaticText(self, wx.ID_ANY, "Pyfa Update Available!", wx.DefaultPosition, wx.DefaultSize,
+ wx.ALIGN_CENTRE)
+ self.headingText.Wrap(-1)
+ 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 )
+ 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 )
+ mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
+ wx.EXPAND | wx.ALL, 5)
- versionSizer = wx.BoxSizer( wx.HORIZONTAL )
+ versionSizer = wx.BoxSizer(wx.HORIZONTAL)
- if(self.releaseInfo['prerelease']):
- self.releaseText = wx.StaticText( self, wx.ID_ANY, "Pre-release", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT )
- self.releaseText.SetFont( wx.Font( 12, 74, 90, 92, False) )
- self.releaseText.SetForegroundColour( wx.Colour( 230, 0, 0 ) )
+ if (self.releaseInfo['prerelease']):
+ self.releaseText = wx.StaticText(self, wx.ID_ANY, "Pre-release", wx.DefaultPosition, wx.DefaultSize,
+ wx.ALIGN_RIGHT)
+ self.releaseText.SetFont(wx.Font(12, 74, 90, 92, False))
+ self.releaseText.SetForegroundColour(wx.Colour(230, 0, 0))
else:
- self.releaseText = wx.StaticText( self, wx.ID_ANY, "Stable", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT )
- self.releaseText.SetFont( wx.Font( 12, 74, 90, 90, False) )
+ self.releaseText = wx.StaticText(self, wx.ID_ANY, "Stable", wx.DefaultPosition, wx.DefaultSize,
+ wx.ALIGN_RIGHT)
+ self.releaseText.SetFont(wx.Font(12, 74, 90, 90, False))
- self.releaseText.Wrap( -1 )
+ self.releaseText.Wrap(-1)
- versionSizer.Add( self.releaseText, 1, wx.ALL, 5 )
+ versionSizer.Add(self.releaseText, 1, wx.ALL, 5)
- self.versionText = wx.StaticText( self, wx.ID_ANY, self.releaseInfo['tag_name'], wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_LEFT )
- self.versionText.Wrap( -1 )
- self.versionText.SetFont( wx.Font( 12, 74, 90, 90, False) )
+ self.versionText = wx.StaticText(self, wx.ID_ANY, self.releaseInfo['tag_name'], wx.DefaultPosition,
+ wx.DefaultSize, wx.ALIGN_LEFT)
+ self.versionText.Wrap(-1)
+ self.versionText.SetFont(wx.Font(12, 74, 90, 90, False))
- versionSizer.Add( self.versionText, 1, wx.ALL, 5 )
- versionSizer.AddSpacer( ( 15, 5), 0, wx.EXPAND, 5 )
+ versionSizer.Add(self.versionText, 1, wx.ALL, 5)
+ versionSizer.AddSpacer((15, 5), 0, wx.EXPAND, 5)
- mainSizer.Add( versionSizer, 0, wx.EXPAND, 5 )
- mainSizer.AddSpacer( ( 0, 5), 0, wx.EXPAND, 5 )
+ mainSizer.Add(versionSizer, 0, wx.EXPAND, 5)
+ mainSizer.AddSpacer((0, 5), 0, wx.EXPAND, 5)
releaseDate = dateutil.parser.parse(self.releaseInfo['published_at'])
- notesSizer = wx.BoxSizer( wx.HORIZONTAL )
- self.notesTextCtrl = wx.TextCtrl( self, wx.ID_ANY, str(releaseDate.date())+":\n\n"+self.releaseInfo['body'], wx.DefaultPosition, wx.DefaultSize, wx.TE_AUTO_URL|wx.TE_MULTILINE|wx.TE_READONLY|wx.DOUBLE_BORDER|wx.TRANSPARENT_WINDOW )
+ notesSizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.notesTextCtrl = wx.TextCtrl(self, wx.ID_ANY, str(releaseDate.date()) + ":\n\n" + self.releaseInfo['body'],
+ wx.DefaultPosition, wx.DefaultSize,
+ wx.TE_AUTO_URL | wx.TE_MULTILINE | wx.TE_READONLY | wx.DOUBLE_BORDER | wx.TRANSPARENT_WINDOW)
- notesSizer.Add( self.notesTextCtrl, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5 )
- mainSizer.Add( notesSizer, 1, wx.EXPAND, 5 )
+ notesSizer.Add(self.notesTextCtrl, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5)
+ mainSizer.Add(notesSizer, 1, wx.EXPAND, 5)
- self.supressCheckbox = wx.CheckBox( self, wx.ID_ANY, "Don't remind me again for this release", wx.DefaultPosition, wx.DefaultSize, 0 )
+ self.supressCheckbox = wx.CheckBox(self, wx.ID_ANY, "Don't remind me again for this release",
+ wx.DefaultPosition, wx.DefaultSize, 0)
self.supressCheckbox.Bind(wx.EVT_CHECKBOX, self.SuppressChange)
- mainSizer.Add( self.supressCheckbox, 0, wx.ALL, 5 )
- mainSizer.Add( wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ), 0, wx.EXPAND |wx.ALL, 5 )
+ mainSizer.Add(self.supressCheckbox, 0, wx.ALL, 5)
+ mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
+ wx.EXPAND | wx.ALL, 5)
- actionSizer = wx.BoxSizer( wx.HORIZONTAL )
+ actionSizer = wx.BoxSizer(wx.HORIZONTAL)
- goSizer = wx.BoxSizer( wx.VERTICAL )
- self.downloadButton = wx.Button( self, wx.ID_ANY, "Download", wx.DefaultPosition, wx.DefaultSize, 0 )
+ goSizer = wx.BoxSizer(wx.VERTICAL)
+ self.downloadButton = wx.Button(self, wx.ID_ANY, "Download", wx.DefaultPosition, wx.DefaultSize, 0)
self.downloadButton.Bind(wx.EVT_BUTTON, self.OnDownload)
- goSizer.Add( self.downloadButton, 0, wx.ALL, 5 )
- actionSizer.Add( goSizer, 1, wx.EXPAND, 5 )
+ goSizer.Add(self.downloadButton, 0, wx.ALL, 5)
+ actionSizer.Add(goSizer, 1, wx.EXPAND, 5)
self.closeButton = wx.Button(self, wx.ID_CLOSE)
self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
- actionSizer.Add( self.closeButton, 0, wx.ALL, 5 )
- mainSizer.Add( actionSizer, 0, wx.EXPAND, 5 )
+ actionSizer.Add(self.closeButton, 0, wx.ALL, 5)
+ mainSizer.Add(actionSizer, 0, wx.EXPAND, 5)
- self.SetSizer( mainSizer )
+ self.SetSizer(mainSizer)
self.Layout()
# Handle use-case of suppressing a release, then a new version becoming available.
@@ -104,7 +114,7 @@ class UpdateDialog(wx.Dialog):
# safely reset this setting
self.UpdateSettings.set('version', None)
- self.Centre( wx.BOTH )
+ self.Centre(wx.BOTH)
def OnClose(self, e):
self.Close()
@@ -116,5 +126,5 @@ class UpdateDialog(wx.Dialog):
self.UpdateSettings.set('version', None)
def OnDownload(self, e):
- wx.LaunchDefaultBrowser('https://github.com/pyfa-org/Pyfa/releases/tag/'+self.releaseInfo['tag_name'])
+ wx.LaunchDefaultBrowser('https://github.com/pyfa-org/Pyfa/releases/tag/' + self.releaseInfo['tag_name'])
self.OnClose(e)
diff --git a/gui/utils/fonts.py b/gui/utils/fonts.py
index 0ee52fb7f..eb2dd95f5 100644
--- a/gui/utils/fonts.py
+++ b/gui/utils/fonts.py
@@ -5,11 +5,9 @@ different wxPython versions
import wx
-
if 'wxMac' in wx.PlatformInfo:
sizes = (10, 11, 12)
else:
sizes = (7, 8, 9)
-
SMALL, NORMAL, BIG = sizes
diff --git a/service/attribute.py b/service/attribute.py
index 12b9b264b..41d10b80a 100644
--- a/service/attribute.py
+++ b/service/attribute.py
@@ -19,8 +19,10 @@
import eos.db
+
class Attribute():
instance = None
+
@classmethod
def getInstance(cls):
if cls.instance is None:
diff --git a/service/character.py b/service/character.py
index f93345224..3851c44bb 100644
--- a/service/character.py
+++ b/service/character.py
@@ -40,6 +40,7 @@ from eos.saveddata.fighter import Fighter as es_Fighter
logger = logging.getLogger(__name__)
+
class CharacterImportThread(threading.Thread):
def __init__(self, paths, callback):
threading.Thread.__init__(self)
@@ -80,6 +81,7 @@ class CharacterImportThread(threading.Thread):
wx.CallAfter(self.callback)
+
class SkillBackupThread(threading.Thread):
def __init__(self, path, saveFmt, activeFit, callback):
threading.Thread.__init__(self)
@@ -100,11 +102,12 @@ class SkillBackupThread(threading.Thread):
with gzip.open(path, mode='wb') as backupFile:
backupFile.write(backupData)
else:
- with open(path, mode='w',encoding='utf-8') as backupFile:
+ with open(path, mode='w', encoding='utf-8') as backupFile:
backupFile.write(backupData)
wx.CallAfter(self.callback)
+
class Character(object):
instance = None
skillReqsDict = {}
@@ -151,7 +154,7 @@ class Character(object):
for s in self.skillReqsDict['skills']:
skillKey = str(s["skillID"]) + "::" + s["skill"] + "::" + str(int(s["level"]))
if skillKey in skillsSeen:
- pass # Duplicate skills confuse EVEMon
+ pass # Duplicate skills confuse EVEMon
else:
skillsSeen.add(skillKey)
entry = ElementTree.SubElement(root, "entry")
@@ -230,7 +233,7 @@ class Character(object):
group = eos.db.getGroup(groupID)
skills = []
for skill in group.items:
- if skill.published == True:
+ if skill.published is True:
skills.append((skill.ID, skill.name))
return skills
@@ -305,7 +308,7 @@ class Character(object):
if char.name == charName:
charID = char.characterID
- if charID == None:
+ if charID is None:
return
sheet = auth.character(charID).CharacterSheet()
diff --git a/service/crest.py b/service/crest.py
index edb6af5c5..4af0ccb89 100644
--- a/service/crest.py
+++ b/service/crest.py
@@ -16,16 +16,18 @@ from service.pycrest.eve import EVE
logger = logging.getLogger(__name__)
+
class Servers(Enum):
TQ = 0
SISI = 1
+
class CrestModes(Enum):
IMPLICIT = 0
USER = 1
-class Crest():
+class Crest():
clientIDs = {
Servers.TQ: 'f9be379951c046339dc13a00e6be7704',
Servers.SISI: 'af87365240d644f7950af563b8418bad'
@@ -36,9 +38,10 @@ class Crest():
clientTest = True
_instance = None
+
@classmethod
def getInstance(cls):
- if cls._instance == None:
+ if cls._instance is None:
cls._instance = Crest()
return cls._instance
@@ -74,7 +77,8 @@ class Crest():
# Base EVE connection that is copied to all characters
self.eve = EVE(
- client_id=self.settings.get('clientID') if self.settings.get('mode') == CrestModes.USER else self.clientIDs.get(self.settings.get('server')),
+ client_id=self.settings.get('clientID') if self.settings.get(
+ 'mode') == CrestModes.USER else self.clientIDs.get(self.settings.get('server')),
api_key=self.settings.get('clientSecret') if self.settings.get('mode') == CrestModes.USER else None,
redirect_uri=self.clientCallback,
testing=self.isTestServer
@@ -134,16 +138,16 @@ class Crest():
def getFittings(self, charID):
char = self.getCrestCharacter(charID)
- return char.eve.get('%scharacters/%d/fittings/'%(char.eve._authed_endpoint,char.ID))
+ return char.eve.get('%scharacters/%d/fittings/' % (char.eve._authed_endpoint, char.ID))
def postFitting(self, charID, json):
- #@todo: new fitting ID can be recovered from Location header, ie: Location -> https://api-sisi.testeveonline.com/characters/1611853631/fittings/37486494/
+ # @todo: new fitting ID can be recovered from Location header, ie: Location -> https://api-sisi.testeveonline.com/characters/1611853631/fittings/37486494/
char = self.getCrestCharacter(charID)
- return char.eve.post('%scharacters/%d/fittings/'%(char.eve._authed_endpoint,char.ID), data=json)
+ return char.eve.post('%scharacters/%d/fittings/' % (char.eve._authed_endpoint, char.ID), data=json)
def delFitting(self, charID, fittingID):
char = self.getCrestCharacter(charID)
- return char.eve.delete('%scharacters/%d/fittings/%d/'%(char.eve._authed_endpoint, char.ID, fittingID))
+ return char.eve.delete('%scharacters/%d/fittings/%d/' % (char.eve._authed_endpoint, char.ID, fittingID))
def logout(self):
"""Logout of implicit character"""
@@ -160,7 +164,8 @@ class Crest():
logging.debug("Starting server")
if self.httpd:
self.stopServer()
- time.sleep(1) # we need this to ensure that the previous get_request finishes, and then the socket will close
+ time.sleep(1)
+ # we need this to ensure that the previous get_request finishes, and then the socket will close
self.httpd = StoppableHTTPServer(('', 6461), AuthHandler)
thread.start_new_thread(self.httpd.serve, (self.handleLogin,))
@@ -175,7 +180,7 @@ class Crest():
logger.warn("OAUTH state mismatch")
return
- logger.debug("Handling CREST login with: %s"%message)
+ logger.debug("Handling CREST login with: %s" % message)
if 'access_token' in message: # implicit
eve = copy.deepcopy(self.eve)
@@ -193,7 +198,7 @@ class Crest():
self.implicitCharacter = CrestChar(info['CharacterID'], info['CharacterName'])
self.implicitCharacter.eve = eve
- #self.implicitCharacter.fetchImage()
+ # self.implicitCharacter.fetchImage()
wx.PostEvent(self.mainFrame, GE.SsoLogin(type=CrestModes.IMPLICIT))
elif 'code' in message:
diff --git a/service/damagePattern.py b/service/damagePattern.py
index ac5fc8b44..2343693d3 100644
--- a/service/damagePattern.py
+++ b/service/damagePattern.py
@@ -22,12 +22,14 @@ import copy
import eos.db
from eos.saveddata.damagePattern import DamagePattern as es_DamagePattern
+
class ImportError(Exception):
- pass
+ pass
class DamagePattern():
instance = None
+
@classmethod
def getInstance(cls):
if cls.instance is None:
diff --git a/service/eveapi.py b/service/eveapi.py
index 0b02f2159..d1c9835ae 100644
--- a/service/eveapi.py
+++ b/service/eveapi.py
@@ -174,6 +174,7 @@ proxySSL = False
_default_useragent = "eveapi.py/1.3"
_useragent = None # use set_user_agent() to set this.
+
# -----------------------------------------------------------------------------
@@ -309,6 +310,7 @@ def _ParseXML(response, fromContext, storeFunc):
return result
+
# -----------------------------------------------------------------------------
# API Classes
# -----------------------------------------------------------------------------
@@ -414,7 +416,8 @@ class _RootContext(_Context):
if retrieve_fallback:
# implementor is handling fallbacks...
try:
- return _ParseXML(response, True, store and (lambda obj: cache.store(self._host, path, kw, response, obj)))
+ return _ParseXML(response, True,
+ store and (lambda obj: cache.store(self._host, path, kw, response, obj)))
except Error as e:
response = retrieve_fallback(self._host, path, kw, reason=e)
if response is not None:
@@ -563,7 +566,9 @@ class _Parser(object):
if not self.container._cols or (numAttr > numCols):
# the row data contains more attributes than were defined.
self.container._cols = attributes[0::2]
- self.container.append([_castfunc(attributes[i], attributes[i + 1]) for i in xrange(0, len(attributes), 2)])
+ self.container.append(
+ [_castfunc(attributes[i], attributes[i + 1]) for i in xrange(0, len(attributes), 2)]
+ )
#
this._isrow = True
@@ -675,9 +680,11 @@ class _Parser(object):
# into a Rowset, adding the sibling element and this one.
rs = Rowset()
rs.__catch = rs._name = this._name
- row = [_castfunc(attributes[i], attributes[i + 1]) for i in xrange(0, len(attributes), 2)] + [getattr(this, col) for col in attributes2]
+ row = [_castfunc(attributes[i], attributes[i + 1]) for i in xrange(0, len(attributes), 2)] + \
+ [getattr(this, col) for col in attributes2]
rs.append(row)
- row = [getattr(sibling, attributes[i]) for i in xrange(0, len(attributes), 2)] + [getattr(sibling, col) for col in attributes2]
+ row = [getattr(sibling, attributes[i]) for i in xrange(0, len(attributes), 2)] + \
+ [getattr(sibling, col) for col in attributes2]
rs.append(row)
rs._cols = [attributes[i] for i in xrange(0, len(attributes), 2)] + [col for col in attributes2]
setattr(self.container, this._name, rs)
diff --git a/service/fit.py b/service/fit.py
index 877ce4d94..61b8ccc3b 100644
--- a/service/fit.py
+++ b/service/fit.py
@@ -17,39 +17,30 @@
# along with pyfa. If not, see .
# ===============================================================================
-import locale
import copy
-import threading
import logging
-import wx
-from codecs import open
-
-import xml.parsers.expat
import eos.db
-from eos.types import State, Slot, Module, Drone, Fighter, Fit as FitType
-
-from eos.saveddata.ship import Ship as es_Ship
-from eos.saveddata.citadel import Citadel as es_Citadel
-from eos.saveddata.implant import Implant as es_Implant
from eos.saveddata.booster import Booster as es_Booster
-from eos.saveddata.module import Module as es_Module
-from eos.saveddata.fighter import Fighter as es_Fighter
-from eos.saveddata.drone import Drone as es_Drone
from eos.saveddata.cargo import Cargo as es_Cargo
-from eos.saveddata.damagePattern import DamagePattern as es_DamagePattern
-
-from service.market import Market
-from service.damagePattern import DamagePattern
-from service.character import Character
from eos.saveddata.character import Character as saveddata_Character
+from eos.saveddata.citadel import Citadel as es_Citadel
+from eos.saveddata.damagePattern import DamagePattern as es_DamagePattern
+from eos.saveddata.drone import Drone as es_Drone
+from eos.saveddata.fighter import Fighter as es_Fighter
+from eos.saveddata.implant import Implant as es_Implant
+from eos.saveddata.module import Module as es_Module
+from eos.saveddata.ship import Ship as es_Ship
+from eos.types import State, Slot, Fit as FitType
+from service.character import Character
+from service.damagePattern import DamagePattern
from service.fleet import Fleet
+from service.market import Market
from service.settings import SettingsProvider
logger = logging.getLogger(__name__)
-
class Fit(object):
instance = None
diff --git a/service/fleet.py b/service/fleet.py
index a3f255336..fe59e8af8 100644
--- a/service/fleet.py
+++ b/service/fleet.py
@@ -1,217 +1,218 @@
-# =============================================================================
-# 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 .
-# =============================================================================
-
-import copy
-import eos.db
-from eos.saveddata.fleet import Fleet as Fleet_
-from eos.saveddata.fleet import Fleet as Wing
-from eos.saveddata.fleet import Fleet as Squad
-
-class Fleet(object):
- instance = None
- @classmethod
- def getInstance(cls):
- if cls.instance is None:
- cls.instance = Fleet()
-
- return cls.instance
-
- def __init__(self):
- pass
-
- def getFleetList(self):
- fleetList = []
- fleets = eos.db.getFleetList()
- for fleet in fleets:
- fleetList.append((fleet.ID, fleet.name, fleet.count()))
-
- return fleetList
-
- def getFleetByID(self, ID):
- f = eos.db.getFleet(ID)
- return f
-
- def addFleet(self):
- f = Fleet_()
- eos.db.save(f)
- return f
-
- def renameFleet(self, fleet, newName):
- fleet.name = newName
- eos.db.commit()
-
- def copyFleet(self, fleet):
- newFleet = copy.deepcopy(fleet)
- eos.db.save(newFleet)
- return newFleet
-
- def copyFleetByID(self, ID):
- fleet = self.getFleetByID(ID)
- return self.copyFleet(fleet)
-
- def deleteFleet(self, fleet):
- eos.db.remove(fleet)
-
- def deleteFleetByID(self, ID):
- fleet = self.getFleetByID(ID)
- self.deleteFleet(fleet)
-
- def makeLinearFleet(self, fit):
- f = Fleet_()
- w = Wing()
- f.wings.append(w)
- s = Squad()
- w.squads.append(s)
- s.members.append(fit)
- fit.fleet = f
- eos.db.save(f)
-
- def setLinearFleetCom(self, boostee, booster):
- #if boostee == booster:
- # return
- if self.getLinearFleet(boostee) is None:
- self.removeAssociatedFleetData(boostee)
- self.makeLinearFleet(boostee)
- squadIDs = set(eos.db.getSquadsIDsWithFitID(boostee.ID))
- squad = eos.db.getSquad(squadIDs.pop())
- if squad.wing.gang.leader is not None and booster is None:
- try:
- squad.wing.gang.leader.boostsFits.remove(boostee.ID)
- except KeyError:
- pass
- squad.wing.gang.leader = booster
- if self.anyBoosters(squad) is False:
- self.removeAssociatedFleetData(boostee)
- from service.fit import Fit
- sFit = Fit.getInstance()
- sFit.recalc(boostee, withBoosters=True)
-
- def setLinearWingCom(self, boostee, booster):
- #if boostee == booster:
- # return
- if self.getLinearFleet(boostee) is None:
- self.removeAssociatedFleetData(boostee)
- self.makeLinearFleet(boostee)
- squadIDs = set(eos.db.getSquadsIDsWithFitID(boostee.ID))
- squad = eos.db.getSquad(squadIDs.pop())
- if squad.wing.leader is not None and booster is None:
- try:
- squad.wing.leader.boostsFits.remove(boostee.ID)
- except KeyError:
- pass
- squad.wing.leader = booster
- if self.anyBoosters(squad) is False:
- self.removeAssociatedFleetData(boostee)
- from service.fit import Fit
- sFit = Fit.getInstance()
- sFit.recalc(boostee, withBoosters=True)
-
- def setLinearSquadCom(self, boostee, booster):
- #if boostee == booster:
- # return
- if self.getLinearFleet(boostee) is None:
- self.removeAssociatedFleetData(boostee)
- self.makeLinearFleet(boostee)
- squadIDs = set(eos.db.getSquadsIDsWithFitID(boostee.ID))
- squad = eos.db.getSquad(squadIDs.pop())
- if squad.leader is not None and booster is None:
- try:
- squad.leader.boostsFits.remove(boostee.ID)
- except KeyError:
- pass
- squad.leader = booster
- if self.anyBoosters(squad) is False:
- self.removeAssociatedFleetData(boostee)
- from service.fit import Fit
- sFit = Fit.getInstance()
- sFit.recalc(boostee, withBoosters=True)
-
-
- def getLinearFleet(self, fit):
- sqIDs = eos.db.getSquadsIDsWithFitID(fit.ID)
- if len(sqIDs) != 1:
- return None
- s = eos.db.getSquad(sqIDs[0])
- if len(s.members) != 1:
- return None
- w = s.wing
- if len(w.squads) != 1:
- return None
- f = w.gang
- if len(f.wings) != 1:
- return None
- return f
-
- def removeAssociatedFleetData(self, fit):
- squadIDs = set(eos.db.getSquadsIDsWithFitID(fit.ID))
- if len(squadIDs) == 0:
- return
- squads = list(eos.db.getSquad(sqID) for sqID in squadIDs)
- wingIDs = set(squad.wing.ID for squad in squads)
- fleetIDs = set(squad.wing.gang.ID for squad in squads)
- for fleetID in fleetIDs:
- fleet = eos.db.getFleet(fleetID)
- for wing in fleet.wings:
- wingIDs.add(wing.ID)
- for wingID in wingIDs:
- wing = eos.db.getWing(wingID)
- for squad in wing.squads:
- squadIDs.add(squad.ID)
- for squadID in squadIDs:
- squad = eos.db.getSquad(squadID)
- if squad.leader is not None:
- try:
- squad.leader.boostsFits.remove(fit.ID)
- except KeyError:
- pass
- eos.db.remove(squad)
- for wingID in wingIDs:
- wing = eos.db.getWing(wingID)
- if wing.leader is not None:
- try:
- wing.leader.boostsFits.remove(fit.ID)
- except KeyError:
- pass
- eos.db.remove(wing)
- for fleetID in fleetIDs:
- fleet = eos.db.getFleet(fleetID)
- if fleet.leader is not None:
- try:
- fleet.leader.boostsFits.remove(fit.ID)
- except KeyError:
- pass
- eos.db.remove(fleet)
- fit.fleet = None
- return
-
- def anyBoosters(self, squad):
- wing = squad.wing
- fleet = wing.gang
- if squad.leader is None and wing.leader is None and fleet.leader is None:
- return False
- return True
-
- def loadLinearFleet(self, fit):
- if self.getLinearFleet(fit) is None:
- return None
- squadID = eos.db.getSquadsIDsWithFitID(fit.ID)[0]
- s = eos.db.getSquad(squadID)
- w = s.wing
- f = w.gang
- return (f.leader, w.leader, s.leader)
+# =============================================================================
+# 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 .
+# =============================================================================
+
+import copy
+import eos.db
+from eos.saveddata.fleet import Fleet as Fleet_
+from eos.saveddata.fleet import Fleet as Wing
+from eos.saveddata.fleet import Fleet as Squad
+
+
+class Fleet(object):
+ instance = None
+
+ @classmethod
+ def getInstance(cls):
+ if cls.instance is None:
+ cls.instance = Fleet()
+
+ return cls.instance
+
+ def __init__(self):
+ pass
+
+ def getFleetList(self):
+ fleetList = []
+ fleets = eos.db.getFleetList()
+ for fleet in fleets:
+ fleetList.append((fleet.ID, fleet.name, fleet.count()))
+
+ return fleetList
+
+ def getFleetByID(self, ID):
+ f = eos.db.getFleet(ID)
+ return f
+
+ def addFleet(self):
+ f = Fleet_()
+ eos.db.save(f)
+ return f
+
+ def renameFleet(self, fleet, newName):
+ fleet.name = newName
+ eos.db.commit()
+
+ def copyFleet(self, fleet):
+ newFleet = copy.deepcopy(fleet)
+ eos.db.save(newFleet)
+ return newFleet
+
+ def copyFleetByID(self, ID):
+ fleet = self.getFleetByID(ID)
+ return self.copyFleet(fleet)
+
+ def deleteFleet(self, fleet):
+ eos.db.remove(fleet)
+
+ def deleteFleetByID(self, ID):
+ fleet = self.getFleetByID(ID)
+ self.deleteFleet(fleet)
+
+ def makeLinearFleet(self, fit):
+ f = Fleet_()
+ w = Wing()
+ f.wings.append(w)
+ s = Squad()
+ w.squads.append(s)
+ s.members.append(fit)
+ fit.fleet = f
+ eos.db.save(f)
+
+ def setLinearFleetCom(self, boostee, booster):
+ # if boostee == booster:
+ # return
+ if self.getLinearFleet(boostee) is None:
+ self.removeAssociatedFleetData(boostee)
+ self.makeLinearFleet(boostee)
+ squadIDs = set(eos.db.getSquadsIDsWithFitID(boostee.ID))
+ squad = eos.db.getSquad(squadIDs.pop())
+ if squad.wing.gang.leader is not None and booster is None:
+ try:
+ squad.wing.gang.leader.boostsFits.remove(boostee.ID)
+ except KeyError:
+ pass
+ squad.wing.gang.leader = booster
+ if self.anyBoosters(squad) is False:
+ self.removeAssociatedFleetData(boostee)
+ from service.fit import Fit
+ sFit = Fit.getInstance()
+ sFit.recalc(boostee, withBoosters=True)
+
+ def setLinearWingCom(self, boostee, booster):
+ # if boostee == booster:
+ # return
+ if self.getLinearFleet(boostee) is None:
+ self.removeAssociatedFleetData(boostee)
+ self.makeLinearFleet(boostee)
+ squadIDs = set(eos.db.getSquadsIDsWithFitID(boostee.ID))
+ squad = eos.db.getSquad(squadIDs.pop())
+ if squad.wing.leader is not None and booster is None:
+ try:
+ squad.wing.leader.boostsFits.remove(boostee.ID)
+ except KeyError:
+ pass
+ squad.wing.leader = booster
+ if self.anyBoosters(squad) is False:
+ self.removeAssociatedFleetData(boostee)
+ from service.fit import Fit
+ sFit = Fit.getInstance()
+ sFit.recalc(boostee, withBoosters=True)
+
+ def setLinearSquadCom(self, boostee, booster):
+ # if boostee == booster:
+ # return
+ if self.getLinearFleet(boostee) is None:
+ self.removeAssociatedFleetData(boostee)
+ self.makeLinearFleet(boostee)
+ squadIDs = set(eos.db.getSquadsIDsWithFitID(boostee.ID))
+ squad = eos.db.getSquad(squadIDs.pop())
+ if squad.leader is not None and booster is None:
+ try:
+ squad.leader.boostsFits.remove(boostee.ID)
+ except KeyError:
+ pass
+ squad.leader = booster
+ if self.anyBoosters(squad) is False:
+ self.removeAssociatedFleetData(boostee)
+ from service.fit import Fit
+ sFit = Fit.getInstance()
+ sFit.recalc(boostee, withBoosters=True)
+
+ def getLinearFleet(self, fit):
+ sqIDs = eos.db.getSquadsIDsWithFitID(fit.ID)
+ if len(sqIDs) != 1:
+ return None
+ s = eos.db.getSquad(sqIDs[0])
+ if len(s.members) != 1:
+ return None
+ w = s.wing
+ if len(w.squads) != 1:
+ return None
+ f = w.gang
+ if len(f.wings) != 1:
+ return None
+ return f
+
+ def removeAssociatedFleetData(self, fit):
+ squadIDs = set(eos.db.getSquadsIDsWithFitID(fit.ID))
+ if len(squadIDs) == 0:
+ return
+ squads = list(eos.db.getSquad(sqID) for sqID in squadIDs)
+ wingIDs = set(squad.wing.ID for squad in squads)
+ fleetIDs = set(squad.wing.gang.ID for squad in squads)
+ for fleetID in fleetIDs:
+ fleet = eos.db.getFleet(fleetID)
+ for wing in fleet.wings:
+ wingIDs.add(wing.ID)
+ for wingID in wingIDs:
+ wing = eos.db.getWing(wingID)
+ for squad in wing.squads:
+ squadIDs.add(squad.ID)
+ for squadID in squadIDs:
+ squad = eos.db.getSquad(squadID)
+ if squad.leader is not None:
+ try:
+ squad.leader.boostsFits.remove(fit.ID)
+ except KeyError:
+ pass
+ eos.db.remove(squad)
+ for wingID in wingIDs:
+ wing = eos.db.getWing(wingID)
+ if wing.leader is not None:
+ try:
+ wing.leader.boostsFits.remove(fit.ID)
+ except KeyError:
+ pass
+ eos.db.remove(wing)
+ for fleetID in fleetIDs:
+ fleet = eos.db.getFleet(fleetID)
+ if fleet.leader is not None:
+ try:
+ fleet.leader.boostsFits.remove(fit.ID)
+ except KeyError:
+ pass
+ eos.db.remove(fleet)
+ fit.fleet = None
+ return
+
+ def anyBoosters(self, squad):
+ wing = squad.wing
+ fleet = wing.gang
+ if squad.leader is None and wing.leader is None and fleet.leader is None:
+ return False
+ return True
+
+ def loadLinearFleet(self, fit):
+ if self.getLinearFleet(fit) is None:
+ return None
+ squadID = eos.db.getSquadsIDsWithFitID(fit.ID)[0]
+ s = eos.db.getSquad(squadID)
+ w = s.wing
+ f = w.gang
+ return (f.leader, w.leader, s.leader)
diff --git a/service/implantSet.py b/service/implantSet.py
index add0808cc..f7df17bab 100644
--- a/service/implantSet.py
+++ b/service/implantSet.py
@@ -24,9 +24,11 @@ from service.market import Market
from eos.saveddata.implant import Implant as es_Implant
from eos.saveddata.implantSet import ImplantSet as es_ImplantSet
+
class ImportError(Exception):
pass
+
class ImplantSets(object):
instance = None
diff --git a/service/market.py b/service/market.py
index 4ea0ee5ca..30972795e 100644
--- a/service/market.py
+++ b/service/market.py
@@ -1,4 +1,4 @@
-#===============================================================================
+# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
@@ -15,7 +15,7 @@
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see .
-#===============================================================================
+# ===============================================================================
import re
import threading
@@ -43,6 +43,7 @@ logger = logging.getLogger(__name__)
# Event which tells threads dependent on Market that it's initialized
mktRdy = threading.Event()
+
class ShipBrowserWorkerThread(threading.Thread):
def run(self):
self.queue = Queue.Queue()
@@ -73,6 +74,7 @@ class ShipBrowserWorkerThread(threading.Thread):
except:
pass
+
class PriceWorkerThread(threading.Thread):
def run(self):
self.queue = Queue.Queue()
@@ -107,6 +109,7 @@ class PriceWorkerThread(threading.Thread):
self.wait[itemID] = []
self.wait[itemID].append(callback)
+
class SearchWorkerThread(threading.Thread):
def run(self):
self.cv = threading.Condition()
@@ -131,7 +134,7 @@ class SearchWorkerThread(threading.Thread):
elif filterOn: # filter by selected categories
filter = e_Category.name.in_(filterOn)
else:
- filter=None
+ filter = None
results = eos.db.searchItems(request, where=filter,
join=(e_Item.group, e_Group.category),
@@ -150,15 +153,18 @@ class SearchWorkerThread(threading.Thread):
self.cv.notify()
self.cv.release()
+
class Market():
instance = None
+
def __init__(self):
self.priceCache = {}
- #Init recently used module storage
+ # Init recently used module storage
serviceMarketRecentlyUsedModules = {"pyfaMarketRecentlyUsedModules": []}
- self.serviceMarketRecentlyUsedModules = SettingsProvider.getInstance().getSettings("pyfaMarketRecentlyUsedModules", serviceMarketRecentlyUsedModules)
+ self.serviceMarketRecentlyUsedModules = SettingsProvider.getInstance().getSettings(
+ "pyfaMarketRecentlyUsedModules", serviceMarketRecentlyUsedModules)
# Start price fetcher
self.priceWorkerThread = PriceWorkerThread()
@@ -188,36 +194,37 @@ class Market():
self.les_grp.description = ""
self.les_grp.icon = None
self.ITEMS_FORCEGROUP = {
- "Opux Luxury Yacht": self.les_grp, # One of those is wedding present at CCP fanfest, another was hijacked from ISD guy during an event
+ "Opux Luxury Yacht": self.les_grp,
+ # One of those is wedding present at CCP fanfest, another was hijacked from ISD guy during an event
"Silver Magnate": self.les_grp, # Amarr Championship prize
"Gold Magnate": self.les_grp, # Amarr Championship prize
"Armageddon Imperial Issue": self.les_grp, # Amarr Championship prize
- "Apocalypse Imperial Issue": self.les_grp, # Amarr Championship prize
- "Guardian-Vexor": self.les_grp, # Illegal rewards for the Gallente Frontier Tour Lines event arc
- "Megathron Federate Issue": self.les_grp, # Reward during Crielere event
+ "Apocalypse Imperial Issue": self.les_grp, # Amarr Championship prize
+ "Guardian-Vexor": self.les_grp, # Illegal rewards for the Gallente Frontier Tour Lines event arc
+ "Megathron Federate Issue": self.les_grp, # Reward during Crielere event
"Raven State Issue": self.les_grp, # AT4 prize
- "Tempest Tribal Issue": self.les_grp, # AT4 prize
- "Apotheosis": self.les_grp, # 5th EVE anniversary present
- "Zephyr": self.les_grp, # 2010 new year gift
- "Primae": self.les_grp, # Promotion of planetary interaction
- "Freki": self.les_grp, # AT7 prize
- "Mimir": self.les_grp, # AT7 prize
- "Utu": self.les_grp, # AT8 prize
- "Adrestia": self.les_grp, # AT8 prize
- "Echelon": self.les_grp, # 2011 new year gift
- "Malice": self.les_grp, # AT9 prize
- "Vangel": self.les_grp, # AT9 prize
- "Cambion": self.les_grp, # AT10 prize
- "Etana": self.les_grp, # AT10 prize
- "Chremoas": self.les_grp, # AT11 prize :(
- "Moracha": self.les_grp, # AT11 prize
- "Stratios Emergency Responder": self.les_grp, # Issued for Somer Blink lottery
- "Miasmos Quafe Ultra Edition": self.les_grp, # Gift to people who purchased FF HD stream
+ "Tempest Tribal Issue": self.les_grp, # AT4 prize
+ "Apotheosis": self.les_grp, # 5th EVE anniversary present
+ "Zephyr": self.les_grp, # 2010 new year gift
+ "Primae": self.les_grp, # Promotion of planetary interaction
+ "Freki": self.les_grp, # AT7 prize
+ "Mimir": self.les_grp, # AT7 prize
+ "Utu": self.les_grp, # AT8 prize
+ "Adrestia": self.les_grp, # AT8 prize
+ "Echelon": self.les_grp, # 2011 new year gift
+ "Malice": self.les_grp, # AT9 prize
+ "Vangel": self.les_grp, # AT9 prize
+ "Cambion": self.les_grp, # AT10 prize
+ "Etana": self.les_grp, # AT10 prize
+ "Chremoas": self.les_grp, # AT11 prize :(
+ "Moracha": self.les_grp, # AT11 prize
+ "Stratios Emergency Responder": self.les_grp, # Issued for Somer Blink lottery
+ "Miasmos Quafe Ultra Edition": self.les_grp, # Gift to people who purchased FF HD stream
"InterBus Shuttle": self.les_grp,
- "Leopard": self.les_grp, # 2013 new year gift
- "Whiptail": self.les_grp, # AT12 prize
- "Chameleon": self.les_grp, # AT12 prize
- "Victorieux Luxury Yacht": self.les_grp, # Worlds Collide prize \o/ chinese getting owned
+ "Leopard": self.les_grp, # 2013 new year gift
+ "Whiptail": self.les_grp, # AT12 prize
+ "Chameleon": self.les_grp, # AT12 prize
+ "Victorieux Luxury Yacht": self.les_grp, # Worlds Collide prize \o/ chinese getting owned
"Imp": self.les_grp, # AT13 prize
"Fiend": self.les_grp, # AT13 prize
}
@@ -228,8 +235,8 @@ class Market():
# List of items which are forcibly published or hidden
self.ITEMS_FORCEPUBLISHED = {
- "Data Subverter I": False, # Not used in EVE, probably will appear with Dust link
- "QA Cross Protocol Analyzer": False, # QA modules used by CCP internally
+ "Data Subverter I": False, # Not used in EVE, probably will appear with Dust link
+ "QA Cross Protocol Analyzer": False, # QA modules used by CCP internally
"QA Damage Module": False,
"QA ECCM": False,
"QA Immunity Module": False,
@@ -265,7 +272,7 @@ class Market():
# List of groups which are forcibly published
self.GROUPS_FORCEPUBLISHED = {
- "Prototype Exploration Ship": False } # We moved the only ship from this group to other group anyway
+ "Prototype Exploration Ship": False} # We moved the only ship from this group to other group anyway
# Dictionary of items with forced meta groups, uses following format:
# Item name: (metagroup name, parent type name)
@@ -274,75 +281,96 @@ class Market():
"'Wild' Miner I": ("Storyline", "Miner I"),
"Medium Nano Armor Repair Unit I": ("Tech I", "Medium Armor Repairer I"),
"Large 'Reprieve' Vestment Reconstructer I": ("Storyline", "Large Armor Repairer I"),
- "Khanid Navy Torpedo Launcher": ("Faction", "Torpedo Launcher I"),}
+ "Khanid Navy Torpedo Launcher": ("Faction", "Torpedo Launcher I"), }
# Parent type name: set(item names)
self.ITEMS_FORCEDMETAGROUP_R = {}
for item, value in self.ITEMS_FORCEDMETAGROUP.items():
parent = value[1]
- if not parent in self.ITEMS_FORCEDMETAGROUP_R:
+ if parent not in self.ITEMS_FORCEDMETAGROUP_R:
self.ITEMS_FORCEDMETAGROUP_R[parent] = set()
self.ITEMS_FORCEDMETAGROUP_R[parent].add(item)
# Dictionary of items with forced market group (service assumes they have no
# market group assigned in db, otherwise they'll appear in both original and forced groups)
self.ITEMS_FORCEDMARKETGROUP = {
- "'Alpha' Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
- "'Codex' Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
- "'Daemon' Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
- "'Libram' Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
- "Advanced Cerebral Accelerator": 977, # Implants & Boosters > Booster
- "Civilian Damage Control": 615, # Ship Equipment > Hull & Armor > Damage Controls
- "Civilian EM Ward Field": 1695, # Ship Equipment > Shield > Shield Hardeners > EM Shield Hardeners
- "Civilian Explosive Deflection Field": 1694, # Ship Equipment > Shield > Shield Hardeners > Explosive Shield Hardeners
- "Civilian Hobgoblin": 837, # Drones > Combat Drones > Light Scout Drones
- "Civilian Kinetic Deflection Field": 1693, # Ship Equipment > Shield > Shield Hardeners > Kinetic Shield Hardeners
- "Civilian Light Missile Launcher": 640, # Ship Equipment > Turrets & Bays > Missile Launchers > Light Missile Launchers
- "Civilian Scourge Light Missile": 920, # Ammunition & Charges > Missiles > Light Missiles > Standard Light Missiles
- "Civilian Small Remote Armor Repairer": 1059, # Ship Equipment > Hull & Armor > Remote Armor Repairers > Small
- "Civilian Small Remote Shield Booster": 603, # Ship Equipment > Shield > Remote Shield Boosters > Small
- "Civilian Stasis Webifier": 683, # Ship Equipment > Electronic Warfare > Stasis Webifiers
- "Civilian Thermic Dissipation Field": 1692, # Ship Equipment > Shield > Shield Hardeners > Thermal Shield Hardeners
- "Civilian Warp Disruptor": 1935, # Ship Equipment > Electronic Warfare > Warp Disruptors
- "Hardwiring - Zainou 'Sharpshooter' ZMX10": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
- "Hardwiring - Zainou 'Sharpshooter' ZMX100": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
- "Hardwiring - Zainou 'Sharpshooter' ZMX1000": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
- "Hardwiring - Zainou 'Sharpshooter' ZMX11": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
- "Hardwiring - Zainou 'Sharpshooter' ZMX110": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
- "Hardwiring - Zainou 'Sharpshooter' ZMX1100": 1493, # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
- "Nugoehuvi Synth Blue Pill Booster": 977, # Implants & Boosters > Booster
- "Prototype Cerebral Accelerator": 977, # Implants & Boosters > Booster
- "Prototype Iris Probe Launcher": 712, # Ship Equipment > Turrets & Bays > Scan Probe Launchers
- "Shadow": 1310, # Drones > Combat Drones > Fighter Bombers
- "Sleeper Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
- "Standard Cerebral Accelerator": 977, # Implants & Boosters > Booster
- "Talocan Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
- "Terran Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
- "Tetrimon Data Analyzer I": 714 # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
+ "'Alpha' Data Analyzer I": 714,
+ # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
+ "'Codex' Data Analyzer I": 714,
+ # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
+ "'Daemon' Data Analyzer I": 714,
+ # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
+ "'Libram' Data Analyzer I": 714,
+ # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
+ "Advanced Cerebral Accelerator": 977, # Implants & Boosters > Booster
+ "Civilian Damage Control": 615, # Ship Equipment > Hull & Armor > Damage Controls
+ "Civilian EM Ward Field": 1695, # Ship Equipment > Shield > Shield Hardeners > EM Shield Hardeners
+ "Civilian Explosive Deflection Field": 1694,
+ # Ship Equipment > Shield > Shield Hardeners > Explosive Shield Hardeners
+ "Civilian Hobgoblin": 837, # Drones > Combat Drones > Light Scout Drones
+ "Civilian Kinetic Deflection Field": 1693,
+ # Ship Equipment > Shield > Shield Hardeners > Kinetic Shield Hardeners
+ "Civilian Light Missile Launcher": 640,
+ # Ship Equipment > Turrets & Bays > Missile Launchers > Light Missile Launchers
+ "Civilian Scourge Light Missile": 920,
+ # Ammunition & Charges > Missiles > Light Missiles > Standard Light Missiles
+ "Civilian Small Remote Armor Repairer": 1059,
+ # Ship Equipment > Hull & Armor > Remote Armor Repairers > Small
+ "Civilian Small Remote Shield Booster": 603, # Ship Equipment > Shield > Remote Shield Boosters > Small
+ "Civilian Stasis Webifier": 683, # Ship Equipment > Electronic Warfare > Stasis Webifiers
+ "Civilian Thermic Dissipation Field": 1692,
+ # Ship Equipment > Shield > Shield Hardeners > Thermal Shield Hardeners
+ "Civilian Warp Disruptor": 1935, # Ship Equipment > Electronic Warfare > Warp Disruptors
+ "Hardwiring - Zainou 'Sharpshooter' ZMX10": 1493,
+ # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
+ "Hardwiring - Zainou 'Sharpshooter' ZMX100": 1493,
+ # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
+ "Hardwiring - Zainou 'Sharpshooter' ZMX1000": 1493,
+ # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
+ "Hardwiring - Zainou 'Sharpshooter' ZMX11": 1493,
+ # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
+ "Hardwiring - Zainou 'Sharpshooter' ZMX110": 1493,
+ # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
+ "Hardwiring - Zainou 'Sharpshooter' ZMX1100": 1493,
+ # Implants & Boosters > Implants > Skill Hardwiring > Missile Implants > Implant Slot 06
+ "Nugoehuvi Synth Blue Pill Booster": 977, # Implants & Boosters > Booster
+ "Prototype Cerebral Accelerator": 977, # Implants & Boosters > Booster
+ "Prototype Iris Probe Launcher": 712, # Ship Equipment > Turrets & Bays > Scan Probe Launchers
+ "Shadow": 1310, # Drones > Combat Drones > Fighter Bombers
+ "Sleeper Data Analyzer I": 714,
+ # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
+ "Standard Cerebral Accelerator": 977, # Implants & Boosters > Booster
+ "Talocan Data Analyzer I": 714,
+ # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
+ "Terran Data Analyzer I": 714,
+ # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
+ "Tetrimon Data Analyzer I": 714
+ # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners
}
self.ITEMS_FORCEDMARKETGROUP_R = self.__makeRevDict(self.ITEMS_FORCEDMARKETGROUP)
self.FORCEDMARKETGROUP = {
- 685: False, # Ship Equipment > Electronic Warfare > ECCM
- 681: False, # Ship Equipment > Electronic Warfare > Sensor Backup Arrays
+ 685: False, # Ship Equipment > Electronic Warfare > ECCM
+ 681: False, # Ship Equipment > Electronic Warfare > Sensor Backup Arrays
}
# Misc definitions
# 0 is for items w/o meta group
- self.META_MAP = OrderedDict([("normal", frozenset((0, 1, 2, 14))),
+ self.META_MAP = OrderedDict([("normal", frozenset((0, 1, 2, 14))),
("faction", frozenset((4, 3))),
("complex", frozenset((6,))),
("officer", frozenset((5,)))])
- self.SEARCH_CATEGORIES = ("Drone", "Module", "Subsystem", "Charge", "Implant", "Deployable", "Fighter", "Structure", "Structure Module")
+ self.SEARCH_CATEGORIES = (
+ "Drone", "Module", "Subsystem", "Charge", "Implant", "Deployable", "Fighter", "Structure", "Structure Module")
self.SEARCH_GROUPS = ("Ice Product",)
- self.ROOT_MARKET_GROUPS = (9, # Modules
+ self.ROOT_MARKET_GROUPS = (9, # Modules
1111, # Rigs
- 157, # Drones
- 11, # Ammo
+ 157, # Drones
+ 11, # Ammo
1112, # Subsystems
- 24, # Implants & Boosters
- 404, # Deployables
+ 24, # Implants & Boosters
+ 404, # Deployables
2202, # Structure Equipment
- 2203 # Structure Modifications
+ 2203 # Structure Modifications
)
# Tell other threads that Market is at their service
mktRdy.set()
@@ -560,7 +588,8 @@ class Market():
groupItems = set(group.items)
if hasattr(group, 'addItems'):
groupItems.update(group.addItems)
- items = set(filter(lambda item: self.getPublicityByItem(item) and self.getGroupByItem(item) == group, groupItems))
+ items = set(
+ filter(lambda item: self.getPublicityByItem(item) and self.getGroupByItem(item) == group, groupItems))
return items
def getItemsByMarketGroup(self, mg, vars=True):
diff --git a/service/network.py b/service/network.py
index 48769a48b..481c77a41 100644
--- a/service/network.py
+++ b/service/network.py
@@ -29,21 +29,27 @@ from service.settings import NetworkSettings
timeout = 3
socket.setdefaulttimeout(timeout)
+
class Error(StandardError):
def __init__(self, msg=None):
self.message = msg
+
class RequestError(StandardError):
pass
+
class AuthenticationError(StandardError):
- pass
+ pass
+
class ServerError(StandardError):
- pass
+ pass
+
class TimeoutError(StandardError):
- pass
+ pass
+
class Network():
# Request constants - every request must supply this, as it is checked if
@@ -73,7 +79,8 @@ class Network():
raise Error("Access not enabled - please enable in Preferences > Network")
# Set up some things for the request
- versionString = "{0} {1} - {2} {3}".format(config.version, config.tag, config.expansionName, config.expansionVersion)
+ versionString = "{0} {1} - {2} {3}".format(config.version, config.tag, config.expansionName,
+ config.expansionVersion)
headers = {"User-Agent": "pyfa {0} (Python-urllib2)".format(versionString)}
proxy = NetworkSettings.getInstance().getProxySettings()
diff --git a/service/port.py b/service/port.py
index 3f2751b4f..d6645ed23 100644
--- a/service/port.py
+++ b/service/port.py
@@ -171,6 +171,7 @@ class Port(object):
return fits
"""Service which houses all import/export format functions"""
+
@classmethod
def exportCrest(cls, ofit, callback=None):
# A few notes:
@@ -379,6 +380,7 @@ class Port(object):
if len(s) > 10:
return s[:10] + "..."
return s
+
logger.exception("Couldn't import ship data %r", [logtransform(s) for s in info])
return None
@@ -821,7 +823,8 @@ class Port(object):
slot = module.slot
if slot not in stuff:
stuff[slot] = []
- curr = module.item.name if module.item else ("[Empty %s slot]" % Slot.getName(slot).capitalize() if slot is not None else "")
+ curr = module.item.name if module.item else (
+ "[Empty %s slot]" % Slot.getName(slot).capitalize() if slot is not None else "")
if module.charge and sFit.serviceFittingOptions["exportCharges"]:
curr += ", %s" % module.charge.name
if module.state == State.OFFLINE:
@@ -1075,6 +1078,7 @@ class FitBackupThread(threading.Thread):
# Send done signal to GUI
wx.CallAfter(self.callback, -1)
+
class FitImportThread(threading.Thread):
def __init__(self, paths, callback):
threading.Thread.__init__(self)
diff --git a/service/prefetch.py b/service/prefetch.py
index c3705dd54..8d8348322 100644
--- a/service/prefetch.py
+++ b/service/prefetch.py
@@ -1,70 +1,72 @@
-# =============================================================================
-# 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 .
-# =============================================================================
-
-import threading
-import os
-
-import config
-from eos import db
-from eos.db import migration
-from eos.db.saveddata.loadDefaultDatabaseValues import DefaultDatabaseValues
-from eos.saveddata.character import Character as es_Character
-
-class PrefetchThread(threading.Thread):
- def run(self):
- # We're a daemon thread, as such, interpreter might get shut down while we do stuff
- # Make sure we don't throw tracebacks to console
- try:
- es_Character.setSkillList(db.getItemsByCategory("Skill", eager=("effects", "attributes", "attributes.info.icon", "attributes.info.unit", "icon")))
- except:
- pass
-
-
-prefetch = PrefetchThread()
-prefetch.daemon = True
-prefetch.start()
-
-# The following code does not belong here, however until we rebuild skeletons
-# to include modified pyfa.py, this is the best place to put it. See GH issue
-# #176
-# @ todo: move this to pyfa.py
-
-# Make sure the saveddata db exists
-if config.savePath and not os.path.exists(config.savePath):
- os.mkdir(config.savePath)
-
-if config.saveDB and os.path.isfile(config.saveDB):
- # If database exists, run migration after init'd database
- db.saveddata_meta.create_all()
- migration.update(db.saveddata_engine)
- # Import default database values
- # Import values that must exist otherwise Pyfa breaks
- DefaultDatabaseValues.importRequiredDefaults()
-elif config.saveDB:
- # If database does not exist, do not worry about migration. Simply
- # create and set version
- db.saveddata_meta.create_all()
- db.saveddata_engine.execute('PRAGMA user_version = {}'.format(migration.getAppVersion()))
- # Import default database values
- # Import values that must exist otherwise Pyfa breaks
- DefaultDatabaseValues.importRequiredDefaults()
- # Import default values for damage profiles
- DefaultDatabaseValues.importDamageProfileDefaults()
- # Import default values for target resist profiles
- DefaultDatabaseValues.importResistProfileDefaults()
+# =============================================================================
+# 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 .
+# =============================================================================
+
+import threading
+import os
+
+import config
+from eos import db
+from eos.db import migration
+from eos.db.saveddata.loadDefaultDatabaseValues import DefaultDatabaseValues
+from eos.saveddata.character import Character as es_Character
+
+
+class PrefetchThread(threading.Thread):
+ def run(self):
+ # We're a daemon thread, as such, interpreter might get shut down while we do stuff
+ # Make sure we don't throw tracebacks to console
+ try:
+ es_Character.setSkillList(db.getItemsByCategory("Skill", eager=(
+ "effects", "attributes", "attributes.info.icon", "attributes.info.unit", "icon")))
+ except:
+ pass
+
+
+prefetch = PrefetchThread()
+prefetch.daemon = True
+prefetch.start()
+
+# The following code does not belong here, however until we rebuild skeletons
+# to include modified pyfa.py, this is the best place to put it. See GH issue
+# #176
+# @ todo: move this to pyfa.py
+
+# Make sure the saveddata db exists
+if config.savePath and not os.path.exists(config.savePath):
+ os.mkdir(config.savePath)
+
+if config.saveDB and os.path.isfile(config.saveDB):
+ # If database exists, run migration after init'd database
+ db.saveddata_meta.create_all()
+ migration.update(db.saveddata_engine)
+ # Import default database values
+ # Import values that must exist otherwise Pyfa breaks
+ DefaultDatabaseValues.importRequiredDefaults()
+elif config.saveDB:
+ # If database does not exist, do not worry about migration. Simply
+ # create and set version
+ db.saveddata_meta.create_all()
+ db.saveddata_engine.execute('PRAGMA user_version = {}'.format(migration.getAppVersion()))
+ # Import default database values
+ # Import values that must exist otherwise Pyfa breaks
+ DefaultDatabaseValues.importRequiredDefaults()
+ # Import default values for damage profiles
+ DefaultDatabaseValues.importDamageProfileDefaults()
+ # Import default values for target resist profiles
+ DefaultDatabaseValues.importResistProfileDefaults()
diff --git a/service/pycrest/eve.py b/service/pycrest/eve.py
index a46ad6c91..2322c704e 100644
--- a/service/pycrest/eve.py
+++ b/service/pycrest/eve.py
@@ -22,7 +22,6 @@ try:
except ImportError: # pragma: no cover
import cPickle as pickle
-
logger = logging.getLogger("pycrest.eve")
cache_re = re.compile(r'max-age=([0-9]+)')
diff --git a/service/pycrest/weak_ciphers.py b/service/pycrest/weak_ciphers.py
index ad0adec03..e3a82ca15 100644
--- a/service/pycrest/weak_ciphers.py
+++ b/service/pycrest/weak_ciphers.py
@@ -67,7 +67,7 @@ class WeakCiphersHTTPSConnection(urllib3.connection.VerifiedHTTPSConnection): #
warnings.warn((
'System time is way off (before {0}). This will probably '
'lead to SSL verification errors').format(
- urllib3.connection.RECENT_DATE),
+ urllib3.connection.RECENT_DATE),
SystemTimeWarning
)
@@ -103,13 +103,11 @@ class WeakCiphersHTTPSConnection(urllib3.connection.VerifiedHTTPSConnection): #
class WeakCiphersHTTPSConnectionPool(
- urllib3.connectionpool.HTTPSConnectionPool):
-
+ urllib3.connectionpool.HTTPSConnectionPool):
ConnectionCls = WeakCiphersHTTPSConnection
class WeakCiphersPoolManager(urllib3.poolmanager.PoolManager):
-
def _new_pool(self, scheme, host, port):
if scheme == 'https':
return WeakCiphersHTTPSConnectionPool(host, port, **(self.connection_pool_kw))
diff --git a/service/server.py b/service/server.py
index 49e193cee..98bd138f1 100644
--- a/service/server.py
+++ b/service/server.py
@@ -77,7 +77,6 @@ class AuthHandler(BaseHTTPServer.BaseHTTPRequestHandler):
# http://code.activestate.com/recipes/425210-simple-stoppable-server-using-socket-timeout/
class StoppableHTTPServer(BaseHTTPServer.HTTPServer):
-
def server_bind(self):
BaseHTTPServer.HTTPServer.server_bind(self)
self.settings = CRESTSettings.getInstance()
diff --git a/service/settings.py b/service/settings.py
index 579d484c2..68c1a2105 100644
--- a/service/settings.py
+++ b/service/settings.py
@@ -119,9 +119,9 @@ class NetworkSettings(object):
_instance = None
# constants for serviceNetworkDefaultSettings["mode"] parameter
- PROXY_MODE_NONE = 0 # 0 - No proxy
+ PROXY_MODE_NONE = 0 # 0 - No proxy
PROXY_MODE_AUTODETECT = 1 # 1 - Auto-detected proxy settings
- PROXY_MODE_MANUAL = 2 # 2 - Manual proxy settings
+ PROXY_MODE_MANUAL = 2 # 2 - Manual proxy settings
@classmethod
def getInstance(cls):
@@ -254,8 +254,15 @@ class HTMLExportSettings(object):
return cls._instance
def __init__(self):
- serviceHTMLExportDefaultSettings = {"enabled": False, "path": config.pyfaPath + os.sep + 'pyfaFits.html', "minimal": False}
- self.serviceHTMLExportSettings = SettingsProvider.getInstance().getSettings("pyfaServiceHTMLExportSettings", serviceHTMLExportDefaultSettings)
+ serviceHTMLExportDefaultSettings = {
+ "enabled": False,
+ "path": config.pyfaPath + os.sep + 'pyfaFits.html',
+ "minimal": False
+ }
+ self.serviceHTMLExportSettings = SettingsProvider.getInstance().getSettings(
+ "pyfaServiceHTMLExportSettings",
+ serviceHTMLExportDefaultSettings
+ )
def getEnabled(self):
return self.serviceHTMLExportSettings["enabled"]
@@ -295,7 +302,10 @@ class UpdateSettings(object):
# prerelease - If True, suppress prerelease notifications
# version - Set to release tag that user does not want notifications for
serviceUpdateDefaultSettings = {"prerelease": True, 'version': None}
- self.serviceUpdateSettings = SettingsProvider.getInstance().getSettings("pyfaServiceUpdateSettings", serviceUpdateDefaultSettings)
+ self.serviceUpdateSettings = SettingsProvider.getInstance().getSettings(
+ "pyfaServiceUpdateSettings",
+ serviceUpdateDefaultSettings
+ )
def get(self, type):
return self.serviceUpdateSettings[type]
@@ -315,13 +325,15 @@ class CRESTSettings(object):
return cls._instance
def __init__(self):
-
# mode
# 0 - Implicit authentication
# 1 - User-supplied client details
serviceCRESTDefaultSettings = {"mode": 0, "server": 0, "clientID": "", "clientSecret": "", "timeout": 60}
- self.serviceCRESTSettings = SettingsProvider.getInstance().getSettings("pyfaServiceCRESTSettings", serviceCRESTDefaultSettings)
+ self.serviceCRESTSettings = SettingsProvider.getInstance().getSettings(
+ "pyfaServiceCRESTSettings",
+ serviceCRESTDefaultSettings
+ )
def get(self, type):
return self.serviceCRESTSettings[type]
@@ -329,5 +341,4 @@ class CRESTSettings(object):
def set(self, type, value):
self.serviceCRESTSettings[type] = value
-
# @todo: migrate fit settings (from fit service) here?
diff --git a/service/targetResists.py b/service/targetResists.py
index dc208e78a..2a4863c5d 100644
--- a/service/targetResists.py
+++ b/service/targetResists.py
@@ -24,10 +24,12 @@ from eos.saveddata.targetResists import TargetResists as es_TargetResists
class ImportError(Exception):
- pass
+ pass
+
class TargetResists(object):
instance = None
+
@classmethod
def getInstance(cls):
if cls.instance is None:
diff --git a/service/update.py b/service/update.py
index 2b594bbf8..05f05efd7 100644
--- a/service/update.py
+++ b/service/update.py
@@ -42,7 +42,10 @@ class CheckUpdateThread(threading.Thread):
try:
response = network.request('https://api.github.com/repos/pyfa-org/Pyfa/releases', network.UPDATE)
jsonResponse = json.loads(response.read())
- jsonResponse.sort(key=lambda x: calendar.timegm(dateutil.parser.parse(x['published_at']).utctimetuple()), reverse=True)
+ jsonResponse.sort(
+ key=lambda x: calendar.timegm(dateutil.parser.parse(x['published_at']).utctimetuple()),
+ reverse=True
+ )
for release in jsonResponse:
# Suppress pre releases
@@ -63,7 +66,9 @@ class CheckUpdateThread(threading.Thread):
else:
rVersion = release['tag_name'].replace('v', '', 1)
- if config.tag is 'git' and not release['prerelease'] and self.versiontuple(rVersion) >= self.versiontuple(config.version):
+ if config.tag is 'git' and \
+ not release['prerelease'] and \
+ self.versiontuple(rVersion) >= self.versiontuple(config.version):
wx.CallAfter(self.callback, release) # git (dev/Singularity) -> Stable
elif config.expansionName is not "Singularity":
if release['prerelease']:
diff --git a/tox.ini b/tox.ini
index 3ce2756f3..5eae895b9 100644
--- a/tox.ini
+++ b/tox.ini
@@ -12,4 +12,4 @@ commands = py.test -vv --cov Pyfa tests/
[testenv:pep8]
deps = flake8
-commands = flake8 --exclude=.svn,CVS,.bzr,.hg,.git,__pycache__,venv,tests,.tox,build,dist,__init__.py --ignore=E501,E731 gui_service gui eos utils config.py pyfa.py
+commands = flake8 --exclude=.svn,CVS,.bzr,.hg,.git,__pycache__,venv,tests,.tox,build,dist,__init__.py --ignore=E501,E731 service gui eos utils config.py pyfa.py