From 160c2f09422233b246b9e5390b34a29aa796f354 Mon Sep 17 00:00:00 2001 From: DarkPhoenix Date: Wed, 21 Aug 2019 17:39:06 +0300 Subject: [PATCH] Implement additions pane pasting via ctrl-v --- gui/mainFrame.py | 23 ++++++++++- service/port/eft.py | 90 +++++++++++++++++++++++++++++++++++++++++--- service/port/port.py | 48 ++++++++++++++++------- 3 files changed, 139 insertions(+), 22 deletions(-) diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 9c126bb54..9c92b3c82 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -739,11 +739,30 @@ class MainFrame(wx.Frame): activeFit = self.getActiveFit() try: importType, importData = Port().importFitFromBuffer(clipboard, activeFit) - # If it's mutated item - make sure there's at least base item specified if importType == "MutatedItem": # we've imported an Abyssal module, need to fire off the command to add it to the fit self.command.Submit(cmd.GuiImportLocalMutatedModuleCommand(activeFit, *importData[0])) - return # no need to do anything else + return + if importType == "AdditionsDrones": + if self.command.Submit(cmd.GuiImportLocalDronesCommand(activeFit, importData[0])): + self.additionsPane.select("Drones") + return + if importType == "AdditionsFighters": + if self.command.Submit(cmd.GuiImportLocalFightersCommand(activeFit, importData[0])): + self.additionsPane.select("Fighters") + return + if importType == "AdditionsImplants": + if self.command.Submit(cmd.GuiImportImplantsCommand(activeFit, importData[0])): + self.additionsPane.select("Implants") + return + if importType == "AdditionsBoosters": + if self.command.Submit(cmd.GuiImportBoostersCommand(activeFit, importData[0])): + self.additionsPane.select("Boosters") + return + if importType == "AdditionsCargo": + if self.command.Submit(cmd.GuiImportCargosCommand(activeFit, importData[0])): + self.additionsPane.select("Cargo") + return except: pyfalog.error("Attempt to import failed:\n{0}", clipboard) else: diff --git a/service/port/eft.py b/service/port/eft.py index 492abba9c..50a3a5219 100644 --- a/service/port/eft.py +++ b/service/port/eft.py @@ -54,6 +54,7 @@ EFT_OPTIONS = ( MODULE_CATS = ('Module', 'Subsystem', 'Structure Module') SLOT_ORDER = (FittingSlot.LOW, FittingSlot.MED, FittingSlot.HIGH, FittingSlot.RIG, FittingSlot.SUBSYSTEM, FittingSlot.SERVICE) OFFLINE_SUFFIX = '/OFFLINE' +NAME_CHARS = '[^,/\[\]]' # Characters which are allowed to be used in name def exportEft(fit, options, callback): @@ -193,10 +194,9 @@ def importEft(lines): aFit = AbstractFit() aFit.mutations = _importGetMutationData(lines) - nameChars = '[^,/\[\]]' # Characters which are allowed to be used in name stubPattern = '^\[.+?\]$' - modulePattern = '^(?P{0}+?)(,\s*(?P{0}+?))?(?P\s*{1})?(\s*\[(?P\d+?)\])?$'.format(nameChars, OFFLINE_SUFFIX) - droneCargoPattern = '^(?P{}+?) x(?P\d+?)$'.format(nameChars) + modulePattern = '^(?P{0}+?)(,\s*(?P{0}+?))?(?P\s*{1})?(\s*\[(?P\d+?)\])?$'.format(NAME_CHARS, OFFLINE_SUFFIX) + droneCargoPattern = '^(?P{}+?) x(?P\d+?)$'.format(NAME_CHARS) sections = [] for section in _importSectionIter(lines): @@ -864,12 +864,20 @@ class AbstractFit: self.cargo[itemSpec.item].amount += itemSpec.amount + +def _lineIter(text): + """Iterate over non-blank lines.""" + for line in text.splitlines(): + line = line.strip() + if line: + yield line + + def parseAdditions(text): items = [] sMkt = Market.getInstance() - pattern = '^(?P[^,/\[\]]+?)( x(?P\d+?))?$' - for line in text.splitlines(): - line = line.strip() + pattern = '^(?P{}+?)( x(?P\d+?))?$'.format(NAME_CHARS) + for line in _lineIter(text): m = re.match(pattern, line) if not m: continue @@ -880,3 +888,73 @@ def parseAdditions(text): amount = 1 if amount is None else int(amount) items.append((item, amount)) return items + + +def isValidDroneImport(text): + pattern = 'x\d+$' + for line in _lineIter(text): + if not re.search(pattern, line): + return False, () + itemData = parseAdditions(text) + if not itemData: + return False, () + for item, amount in itemData: + if not item.isDrone: + return False, () + return True, itemData + + +def isValidFighterImport(text): + pattern = 'x\d+$' + for line in _lineIter(text): + if not re.search(pattern, line): + return False, () + itemData = parseAdditions(text) + if not itemData: + return False, () + for item, amount in itemData: + if not item.isFighter: + return False, () + return True, itemData + + +def isValidCargoImport(text): + pattern = 'x\d+$' + for line in _lineIter(text): + if not re.search(pattern, line): + return False, () + itemData = parseAdditions(text) + if not itemData: + return False, () + for item, amount in itemData: + if item.isAbyssal: + return False, () + return True, itemData + + +def isValidImplantImport(text): + pattern = 'x\d+$' + for line in _lineIter(text): + if re.search(pattern, line): + return False, () + itemData = parseAdditions(text) + if not itemData: + return False, () + for item, amount in itemData: + if not item.isImplant: + return False, () + return True, itemData + + +def isValidBoosterImport(text): + pattern = 'x\d+$' + for line in _lineIter(text): + if re.search(pattern, line): + return False, () + itemData = parseAdditions(text) + if not itemData: + return False, () + for item, amount in itemData: + if not item.isBooster: + return False, () + return True, itemData diff --git a/service/port/port.py b/service/port/port.py index 38c687c3e..2db627bbc 100644 --- a/service/port/port.py +++ b/service/port/port.py @@ -32,7 +32,10 @@ from eos import db from eos.const import ImplantLocation from service.fit import Fit as svcFit from service.port.dna import exportDna, importDna -from service.port.eft import exportEft, importEft, importEftCfg +from service.port.eft import ( + exportEft, importEft, importEftCfg, + isValidDroneImport, isValidFighterImport, isValidCargoImport, + isValidImplantImport, isValidBoosterImport) from service.port.esi import exportESI, importESI from service.port.multibuy import exportMultiBuy from service.port.shared import IPortUser, UserCancelException, processing_notify @@ -144,7 +147,7 @@ class Port: continue try: - _, fitsImport = Port.importAuto(srcString, path, iportuser=iportuser) + importType, makesNewFits, fitsImport = Port.importAuto(srcString, path, iportuser=iportuser) fit_list += fitsImport except xml.parsers.expat.ExpatError: pyfalog.warning("Malformed XML in:\n{0}", path) @@ -188,9 +191,9 @@ class Port: # TODO: catch the exception? # activeFit is reserved?, bufferStr is unicode? (assume only clipboard string? sFit = svcFit.getInstance() - importType, importData = Port.importAuto(bufferStr, activeFit=activeFit) + importType, makesNewFits, importData = Port.importAuto(bufferStr, activeFit=activeFit) - if importType != "MutatedItem": + if makesNewFits: for fit in importData: fit.character = sFit.character fit.damagePattern = sFit.pattern @@ -217,41 +220,58 @@ class Port: # If XML-style start of tag encountered, detect as XML if re.search(RE_XML_START, firstLine): - return "XML", cls.importXml(string, iportuser) + return "XML", True, cls.importXml(string, iportuser) # If JSON-style start, parse as CREST/JSON if firstLine[0] == '{': - return "JSON", (cls.importESI(string),) + return "JSON", True, (cls.importESI(string),) # 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 path is not None: filename = os.path.split(path)[1] shipName = filename.rsplit('.')[0] - return "EFT Config", cls.importEftCfg(shipName, lines, iportuser) + return "EFT Config", True, cls.importEftCfg(shipName, lines, iportuser) # If no file is specified and there's comma between brackets, # consider that we have [ship, setup name] and detect like eft export format if re.match("\[.*,.*\]", firstLine): - return "EFT", (cls.importEft(lines),) + return "EFT", True, (cls.importEft(lines),) # Check if string is in DNA format dnaPattern = "\d+(:\d+(;\d+))*::" if re.match(dnaPattern, firstLine): - return "DNA", (cls.importDna(string),) + return "DNA", True, (cls.importDna(string),) dnaChatPattern = "{})>(?P[^<>]+)".format(dnaPattern) m = re.search(dnaChatPattern, firstLine) if m: - return "DNA", (cls.importDna(m.group("dna"), fitName=m.group("fitName")),) + return "DNA", True, (cls.importDna(m.group("dna"), fitName=m.group("fitName")),) - - # Assume that we import stand-alone abyssal module if all else fails if activeFit is not None: + # Try to import mutated module try: - return "MutatedItem", (parseMutant(lines),) + baseItem, mutaplasmidItem, mutations = parseMutant(lines) except: pass - + else: + if baseItem is not None and mutaplasmidItem is not None: + return "MutatedItem", False, ((baseItem, mutaplasmidItem, mutations),) + # Try to import into one of additions panels + isDrone, droneData = isValidDroneImport(string) + if isDrone: + return "AdditionsDrones", False, (droneData,) + isFighter, fighterData = isValidFighterImport(string) + if isFighter: + return "AdditionsFighters", False, (fighterData,) + isImplant, implantData = isValidImplantImport(string) + if isImplant: + return "AdditionsImplants", False, (implantData,) + isBooster, boosterData = isValidBoosterImport(string) + if isBooster: + return "AdditionsBoosters", False, (boosterData,) + isCargo, cargoData = isValidCargoImport(string) + if isCargo: + return "AdditionsCargo", False, (cargoData,) # EFT-related methods @staticmethod