def backupToXml(self, event): """ 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, ) if saveDialog.ShowModal() == wx.ID_OK: filePath = saveDialog.GetPath() if '.' not in os.path.basename(filePath): filePath += ".xml" sFit = 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_CAN_ABORT | wx.PD_SMOOTH | wx.PD_ELAPSED_TIME | wx.PD_APP_MODAL ) Port.backupFits(filePath, self) self.progressDialog.ShowModal()
def generateMinimalHTML(self, sMkt, sFit, dnaUrl): """ Generate a minimal HTML version of the fittings, without any javascript or styling""" categoryList = list(sMkt.getShipRoot()) categoryList.sort(key=lambda _ship: _ship.name) count = 0 HTML = '' for group in categoryList: # init market group string to give ships something to attach to ships = list(sMkt.getShipList(group.ID)) ships.sort(key=lambda _ship: _ship.name) ships.sort(key=lambda _ship: _ship.name) for ship in ships: fits = sFit.getFitsWithShip(ship.ID) for fit in fits: if self.stopRunning: return try: dnaFit = Port.exportDna(getFit(fit[0])) HTML += '<a class="outOfGameBrowserLink" target="_blank" href="' + dnaUrl + dnaFit + '">' \ + ship.name + ': ' + \ fit[1] + '</a><br> \n' except: pyfalog.error("Failed to export line") continue finally: if self.callback: wx.CallAfter(self.callback, count) count += 1 return HTML
def showExportDialog(self, event): """ Export active fit """ sFit = Fit.getInstance() fit = sFit.getFit(self.getActiveFit()) defaultFile = "%s - %s.xml" % (fit.ship.item.name, fit.name) if fit else None dlg = wx.FileDialog(self, "Save Fitting As...", wildcard="EVE XML fitting files (*.xml)|*.xml", style=wx.FD_SAVE, defaultFile=defaultFile) if dlg.ShowModal() == wx.ID_OK: self.supress_left_up = True format_ = dlg.GetFilterIndex() path = dlg.GetPath() if format_ == 0: output = Port.exportXml(None, fit) if '.' not in os.path.basename(path): path += ".xml" else: print(("oops, invalid fit format %d" % format_)) try: dlg.Destroy() except RuntimeError: pyfalog.error("Tried to destroy an object that doesn't exist in <showExportDialog>.") return with open(path, "w", encoding="utf-8") as openfile: openfile.write(output) openfile.close() try: dlg.Destroy() except RuntimeError: pyfalog.error("Tried to destroy an object that doesn't exist in <showExportDialog>.")
def exportFitting(self, event): sPort = Port.getInstance() fitID = self.mainFrame.getActiveFit() self.statusbar.SetStatusText("", 0) if fitID is None: self.statusbar.SetStatusText("Please select an active fitting in the main window", 1) return self.statusbar.SetStatusText("Sending request and awaiting response", 1) sCrest = Crest.getInstance() try: sFit = Fit.getInstance() data = sPort.exportCrest(sFit.getFit(fitID)) res = sCrest.postFitting(self.getActiveCharacter(), data) self.statusbar.SetStatusText("%d: %s" % (res.status_code, res.reason), 0) try: text = json.loads(res.text) self.statusbar.SetStatusText(text['message'], 1) except ValueError: self.statusbar.SetStatusText("", 1) except requests.exceptions.ConnectionError: self.statusbar.SetStatusText("Connection error, please check your internet connection", 1)
def importFitFromBuffer(self, bufferStr, activeFit=None): _, fits = Port.importAuto(bufferStr, activeFit=activeFit) for fit in fits: fit.character = self.character fit.damagePattern = self.pattern fit.targetResists = self.targetResists eos.db.save(fit) return fits
def importFitting(self, event): selection = self.fitView.fitSelection if not selection: return data = self.fitTree.fittingsTreeCtrl.GetItemData(selection) sPort = Port.getInstance() import_type, fits = sPort.importFitFromBuffer(data) self.mainFrame._openAfterImport(fits)
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() fits = [] for path in paths: if callback: # Pulse wx.CallAfter(callback, "Processing file:\n%s"%path) file = open(path, "r") srcString = file.read() codec_found = None # If file had ANSI encoding, convert it to unicode using system # default codepage, or use fallbacks UTF-16, then cp1252 on any # encoding errors if isinstance(srcString, str): attempt_codecs = (defcodepage, "utf-16", "cp1252") for page in attempt_codecs: try: srcString = unicode(srcString, page) codec_found = page except UnicodeDecodeError: logger.warn("Error unicode decoding %s from page %s, trying next codec", path, page) else: break else: # nasty hack to detect other transparent utf-16 loading if srcString[0] == '<' and 'utf-16' in srcString[:128].lower(): codec_found = "utf-16" else: codec_found = "utf-8" _, fitsImport = Port.importAuto(srcString, path, callback=callback, encoding=codec_found) fits += fitsImport IDs = [] 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, "Processing complete, saving fits to database\n(%d/%d)" % (i+1, numFits) ) return fits
def fileImportDialog(self, event): """Handles importing single/multiple EVE XML / EFT cfg fit files""" 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 width in window parent=self, style=wx.PD_CAN_ABORT | wx.PD_SMOOTH | wx.PD_ELAPSED_TIME | wx.PD_APP_MODAL ) # self.progressDialog.message = None Port.importFitsThreaded(dlg.GetPaths(), self) self.progressDialog.ShowModal() try: dlg.Destroy() except RuntimeError: pyfalog.error("Tried to destroy an object that doesn't exist in <fileImportDialog>.")
def test_import_xml(print_db_info): usr = PortUser() # for path in XML_FILES: xml_file = "jeffy_ja-en[99].xml" fit_count = int(re.search(r"\[(\d+)\]", xml_file).group(1)) fits = None with open(os.path.join(script_dir, xml_file), "r") as file_: srcString = file_.read() srcString = str(srcString, "utf-8") # (basestring, IPortUser, basestring) -> list[eos.saveddata.fit.Fit] usr.on_port_process_start() #stpw.reset() #with stpw: fits = Port.importXml(srcString, usr) assert fits is not None and len(fits) is fit_count
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() fits = [] for path in paths: if callback: # Pulse wx.CallAfter(callback, "Processing file:\n%s"%path) 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") _, fitsImport = Port.importAuto(srcString, path, callback=callback) fits += fitsImport IDs = [] 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, "Processing complete, saving fits to database\n(%d/%d)" % (i+1, numFits) ) return fits
def importFit(self, path): filename = os.path.split(path)[1] 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") _, fits = Port.importAuto(srcString, filename) for fit in fits: fit.character = self.character fit.damagePattern = self.pattern return fits
def exportFitting(self, event): sPort = Port.getInstance() fitID = self.mainFrame.getActiveFit() self.statusbar.SetStatusText("", 0) if fitID is None: self.statusbar.SetStatusText("Please select an active fitting in the main window", 1) return self.statusbar.SetStatusText("Sending request and awaiting response", 1) sEsi = Esi.getInstance() sFit = Fit.getInstance() data = sPort.exportESI(sFit.getFit(fitID)) res = sEsi.postFitting(self.getActiveCharacter(), data) try: res.raise_for_status() self.statusbar.SetStatusText("", 0) self.statusbar.SetStatusText(res.reason, 1) except requests.exceptions.ConnectionError: msg = "Connection error, please check your internet connection" pyfalog.error(msg) self.statusbar.SetStatusText("ERROR", 0) self.statusbar.SetStatusText(msg, 1) except ESIExportException as ex: pyfalog.error(ex) self.statusbar.SetStatusText("ERROR", 0) self.statusbar.SetStatusText("{} - {}".format(res.status_code, res.reason), 1) except APIException as ex: try: ESIExceptionHandler(self, ex) except Exception as ex: self.statusbar.SetStatusText("ERROR", 0) self.statusbar.SetStatusText("{} - {}".format(res.status_code, res.reason), 1) pyfalog.error(ex)
def exportEsi(self, options, callback): fit = getFit(self.mainFrame.getActiveFit()) Port.exportESI(fit, callback)
def clipboardDna(self, options): fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportDna(fit))
def clipboardEft(self, options): fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportEft(fit, options))
def exportXml(self, callback=None, *fitIDs): fits = map(lambda fitID: eos.db.getFit(fitID), fitIDs) return Port.exportXml(callback, *fits)
def clipboardEsi(self, options): fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportESI(fit))
def exportCrest(self, fitID, callback=None): fit = eos.db.getFit(fitID) return Port.exportCrest(fit, callback)
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() fits = [] for path in paths: if callback: # Pulse wx.CallAfter(callback, 1, "Processing file:\n%s"%path) file = open(path, "r") srcString = file.read() if len(srcString) == 0: # ignore blank files continue codec_found = None # If file had ANSI encoding, decode it to unicode using detection # of BOM header or if there is no header try default # codepage then fallback to utf-16, cp1252 if isinstance(srcString, str): encoding_map = ( ('\xef\xbb\xbf', 'utf-8'), ('\xff\xfe\0\0', 'utf-32'), ('\0\0\xfe\xff', 'UTF-32BE'), ('\xff\xfe', 'utf-16'), ('\xfe\xff', 'UTF-16BE')) for bom, encoding in encoding_map: if srcString.startswith(bom): codec_found = encoding savebom = bom if codec_found is None: logger.info("Unicode BOM not found in file %s.", path) attempt_codecs = (defcodepage, "utf-8", "utf-16", "cp1252") for page in attempt_codecs: try: logger.info("Attempting to decode file %s using %s page.", path, page) srcString = unicode(srcString, page) codec_found = page logger.info("File %s decoded using %s page.", path, page) except UnicodeDecodeError: logger.info("Error unicode decoding %s from page %s, trying next codec", path, page) else: break else: logger.info("Unicode BOM detected in %s, using %s page.", path, codec_found) srcString = unicode(srcString[len(savebom):], codec_found) else: # nasty hack to detect other transparent utf-16 loading if srcString[0] == '<' and 'utf-16' in srcString[:128].lower(): codec_found = "utf-16" else: codec_found = "utf-8" if codec_found is None: return False, "Proper codec could not be established for %s" % path try: _, fitsImport = Port.importAuto(srcString, path, callback=callback, encoding=codec_found) fits += fitsImport except xml.parsers.expat.ExpatError, e: return False, "Malformed XML in %s"%path except Exception, e: logger.exception("Unknown exception processing: %s", path) return False, "Unknown Error while processing %s"%path
def clipboardDna(self): fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportDna(fit))
def clipboardXml(self, options): fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportXml(None, fit))
def clipboardMultiBuy(self, options): fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportMultiBuy(fit))
def exportDna(self, fitID): fit = eos.db.getFit(fitID) return Port.exportDna(fit)
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() fits = [] for path in paths: if callback: # Pulse wx.CallAfter(callback, "Processing file:\n%s"%path) file = open(path, "r") srcString = file.read() codec_found = None # If file had ANSI encoding, decode it to unicode using detection # of BOM header or if there is no header try default # codepage then fallback to utf-16, cp1252 if isinstance(srcString, str): encoding_map = (('\xef\xbb\xbf', 'utf-8'),('\xff\xfe\0\0', 'utf-32'),('\0\0\xfe\xff', 'UTF-32BE'),('\xff\xfe', 'utf-16'),('\xfe\xff', 'UTF-16BE')) for bom, encoding in encoding_map: if srcString.startswith(bom): codec_found = encoding savebom = bom if codec_found is None: logger.warn("Unicode BOM not found in file %s.", path) attempt_codecs = (defcodepage, "utf-16", "cp1252") for page in attempt_codecs: try: logger.warn("Attempting to decode file %s using %s page.", path, page) srcString = unicode(srcString, page) codec_found = page logger.warn("File %s decoded using %s page.", path, page) except UnicodeDecodeError: logger.warn("Error unicode decoding %s from page %s, trying next codec", path, page) else: break else: logger.debug("Unicode BOM detected in %s, using %s page.", path, codec_found) srcString = unicode(srcString[len(savebom):], codec_found) else: # nasty hack to detect other transparent utf-16 loading if srcString[0] == '<' and 'utf-16' in srcString[:128].lower(): codec_found = "utf-16" else: codec_found = "utf-8" _, fitsImport = Port.importAuto(srcString, path, callback=callback, encoding=codec_found) fits += fitsImport IDs = [] 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, "Processing complete, saving fits to database\n(%d/%d)" % (i+1, numFits) ) return fits
def exportEftImps(self, fitID): fit = eos.db.getFit(fitID) return Port.exportEftImps(fit)
def exportXml(self, options, callback): fit = getFit(self.mainFrame.getActiveFit()) Port.exportXml([fit], None, callback)
def exportXml(self, *fitIDs): fits = map(lambda fitID: eos.db.getFit(fitID), fitIDs) return Port.exportXml(*fits)
def exportMultiBuy(self, options, callback): fit = getFit(self.mainFrame.getActiveFit()) Port.exportMultiBuy(fit, options, callback)
def importFitFromBuffer(self, bufferStr, activeFit=None): _, fits = Port.importAuto(bufferStr, activeFit=activeFit) for fit in fits: fit.character = self.character fit.damagePattern = self.pattern return fits
def exportMultiBuy(self, fitID): fit = eos.db.getFit(fitID) return Port.exportMultiBuy(fit)
def generateFullHTML(self, sMkt, sFit, dnaUrl): """ Generate the complete HTML with styling and javascript """ timestamp = time.localtime(time.time()) localDate = "%d/%02d/%02d %02d:%02d" % (timestamp[0], timestamp[1], timestamp[2], timestamp[3], timestamp[4]) HTML = """ <!DOCTYPE html> <html> <head> <title>Pyfa Fittings</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="utf-8" /> <link rel="stylesheet" href="https://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css" /> <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script> <script> //http://stackoverflow.com/questions/32453806/uncaught-securityerror-failed-to-execute-replacestate-on-history-cannot-be $(document).bind('mobileinit',function(){ $.mobile.changePage.defaults.changeHash = false; $.mobile.hashListeningEnabled = false; $.mobile.pushStateEnabled = false; }); </script> <script src="https://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script> <style> /* Basic settings */ .ui-li-static.ui-collapsible { padding: 0; } .ui-li-static.ui-collapsible > .ui-collapsible-content > .ui-listview, .ui-li-static.ui-collapsible > .ui-collapsible-heading { margin: 0; } .ui-li-static.ui-collapsible > .ui-collapsible-content { padding-top: 0; padding-bottom: 0; padding-right: 0; border-bottom-width: 0; } /* collapse vertical borders */ .ui-li-static.ui-collapsible > .ui-collapsible-content > .ui-listview > li.ui-last-child, .ui-li-static.ui-collapsible.ui-collapsible-collapsed > .ui-collapsible-heading > a.ui-btn { border-bottom-width: 0; } .ui-li-static.ui-collapsible > .ui-collapsible-content > .ui-listview > li.ui-first-child, .ui-li-static.ui-collapsible > .ui-collapsible-content > .ui-listview > li.ui-first-child > a.ui-btn, .ui-li-static.ui-collapsible > .ui-collapsible-heading > a.ui-btn { border-top-width: 0; } /* Remove right borders */ .ui-li-static.ui-collapsible > .ui-collapsible-heading > a.ui-btn, .ui-li-static.ui-collapsible > .ui-collapsible-content > .ui-listview > .ui-li-static, .ui-li-static.ui-collapsible > .ui-collapsible-content > .ui-listview > li > a.ui-btn, .ui-li-static.ui-collapsible > .ui-collapsible-content { border-right-width: 0; } /* Remove left borders */ /* Here, we need class ui-listview-outer to identify the outermost listview */ .ui-listview-outer > .ui-li-static.ui-collapsible .ui-li-static.ui-collapsible.ui-collapsible, .ui-listview-outer > .ui-li-static.ui-collapsible > .ui-collapsible-heading > a.ui-btn, .ui-li-static.ui-collapsible > .ui-collapsible-content { border-left-width: 0; } .ui-content { max-width: 800px !important; margin: 0 auto !important; } .ui-listview > .ui-li-static.ui-li-has-count { padding-right: 0px } </style> <script> $(document).ready(function() { var start = new Date(%d * 1000); setInterval(function() { var diff = (new Date - start) / 1000; var days = Math.floor((diff %% 31536000) / 86400); var hours = Math.floor(((diff %% 31536000) %% 86400) / 3600); var minutes = Math.floor((((diff %% 31536000) %% 86400) %% 3600) / 60); var seconds = Math.floor(((diff %% 31536000) %% 86400) %% 3600) %% 60; $('.timer').text(days+":"+hours+":"+minutes+":"+seconds+" ago"); }, 1000); $('a[data-dna]').each(function( index ) { var dna = $(this).data('dna'); if (typeof CCPEVE !== 'undefined') { // inside IGB $(this).attr('href', 'javascript:CCPEVE.showFitting("'+dna+'");');} else { // outside IGB $(this).attr('href', '%s'+dna); } }); }); </script> </head> <body> <div id="canvas" data-role="page"> <div data-role="header"> <h1>Pyfa fits</h1> </div> <div data-role="content"> <div style="text-align: center;"><strong>Last updated:</strong> %s <small>(<span class="timer"></span>)</small></div> """ % (time.time(), dnaUrl, localDate) HTML += ' <ul data-role="listview" class="ui-listview-outer" data-inset="true" data-filter="true">\n' categoryList = list(sMkt.getShipRoot()) categoryList.sort(key=lambda _ship: _ship.name) count = 0 for group in categoryList: # init market group string to give ships something to attach to HTMLgroup = '' ships = list(sMkt.getShipList(group.ID)) ships.sort(key=lambda _ship: _ship.name) # Keep track of how many ships per group groupFits = 0 for ship in ships: fits = sFit.getFitsWithShip(ship.ID) if len(fits) > 0: groupFits += len(fits) HTMLship = ( ' <li data-role="collapsible" data-iconpos="right" data-shadow="false" ' 'data-corners="false">\n' ' <h2>' + ship.name + ' <span class="ui-li-count">' + str( len(fits)) + '</span></h2>\n' ' <ul data-role="listview" data-shadow="false" data-inset="true" ' 'data-corners="false">\n' ) for fit in fits: if self.stopRunning: return try: eftFit = Port.exportEft(getFit(fit[0])) print(eftFit) HTMLfit = ( ' <li data-role="collapsible" data-iconpos="right" data-shadow="false" ' 'data-corners="false">\n' ' <h2>' + fit[1] + '</h2>\n' ' <ul data-role="listview" data-shadow="false" data-inset="true" ' 'data-corners="false">\n' ) HTMLfit += ' <li><pre>' + eftFit + '\n </pre></li>\n' HTMLfit += ' </ul>\n </li>\n' HTMLship += HTMLfit except: pyfalog.warning("Failed to export line") continue finally: if self.callback: wx.CallAfter(self.callback, count) count += 1 HTMLgroup += HTMLship + (' </ul>\n' ' </li>\n') if groupFits > 0: # Market group header HTML += ( ' <li data-role="collapsible" data-iconpos="right" data-shadow="false" data-corners="false">\n' ' <h2>' + group.groupName + ' <span class="ui-li-count">' + str(groupFits) + '</span></h2>\n' ' <ul data-role="listview" data-shadow="false" data-inset="true" data-corners="false">\n' + HTMLgroup + ' </ul>\n' ' </li>' ) HTML += """ </ul> </div> </div> </body> </html>""" return HTML
def clipboardEftImps(self): fit = db_getFit(self.getActiveFit()) toClipboard(Port.exportEftImps(fit))