From 25e30672fe70d8796d6e1bb4279836d7ea50399f Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 15 Dec 2014 18:32:03 -0500 Subject: [PATCH 1/4] Start conversion of various wait dialogs to wx.ProgresDialog. Implemented new wx.ProgresDialog for fitting backup --- eos/db/__init__.py | 2 +- eos/db/saveddata/queries.py | 5 +++++ gui/mainFrame.py | 28 +++++++++++++++++++++++----- service/fit.py | 12 +++++++----- service/port.py | 8 ++++++-- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/eos/db/__init__.py b/eos/db/__init__.py index bedb917d6..8867d63c5 100644 --- a/eos/db/__init__.py +++ b/eos/db/__init__.py @@ -75,7 +75,7 @@ from eos.db.saveddata.queries import getUser, getCharacter, getFit, getFitsWithS getFitList, getFleetList, getFleet, save, remove, commit, add, \ getCharactersForUser, getMiscData, getSquadsIDsWithFitID, getWing, \ getSquad, getBoosterFits, getProjectedFits, getTargetResistsList, getTargetResists,\ - clearPrices + clearPrices, countAllFits #If using in memory saveddata, you'll want to reflect it so the data structure is good. if config.saveddata_connectionstring == "sqlite:///:memory:": diff --git a/eos/db/saveddata/queries.py b/eos/db/saveddata/queries.py index 9fee22561..be7c078fc 100644 --- a/eos/db/saveddata/queries.py +++ b/eos/db/saveddata/queries.py @@ -267,6 +267,11 @@ def getBoosterFits(ownerID=None, where=None, eager=None): fits = saveddata_session.query(Fit).options(*eager).filter(filter).all() return fits +def countAllFits(): + with sd_lock: + count = saveddata_session.query(Fit).count() + return count + def countFitsWithShip(shipID, ownerID=None, where=None, eager=None): """ Get all the fits using a certain ship. diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 2d71da48a..0c507b1ce 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -54,6 +54,9 @@ from gui.utils.clipboard import toClipboard, fromClipboard from gui.fleetBrowser import FleetBrowser from gui.updateDialog import UpdateDialog from gui.builtinViews import * + +from time import gmtime, strftime + import locale locale.setlocale(locale.LC_ALL, '') @@ -571,22 +574,37 @@ class MainFrame(wx.Frame): pass dlg.Destroy() + def updateProgressDialog(self,count): + if count == -1: + self.progressDialog.Destroy() + else: + self.progressDialog.Update(count) + def backupToXml(self, event): sFit = service.Fit.getInstance() + + defaultFile = "pyfa-fits-%s.xml"%strftime("%Y%m%d_%H%M%S", gmtime()) + saveDialog = wx.FileDialog( self, "Save Backup As...", wildcard = "EVE XML fitting file (*.xml)|*.xml", - style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) + style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + defaultFile=defaultFile) + if (saveDialog.ShowModal() == wx.ID_OK): filePath = saveDialog.GetPath() if '.' not in os.path.basename(filePath): filePath += ".xml" - self.waitDialog = animUtils.WaitDialog(self) - sFit.backupFits(filePath, self.closeWaitDialog) - self.waitDialog.ShowModal() - saveDialog.Destroy() + max = sFit.countAllFits() + self.progressDialog = wx.ProgressDialog("Backup fits", + "Backing up %d fits to: %s"%(max, filePath), + maximum = max, parent=self, + style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME) + + sFit.backupFits(filePath, self.updateProgressDialog) + self.progressDialog.ShowModal() def exportSkillsNeeded(self, event): sCharacter = service.Character.getInstance() diff --git a/service/fit.py b/service/fit.py index e731c3edf..a9005e5a5 100644 --- a/service/fit.py +++ b/service/fit.py @@ -47,12 +47,11 @@ class FitBackupThread(threading.Thread): path = self.path sFit = Fit.getInstance() allFits = map(lambda x: x[0], sFit.getAllFits()) - backedUpFits = sFit.exportXml(*allFits) + backedUpFits = sFit.exportXml(self.callback, *allFits) backupFile = open(path, "w", encoding="utf-8") backupFile.write(backedUpFits) backupFile.close() - wx.CallAfter(self.callback) - + wx.CallAfter(self.callback, -1) class FitImportThread(threading.Thread): def __init__(self, paths, callback): @@ -127,6 +126,9 @@ class Fit(object): return names + def countAllFits(self): + return eos.db.countAllFits() + def countFitsWithShip(self, shipID): count = eos.db.countFitsWithShip(shipID) return count @@ -758,9 +760,9 @@ class Fit(object): fit = eos.db.getFit(fitID) return Port.exportDna(fit) - def exportXml(self, *fitIDs): + def exportXml(self, callback = None, *fitIDs): fits = map(lambda fitID: eos.db.getFit(fitID), fitIDs) - return Port.exportXml(*fits) + return Port.exportXml(callback, *fits) def backupFits(self, path, callback): thread = FitBackupThread(path, callback) diff --git a/service/port.py b/service/port.py index b69a69007..535665d3d 100644 --- a/service/port.py +++ b/service/port.py @@ -23,6 +23,7 @@ import json from eos.types import State, Slot, Module, Cargo, Fit, Ship, Drone, Implant, Booster import service +import wx try: from collections import OrderedDict @@ -503,11 +504,11 @@ class Port(object): return dna + "::" @classmethod - def exportXml(cls, *fits): + def exportXml(cls, callback=None, *fits): doc = xml.dom.minidom.Document() fittings = doc.createElement("fittings") doc.appendChild(fittings) - for fit in fits: + for i, fit in enumerate(fits): try: fitting = doc.createElement("fitting") fitting.setAttribute("name", fit.name) @@ -571,5 +572,8 @@ class Port(object): except: print "Failed on fitID: %d"%fit.ID continue + finally: + if callback: + wx.CallAfter(callback, i) return doc.toprettyxml() From 26e50f2e8a85caa88ba6512f399566d16dd738be Mon Sep 17 00:00:00 2001 From: blitzmann Date: Wed, 17 Dec 2014 21:34:43 -0500 Subject: [PATCH 2/4] Implement ProgressDialog for fit file imports (EVE XML / EFT cfg). To make it simpler, changed the way fits are imported and saved from a per-file basis (process file->save fits->process file->save fits) to a per-batch basis (process file->process file -> save all fits). --- gui/mainFrame.py | 33 ++++++++++++++++++++----------- service/fit.py | 51 +++++++++++++++++++++++++++--------------------- service/port.py | 20 ++++++++++++------- 3 files changed, 64 insertions(+), 40 deletions(-) diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 0c507b1ce..053fe08f7 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -336,21 +336,32 @@ class MainFrame(wx.Frame): dlg=wx.FileDialog( self, "Open One Or More Fitting Files", - wildcard = "EFT text fitting files (*.cfg)|*.cfg|" \ - "EVE XML fitting files (*.xml)|*.xml|" \ + wildcard = "EVE XML fitting files (*.xml)|*.xml|" \ + "EFT text fitting files (*.cfg)|*.cfg|" \ "All Files (*)|*", style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE) if (dlg.ShowModal() == wx.ID_OK): - self.waitDialog = animUtils.WaitDialog(self, title = "Importing") - sFit.importFitsThreaded(dlg.GetPaths(), self.importCallback) - dlg.Destroy() - self.waitDialog.ShowModal() - def importCallback(self, fits): - self.waitDialog.Destroy() - sFit = service.Fit.getInstance() - IDs = sFit.saveImportedFits(fits) - self._openAfterImport(len(fits), IDs) + self.progressDialog = wx.ProgressDialog("Importing fits", " "*100, parent=self, + style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME) + self.progressDialog.message = None + sFit.importFitsThreaded(dlg.GetPaths(), self.importCallback) + self.progressDialog.ShowModal() + dlg.Destroy() + + def importCallback(self, info): + if info == -1: + self.progressDialog.Destroy() + elif info != self.progressDialog.message and info is not None: + self.progressDialog.message = info + self.progressDialog.Pulse(info) + else: + self.progressDialog.Pulse() + + # @todo: implement saveImportedFits where needed, modify _openAfterImport + #sFit = service.Fit.getInstance() + #IDs = sFit.saveImportedFits(fits) + #self._openAfterImport(len(fits), IDs) def _openAfterImport(self, importCount, fitIDs): if importCount == 1: diff --git a/service/fit.py b/service/fit.py index a9005e5a5..3c5faa9fc 100644 --- a/service/fit.py +++ b/service/fit.py @@ -17,7 +17,6 @@ # along with pyfa. If not, see . #=============================================================================== -import os.path import locale import copy import threading @@ -53,6 +52,7 @@ class FitBackupThread(threading.Thread): backupFile.close() wx.CallAfter(self.callback, -1) + class FitImportThread(threading.Thread): def __init__(self, paths, callback): threading.Thread.__init__(self) @@ -60,14 +60,10 @@ class FitImportThread(threading.Thread): self.callback = callback def run(self): - importedFits = [] - paths = self.paths sFit = Fit.getInstance() - for path in paths: - pathImported = sFit.importFit(path) - if pathImported is not None: - importedFits += pathImported - wx.CallAfter(self.callback, importedFits) + sFit.importFitFromFiles(self.paths, self.callback) + + wx.CallAfter(self.callback, -1) class Fit(object): @@ -772,26 +768,37 @@ class Fit(object): thread = FitImportThread(paths, callback) thread.start() - def importFit(self, path): - filename = os.path.split(path)[1] - + def importFitFromFiles(self, paths, callback=None): defcodepage = locale.getpreferredencoding() - file = open(path, "r") - srcString = file.read() - # If file had ANSI encoding, convert it to unicode using system - # default codepage, or use fallback cp1252 on any encoding errors - if isinstance(srcString, str): - try: - srcString = unicode(srcString, defcodepage) - except UnicodeDecodeError: - srcString = unicode(srcString, "cp1252") + fitImport = [] + for path in paths: + if callback: # Pulse + wx.CallAfter(callback, "Processing file:\n%s"%path) - _, fits = Port.importAuto(srcString, filename) - for fit in fits: + file = open(path, "r") + srcString = file.read() + # If file had ANSI encoding, convert it to unicode using system + # default codepage, or use fallback cp1252 on any encoding errors + if isinstance(srcString, str): + try: + srcString = unicode(srcString, defcodepage) + except UnicodeDecodeError: + srcString = unicode(srcString, "cp1252") + + _, fits = Port.importAuto(srcString, path, callback=callback) + fitImport += fits + + IDs = [] + for i, fit in enumerate(fitImport): fit.character = self.character fit.damagePattern = self.pattern fit.targetResists = self.targetResists + eos.db.save(fit) + IDs.append(fit.ID) + if callback: # Pulse + wx.CallAfter(callback, "Saving fit\n%d/%d"%(i+1, len(fitImport))) + return fits def importFitFromBuffer(self, bufferStr, activeFit=None): diff --git a/service/port.py b/service/port.py index 535665d3d..800447d19 100644 --- a/service/port.py +++ b/service/port.py @@ -19,7 +19,6 @@ import re import xml.dom -import json from eos.types import State, Slot, Module, Cargo, Fit, Ship, Drone, Implant, Booster import service @@ -36,20 +35,20 @@ class Port(object): """Service which houses all import/export format functions""" @classmethod - def importAuto(cls, string, sourceFileName=None, activeFit=None): + def importAuto(cls, string, sourceFileName=None, activeFit=None, callback=None): # Get first line and strip space symbols of it to avoid possible detection errors firstLine = re.split("[\n\r]+", string.strip(), maxsplit=1)[0] firstLine = firstLine.strip() # If XML-style start of tag encountered, detect as XML if re.match("<", firstLine): - return "XML", cls.importXml(string) + return "XML", cls.importXml(string, callback) # If we've got source file name which is used to describe ship name # and first line contains something like [setup name], detect as eft config file if re.match("\[.*\]", firstLine) and sourceFileName is not None: shipName = sourceFileName.rsplit('.')[0] - return "EFT Config", cls.importEftCfg(shipName, string) + return "EFT Config", cls.importEftCfg(shipName, string, callback) # If no file is specified and there's comma between brackets, # consider that we have [ship, setup name] and detect like eft export format @@ -201,7 +200,7 @@ class Port(object): return fit @staticmethod - def importEftCfg(shipname, contents): + def importEftCfg(shipname, contents, callback=None): """Handle import from EFT config store file""" # Check if we have such ship in database, bail if we don't @@ -347,6 +346,9 @@ class Port(object): f.modules.append(m) # Append fit to list of fits fits.append(f) + + if callback: + wx.CallAfter(callback, None) # Skip fit silently if we get an exception except Exception: pass @@ -354,14 +356,16 @@ class Port(object): return fits @staticmethod - def importXml(text): + def importXml(text, callback=None): sMkt = service.Market.getInstance() doc = xml.dom.minidom.parseString(text.encode("utf-8")) fittings = doc.getElementsByTagName("fittings").item(0) fittings = fittings.getElementsByTagName("fitting") fits = [] - for fitting in fittings: + + for i, fitting in enumerate(fittings): + print "fitting" f = Fit() f.name = fitting.getAttribute("name") # Maelstrom @@ -403,6 +407,8 @@ class Port(object): except KeyboardInterrupt: continue fits.append(f) + if callback: + wx.CallAfter(callback, None) return fits From c59b8186775b2de7379d000143d174976a6014a2 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Fri, 19 Dec 2014 00:13:06 -0500 Subject: [PATCH 3/4] Add wx.ProgressDialog to HTML export, along with some documentation and silent try-except in HTML export --- gui/mainFrame.py | 193 +++++++++++++++++++++------------------- gui/utils/exportHtml.py | 42 ++++++--- service/fit.py | 31 ++++--- service/port.py | 1 - 4 files changed, 150 insertions(+), 117 deletions(-) diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 053fe08f7..61a5573b9 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -330,57 +330,16 @@ class MainFrame(wx.Frame): dlg.ShowModal() dlg.Destroy() - def showImportDialog(self, event): - fits = [] - sFit = service.Fit.getInstance() - dlg=wx.FileDialog( - self, - "Open One Or More Fitting Files", - wildcard = "EVE XML fitting files (*.xml)|*.xml|" \ - "EFT text fitting files (*.cfg)|*.cfg|" \ - "All Files (*)|*", - style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE) - if (dlg.ShowModal() == wx.ID_OK): - - self.progressDialog = wx.ProgressDialog("Importing fits", " "*100, parent=self, - style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME) - self.progressDialog.message = None - sFit.importFitsThreaded(dlg.GetPaths(), self.importCallback) - self.progressDialog.ShowModal() - dlg.Destroy() - - def importCallback(self, info): - if info == -1: - self.progressDialog.Destroy() - elif info != self.progressDialog.message and info is not None: - self.progressDialog.message = info - self.progressDialog.Pulse(info) - else: - self.progressDialog.Pulse() - - # @todo: implement saveImportedFits where needed, modify _openAfterImport - #sFit = service.Fit.getInstance() - #IDs = sFit.saveImportedFits(fits) - #self._openAfterImport(len(fits), IDs) - - def _openAfterImport(self, importCount, fitIDs): - if importCount == 1: - wx.PostEvent(self, FitSelected(fitID=fitIDs[0])) - - self.shipBrowser.RefreshContent() - def showExportDialog(self, event): - dlg=wx.FileDialog( - self, - "Save Fitting As...", - wildcard = "EVE XML fitting files (*.xml)|*.xml", - style = wx.FD_SAVE) - if (dlg.ShowModal() == wx.ID_OK): + """ Export active fit """ + dlg = wx.FileDialog(self, "Save Fitting As...", + wildcard = "EVE XML fitting files (*.xml)|*.xml", + style = wx.FD_SAVE) + if dlg.ShowModal() == wx.ID_OK: sFit = service.Fit.getInstance() format = dlg.GetFilterIndex() - output = "" path = dlg.GetPath() - if (format == 0): + if format == 0: output = sFit.exportXml(self.getActiveFit()) if '.' not in os.path.basename(path): path += ".xml" @@ -420,7 +379,7 @@ class MainFrame(wx.Frame): # Target Resists editor self.Bind(wx.EVT_MENU, self.showTargetResistsEditor, id=menuBar.targetResistsEditorId) # Import dialog - self.Bind(wx.EVT_MENU, self.showImportDialog, id=wx.ID_OPEN) + self.Bind(wx.EVT_MENU, self.fileImportDialog, id=wx.ID_OPEN) # Export dialog self.Bind(wx.EVT_MENU, self.showExportDialog, id=wx.ID_SAVEAS) # Import from Clipboard @@ -565,12 +524,10 @@ class MainFrame(wx.Frame): sFit = service.Fit.getInstance() try: fits = sFit.importFitFromBuffer(fromClipboard(), self.getActiveFit()) - IDs = sFit.saveImportedFits(fits) - self._openAfterImport(len(fits), IDs) + #self._openAfterImport(len(fits), IDs) except: pass - def exportToClipboard(self, event): CopySelectDict = {CopySelectDialog.copyFormatEft: self.clipboardEft, CopySelectDialog.copyFormatEftImps: self.clipboardEftImps, @@ -585,59 +542,103 @@ class MainFrame(wx.Frame): pass dlg.Destroy() - def updateProgressDialog(self,count): - if count == -1: + def fileImportDialog(self, event): + """Handles importing single/multiple EVE XML / EFT cfg fit files""" + sFit = service.Fit.getInstance() + dlg = wx.FileDialog(self, "Open One Or More Fitting Files", + wildcard = "EVE XML fitting files (*.xml)|*.xml|" \ + "EFT text fitting files (*.cfg)|*.cfg|" \ + "All Files (*)|*", + style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE) + if (dlg.ShowModal() == wx.ID_OK): + self.progressDialog = wx.ProgressDialog( + "Importing fits", + " "*100, # set some arbitrary spacing to create wifth in window + parent=self, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME) + self.progressDialog.message = None + sFit.importFitsThreaded(dlg.GetPaths(), self.importCallback) + self.progressDialog.ShowModal() + dlg.Destroy() + + def importCallback(self, info): + """ + While importing fits from file, the logic calls back to this function to + update progress bar to show activity. If -1, closes dialog. If None, + simply Pulse()s progress. If there is a message to show new activity, + overwrites cached message and updates dialog + """ + if info == -1: self.progressDialog.Destroy() + elif info != self.progressDialog.message and info is not None: + self.progressDialog.message = info + self.progressDialog.Pulse(info) else: - self.progressDialog.Update(count) + self.progressDialog.Pulse() + + # @todo: modify _openAfterImport + #self._openAfterImport(len(fits), IDs) + + def _openAfterImport(self, importCount, fitIDs): + if importCount == 1: + wx.PostEvent(self, FitSelected(fitID=fitIDs[0])) + + self.shipBrowser.RefreshContent() def backupToXml(self, event): - sFit = service.Fit.getInstance() - + """ Back up all fits to EVE XML file """ defaultFile = "pyfa-fits-%s.xml"%strftime("%Y%m%d_%H%M%S", gmtime()) - saveDialog = wx.FileDialog( - self, - "Save Backup As...", - wildcard = "EVE XML fitting file (*.xml)|*.xml", - style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, - defaultFile=defaultFile) + saveDialog = wx.FileDialog(self, "Save Backup As...", + wildcard = "EVE XML fitting file (*.xml)|*.xml", + style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, + defaultFile=defaultFile) - if (saveDialog.ShowModal() == wx.ID_OK): + if saveDialog.ShowModal() == wx.ID_OK: filePath = saveDialog.GetPath() if '.' not in os.path.basename(filePath): filePath += ".xml" + sFit = service.Fit.getInstance() max = sFit.countAllFits() + self.progressDialog = wx.ProgressDialog("Backup fits", "Backing up %d fits to: %s"%(max, filePath), - maximum = max, parent=self, - style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME) + maximum=max, parent=self, + style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME) - sFit.backupFits(filePath, self.updateProgressDialog) + sFit.backupFits(filePath, self.backupCallback) self.progressDialog.ShowModal() + def backupCallback(self, info): + #print info + if info == -1: + self.progressDialog.Destroy() + else: + self.progressDialog.Update(info) + def exportSkillsNeeded(self, event): + """ Exports skills needed for active fit and active character """ sCharacter = service.Character.getInstance() - saveDialog = wx.FileDialog( - self, - "Export Skills Needed As...", - wildcard = "EVEMon skills training file (*.emp)|*.emp|" \ - "EVEMon skills training XML file (*.xml)|*.xml|" \ - "Text skills training file (*.txt)|*.txt", - style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) - if (saveDialog.ShowModal() == wx.ID_OK): + saveDialog = wx.FileDialog(self, "Export Skills Needed As...", + wildcard = "EVEMon skills training file (*.emp)|*.emp|" \ + "EVEMon skills training XML file (*.xml)|*.xml|" \ + "Text skills training file (*.txt)|*.txt", + style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) + + if saveDialog.ShowModal() == wx.ID_OK: saveFmtInt = saveDialog.GetFilterIndex() - saveFmt = "" + if saveFmtInt == 0: # Per ordering of wildcards above saveFmt = "emp" elif saveFmtInt == 1: saveFmt = "xml" else: saveFmt = "txt" + filePath = saveDialog.GetPath() if '.' not in os.path.basename(filePath): filePath += ".{0}".format(saveFmt) + self.waitDialog = animUtils.WaitDialog(self) sCharacter.backupSkills(filePath, saveFmt, self.getActiveFit(), self.closeWaitDialog) self.waitDialog.ShowModal() @@ -645,29 +646,39 @@ 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") + """ Imports character XML file from EVE API """ + dlg = wx.FileDialog(self, "Open One Or More Character Files", + wildcard="EVE API XML character files (*.xml)|*.xml|" \ + "All Files (*)|*", + style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE) + + if dlg.ShowModal() == wx.ID_OK: + self.waitDialog = animUtils.WaitDialog(self, title="Importing Character") + sCharacter = service.Character.getInstance() sCharacter.importCharacter(dlg.GetPaths(), self.importCharacterCallback) dlg.Destroy() self.waitDialog.ShowModal() - def exportHtml(self, event): - from gui.utils.exportHtml import exportHtml - self.waitDialog = animUtils.WaitDialog(self) - exportHtml.getInstance().refreshFittingHtml(True, self.closeWaitDialog) - self.waitDialog.ShowModal() - def importCharacterCallback(self): self.waitDialog.Destroy() wx.PostEvent(self, GE.CharListUpdated()) + def exportHtml(self, event): + from gui.utils.exportHtml import exportHtml + sFit = service.Fit.getInstance() + settings = service.settings.HTMLExportSettings.getInstance() + + max = sFit.countAllFits() + path = settings.getPath() + print max + self.progressDialog = wx.ProgressDialog("Backup fits", + "Generating HTML file at:\n%s"%path, + maximum=max, parent=self, + style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME) + + exportHtml.getInstance().refreshFittingHtml(True, self.backupCallback) + self.progressDialog.ShowModal() + def closeWaitDialog(self): self.waitDialog.Destroy() @@ -679,7 +690,7 @@ class MainFrame(wx.Frame): else: self.graphFrame.SetFocus() - def openWXInspectTool(self,event): + def openWXInspectTool(self, event): from wx.lib.inspection import InspectionTool if not InspectionTool().initialized: InspectionTool().Init() diff --git a/gui/utils/exportHtml.py b/gui/utils/exportHtml.py index c61c2444a..281b5c32c 100644 --- a/gui/utils/exportHtml.py +++ b/gui/utils/exportHtml.py @@ -7,7 +7,7 @@ class exportHtml(): _instance = None @classmethod def getInstance(cls): - if cls._instance == None: + if cls._instance is None: cls._instance = exportHtml() return cls._instance @@ -15,17 +15,17 @@ class exportHtml(): def __init__(self): self.thread = exportHtmlThread() - def refreshFittingHtml(self, force = False, callback = False): + def refreshFittingHtml(self, force=False, callback=False): settings = service.settings.HTMLExportSettings.getInstance() - if (force or settings.getEnabled()): + if force or settings.getEnabled(): self.thread.stop() self.thread = exportHtmlThread(callback) self.thread.start() class exportHtmlThread(threading.Thread): - def __init__(self, callback = False): + def __init__(self, callback=False): threading.Thread.__init__(self) self.callback = callback self.stopRunning = False @@ -40,7 +40,7 @@ class exportHtmlThread(threading.Thread): return sMkt = service.Market.getInstance() - sFit = service.Fit.getInstance() + sFit = service.Fit.getInstance() settings = service.settings.HTMLExportSettings.getInstance() timestamp = time.localtime(time.time()) @@ -135,6 +135,9 @@ class exportHtmlThread(threading.Thread): HTML += '
    \n' categoryList = list(sMkt.getShipRoot()) categoryList.sort(key=lambda ship: ship.name) + + count = 1 + for group in categoryList: # init market group string to give ships something to attach to HTMLgroup = '' @@ -153,9 +156,17 @@ class exportHtmlThread(threading.Thread): if self.stopRunning: return fit = fits[0] - dnaFit = sFit.exportDna(fit[0]) - HTMLgroup += ( - '
  • ' + ship.name + ": " + fit[1] + '
  • \n') + try: + print fit[0] + dnaFit = sFit.exportDna(fit[0]) + HTMLgroup += ( + '
  • ' + ship.name + ": " + fit[1] + '
  • \n') + except: + pass + finally: + count += 1 + if self.callback: + wx.CallAfter(self.callback, count) else: # Ship group header HTMLship = ( @@ -166,11 +177,18 @@ class exportHtmlThread(threading.Thread): for fit in fits: if self.stopRunning: return - dnaFit = sFit.exportDna(fit[0]) - HTMLship += '
  • ' + fit[1] + '
  • \n' - + try: + dnaFit = sFit.exportDna(fit[0]) + HTMLship += '
  • ' + fit[1] + '
  • \n' + except: + continue + finally: + count += 1 + if self.callback: + wx.CallAfter(self.callback, count) HTMLgroup += HTMLship + ('
\n' ' \n') + if groupFits > 0: # Market group header HTML += ( @@ -197,5 +215,5 @@ class exportHtmlThread(threading.Thread): pass if self.callback: - wx.CallAfter(self.callback) + wx.CallAfter(self.callback, -1) diff --git a/service/fit.py b/service/fit.py index 3c5faa9fc..25635b070 100644 --- a/service/fit.py +++ b/service/fit.py @@ -50,6 +50,8 @@ class FitBackupThread(threading.Thread): backupFile = open(path, "w", encoding="utf-8") backupFile.write(backedUpFits) backupFile.close() + + # Send done signal to GUI wx.CallAfter(self.callback, -1) @@ -63,6 +65,7 @@ class FitImportThread(threading.Thread): sFit = Fit.getInstance() sFit.importFitFromFiles(self.paths, self.callback) + # Send done signal to GUI wx.CallAfter(self.callback, -1) @@ -769,9 +772,16 @@ class Fit(object): thread.start() def importFitFromFiles(self, paths, callback=None): + """ + Imports fits from file(s). First processes all provided paths and stores + assembled fits into a list. This allows us to call back to the GUI as + fits are processed as well as when fits are being saved. + + returns + """ defcodepage = locale.getpreferredencoding() - fitImport = [] + fits = [] for path in paths: if callback: # Pulse wx.CallAfter(callback, "Processing file:\n%s"%path) @@ -786,18 +796,20 @@ class Fit(object): except UnicodeDecodeError: srcString = unicode(srcString, "cp1252") - _, fits = Port.importAuto(srcString, path, callback=callback) - fitImport += fits + _, fitsImport = Port.importAuto(srcString, path, callback=callback) + fits += fitsImport IDs = [] - for i, fit in enumerate(fitImport): + numFits = len(fits) + for i, fit in enumerate(fits): + # Set some more fit attributes and save fit.character = self.character fit.damagePattern = self.pattern fit.targetResists = self.targetResists eos.db.save(fit) IDs.append(fit.ID) if callback: # Pulse - wx.CallAfter(callback, "Saving fit\n%d/%d"%(i+1, len(fitImport))) + wx.CallAfter(callback, "Saving fit\n%d/%d"%(i+1, numFits)) return fits @@ -807,15 +819,8 @@ class Fit(object): fit.character = self.character fit.damagePattern = self.pattern fit.targetResists = self.targetResists - return fits - - def saveImportedFits(self, fits): - IDs = [] - for fit in fits: eos.db.save(fit) - IDs.append(fit.ID) - - return IDs + return fits def checkStates(self, fit, base): changed = False diff --git a/service/port.py b/service/port.py index 800447d19..600cb4bcc 100644 --- a/service/port.py +++ b/service/port.py @@ -365,7 +365,6 @@ class Port(object): fits = [] for i, fitting in enumerate(fittings): - print "fitting" f = Fit() f.name = fitting.getAttribute("name") # Maelstrom From e42671fbec65cf934e28fd5ddcb1be298012674d Mon Sep 17 00:00:00 2001 From: blitzmann Date: Wed, 31 Dec 2014 16:00:09 -0500 Subject: [PATCH 4/4] Workaround for seg fault (see comments in pull request # 232) --- gui/mainFrame.py | 8 +++----- gui/utils/exportHtml.py | 1 - 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 61a5573b9..4fa5866d1 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -568,7 +568,7 @@ class MainFrame(wx.Frame): overwrites cached message and updates dialog """ if info == -1: - self.progressDialog.Destroy() + self.progressDialog.Hide() elif info != self.progressDialog.message and info is not None: self.progressDialog.message = info self.progressDialog.Pulse(info) @@ -610,9 +610,8 @@ class MainFrame(wx.Frame): self.progressDialog.ShowModal() def backupCallback(self, info): - #print info if info == -1: - self.progressDialog.Destroy() + self.progressDialog.Hide() else: self.progressDialog.Update(info) @@ -670,9 +669,8 @@ class MainFrame(wx.Frame): max = sFit.countAllFits() path = settings.getPath() - print max self.progressDialog = wx.ProgressDialog("Backup fits", - "Generating HTML file at:\n%s"%path, + "Generating HTML file at: %s"%path, maximum=max, parent=self, style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME) diff --git a/gui/utils/exportHtml.py b/gui/utils/exportHtml.py index 281b5c32c..726bec265 100644 --- a/gui/utils/exportHtml.py +++ b/gui/utils/exportHtml.py @@ -157,7 +157,6 @@ class exportHtmlThread(threading.Thread): return fit = fits[0] try: - print fit[0] dnaFit = sFit.exportDna(fit[0]) HTMLgroup += ( '
  • ' + ship.name + ": " + fit[1] + '
  • \n')