Add html export support

This commit is contained in:
Erik Snoeijs
2012-07-08 13:45:45 +02:00
committed by cncfanatics
parent 447e0c9349
commit 3270432f0b
5 changed files with 391 additions and 184 deletions

View File

@@ -1 +1 @@
__all__ = ["pyfaGlobalPreferences"] __all__ = ["pyfaGlobalPreferences","pyfaHTMLExportPreferences"]

View File

@@ -0,0 +1,74 @@
import wx
import service
import urllib2
import os
from gui.preferenceView import PreferenceView
from gui import bitmapLoader
import gui.mainFrame
import service
import gui.globalEvents as GE
class PFHTMLExportPref ( PreferenceView):
title = "Pyfa HTML Export Options"
desc = """Turning this feature on will create a HTML file at the specified location
with all your fits in it. If you browse to this HTML file from the
in-game browser you can easily view and import your fits by clicking on them.
The file will be updated every time a fit changes or gets added.
"""
def populatePanel( self, panel ):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.HTMLExportSettings = service.settings.HTMLExportSettings.getInstance()
self.dirtySettings = False
mainSizer = wx.BoxSizer( wx.VERTICAL )
self.stTitle = wx.StaticText( panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0 )
self.stTitle.Wrap( -1 )
self.stTitle.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
mainSizer.Add( self.stTitle, 0, wx.ALL, 5 )
self.stDesc = wx.StaticText( panel, wx.ID_ANY, self.desc, wx.DefaultPosition, wx.DefaultSize, 0 )
mainSizer.Add( self.stDesc, 0, wx.ALL, 5 )
self.exportEnabled = wx.CheckBox( panel, wx.ID_ANY, u"Enable HTML export", wx.DefaultPosition, wx.DefaultSize, 0 )
self.exportEnabled.SetValue(self.HTMLExportSettings.getEnabled())
self.exportEnabled.Bind(wx.EVT_CHECKBOX, self.OnExportEnabledChange)
mainSizer.Add( self.exportEnabled, 0, wx.ALL|wx.EXPAND, 5 )
self.PathLinkCtrl = wx.HyperlinkCtrl( panel, wx.ID_ANY, str(self.HTMLExportSettings.getPath()), 'file:///' + str(self.HTMLExportSettings.getPath()), wx.DefaultPosition, wx.DefaultSize, wx.HL_ALIGN_LEFT|wx.NO_BORDER|wx.HL_CONTEXTMENU )
mainSizer.Add( self.PathLinkCtrl, 0, wx.ALL|wx.EXPAND, 5)
self.fileSelectDialog = wx.FileDialog(None, "Save Fitting As...", wildcard = "EvE IGB HTML fitting file (*.html)|*.html", style = wx.FD_SAVE)
self.fileSelectDialog.SetPath(self.HTMLExportSettings.getPath())
self.fileSelectDialog.SetFilename(os.path.basename(self.HTMLExportSettings.getPath()));
self.fileSelectButton = wx.Button(panel, -1, "Set export destination", pos=(0,0))
self.fileSelectButton.Bind(wx.EVT_BUTTON, self.selectHTMLExportFilePath)
mainSizer.Add( self.fileSelectButton, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
panel.SetSizer( mainSizer )
panel.Layout()
def setPathLinkCtrlValues(self, path):
self.PathLinkCtrl.SetLabel(self.HTMLExportSettings.getPath())
self.PathLinkCtrl.SetURL('file:///' + self.HTMLExportSettings.getPath())
self.PathLinkCtrl.SetSize(wx.DefaultSize);
self.PathLinkCtrl.Refresh()
def selectHTMLExportFilePath(self, event):
if self.fileSelectDialog.ShowModal() == wx.ID_OK:
self.HTMLExportSettings.setPath(self.fileSelectDialog.GetPath())
self.dirtySettings = True
self.setPathLinkCtrlValues(self.HTMLExportSettings.getPath())
def OnExportEnabledChange(self, event):
self.HTMLExportSettings.setEnabled(self.exportEnabled.GetValue())
def getImage(self):
return bitmapLoader.getBitmap("pyfa64", "icons")
PFHTMLExportPref.register()

View File

@@ -30,6 +30,7 @@ from eos.types import Slot
from gui.builtinViewColumns.state import State from gui.builtinViewColumns.state import State
from gui import bitmapLoader from gui import bitmapLoader
import gui.builtinViews.emptyView import gui.builtinViews.emptyView
from gui.utils.exportHtml import exportHtml
import gui.globalEvents as GE import gui.globalEvents as GE
@@ -374,13 +375,17 @@ class FittingView(d.Display):
if self.activeFitID is not None and self.activeFitID == event.fitID: if self.activeFitID is not None and self.activeFitID == event.fitID:
self.generateMods() self.generateMods()
self.refresh(self.mods) self.refresh(self.mods)
exportHtml.getInstance().refreshFittingHTMl()
self.Show(self.activeFitID is not None and self.activeFitID == event.fitID) self.Show(self.activeFitID is not None and self.activeFitID == event.fitID)
except wx._core.PyDeadObjectError: except wx._core.PyDeadObjectError:
pass pass
finally: finally:
event.Skip() event.Skip()
def scheduleMenu(self, event): def scheduleMenu(self, event):
event.Skip() event.Skip()
if self.getColumn(event.Position) != self.getColIndex(State): if self.getColumn(event.Position) != self.getColIndex(State):

95
gui/utils/exportHtml.py Normal file
View File

@@ -0,0 +1,95 @@
import threading
import time
import service
class exportHtml():
_instance = None
@classmethod
def getInstance(cls):
if cls._instance == None:
cls._instance = exportHtml()
return cls._instance
def __init__(self):
self.thread = exportHtmlThread()
def refreshFittingHTMl(self):
settings = service.settings.HTMLExportSettings.getInstance()
if (settings.getEnabled()):
self.thread.stop()
self.thread = exportHtmlThread()
self.thread.start()
class exportHtmlThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.stopRunning = False
def stop(self):
self.stopRunning = True
def run(self):
# wait 1 second just in case a lot of modifications get made
time.sleep(1);
if self.stopRunning:
return;
sMarket = service.Market.getInstance()
sFit = service.Fit.getInstance()
settings = service.settings.HTMLExportSettings.getInstance()
HTML = """
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>
</head>
<body>
<div id="canvas" data-role="page">
<div data-role="header">
<h1>PyFa fits</h1>
</div>
<div data-role="content">
"""
HTML += '<ul data-role="listview" data-inset="true" data-filter="true">';
categoryList = [];
self.categoryList = list(sMarket.getShipRoot())
self.categoryList.sort(key=lambda ship: ship.name)
for shipType in self.categoryList:
ships = sMarket.getShipList(shipType.ID)
for ship in ships:
HTMLship = '<li><h2>' + ship.name + '</h2><ul>'
fits = sFit.getFitsWithShip(ship.ID)
for fit in fits:
if self.stopRunning:
return;
dnaFit = sFit.exportDna(fit[0])
HTMLship += "<li><a href=\"javascript:CCPEVE.showFitting('" + dnaFit + "');\" >" + fit[1] + "</a></li>"
HTMLship += "</ul></li>"
if len(fits) > 0:
HTML += HTMLship
HTML += """
</ul>
</div>
</div>
</body>
"""
try:
FILE = open(settings.getPath(), "w")
FILE.write(HTML);
FILE.close();
except IOError:
print "Failed to write to " + settings.getPath()
pass

View File

@@ -1,182 +1,215 @@
#=============================================================================== #===============================================================================
# Copyright (C) 2010 Diego Duclos # Copyright (C) 2010 Diego Duclos
# #
# This file is part of pyfa. # This file is part of pyfa.
# #
# pyfa is free software: you can redistribute it and/or modify # pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# pyfa is distributed in the hope that it will be useful, # pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# 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 config
import urllib2 import urllib2
class SettingsProvider(): class SettingsProvider():
BASE_PATH = os.path.join(config.savePath, "settings") BASE_PATH = os.path.join(config.savePath, "settings")
settings = {} settings = {}
_instance = None _instance = None
@classmethod @classmethod
def getInstance(cls): def getInstance(cls):
if cls._instance == None: if cls._instance == 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 not os.path.exists(p): if not os.path.exists(p):
info = {} info = {}
if defaults: if defaults:
for item in defaults: for item in defaults:
info[item] = defaults[item] info[item] = defaults[item]
else: else:
try: try:
f = open(p, "rb") f = open(p, "rb")
info = cPickle.load(f) info = cPickle.load(f)
for item in defaults: for item in defaults:
if item not in info: if item not in info:
info[item] = defaults[item] info[item] = defaults[item]
except: except:
info = {} info = {}
if defaults: if defaults:
for item in defaults: for item in defaults:
info[item] = defaults[item] info[item] = defaults[item]
self.settings[area] = s = Settings(p, info) self.settings[area] = s = Settings(p, info)
return s return s
def saveAll(self): def saveAll(self):
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
self.info = info self.info = info
def save(self): def save(self):
f = open(self.location, "wb") f = open(self.location, "wb")
cPickle.dump(self.info, f, cPickle.HIGHEST_PROTOCOL) cPickle.dump(self.info, f, cPickle.HIGHEST_PROTOCOL)
def __getitem__(self, k): def __getitem__(self, k):
return self.info[k] return self.info[k]
def __setitem__(self, k, v): def __setitem__(self, k, v):
self.info[k] = v self.info[k] = v
def __iter__(self): def __iter__(self):
return self.info.__iter__() return self.info.__iter__()
def iterkeys(self): def iterkeys(self):
return self.info.iterkeys() return self.info.iterkeys()
def itervalues(self): def itervalues(self):
return self.info.itervalues() return self.info.itervalues()
def iteritems(self): def iteritems(self):
return self.info.iteritems() return self.info.iteritems()
def keys(self): def keys(self):
return self.info.keys() return self.info.keys()
def values(self): def values(self):
return self.info.values() return self.info.values()
def items(self): def items(self):
return self.info.items() return self.info.items()
class ProxySettings():
_instance = None
@classmethod class ProxySettings():
def getInstance(cls): _instance = None
if cls._instance == None: @classmethod
cls._instance = ProxySettings() def getInstance(cls):
if cls._instance == None:
return cls._instance cls._instance = ProxySettings()
def __init__(self): return cls._instance
# mode def __init__(self):
# 0 - No proxy
# 1 - Auto-detected proxy settings # mode
# 2 - Manual proxy settings # 0 - No proxy
serviceProxyDefaultSettings = {"mode": 1, "type": "https", "address": "", "port": ""} # 1 - Auto-detected proxy settings
# 2 - Manual proxy settings
self.serviceProxySettings = SettingsProvider.getInstance().getSettings("pyfaServiceProxySettings", serviceProxyDefaultSettings) serviceProxyDefaultSettings = {"mode": 1, "type": "https", "address": "", "port": ""}
def getMode(self): self.serviceProxySettings = SettingsProvider.getInstance().getSettings("pyfaServiceProxySettings", serviceProxyDefaultSettings)
return self.serviceProxySettings["mode"]
def getMode(self):
def getAddress(self): return self.serviceProxySettings["mode"]
return self.serviceProxySettings["address"]
def getAddress(self):
def getPort(self): return self.serviceProxySettings["address"]
return self.serviceProxySettings["port"]
def getPort(self):
def getType(self): return self.serviceProxySettings["port"]
return self.serviceProxySettings["type"]
def getType(self):
def setMode(self, mode): return self.serviceProxySettings["type"]
self.serviceProxySettings["mode"] = mode
def setMode(self, mode):
def setAddress(self, addr): self.serviceProxySettings["mode"] = mode
self.serviceProxySettings["address"] = addr
def setAddress(self, addr):
def setPort(self, port): self.serviceProxySettings["address"] = addr
self.serviceProxySettings["port"] = port
def setPort(self, port):
def setType(self, type): self.serviceProxySettings["port"] = port
self.serviceProxySettings["type"] = type
def setType(self, type):
def autodetect(self): self.serviceProxySettings["type"] = type
proxy = None def autodetect(self):
proxAddr = proxPort = ""
proxydict = urllib2.ProxyHandler().proxies proxy = None
txt = "Auto-detected: " proxAddr = proxPort = ""
proxydict = urllib2.ProxyHandler().proxies
validPrefixes = ("http", "https") txt = "Auto-detected: "
for prefix in validPrefixes: validPrefixes = ("http", "https")
if not prefix in proxydict:
continue for prefix in validPrefixes:
proxyline = proxydict[prefix] if not prefix in proxydict:
proto = "{0}://".format(prefix) continue
if proxyline[:len(proto)] == proto: proxyline = proxydict[prefix]
proxyline = proxyline[len(proto):] proto = "{0}://".format(prefix)
proxAddr, proxPort = proxyline.split(":") if proxyline[:len(proto)] == proto:
proxPort = int(proxPort.rstrip("/")) proxyline = proxyline[len(proto):]
proxy = (proxAddr, proxPort) proxAddr, proxPort = proxyline.split(":")
break proxPort = int(proxPort.rstrip("/"))
proxy = (proxAddr, proxPort)
return proxy break
def getProxySettings(self): return proxy
if self.getMode() == 0: def getProxySettings(self):
return None
if self.getMode() == 1: if self.getMode() == 0:
return self.autodetect() return None
if self.getMode() == 2: if self.getMode() == 1:
return (self.getAddress(), int(self.getPort())) return self.autodetect()
if self.getMode() == 2:
return (self.getAddress(), int(self.getPort()))
"""
Settings used by the HTML export feature.
"""
class HTMLExportSettings():
_instance = None
@classmethod
def getInstance(cls):
if cls._instance == None:
cls._instance = HTMLExportSettings()
return cls._instance
def __init__(self):
serviceHTMLExportDefaultSettings = {"enabled": False, "path": config.pyfaPath + os.sep + 'pyfaFits.html' }
self.serviceHTMLExportSettings = SettingsProvider.getInstance().getSettings("pyfaServiceHTMLExportSettings", serviceHTMLExportDefaultSettings)
def getEnabled(self):
return self.serviceHTMLExportSettings["enabled"]
def setEnabled(self, enabled):
self.serviceHTMLExportSettings["enabled"] = enabled
def getPath(self):
return self.serviceHTMLExportSettings["path"]
def setPath(self, path):
self.serviceHTMLExportSettings["path"] = path