Merge pull request #2 from MartyMacGyver/add_character_importer
Added the character import enhancement (reads native EVE CCP XML), skill exporter, cleanups
This commit is contained in:
@@ -17,6 +17,7 @@ version = "1.1.15"
|
||||
tag = "git"
|
||||
expansionName = "Odyssey"
|
||||
expansionVersion = "1.0"
|
||||
evemonMinVersion = "4081"
|
||||
|
||||
pyfaPath = None
|
||||
savePath = None
|
||||
|
||||
@@ -126,6 +126,9 @@ class Character(object):
|
||||
return
|
||||
|
||||
sheet = auth.character(charID).CharacterSheet()
|
||||
apiUpdateCharSheet(sheet)
|
||||
|
||||
def apiUpdateCharSheet(self, sheet):
|
||||
del self.__skills[:]
|
||||
self.__skillIdMap.clear()
|
||||
for skillRow in sheet.skills:
|
||||
|
||||
@@ -42,7 +42,7 @@ The file will be updated every time a fit changes or gets added.
|
||||
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 = 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()));
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ class FittingViewDrop(wx.PyDropTarget):
|
||||
def __init__(self, dropFn):
|
||||
wx.PyDropTarget.__init__(self)
|
||||
self.dropFn = dropFn
|
||||
# this is really transferring an EvE itemID
|
||||
# this is really transferring an EVE itemID
|
||||
self.dropData = wx.PyTextDataObject()
|
||||
self.SetDataObject(self.dropData)
|
||||
|
||||
|
||||
@@ -30,9 +30,6 @@ from wx.lib.buttons import GenBitmapButton
|
||||
import sys
|
||||
import gui.globalEvents as GE
|
||||
|
||||
CharListUpdated, CHAR_LIST_UPDATED = wx.lib.newevent.NewEvent()
|
||||
CharChanged, CHAR_CHANGED = wx.lib.newevent.NewEvent()
|
||||
|
||||
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,
|
||||
@@ -136,7 +133,7 @@ class CharacterEditor(wx.Frame):
|
||||
|
||||
def editingFinished(self, event):
|
||||
del self.disableWin
|
||||
wx.PostEvent(self.mainFrame, CharListUpdated())
|
||||
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
|
||||
self.Destroy()
|
||||
|
||||
def registerEvents(self):
|
||||
@@ -145,7 +142,7 @@ class CharacterEditor(wx.Frame):
|
||||
|
||||
def closeEvent(self, event):
|
||||
del self.disableWin
|
||||
wx.PostEvent(self.mainFrame, CharListUpdated())
|
||||
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
|
||||
self.Destroy()
|
||||
|
||||
def restrict(self):
|
||||
@@ -182,7 +179,7 @@ class CharacterEditor(wx.Frame):
|
||||
else:
|
||||
self.unrestrict()
|
||||
|
||||
wx.PostEvent(self, CharChanged())
|
||||
wx.PostEvent(self, GE.CharChanged())
|
||||
if event is not None:
|
||||
event.Skip()
|
||||
|
||||
@@ -253,7 +250,7 @@ class CharacterEditor(wx.Frame):
|
||||
self.unrestrict()
|
||||
self.btnSave.SetLabel("Copy")
|
||||
self.rename(None)
|
||||
wx.PostEvent(self, CharChanged())
|
||||
wx.PostEvent(self, GE.CharChanged())
|
||||
|
||||
def delete(self, event):
|
||||
cChar = service.Character.getInstance()
|
||||
@@ -265,7 +262,7 @@ class CharacterEditor(wx.Frame):
|
||||
if cChar.getCharName(newSelection) in ("All 0", "All 5"):
|
||||
self.restrict()
|
||||
|
||||
wx.PostEvent(self, CharChanged())
|
||||
wx.PostEvent(self, GE.CharChanged())
|
||||
|
||||
def Destroy(self):
|
||||
cFit = service.Fit.getInstance()
|
||||
@@ -452,7 +449,7 @@ class ImplantsTreeView (wx.Panel):
|
||||
self.btnRemove.Bind(wx.EVT_BUTTON, self.removeImplant)
|
||||
|
||||
#Bind the change of a character*
|
||||
self.Parent.Parent.Bind(CHAR_CHANGED, self.charChanged)
|
||||
self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.charChanged)
|
||||
self.Enable(False)
|
||||
self.Layout()
|
||||
|
||||
@@ -537,7 +534,7 @@ class AvailableImplantsView(d.Display):
|
||||
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)
|
||||
self.Parent.Parent.Bind(CHAR_CHANGED, self.charChanged)
|
||||
self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.charChanged)
|
||||
|
||||
self.apiUrlCreatePredefined = u"https://community.eveonline.com/support/api-key/update/"
|
||||
self.apiUrlKeyList = u"https://community.eveonline.com/support/api-key/"
|
||||
|
||||
@@ -48,7 +48,7 @@ class CharacterSelection(wx.Panel):
|
||||
|
||||
self.skillReqsStaticBitmap.SetBitmap(self.cleanSkills)
|
||||
self.Bind(wx.EVT_CHOICE, self.charChanged)
|
||||
self.mainFrame.Bind(ce.CHAR_LIST_UPDATED, self.refreshCharacterList)
|
||||
self.mainFrame.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList)
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
|
||||
|
||||
# panelSize = wx.Size(-1,30)
|
||||
|
||||
@@ -31,9 +31,9 @@ class CopySelectDialog(wx.Dialog):
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
copyFormats = [u"EFT", u"EFT (Implants)", u"XML", u"DNA"]
|
||||
copyFormatTooltips = {CopySelectDialog.copyFormatEft: u"Eve Fitting Tool text format",
|
||||
CopySelectDialog.copyFormatEftImps: u"Eve Fitting Tool text format",
|
||||
CopySelectDialog.copyFormatXml: u"EvE native XML format",
|
||||
copyFormatTooltips = {CopySelectDialog.copyFormatEft: u"EFT text format",
|
||||
CopySelectDialog.copyFormatEftImps: u"EFT text format",
|
||||
CopySelectDialog.copyFormatXml: u"EVE native XML format",
|
||||
CopySelectDialog.copyFormatDna: u"A one-line text format"}
|
||||
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)
|
||||
|
||||
@@ -30,7 +30,7 @@ class DroneViewDrop(wx.PyDropTarget):
|
||||
def __init__(self, dropFn):
|
||||
wx.PyDropTarget.__init__(self)
|
||||
self.dropFn = dropFn
|
||||
# this is really transferring an EvE itemID
|
||||
# this is really transferring an EVE itemID
|
||||
self.dropData = wx.PyTextDataObject()
|
||||
self.SetDataObject(self.dropData)
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ class GangView ( ScrolledPanel ):
|
||||
self.SetupScrolling()
|
||||
self.Disable()
|
||||
|
||||
self.mainFrame.Bind(CharEditor.CHAR_LIST_UPDATED, self.RefreshCharacterList)
|
||||
self.mainFrame.Bind(GE.CHAR_LIST_UPDATED, self.RefreshCharacterList)
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitSelected)
|
||||
self.mainFrame.Bind(gui.shipBrowser.EVT_FIT_RENAMED, self.fitRenamed)
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import wx.lib.newevent
|
||||
|
||||
FitChanged, FIT_CHANGED = wx.lib.newevent.NewEvent()
|
||||
FitChanged, FIT_CHANGED = wx.lib.newevent.NewEvent()
|
||||
CharListUpdated, CHAR_LIST_UPDATED = wx.lib.newevent.NewEvent()
|
||||
CharChanged, CHAR_CHANGED = wx.lib.newevent.NewEvent()
|
||||
|
||||
@@ -32,6 +32,7 @@ import config
|
||||
import gui.aboutData
|
||||
import gui.chromeTabs
|
||||
import gui.utils.animUtils as animUtils
|
||||
import gui.globalEvents as GE
|
||||
|
||||
from gui import bitmapLoader
|
||||
from gui.mainMenuBar import MainMenuBar
|
||||
@@ -264,7 +265,7 @@ class MainFrame(wx.Frame):
|
||||
self,
|
||||
"Open One Or More Fitting Files",
|
||||
wildcard = "EFT text fitting files (*.cfg)|*.cfg|" \
|
||||
"EvE XML fitting files (*.xml)|*.xml|" \
|
||||
"EVE XML fitting files (*.xml)|*.xml|" \
|
||||
"All Files (*)|*",
|
||||
style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE)
|
||||
if (dlg.ShowModal() == wx.ID_OK):
|
||||
@@ -273,7 +274,6 @@ class MainFrame(wx.Frame):
|
||||
dlg.Destroy()
|
||||
self.waitDialog.ShowModal()
|
||||
|
||||
|
||||
def importCallback(self, fits):
|
||||
self.waitDialog.Destroy()
|
||||
sFit = service.Fit.getInstance()
|
||||
@@ -291,7 +291,7 @@ class MainFrame(wx.Frame):
|
||||
dlg=wx.FileDialog(
|
||||
self,
|
||||
"Save Fitting As...",
|
||||
wildcard = "EvE XML fitting files (*.xml)|*.xml",
|
||||
wildcard = "EVE XML fitting files (*.xml)|*.xml",
|
||||
style = wx.FD_SAVE)
|
||||
if (dlg.ShowModal() == wx.ID_OK):
|
||||
sFit = service.Fit.getInstance()
|
||||
@@ -339,6 +339,8 @@ class MainFrame(wx.Frame):
|
||||
self.Bind(wx.EVT_MENU, self.backupToXml, id=menuBar.backupFitsId)
|
||||
# Export skills needed
|
||||
self.Bind(wx.EVT_MENU, self.exportSkillsNeeded, id=menuBar.exportSkillsNeededId)
|
||||
# Import character
|
||||
self.Bind(wx.EVT_MENU, self.importCharacter, id=menuBar.importCharacterId)
|
||||
# Preference dialog
|
||||
self.Bind(wx.EVT_MENU, self.showPreferenceDialog, id = menuBar.preferencesId)
|
||||
|
||||
@@ -467,7 +469,7 @@ class MainFrame(wx.Frame):
|
||||
saveDialog = wx.FileDialog(
|
||||
self,
|
||||
"Save Backup As...",
|
||||
wildcard = "EvE XML fitting file (*.xml)|*.xml",
|
||||
wildcard = "EVE XML fitting file (*.xml)|*.xml",
|
||||
style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
|
||||
if (saveDialog.ShowModal() == wx.ID_OK):
|
||||
filePath = saveDialog.GetPath()
|
||||
@@ -504,6 +506,24 @@ class MainFrame(wx.Frame):
|
||||
|
||||
saveDialog.Destroy()
|
||||
|
||||
def importCharacter(self, event):
|
||||
sCharacter = service.Character.getInstance()
|
||||
dlg=wx.FileDialog(
|
||||
self,
|
||||
"Open One Or More Character Files",
|
||||
wildcard = "EVE CCP API XML character files (*.xml)|*.xml|" \
|
||||
"All Files (*)|*",
|
||||
style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE)
|
||||
if (dlg.ShowModal() == wx.ID_OK):
|
||||
self.waitDialog = animUtils.WaitDialog(self, title = "Importing Character")
|
||||
sCharacter.importCharacter(dlg.GetPaths(), self.importCharacterCallback)
|
||||
dlg.Destroy()
|
||||
self.waitDialog.ShowModal()
|
||||
|
||||
def importCharacterCallback(self):
|
||||
self.waitDialog.Destroy()
|
||||
wx.PostEvent(self, GE.CharListUpdated())
|
||||
|
||||
def closeWaitDialog(self):
|
||||
self.waitDialog.Destroy()
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ class MainMenuBar(wx.MenuBar):
|
||||
self.graphFrameId = wx.NewId()
|
||||
self.backupFitsId = wx.NewId()
|
||||
self.exportSkillsNeededId = wx.NewId()
|
||||
self.importCharacterId = wx.NewId()
|
||||
self.preferencesId = wx.NewId()
|
||||
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
@@ -45,10 +46,11 @@ class MainMenuBar(wx.MenuBar):
|
||||
fileMenu.Append(self.mainFrame.closePageId, "&Close Tab\tCTRL+W", "Close the current fit")
|
||||
fileMenu.AppendSeparator()
|
||||
|
||||
fileMenu.Append(self.backupFitsId, "&Backup fits", "Backup all fittings to a XML file")
|
||||
fileMenu.Append(wx.ID_OPEN, "&Import\tCTRL+O", "Import a fit into pyfa.")
|
||||
fileMenu.Append(wx.ID_SAVEAS, "&Export\tCTRL+S", "Export the fit to another format.")
|
||||
fileMenu.Append(self.backupFitsId, "&Backup All Fittings", "Backup all fittings to a XML file")
|
||||
fileMenu.Append(wx.ID_OPEN, "&Import Fittings\tCTRL+O", "Import fittings into pyfa")
|
||||
fileMenu.Append(wx.ID_SAVEAS, "&Export Fitting\tCTRL+S", "Export fitting to another format")
|
||||
fileMenu.Append(self.exportSkillsNeededId, "Export &Skills Needed", "Export skills needed for this fitting")
|
||||
fileMenu.Append(self.importCharacterId, "Import C&haracters", "Import characters into pyfa")
|
||||
fileMenu.AppendSeparator()
|
||||
|
||||
fileMenu.Append(wx.ID_EXIT)
|
||||
|
||||
@@ -31,7 +31,7 @@ class ProjectedViewDrop(wx.PyDropTarget):
|
||||
def __init__(self, dropFn):
|
||||
wx.PyDropTarget.__init__(self)
|
||||
self.dropFn = dropFn
|
||||
# this is really transferring an EvE itemID
|
||||
# this is really transferring an EVE itemID
|
||||
self.dropData = wx.PyTextDataObject()
|
||||
self.SetDataObject(self.dropData)
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ import eos.types
|
||||
import copy
|
||||
import service
|
||||
import itertools
|
||||
from eos import eveapi
|
||||
import config
|
||||
|
||||
import os.path
|
||||
import locale
|
||||
@@ -34,7 +36,23 @@ from xml.dom import minidom
|
||||
|
||||
import gzip
|
||||
|
||||
EVEMON_COMPATIBLE_VERSION = "4081"
|
||||
class CharacterImportThread(threading.Thread):
|
||||
def __init__(self, paths, callback):
|
||||
threading.Thread.__init__(self)
|
||||
self.paths = paths
|
||||
self.callback = callback
|
||||
|
||||
def run(self):
|
||||
paths = self.paths
|
||||
sCharacter = Character.getInstance()
|
||||
for path in paths:
|
||||
with open(path, mode='r') as charFile:
|
||||
sheet = eveapi.ParseXML(charFile)
|
||||
charID = sCharacter.new()
|
||||
sCharacter.rename(charID, sheet.name+" (imported)")
|
||||
sCharacter.apiUpdateCharSheet(charID, sheet)
|
||||
|
||||
wx.CallAfter(self.callback)
|
||||
|
||||
class SkillBackupThread(threading.Thread):
|
||||
def __init__(self, path, saveFmt, activeFit, callback):
|
||||
@@ -56,15 +74,15 @@ class SkillBackupThread(threading.Thread):
|
||||
backupData = sCharacter.exportText()
|
||||
|
||||
if self.saveFmt == "emp":
|
||||
with gzip.open(path, "wb") as backupFile:
|
||||
with gzip.open(path, mode='wb') as backupFile:
|
||||
backupFile.write(backupData)
|
||||
else:
|
||||
with open(path, "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():
|
||||
class Character(object):
|
||||
instance = None
|
||||
skillReqsDict = {}
|
||||
|
||||
@@ -93,7 +111,7 @@ class Character():
|
||||
def exportXml(self):
|
||||
root = ElementTree.Element("plan")
|
||||
root.attrib["name"] = "Pyfa exported plan for "+self.skillReqsDict['charname']
|
||||
root.attrib["revision"] = EVEMON_COMPATIBLE_VERSION
|
||||
root.attrib["revision"] = config.evemonMinVersion
|
||||
|
||||
sorts = ElementTree.SubElement(root, "sorting")
|
||||
sorts.attrib["criteria"] = "None"
|
||||
@@ -127,6 +145,10 @@ class Character():
|
||||
thread = SkillBackupThread(path, saveFmt, activeFit, callback)
|
||||
thread.start()
|
||||
|
||||
def importCharacter(self, path, callback):
|
||||
thread = CharacterImportThread(path, callback)
|
||||
thread.start()
|
||||
|
||||
def all0(self):
|
||||
all0 = eos.types.Character.getAll0()
|
||||
eos.db.commit()
|
||||
@@ -222,6 +244,11 @@ class Character():
|
||||
char.apiFetch(charName, proxy = service.settings.ProxySettings.getInstance().getProxySettings())
|
||||
eos.db.commit()
|
||||
|
||||
def apiUpdateCharSheet(self, charID, sheet):
|
||||
char = eos.db.getCharacter(charID)
|
||||
char.apiUpdateCharSheet(sheet)
|
||||
eos.db.commit()
|
||||
|
||||
def changeLevel(self, charID, skillID, level):
|
||||
char = eos.db.getCharacter(charID)
|
||||
skill = char.getSkill(skillID)
|
||||
|
||||
Reference in New Issue
Block a user