Handle unicode, utf8, and windows-1252

This commit is contained in:
Ebag333
2016-11-26 22:57:53 -08:00
parent 459d55c31a
commit 0d4f24ade9
6 changed files with 333 additions and 243 deletions

109
config.py
View File

@@ -31,18 +31,20 @@ gameDB = None
class StreamToLogger(object): class StreamToLogger(object):
""" """
Fake file-like stream object that redirects writes to a logger instance. Fake file-like stream object that redirects writes to a logger instance.
From: http://www.electricmonk.nl/log/2011/08/14/redirect-stdout-and-stderr-to-a-logger-in-python/ From: http://www.electricmonk.nl/log/2011/08/14/redirect-stdout-and-stderr-to-a-logger-in-python/
""" """
def __init__(self, logger, log_level=logging.INFO):
self.logger = logger def __init__(self, logger, log_level=logging.INFO):
self.log_level = log_level self.logger = logger
self.linebuf = '' self.log_level = log_level
self.linebuf = ''
def write(self, buf):
for line in buf.rstrip().splitlines():
self.logger.log(self.log_level, line.rstrip())
def write(self, buf):
for line in buf.rstrip().splitlines():
self.logger.log(self.log_level, line.rstrip())
def isFrozen(): def isFrozen():
if hasattr(sys, 'frozen'): if hasattr(sys, 'frozen'):
@@ -50,16 +52,12 @@ def isFrozen():
else: else:
return False return False
def getPyfaRoot():
base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0]
root = os.path.dirname(os.path.realpath(os.path.abspath(base)))
root = unicode(root, sys.getfilesystemencoding())
return root
def __createDirs(path): def __createDirs(path):
if not os.path.exists(path): if not os.path.exists(path):
os.makedirs(path) os.makedirs(path)
def defPaths(customSavePath): def defPaths(customSavePath):
global debug global debug
global pyfaPath global pyfaPath
@@ -77,32 +75,32 @@ def defPaths(customSavePath):
# Python 2.X uses ANSI by default, so we need to convert the character encoding # Python 2.X uses ANSI by default, so we need to convert the character encoding
pyfaPath = getattr(configforced, "pyfaPath", pyfaPath) pyfaPath = getattr(configforced, "pyfaPath", pyfaPath)
if pyfaPath is None: if pyfaPath is None:
pyfaPath = getPyfaRoot() pyfaPath = getPyfaPath()
# Where we store the saved fits etc, default is the current users home directory # Where we store the saved fits etc, default is the current users home directory
if saveInRoot is True: if saveInRoot is True:
savePath = getattr(configforced, "savePath", None) savePath = getattr(configforced, "savePath", None)
if savePath is None: if savePath is None:
savePath = os.path.join(pyfaPath, "saveddata") savePath = getPyfaPath("saveddata")
else: else:
savePath = getattr(configforced, "savePath", None) savePath = getattr(configforced, "savePath", None)
if savePath is None: if savePath is None:
if customSavePath is None: # customSavePath is not overriden if customSavePath is None: # customSavePath is not overriden
savePath = unicode(os.path.expanduser(os.path.join("~", ".pyfa")), savePath = getSavePath()
sys.getfilesystemencoding())
else: else:
savePath = customSavePath savePath = customSavePath
__createDirs(savePath) __createDirs(savePath)
if isFrozen(): if isFrozen():
os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(pyfaPath, "cacert.pem") certName = "cacert.pem"
os.environ["SSL_CERT_FILE"] = os.path.join(pyfaPath, "cacert.pem") os.environ["REQUESTS_CA_BUNDLE"] = getPyfaPath(certName)
os.environ["SSL_CERT_FILE"] = getPyfaPath(certName)
format = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s' loggingFormat = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s'
logging.basicConfig(format=format, level=logLevel) logging.basicConfig(format=loggingFormat, level=logLevel)
handler = logging.handlers.RotatingFileHandler(os.path.join(savePath, "log.txt"), maxBytes=1000000, backupCount=3) handler = logging.handlers.RotatingFileHandler(getSavePath("log.txt"), maxBytes=1000000, backupCount=3)
formatter = logging.Formatter(format) formatter = logging.Formatter(loggingFormat)
handler.setFormatter(formatter) handler.setFormatter(formatter)
logging.getLogger('').addHandler(handler) logging.getLogger('').addHandler(handler)
@@ -114,23 +112,68 @@ def defPaths(customSavePath):
sys.stdout = sl sys.stdout = sl
# This interferes with cx_Freeze's own handling of exceptions. Find a way to fix this. # This interferes with cx_Freeze's own handling of exceptions. Find a way to fix this.
#stderr_logger = logging.getLogger('STDERR') # stderr_logger = logging.getLogger('STDERR')
#sl = StreamToLogger(stderr_logger, logging.ERROR) # sl = StreamToLogger(stderr_logger, logging.ERROR)
#sys.stderr = sl # sys.stderr = sl
# The database where we store all the fits etc # The database where we store all the fits etc
saveDB = os.path.join(savePath, "saveddata.db") saveDB = getSavePath("saveddata.db")
# The database where the static EVE data from the datadump is kept. # The database where the static EVE data from the datadump is kept.
# This is not the standard sqlite datadump but a modified version created by eos # This is not the standard sqlite datadump but a modified version created by eos
# maintenance script # maintenance script
gameDB = os.path.join(pyfaPath, "eve.db") gameDB = getPyfaPath("eve.db")
## DON'T MODIFY ANYTHING BELOW ## ## DON'T MODIFY ANYTHING BELOW ##
import eos.config import eos.config
#Caching modifiers, disable all gamedata caching, its unneeded. # Caching modifiers, disable all gamedata caching, its unneeded.
eos.config.gamedataCache = False eos.config.gamedataCache = False
# saveddata db location modifier, shouldn't ever need to touch this # saveddata db location modifier, shouldn't ever need to touch this
eos.config.saveddata_connectionstring = "sqlite:///" + saveDB + "?check_same_thread=False" eos.config.saveddata_connectionstring = "sqlite:///" + saveDB + "?check_same_thread=False"
eos.config.gamedata_connectionstring = "sqlite:///" + gameDB + "?check_same_thread=False" eos.config.gamedata_connectionstring = "sqlite:///" + gameDB + "?check_same_thread=False"
def getPyfaPath(Append=None):
base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0]
root = os.path.dirname(os.path.realpath(os.path.abspath(base)))
if type(root) == str: # leave unicode ones alone
try:
root = root.decode('utf8')
except UnicodeDecodeError:
root = root.decode('windows-1252')
if not Append:
return root
if type(root) == str: # leave unicode ones alone
try:
path = os.path.abspath(os.path.join(root, Append)).decode('utf8')
except UnicodeDecodeError:
path = os.path.abspath(os.path.join(root, Append)).decode('windows-1252')
else:
path = os.path.abspath(os.path.join(root, Append))
return path
def getSavePath(Append=None):
root = os.path.expanduser(os.path.join("~", ".pyfa"))
if type(root) == str: # leave unicode ones alone
try:
root = root.decode('utf8')
except UnicodeDecodeError:
root = root.decode('windows-1252')
if not Append:
return root
if type(root) == str: # leave unicode ones alone
try:
path = os.path.abspath(os.path.join(root, Append)).decode('utf8')
except UnicodeDecodeError:
path = os.path.abspath(os.path.join(root, Append)).decode('windows-1252')
else:
path = os.path.abspath(os.path.join(root, Append))
return path

View File

@@ -1,4 +1,4 @@
#=============================================================================== # ===============================================================================
# Copyright (C) 2010 Diego Duclos # Copyright (C) 2010 Diego Duclos
# #
# This file is part of pyfa. # This file is part of pyfa.
@@ -15,23 +15,25 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>. # along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#=============================================================================== # ===============================================================================
import os.path
import config
import wx
import zipfile
import cStringIO import cStringIO
import os.path
import zipfile
import wx
import config
try: try:
from collections import OrderedDict from collections import OrderedDict
except ImportError: except ImportError:
from utils.compat import OrderedDict from utils.compat import OrderedDict
class BitmapLoader():
class BitmapLoader():
try: try:
archive = zipfile.ZipFile(os.path.join(config.pyfaPath, 'imgs.zip'), 'r') archive = zipfile.ZipFile(config.getPyfaPath('imgs.zip'), 'r')
except IOError: except IOError:
archive = None archive = None
@@ -42,7 +44,7 @@ class BitmapLoader():
@classmethod @classmethod
def getStaticBitmap(cls, name, parent, location): def getStaticBitmap(cls, name, parent, location):
static = wx.StaticBitmap(parent) static = wx.StaticBitmap(parent)
static.SetBitmap(cls.getBitmap(name,location)) static.SetBitmap(cls.getBitmap(name, location))
return static return static
@classmethod @classmethod
@@ -85,7 +87,7 @@ class BitmapLoader():
except KeyError: except KeyError:
print "Missing icon file from zip: {0}".format(path) print "Missing icon file from zip: {0}".format(path)
else: else:
path = os.path.join(config.pyfaPath, 'imgs', location, filename) path = config.getPyfaPath('imgs\\' + location + "\\" + filename)
if os.path.exists(path): if os.path.exists(path):
return wx.Image(path) return wx.Image(path)

View File

@@ -1,4 +1,4 @@
#=============================================================================== # ===============================================================================
# Copyright (C) 2010 Diego Duclos # Copyright (C) 2010 Diego Duclos
# #
# This file is part of pyfa. # This file is part of pyfa.
@@ -15,21 +15,23 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>. # along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#=============================================================================== # ===============================================================================
import os
import wx import wx
import os
from gui.bitmapLoader import BitmapLoader
import gui.display import gui.display
import gui.globalEvents as GE import gui.globalEvents as GE
from gui.graph import Graph
import service
import gui.mainFrame import gui.mainFrame
import service
from gui.bitmapLoader import BitmapLoader
from gui.graph import Graph
enabled = True enabled = True
mplImported = False mplImported = False
class GraphFrame(wx.Frame): class GraphFrame(wx.Frame):
def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT): def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):
@@ -46,9 +48,20 @@ class GraphFrame(wx.Frame):
try: try:
cache_dir = mpl._get_cachedir() cache_dir = mpl._get_cachedir()
except: except:
cache_dir = unicode(os.path.expanduser(os.path.join("~", ".matplotlib"))) cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib"))
if type(cache_dir) == str: # leave unicode ones alone
try:
cache_dir = cache_dir.decode('utf8')
except UnicodeDecodeError:
cache_dir = cache_dir.decode('windows-1252')
cache_file = os.path.join(cache_dir, 'fontList.cache') cache_file = os.path.join(cache_dir, 'fontList.cache')
if type(cache_file) == str: # leave unicode ones alone
try:
cache_file = cache_file.decode('utf8')
except UnicodeDecodeError:
cache_file = cache_file.decode('windows-1252')
if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file): if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file):
# remove matplotlib font cache, see #234 # remove matplotlib font cache, see #234
os.remove(cache_file) os.remove(cache_file)
@@ -58,7 +71,7 @@ class GraphFrame(wx.Frame):
from matplotlib.figure import Figure from matplotlib.figure import Figure
enabled = True enabled = True
if mpl.__version__[0] != "1": if mpl.__version__[0] != "1":
print "pyfa: Found matplotlib version ",mpl.__version__, " - activating OVER9000 workarounds" print "pyfa: Found matplotlib version ", mpl.__version__, " - activating OVER9000 workarounds"
print "pyfa: Recommended minimum matplotlib version is 1.0.0" print "pyfa: Recommended minimum matplotlib version is 1.0.0"
self.legendFix = True self.legendFix = True
except: except:
@@ -91,19 +104,20 @@ class GraphFrame(wx.Frame):
self.figure = Figure(figsize=(4, 3)) self.figure = Figure(figsize=(4, 3))
rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get() rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
clr = [c/255. for c in rgbtuple] clr = [c / 255. for c in rgbtuple]
self.figure.set_facecolor( clr ) self.figure.set_facecolor(clr)
self.figure.set_edgecolor( clr ) self.figure.set_edgecolor(clr)
self.canvas = Canvas(self, -1, self.figure) self.canvas = Canvas(self, -1, self.figure)
self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) ) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))
self.subplot = self.figure.add_subplot(111) self.subplot = self.figure.add_subplot(111)
self.subplot.grid(True) self.subplot.grid(True)
self.mainSizer.Add(self.canvas, 1, wx.EXPAND) 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.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
wx.EXPAND)
self.gridPanel = wx.Panel(self) self.gridPanel = wx.Panel(self)
self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND) self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND)
@@ -122,8 +136,8 @@ class GraphFrame(wx.Frame):
self.graphSelection.SetSelection(0) self.graphSelection.SetSelection(0)
self.fields = {} self.fields = {}
self.select(0) self.select(0)
self.sl1 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) 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.sl1, 0, wx.EXPAND)
self.mainSizer.Add(self.fitList, 0, wx.EXPAND) self.mainSizer.Add(self.fitList, 0, wx.EXPAND)
self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem) self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
@@ -160,18 +174,18 @@ class GraphFrame(wx.Frame):
self.gridPanel.DestroyChildren() self.gridPanel.DestroyChildren()
self.fields.clear() self.fields.clear()
#Setup textboxes # Setup textboxes
for field, defaultVal in view.getFields().iteritems(): for field, defaultVal in view.getFields().iteritems():
textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0) textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
self.fields[field] = textBox self.fields[field] = textBox
textBox.Bind(wx.EVT_TEXT, self.onFieldChanged) textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3) sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)
if defaultVal is not None: if defaultVal is not None:
if not isinstance(defaultVal, basestring): if not isinstance(defaultVal, basestring):
defaultVal = ("%f" % defaultVal).rstrip("0") defaultVal = ("%f" % defaultVal).rstrip("0")
if defaultVal[-1:] == ".": if defaultVal[-1:] == ".":
defaultVal = defaultVal + "0" defaultVal += "0"
textBox.ChangeValue(defaultVal) textBox.ChangeValue(defaultVal)
@@ -189,7 +203,8 @@ class GraphFrame(wx.Frame):
else: else:
label = field label = field
imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3) 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) sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
self.draw() self.draw()
@@ -204,7 +219,7 @@ class GraphFrame(wx.Frame):
try: try:
success, status = view.getPoints(fit, values) success, status = view.getPoints(fit, values)
if not success: if not success:
#TODO: Add a pwetty statys bar to report errors with # TODO: Add a pwetty statys bar to report errors with
self.SetStatusText(status) self.SetStatusText(status)
return return
@@ -218,15 +233,15 @@ class GraphFrame(wx.Frame):
return return
if self.legendFix and len(legend) > 0: if self.legendFix and len(legend) > 0:
leg = self.subplot.legend(tuple(legend), "upper right" , shadow = False) leg = self.subplot.legend(tuple(legend), "upper right", shadow=False)
for t in leg.get_texts(): for t in leg.get_texts():
t.set_fontsize('small') t.set_fontsize('small')
for l in leg.get_lines(): for l in leg.get_lines():
l.set_linewidth(1) l.set_linewidth(1)
elif not self.legendFix and len(legend) >0: elif not self.legendFix and len(legend) > 0:
leg = self.subplot.legend(tuple(legend), "upper right" , shadow = False, frameon = False) leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False)
for t in leg.get_texts(): for t in leg.get_texts():
t.set_fontsize('small') t.set_fontsize('small')
@@ -269,10 +284,10 @@ class FitList(wx.Panel):
fitToolTip = wx.ToolTip("Drag a fit into this list to graph it") fitToolTip = wx.ToolTip("Drag a fit into this list to graph it")
self.fitList.SetToolTip(fitToolTip) self.fitList.SetToolTip(fitToolTip)
class FitDisplay(gui.display.Display): class FitDisplay(gui.display.Display):
DEFAULT_COLS = ["Base Icon", DEFAULT_COLS = ["Base Icon",
"Base Name"] "Base Name"]
def __init__(self, parent): def __init__(self, parent):
gui.display.Display.__init__(self, parent) gui.display.Display.__init__(self, parent)

View File

@@ -1,4 +1,4 @@
#=============================================================================== # ===============================================================================
# Copyright (C) 2010 Diego Duclos # Copyright (C) 2010 Diego Duclos
# #
# This file is part of pyfa. # This file is part of pyfa.
@@ -15,38 +15,41 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>. # along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#=============================================================================== # ===============================================================================
import csv
import re
import sys
import wx import wx
import re
import gui.mainFrame
from gui.bitmapLoader import BitmapLoader
import sys
import wx.lib.mixins.listctrl as listmix
import wx.html import wx.html
from eos.types import Fit, Ship, Citadel, Module, Skill, Booster, Implant, Drone, Mode, Fighter import wx.lib.mixins.listctrl as listmix
from gui.utils.numberFormatter import formatAmount
import service
import config import config
import gui.mainFrame
import service
from eos.types import Fit, Ship, Citadel, Module, Skill, Booster, Implant, Drone, Mode, Fighter
from gui.bitmapLoader import BitmapLoader
from gui.contextMenu import ContextMenu from gui.contextMenu import ContextMenu
from gui.utils.numberFormatter import formatAmount from gui.utils.numberFormatter import formatAmount
import csv
try: try:
from collections import OrderedDict from collections import OrderedDict
except ImportError: except ImportError:
from utils.compat import OrderedDict from utils.compat import OrderedDict
class ItemStatsDialog(wx.Dialog): class ItemStatsDialog(wx.Dialog):
counter = 0 counter = 0
def __init__( def __init__(
self, self,
victim, victim,
fullContext=None, fullContext=None,
pos=wx.DefaultPosition, pos=wx.DefaultPosition,
size=wx.DefaultSize, size=wx.DefaultSize,
maximized = False maximized=False
): ):
wx.Dialog.__init__( wx.Dialog.__init__(
self, self,
@@ -55,7 +58,7 @@ class ItemStatsDialog(wx.Dialog):
title="Item stats", title="Item stats",
pos=pos, pos=pos,
size=size, size=size,
style=wx.CAPTION | wx.CLOSE_BOX | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER| wx.SYSTEM_MENU style=wx.CAPTION | wx.CLOSE_BOX | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU
) )
empty = getattr(victim, "isEmpty", False) empty = getattr(victim, "isEmpty", False)
@@ -77,26 +80,27 @@ class ItemStatsDialog(wx.Dialog):
victim = None victim = None
self.context = itmContext self.context = itmContext
if item.icon is not None: if item.icon is not None:
before,sep,after = item.icon.iconFile.rpartition("_") before, sep, after = item.icon.iconFile.rpartition("_")
iconFile = "%s%s%s" % (before,sep,"0%s" % after if len(after) < 2 else after) iconFile = "%s%s%s" % (before, sep, "0%s" % after if len(after) < 2 else after)
itemImg = BitmapLoader.getBitmap(iconFile, "icons") itemImg = BitmapLoader.getBitmap(iconFile, "icons")
if itemImg is not None: if itemImg is not None:
self.SetIcon(wx.IconFromBitmap(itemImg)) 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)) self.SetMinSize((300, 200))
if "wxGTK" in wx.PlatformInfo: # GTK has huge tab widgets, give it a bit more room if "wxGTK" in wx.PlatformInfo: # GTK has huge tab widgets, give it a bit more room
self.SetSize((580, 500)) self.SetSize((580, 500))
else: else:
self.SetSize((550, 500)) self.SetSize((550, 500))
#self.SetMaxSize((500, -1)) # self.SetMaxSize((500, -1))
self.mainSizer = wx.BoxSizer(wx.VERTICAL) self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.container = ItemStatsContainer(self, victim, item, itmContext) self.container = ItemStatsContainer(self, victim, item, itmContext)
self.mainSizer.Add(self.container, 1, wx.EXPAND) self.mainSizer.Add(self.container, 1, wx.EXPAND)
if "wxGTK" in wx.PlatformInfo: if "wxGTK" in wx.PlatformInfo:
self.closeBtn = wx.Button( self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0 ) self.closeBtn = wx.Button(self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0)
self.mainSizer.Add( self.closeBtn, 0, wx.ALL|wx.ALIGN_RIGHT, 5 ) self.mainSizer.Add(self.closeBtn, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
self.closeBtn.Bind(wx.EVT_BUTTON, self.closeEvent) self.closeBtn.Bind(wx.EVT_BUTTON, self.closeEvent)
self.SetSizer(self.mainSizer) self.SetSizer(self.mainSizer)
@@ -112,13 +116,13 @@ class ItemStatsDialog(wx.Dialog):
counter = ItemStatsDialog.counter counter = ItemStatsDialog.counter
dlgStep = 30 dlgStep = 30
if counter * dlgStep > ppos.x+psize.width-dlgsize.x or counter * dlgStep > ppos.y+psize.height-dlgsize.y: if counter * dlgStep > ppos.x + psize.width - dlgsize.x or counter * dlgStep > ppos.y + psize.height - dlgsize.y:
ItemStatsDialog.counter = 1 ItemStatsDialog.counter = 1
dlgx = ppos.x + counter * dlgStep dlgx = ppos.x + counter * dlgStep
dlgy = ppos.y + counter * dlgStep dlgy = ppos.y + counter * dlgStep
if pos == wx.DefaultPosition: if pos == wx.DefaultPosition:
self.SetPosition((dlgx,dlgy)) self.SetPosition((dlgx, dlgy))
else: else:
self.SetPosition(pos) self.SetPosition(pos)
if maximized: if maximized:
@@ -138,26 +142,26 @@ class ItemStatsDialog(wx.Dialog):
def closeEvent(self, event): def closeEvent(self, event):
if self.dlgOrder==ItemStatsDialog.counter: if self.dlgOrder == ItemStatsDialog.counter:
ItemStatsDialog.counter -= 1 ItemStatsDialog.counter -= 1
self.parentWnd.UnregisterStatsWindow(self) self.parentWnd.UnregisterStatsWindow(self)
self.Destroy() self.Destroy()
########################################################################### ###########################################################################
## Class ItemStatsContainer ## Class ItemStatsContainer
########################################################################### ###########################################################################
class ItemStatsContainer ( wx.Panel ): class ItemStatsContainer(wx.Panel):
def __init__(self, parent, stuff, item, context=None):
def __init__( self, parent, stuff, item, context = None): wx.Panel.__init__(self, parent)
wx.Panel.__init__ ( self, parent )
sMkt = service.Market.getInstance() sMkt = service.Market.getInstance()
mainSizer = wx.BoxSizer( wx.VERTICAL ) mainSizer = wx.BoxSizer(wx.VERTICAL)
self.nbContainer = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 ) self.nbContainer = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add( self.nbContainer, 1, wx.EXPAND |wx.ALL, 2 ) mainSizer.Add(self.nbContainer, 1, wx.EXPAND | wx.ALL, 2)
if item.traits is not None: if item.traits is not None:
self.traits = ItemTraits(self.nbContainer, stuff, item) self.traits = ItemTraits(self.nbContainer, stuff, item)
@@ -188,7 +192,7 @@ class ItemStatsContainer ( wx.Panel ):
self.SetSizer(mainSizer) self.SetSizer(mainSizer)
self.Layout() self.Layout()
def __del__( self ): def __del__(self):
pass pass
def mouseHit(self, event): def mouseHit(self, event):
@@ -196,54 +200,54 @@ class ItemStatsContainer ( wx.Panel ):
if tab != -1: if tab != -1:
self.nbContainer.SetSelection(tab) self.nbContainer.SetSelection(tab)
########################################################################### ###########################################################################
## Class AutoListCtrl ## Class AutoListCtrl
########################################################################### ###########################################################################
class AutoListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ListRowHighlighter): class AutoListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ListRowHighlighter):
def __init__(self, parent, ID, pos=wx.DefaultPosition, def __init__(self, parent, ID, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0): size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, ID, pos, size, style) wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
listmix.ListCtrlAutoWidthMixin.__init__(self) listmix.ListCtrlAutoWidthMixin.__init__(self)
listmix.ListRowHighlighter.__init__(self) listmix.ListRowHighlighter.__init__(self)
########################################################################### ###########################################################################
## Class AutoListCtrl ## Class AutoListCtrl
########################################################################### ###########################################################################
class AutoListCtrlNoHighlight(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ListRowHighlighter): class AutoListCtrlNoHighlight(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ListRowHighlighter):
def __init__(self, parent, ID, pos=wx.DefaultPosition, def __init__(self, parent, ID, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0): size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, ID, pos, size, style) wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
listmix.ListCtrlAutoWidthMixin.__init__(self) listmix.ListCtrlAutoWidthMixin.__init__(self)
########################################################################### ###########################################################################
## Class ItemTraits ## Class ItemTraits
########################################################################### ###########################################################################
class ItemTraits ( wx.Panel ): class ItemTraits(wx.Panel):
def __init__(self, parent, stuff, item): def __init__(self, parent, stuff, item):
wx.Panel.__init__ (self, parent) wx.Panel.__init__(self, parent)
mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(mainSizer) self.SetSizer(mainSizer)
self.traits = wx.html.HtmlWindow(self) self.traits = wx.html.HtmlWindow(self)
self.traits.SetPage(item.traits.traitText) self.traits.SetPage(item.traits.traitText)
mainSizer.Add(self.traits, 1, wx.ALL|wx.EXPAND, 0) mainSizer.Add(self.traits, 1, wx.ALL | wx.EXPAND, 0)
self.Layout() self.Layout()
########################################################################### ###########################################################################
## Class ItemDescription ## Class ItemDescription
########################################################################### ###########################################################################
class ItemDescription ( wx.Panel ): class ItemDescription(wx.Panel):
def __init__(self, parent, stuff, item): def __init__(self, parent, stuff, item):
wx.Panel.__init__ (self, parent) wx.Panel.__init__(self, parent)
mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(mainSizer) self.SetSizer(mainSizer)
@@ -260,28 +264,30 @@ class ItemDescription ( wx.Panel ):
desc = re.sub("<( *)font( *)color( *)=(.*?)>(?P<inside>.*?)<( *)/( *)font( *)>", "\g<inside>", desc) desc = re.sub("<( *)font( *)color( *)=(.*?)>(?P<inside>.*?)<( *)/( *)font( *)>", "\g<inside>", desc)
# Strip URLs # Strip URLs
desc = re.sub("<( *)a(.*?)>(?P<inside>.*?)<( *)/( *)a( *)>", "\g<inside>", desc) desc = re.sub("<( *)a(.*?)>(?P<inside>.*?)<( *)/( *)a( *)>", "\g<inside>", desc)
desc = "<body bgcolor='" + bgcolor.GetAsString(wx.C2S_HTML_SYNTAX) + "' text='" + fgcolor.GetAsString(wx.C2S_HTML_SYNTAX) + "' >" + desc + "</body>" desc = "<body bgcolor='" + bgcolor.GetAsString(wx.C2S_HTML_SYNTAX) + "' text='" + fgcolor.GetAsString(
wx.C2S_HTML_SYNTAX) + "' >" + desc + "</body>"
self.description.SetPage(desc) self.description.SetPage(desc)
mainSizer.Add(self.description, 1, wx.ALL|wx.EXPAND, 0) mainSizer.Add(self.description, 1, wx.ALL | wx.EXPAND, 0)
self.Layout() self.Layout()
########################################################################### ###########################################################################
## Class ItemParams ## Class ItemParams
########################################################################### ###########################################################################
class ItemParams (wx.Panel): class ItemParams(wx.Panel):
def __init__(self, parent, stuff, item, context = None): def __init__(self, parent, stuff, item, context=None):
wx.Panel.__init__ (self, parent) wx.Panel.__init__(self, parent)
mainSizer = wx.BoxSizer( wx.VERTICAL ) mainSizer = wx.BoxSizer(wx.VERTICAL)
self.paramList = AutoListCtrl(self, wx.ID_ANY, self.paramList = AutoListCtrl(self, wx.ID_ANY,
style = #wx.LC_HRULES | style= # wx.LC_HRULES |
#wx.LC_NO_HEADER | # wx.LC_NO_HEADER |
wx.LC_REPORT |wx.LC_SINGLE_SEL |wx.LC_VRULES |wx.NO_BORDER) wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
mainSizer.Add( self.paramList, 1, wx.ALL|wx.EXPAND, 0 ) mainSizer.Add(self.paramList, 1, wx.ALL | wx.EXPAND, 0)
self.SetSizer( mainSizer ) self.SetSizer(mainSizer)
self.toggleView = 1 self.toggleView = 1
self.stuff = stuff self.stuff = stuff
@@ -290,29 +296,31 @@ class ItemParams (wx.Panel):
self.attrValues = {} self.attrValues = {}
self._fetchValues() self._fetchValues()
self.m_staticline = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) self.m_staticline = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add( self.m_staticline, 0, wx.EXPAND) mainSizer.Add(self.m_staticline, 0, wx.EXPAND)
bSizer = wx.BoxSizer( wx.HORIZONTAL ) bSizer = wx.BoxSizer(wx.HORIZONTAL)
self.totalAttrsLabel = wx.StaticText( self, wx.ID_ANY, u" ", wx.DefaultPosition, wx.DefaultSize, 0 ) 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) 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,
bSizer.Add( self.toggleViewBtn, 0, wx.ALIGN_CENTER_VERTICAL) 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,
bSizer.Add( self.exportStatsBtn, 0, wx.ALIGN_CENTER_VERTICAL) 0)
bSizer.Add(self.exportStatsBtn, 0, wx.ALIGN_CENTER_VERTICAL)
if stuff is not None: if stuff is not None:
self.refreshBtn = wx.Button( self, wx.ID_ANY, u"Refresh", wx.DefaultPosition, wx.DefaultSize, wx.BU_EXACTFIT ) self.refreshBtn = wx.Button(self, wx.ID_ANY, u"Refresh", wx.DefaultPosition, wx.DefaultSize, wx.BU_EXACTFIT)
bSizer.Add( self.refreshBtn, 0, wx.ALIGN_CENTER_VERTICAL) bSizer.Add(self.refreshBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.refreshBtn.Bind( wx.EVT_BUTTON, self.RefreshValues ) self.refreshBtn.Bind(wx.EVT_BUTTON, self.RefreshValues)
mainSizer.Add( bSizer, 0, wx.ALIGN_RIGHT) mainSizer.Add(bSizer, 0, wx.ALIGN_RIGHT)
self.PopulateList() self.PopulateList()
self.toggleViewBtn.Bind(wx.EVT_TOGGLEBUTTON,self.ToggleViewMode) self.toggleViewBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleViewMode)
self.exportStatsBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ExportItemStats) self.exportStatsBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ExportItemStats)
def _fetchValues(self): def _fetchValues(self):
@@ -348,7 +356,7 @@ class ItemParams (wx.Panel):
event.Skip() event.Skip()
def ToggleViewMode(self, event): def ToggleViewMode(self, event):
self.toggleView *=-1 self.toggleView *= -1
self.UpdateList() self.UpdateList()
event.Skip() event.Skip()
@@ -412,17 +420,17 @@ class ItemParams (wx.Panel):
) )
def PopulateList(self): def PopulateList(self):
self.paramList.InsertColumn(0,"Attribute") self.paramList.InsertColumn(0, "Attribute")
self.paramList.InsertColumn(1,"Current Value") self.paramList.InsertColumn(1, "Current Value")
if self.stuff is not None: if self.stuff is not None:
self.paramList.InsertColumn(2,"Base Value") self.paramList.InsertColumn(2, "Base Value")
self.paramList.SetColumnWidth(0,110) self.paramList.SetColumnWidth(0, 110)
self.paramList.SetColumnWidth(1,90) self.paramList.SetColumnWidth(1, 90)
if self.stuff is not None: if self.stuff is not None:
self.paramList.SetColumnWidth(2,90) self.paramList.SetColumnWidth(2, 90)
self.paramList.setResizeColumn(0) self.paramList.setResizeColumn(0)
self.imageList = wx.ImageList(16, 16) self.imageList = wx.ImageList(16, 16)
self.paramList.SetImageList(self.imageList,wx.IMAGE_LIST_SMALL) self.paramList.SetImageList(self.imageList, wx.IMAGE_LIST_SMALL)
names = list(self.attrValues.iterkeys()) names = list(self.attrValues.iterkeys())
names.sort() names.sort()
@@ -461,7 +469,6 @@ class ItemParams (wx.Panel):
else: else:
attrIcon = self.imageList.Add(BitmapLoader.getBitmap("7_15", "icons")) attrIcon = self.imageList.Add(BitmapLoader.getBitmap("7_15", "icons"))
index = self.paramList.InsertImageStringItem(sys.maxint, attrName, attrIcon) index = self.paramList.InsertImageStringItem(sys.maxint, attrName, attrIcon)
idNameMap[idCount] = attrName idNameMap[idCount] = attrName
self.paramList.SetItemData(index, idCount) self.paramList.SetItemData(index, idCount)
@@ -485,11 +492,9 @@ class ItemParams (wx.Panel):
if self.stuff is not None: if self.stuff is not None:
self.paramList.SetStringItem(index, 2, valueUnitDefault) self.paramList.SetStringItem(index, 2, valueUnitDefault)
self.paramList.SortItems(lambda id1, id2: cmp(idNameMap[id1], idNameMap[id2])) self.paramList.SortItems(lambda id1, id2: cmp(idNameMap[id1], idNameMap[id2]))
self.paramList.RefreshRows() self.paramList.RefreshRows()
self.totalAttrsLabel.SetLabel("%d attributes. " %idCount) self.totalAttrsLabel.SetLabel("%d attributes. " % idCount)
self.Layout() self.Layout()
def TranslateValueUnit(self, value, unitName, unitDisplayName): def TranslateValueUnit(self, value, unitName, unitDisplayName):
@@ -505,15 +510,16 @@ class ItemParams (wx.Panel):
attribute = service.Attribute.getInstance().getAttributeInfo(value) attribute = service.Attribute.getInstance().getAttributeInfo(value)
return "%s (%d)" % (attribute.name.capitalize(), value) return "%s (%d)" % (attribute.name.capitalize(), value)
trans = {"Inverse Absolute Percent": (lambda: (1-value)*100, unitName), trans = {"Inverse Absolute Percent": (lambda: (1 - value) * 100, unitName),
"Inversed Modifier 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"), "Volume": (lambda: value, u"m\u00B3"),
"Sizeclass": (lambda: value, ""), "Sizeclass": (lambda: value, ""),
"Absolute Percent": (lambda: (value * 100) , unitName), "Absolute Percent": (lambda: (value * 100), unitName),
"Milliseconds": (lambda: value / 1000.0, unitName), "Milliseconds": (lambda: value / 1000.0, unitName),
"typeID": (itemIDCallback, ""), "typeID": (itemIDCallback, ""),
"groupID": (groupIDCallback,""), "groupID": (groupIDCallback, ""),
"attributeID": (attributeIDCallback, "")} "attributeID": (attributeIDCallback, "")}
override = trans.get(unitDisplayName) override = trans.get(unitDisplayName)
@@ -527,9 +533,10 @@ class ItemParams (wx.Panel):
fvalue = formatAmount(v, 3, 0, 0) fvalue = formatAmount(v, 3, 0, 0)
else: else:
fvalue = v fvalue = v
return "%s %s" % (fvalue , override[1]) return "%s %s" % (fvalue, override[1])
else: else:
return "%s %s" % (formatAmount(value, 3, 0),unitName) return "%s %s" % (formatAmount(value, 3, 0), unitName)
class ItemCompare(wx.Panel): class ItemCompare(wx.Panel):
def __init__(self, parent, stuff, item, items, context=None): def __init__(self, parent, stuff, item, items, context=None):
@@ -546,7 +553,8 @@ class ItemCompare(wx.Panel):
self.toggleView = 1 self.toggleView = 1
self.stuff = stuff self.stuff = stuff
self.item = item 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 = {} self.attrs = {}
# get a dict of attrName: attrInfo of all unique attributes across all items # get a dict of attrName: attrInfo of all unique attributes across all items
@@ -618,7 +626,7 @@ class ItemCompare(wx.Panel):
def processPrices(self, prices): def processPrices(self, prices):
for i, price in enumerate(prices): for i, price in enumerate(prices):
self.paramList.SetStringItem(i, len(self.attrs)+1, formatAmount(price.price, 3, 3, 9, currency=True)) self.paramList.SetStringItem(i, len(self.attrs) + 1, formatAmount(price.price, 3, 3, 9, currency=True))
def PopulateList(self): def PopulateList(self):
self.paramList.InsertColumn(0, "Item") self.paramList.InsertColumn(0, "Item")
@@ -626,11 +634,11 @@ class ItemCompare(wx.Panel):
for i, attr in enumerate(self.attrs.keys()): for i, attr in enumerate(self.attrs.keys()):
name = self.attrs[attr].displayName if self.attrs[attr].displayName else attr name = self.attrs[attr].displayName if self.attrs[attr].displayName else attr
self.paramList.InsertColumn(i+1, name) self.paramList.InsertColumn(i + 1, name)
self.paramList.SetColumnWidth(i+1, 120) self.paramList.SetColumnWidth(i + 1, 120)
self.paramList.InsertColumn(len(self.attrs)+1, "Price") self.paramList.InsertColumn(len(self.attrs) + 1, "Price")
self.paramList.SetColumnWidth(len(self.attrs)+1, 60) self.paramList.SetColumnWidth(len(self.attrs) + 1, 60)
sMkt = service.Market.getInstance() sMkt = service.Market.getInstance()
sMkt.getPrices([x.ID for x in self.items], self.processPrices) sMkt.getPrices([x.ID for x in self.items], self.processPrices)
@@ -648,7 +656,7 @@ class ItemCompare(wx.Panel):
else: else:
valueUnit = formatAmount(value, 3, 0, 0) valueUnit = formatAmount(value, 3, 0, 0)
self.paramList.SetStringItem(i, x+1, valueUnit) self.paramList.SetStringItem(i, x + 1, valueUnit)
self.paramList.RefreshRows() self.paramList.RefreshRows()
self.Layout() self.Layout()
@@ -669,7 +677,7 @@ class ItemCompare(wx.Panel):
trans = {"Inverse Absolute Percent": (lambda: (1 - value) * 100, unitName), trans = {"Inverse Absolute Percent": (lambda: (1 - value) * 100, unitName),
"Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName), "Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName),
"Modifier Percent": ( "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"), "Volume": (lambda: value, u"m\u00B3"),
"Sizeclass": (lambda: value, ""), "Sizeclass": (lambda: value, ""),
"Absolute Percent": (lambda: (value * 100), unitName), "Absolute Percent": (lambda: (value * 100), unitName),
@@ -698,19 +706,18 @@ class ItemCompare(wx.Panel):
## Class ItemRequirements ## Class ItemRequirements
########################################################################### ###########################################################################
class ItemRequirements ( wx.Panel ): class ItemRequirements(wx.Panel):
def __init__(self, parent, stuff, item): def __init__(self, parent, stuff, item):
wx.Panel.__init__ (self, parent, style = wx.TAB_TRAVERSAL) wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
#itemId is set by the parent. # itemId is set by the parent.
self.romanNb = ["0","I","II","III","IV","V","VI","VII","VIII","IX","X"] self.romanNb = ["0", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"]
self.skillIdHistory=[] self.skillIdHistory = []
mainSizer = wx.BoxSizer( wx.VERTICAL ) mainSizer = wx.BoxSizer(wx.VERTICAL)
self.reqTree = wx.TreeCtrl(self, style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.NO_BORDER) self.reqTree = wx.TreeCtrl(self, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.NO_BORDER)
mainSizer.Add(self.reqTree, 1, wx.ALL|wx.EXPAND, 0) mainSizer.Add(self.reqTree, 1, wx.ALL | wx.EXPAND, 0)
self.SetSizer(mainSizer) self.SetSizer(mainSizer)
self.root = self.reqTree.AddRoot("WINRARZOR") self.root = self.reqTree.AddRoot("WINRARZOR")
@@ -720,17 +727,17 @@ class ItemRequirements ( wx.Panel ):
self.reqTree.SetImageList(self.imageList) self.reqTree.SetImageList(self.imageList)
skillBookId = self.imageList.Add(BitmapLoader.getBitmap("skill_small", "gui")) skillBookId = self.imageList.Add(BitmapLoader.getBitmap("skill_small", "gui"))
self.getFullSkillTree(item,self.root,skillBookId) self.getFullSkillTree(item, self.root, skillBookId)
self.reqTree.ExpandAll() self.reqTree.ExpandAll()
self.Layout() self.Layout()
def getFullSkillTree(self,parentSkill,parent,sbIconId): def getFullSkillTree(self, parentSkill, parent, sbIconId):
for skill, level in parentSkill.requiredSkills.iteritems(): for skill, level in parentSkill.requiredSkills.iteritems():
child = self.reqTree.AppendItem(parent,"%s %s" %(skill.name,self.romanNb[int(level)]), sbIconId) child = self.reqTree.AppendItem(parent, "%s %s" % (skill.name, self.romanNb[int(level)]), sbIconId)
if skill.ID not in self.skillIdHistory: if skill.ID not in self.skillIdHistory:
self.getFullSkillTree(skill,child,sbIconId) self.getFullSkillTree(skill, child, sbIconId)
self.skillIdHistory.append(skill.ID) self.skillIdHistory.append(skill.ID)
@@ -738,7 +745,7 @@ class ItemRequirements ( wx.Panel ):
## Class ItemEffects ## Class ItemEffects
########################################################################### ###########################################################################
class ItemEffects (wx.Panel): class ItemEffects(wx.Panel):
def __init__(self, parent, stuff, item): def __init__(self, parent, stuff, item):
wx.Panel.__init__(self, parent) wx.Panel.__init__(self, parent)
self.item = item self.item = item
@@ -761,17 +768,17 @@ class ItemEffects (wx.Panel):
def PopulateList(self): def PopulateList(self):
self.effectList.InsertColumn(0,"Name") self.effectList.InsertColumn(0, "Name")
self.effectList.InsertColumn(1,"Active") self.effectList.InsertColumn(1, "Active")
self.effectList.InsertColumn(2, "Type") self.effectList.InsertColumn(2, "Type")
if config.debug: if config.debug:
self.effectList.InsertColumn(3, "Run Time") self.effectList.InsertColumn(3, "Run Time")
self.effectList.InsertColumn(4,"ID") self.effectList.InsertColumn(4, "ID")
#self.effectList.SetColumnWidth(0,385) # self.effectList.SetColumnWidth(0,385)
self.effectList.setResizeColumn(0) self.effectList.setResizeColumn(0)
self.effectList.SetColumnWidth(1,50) self.effectList.SetColumnWidth(1, 50)
self.effectList.SetColumnWidth(2, 80) self.effectList.SetColumnWidth(2, 80)
if config.debug: if config.debug:
self.effectList.SetColumnWidth(3, 65) self.effectList.SetColumnWidth(3, 65)
@@ -840,7 +847,7 @@ class ItemEffects (wx.Panel):
""" """
import os import os
file = os.path.join(config.pyfaPath, "eos", "effects", "%s.py"%event.GetText().lower()) file = config.getPyfaPath("eos\\effects\\%s.py" % event.GetText().lower())
if not os.path.isfile(file): if not os.path.isfile(file):
open(file, 'a').close() open(file, 'a').close()
@@ -848,7 +855,7 @@ class ItemEffects (wx.Panel):
if 'wxMSW' in wx.PlatformInfo: if 'wxMSW' in wx.PlatformInfo:
os.startfile(file) os.startfile(file)
elif 'wxMac' in wx.PlatformInfo: elif 'wxMac' in wx.PlatformInfo:
os.system("open "+file) os.system("open " + file)
else: else:
import subprocess import subprocess
subprocess.call(["xdg-open", file]) subprocess.call(["xdg-open", file])
@@ -862,13 +869,15 @@ class ItemEffects (wx.Panel):
self.Thaw() self.Thaw()
event.Skip() event.Skip()
########################################################################### ###########################################################################
## Class ItemAffectedBy ## Class ItemAffectedBy
########################################################################### ###########################################################################
class ItemAffectedBy (wx.Panel): class ItemAffectedBy(wx.Panel):
ORDER = [Fit, Ship, Citadel, Mode, Module, Drone, Fighter, Implant, Booster, Skill] ORDER = [Fit, Ship, Citadel, Mode, Module, Drone, Fighter, Implant, Booster, Skill]
def __init__(self, parent, stuff, item): def __init__(self, parent, stuff, item):
wx.Panel.__init__(self, parent) wx.Panel.__init__(self, parent)
self.stuff = stuff self.stuff = stuff
@@ -884,33 +893,33 @@ class ItemAffectedBy (wx.Panel):
mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer = wx.BoxSizer(wx.VERTICAL)
self.affectedBy = wx.TreeCtrl(self, style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.NO_BORDER) self.affectedBy = wx.TreeCtrl(self, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.NO_BORDER)
mainSizer.Add(self.affectedBy, 1, wx.ALL|wx.EXPAND, 0) mainSizer.Add(self.affectedBy, 1, wx.ALL | wx.EXPAND, 0)
self.m_staticline = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) self.m_staticline = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add( self.m_staticline, 0, wx.EXPAND) mainSizer.Add(self.m_staticline, 0, wx.EXPAND)
bSizer = wx.BoxSizer( wx.HORIZONTAL ) bSizer = wx.BoxSizer(wx.HORIZONTAL)
self.toggleExpandBtn = wx.ToggleButton( self, wx.ID_ANY, u"Expand All", wx.DefaultPosition, wx.DefaultSize, 0 ) self.toggleExpandBtn = wx.ToggleButton(self, wx.ID_ANY, u"Expand All", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add( self.toggleExpandBtn, 0, wx.ALIGN_CENTER_VERTICAL) bSizer.Add(self.toggleExpandBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.toggleNameBtn = wx.ToggleButton( self, wx.ID_ANY, u"Toggle Names", wx.DefaultPosition, wx.DefaultSize, 0 ) self.toggleNameBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle Names", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add( self.toggleNameBtn, 0, wx.ALIGN_CENTER_VERTICAL) bSizer.Add(self.toggleNameBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.toggleViewBtn = wx.ToggleButton( self, wx.ID_ANY, u"Toggle View", wx.DefaultPosition, wx.DefaultSize, 0 ) self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle View", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add( self.toggleViewBtn, 0, wx.ALIGN_CENTER_VERTICAL) bSizer.Add(self.toggleViewBtn, 0, wx.ALIGN_CENTER_VERTICAL)
if stuff is not None: if stuff is not None:
self.refreshBtn = wx.Button( self, wx.ID_ANY, u"Refresh", wx.DefaultPosition, wx.DefaultSize, wx.BU_EXACTFIT ) self.refreshBtn = wx.Button(self, wx.ID_ANY, u"Refresh", wx.DefaultPosition, wx.DefaultSize, wx.BU_EXACTFIT)
bSizer.Add( self.refreshBtn, 0, wx.ALIGN_CENTER_VERTICAL) bSizer.Add(self.refreshBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.refreshBtn.Bind( wx.EVT_BUTTON, self.RefreshTree ) self.refreshBtn.Bind(wx.EVT_BUTTON, self.RefreshTree)
self.toggleNameBtn.Bind(wx.EVT_TOGGLEBUTTON,self.ToggleNameMode) self.toggleNameBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleNameMode)
self.toggleExpandBtn.Bind(wx.EVT_TOGGLEBUTTON,self.ToggleExpand) self.toggleExpandBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleExpand)
self.toggleViewBtn.Bind(wx.EVT_TOGGLEBUTTON,self.ToggleViewMode) self.toggleViewBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleViewMode)
mainSizer.Add( bSizer, 0, wx.ALIGN_RIGHT) mainSizer.Add(bSizer, 0, wx.ALIGN_RIGHT)
self.SetSizer(mainSizer) self.SetSizer(mainSizer)
self.PopulateTree() self.PopulateTree()
self.Layout() self.Layout()
@@ -950,7 +959,7 @@ class ItemAffectedBy (wx.Panel):
self.Thaw() self.Thaw()
def ToggleExpand(self,event): def ToggleExpand(self, event):
self.expand *= -1 self.expand *= -1
self.ExpandCollapseTree() self.ExpandCollapseTree()
@@ -1059,7 +1068,8 @@ class ItemAffectedBy (wx.Panel):
else: else:
item = afflictor.item 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 # Make sure projected fits are on top
rootOrder = container.keys() rootOrder = container.keys()
@@ -1135,7 +1145,6 @@ class ItemAffectedBy (wx.Panel):
treeItem = self.affectedBy.AppendItem(child, display, itemIcon) treeItem = self.affectedBy.AppendItem(child, display, itemIcon)
self.affectedBy.SetPyData(treeItem, afflictor) self.affectedBy.SetPyData(treeItem, afflictor)
def buildModuleView(self, root): def buildModuleView(self, root):
# We first build a usable dictionary of items. The key is either a fit # We first build a usable dictionary of items. The key is either a fit
# if the afflictions stem from a projected fit, or self.stuff if they # if the afflictions stem from a projected fit, or self.stuff if they
@@ -1259,9 +1268,10 @@ class ItemAffectedBy (wx.Panel):
else: else:
penalized = "" penalized = ""
attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized, attrIcon)) attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier,
attrAmount, penalized, attrIcon))
attrSorted = sorted(attributes, key = lambda attribName: attribName[0]) attrSorted = sorted(attributes, key=lambda attribName: attribName[0])
for attr in attrSorted: for attr in attrSorted:
attrName, displayName, attrModifier, attrAmount, penalized, attrIcon = attr attrName, displayName, attrModifier, attrAmount, penalized, attrIcon = attr

View File

@@ -1,14 +1,17 @@
import os
import base64 import base64
import logging
import os
import re
import time import time
import zlib import zlib
import requests import requests
from requests.adapters import HTTPAdapter
from . import version import config
from compat import bytes_, text_ from compat import bytes_, text_
from errors import APIException from errors import APIException
from requests.adapters import HTTPAdapter from . import version
try: try:
from urllib.parse import urlparse, urlunparse, parse_qsl from urllib.parse import urlparse, urlunparse, parse_qsl
@@ -24,9 +27,7 @@ try:
from urllib.parse import quote from urllib.parse import quote
except ImportError: # pragma: no cover except ImportError: # pragma: no cover
from urllib import quote from urllib import quote
import logging
import re
import config
logger = logging.getLogger("pycrest.eve") logger = logging.getLogger("pycrest.eve")
cache_re = re.compile(r'max-age=([0-9]+)') cache_re = re.compile(r'max-age=([0-9]+)')
@@ -51,7 +52,13 @@ class FileCache(APICache):
os.mkdir(self.path, 0o700) os.mkdir(self.path, 0o700)
def _getpath(self, key): def _getpath(self, key):
return os.path.join(self.path, str(hash(key)) + '.cache') path = os.path.join(self.path, str(hash(key)) + '.cache')
if type(path) == str: # leave unicode ones alone
try:
path = path.decode('utf8')
except UnicodeDecodeError:
path = path.decode('windows-1252')
return path
def put(self, key, value): def put(self, key, value):
with open(self._getpath(key), 'wb') as f: with open(self._getpath(key), 'wb') as f:
@@ -111,7 +118,7 @@ class APIConnection(object):
}) })
session.headers.update(additional_headers) session.headers.update(additional_headers)
session.mount('https://public-crest.eveonline.com', session.mount('https://public-crest.eveonline.com',
HTTPAdapter()) HTTPAdapter())
self._session = session self._session = session
if cache: if cache:
if isinstance(cache, APICache): if isinstance(cache, APICache):
@@ -249,19 +256,18 @@ class EVE(APIConnection):
def temptoken_authorize(self, access_token=None, expires_in=0, refresh_token=None): def temptoken_authorize(self, access_token=None, expires_in=0, refresh_token=None):
self.set_auth_values({'access_token': access_token, self.set_auth_values({'access_token': access_token,
'refresh_token': refresh_token, 'refresh_token': refresh_token,
'expires_in': expires_in}) 'expires_in': expires_in})
class AuthedConnection(EVE): class AuthedConnection(EVE):
def __call__(self): def __call__(self):
if not self._data: if not self._data:
self._data = APIObject(self.get(self._endpoint), self) self._data = APIObject(self.get(self._endpoint), self)
return self._data return self._data
def whoami(self): def whoami(self):
#if 'whoami' not in self._cache: # if 'whoami' not in self._cache:
# print "Setting this whoami cache" # print "Setting this whoami cache"
# self._cache['whoami'] = self.get("%s/verify" % self._oauth_endpoint) # self._cache['whoami'] = self.get("%s/verify" % self._oauth_endpoint)
return self.get("%s/verify" % self._oauth_endpoint) return self.get("%s/verify" % self._oauth_endpoint)
@@ -281,6 +287,7 @@ class AuthedConnection(EVE):
self.refr_authorize(self.refresh_token) self.refr_authorize(self.refresh_token)
return self._session.delete(resource, params=params) return self._session.delete(resource, params=params)
class APIObject(object): class APIObject(object):
def __init__(self, parent, connection): def __init__(self, parent, connection):
self._dict = {} self._dict = {}

View File

@@ -1,4 +1,4 @@
#=============================================================================== # ===============================================================================
# Copyright (C) 2010 Diego Duclos # Copyright (C) 2010 Diego Duclos
# #
# This file is part of pyfa. # This file is part of pyfa.
@@ -15,33 +15,41 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>. # along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#=============================================================================== # ===============================================================================
import cPickle import cPickle
import os.path import os.path
import config
import urllib2 import urllib2
import config
class SettingsProvider(): class SettingsProvider():
BASE_PATH = os.path.join(config.savePath, "settings") BASE_PATH = config.getSavePath("settings")
settings = {} settings = {}
_instance = None _instance = None
@classmethod @classmethod
def getInstance(cls): def getInstance(cls):
if cls._instance == None: if cls._instance is None:
cls._instance = SettingsProvider() cls._instance = SettingsProvider()
return cls._instance return cls._instance
def __init__(self): def __init__(self):
if not os.path.exists(self.BASE_PATH): if not os.path.exists(self.BASE_PATH):
os.mkdir(self.BASE_PATH); os.mkdir(self.BASE_PATH)
def getSettings(self, area, defaults=None): def getSettings(self, area, defaults=None):
s = self.settings.get(area) s = self.settings.get(area)
if s is None: if s is None:
p = os.path.join(self.BASE_PATH, area) p = os.path.join(self.BASE_PATH, area)
if type(p) == str: # leave unicode ones alone
try:
p = p.decode('utf8')
except UnicodeDecodeError:
p = p.decode('windows-1252')
if not os.path.exists(p): if not os.path.exists(p):
info = {} info = {}
@@ -71,6 +79,7 @@ class SettingsProvider():
for settings in self.settings.itervalues(): for settings in self.settings.itervalues():
settings.save() settings.save()
class Settings(): class Settings():
def __init__(self, location, info): def __init__(self, location, info):
self.location = location self.location = location
@@ -115,13 +124,13 @@ class NetworkSettings():
_instance = None _instance = None
# constants for serviceNetworkDefaultSettings["mode"] parameter # 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_AUTODETECT = 1 # 1 - Auto-detected proxy settings
PROXY_MODE_MANUAL = 2 # 2 - Manual proxy settings PROXY_MODE_MANUAL = 2 # 2 - Manual proxy settings
@classmethod @classmethod
def getInstance(cls): def getInstance(cls):
if cls._instance == None: if cls._instance is None:
cls._instance = NetworkSettings() cls._instance = NetworkSettings()
return cls._instance return cls._instance
@@ -184,12 +193,11 @@ class NetworkSettings():
def setAccess(self, access): def setAccess(self, access):
self.serviceNetworkSettings["access"] = access self.serviceNetworkSettings["access"] = access
def autodetect(self): @staticmethod
def autodetect():
proxy = None proxy = None
proxAddr = proxPort = ""
proxydict = urllib2.ProxyHandler().proxies proxydict = urllib2.ProxyHandler().proxies
txt = "Auto-detected: "
validPrefixes = ("http", "https") validPrefixes = ("http", "https")
@@ -237,23 +245,26 @@ class NetworkSettings():
self.serviceNetworkSettings["password"] = password self.serviceNetworkSettings["password"] = password
""" """
Settings used by the HTML export feature. Settings used by the HTML export feature.
""" """
class HTMLExportSettings(): class HTMLExportSettings():
_instance = None _instance = None
@classmethod @classmethod
def getInstance(cls): def getInstance(cls):
if cls._instance == None: if cls._instance is None:
cls._instance = HTMLExportSettings() cls._instance = HTMLExportSettings()
return cls._instance return cls._instance
def __init__(self): def __init__(self):
serviceHTMLExportDefaultSettings = {"enabled": False, "path": config.pyfaPath + os.sep + 'pyfaFits.html', "minimal": False } serviceHTMLExportDefaultSettings = {"enabled": False, "path": config.pyfaPath + os.sep + 'pyfaFits.html',
self.serviceHTMLExportSettings = SettingsProvider.getInstance().getSettings("pyfaServiceHTMLExportSettings", serviceHTMLExportDefaultSettings) "minimal": False}
self.serviceHTMLExportSettings = SettingsProvider.getInstance().getSettings("pyfaServiceHTMLExportSettings",
serviceHTMLExportDefaultSettings)
def getEnabled(self): def getEnabled(self):
return self.serviceHTMLExportSettings["enabled"] return self.serviceHTMLExportSettings["enabled"]
@@ -261,29 +272,30 @@ class HTMLExportSettings():
def setEnabled(self, enabled): def setEnabled(self, enabled):
self.serviceHTMLExportSettings["enabled"] = enabled self.serviceHTMLExportSettings["enabled"] = enabled
def getMinimalEnabled(self): def getMinimalEnabled(self):
return self.serviceHTMLExportSettings["minimal"] return self.serviceHTMLExportSettings["minimal"]
def setMinimalEnabled(self, minimal): def setMinimalEnabled(self, minimal):
self.serviceHTMLExportSettings["minimal"] = minimal self.serviceHTMLExportSettings["minimal"] = minimal
def getPath(self): def getPath(self):
return self.serviceHTMLExportSettings["path"] return self.serviceHTMLExportSettings["path"]
def setPath(self, path): def setPath(self, path):
self.serviceHTMLExportSettings["path"] = path self.serviceHTMLExportSettings["path"] = path
""" """
Settings used by update notification Settings used by update notification
""" """
class UpdateSettings(): class UpdateSettings():
_instance = None _instance = None
@classmethod @classmethod
def getInstance(cls): def getInstance(cls):
if cls._instance == None: if cls._instance is None:
cls._instance = UpdateSettings() cls._instance = UpdateSettings()
return cls._instance return cls._instance
@@ -293,8 +305,9 @@ class UpdateSettings():
# Updates are completely suppressed via network settings # Updates are completely suppressed via network settings
# prerelease - If True, suppress prerelease notifications # prerelease - If True, suppress prerelease notifications
# version - Set to release tag that user does not want notifications for # version - Set to release tag that user does not want notifications for
serviceUpdateDefaultSettings = {"prerelease": True, 'version': None } serviceUpdateDefaultSettings = {"prerelease": True, 'version': None}
self.serviceUpdateSettings = SettingsProvider.getInstance().getSettings("pyfaServiceUpdateSettings", serviceUpdateDefaultSettings) self.serviceUpdateSettings = SettingsProvider.getInstance().getSettings("pyfaServiceUpdateSettings",
serviceUpdateDefaultSettings)
def get(self, type): def get(self, type):
return self.serviceUpdateSettings[type] return self.serviceUpdateSettings[type]
@@ -302,6 +315,7 @@ class UpdateSettings():
def set(self, type, value): def set(self, type, value):
self.serviceUpdateSettings[type] = value self.serviceUpdateSettings[type] = value
class CRESTSettings(): class CRESTSettings():
_instance = None _instance = None
@@ -313,13 +327,13 @@ class CRESTSettings():
return cls._instance return cls._instance
def __init__(self): def __init__(self):
# mode # mode
# 0 - Implicit authentication # 0 - Implicit authentication
# 1 - User-supplied client details # 1 - User-supplied client details
serviceCRESTDefaultSettings = {"mode": 0, "server": 0, "clientID": "", "clientSecret": "", "timeout": 60} 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): def get(self, type):
return self.serviceCRESTSettings[type] return self.serviceCRESTSettings[type]
@@ -327,5 +341,4 @@ class CRESTSettings():
def set(self, type, value): def set(self, type, value):
self.serviceCRESTSettings[type] = value self.serviceCRESTSettings[type] = value
# @todo: migrate fit settings (from fit service) here? # @todo: migrate fit settings (from fit service) here?