Merge branch 'master' into master

This commit is contained in:
Ryan Holmes
2021-10-26 20:37:11 -04:00
committed by GitHub
238 changed files with 61078 additions and 19003 deletions

View File

@@ -193,11 +193,8 @@ class DroneView(Display):
@staticmethod
def droneKey(drone):
sMkt = Market.getInstance()
groupName = sMkt.getMarketGroupByItem(drone.item).marketGroupName
return (DRONE_ORDER.index(groupName), drone.item.name)
groupName = Market.getInstance().getMarketGroupByItem(drone.item).marketGroupName
return (DRONE_ORDER.index(groupName), drone.isMutated, drone.fullName)
def fitChanged(self, event):
event.Skip()

View File

@@ -26,7 +26,7 @@ from gui.builtinContextMenus import itemAmountChange
from gui.builtinContextMenus import itemProjectionRange
from gui.builtinContextMenus import droneSplitStack
from gui.builtinContextMenus import itemVariationChange
from gui.builtinContextMenus import moduleMutations
from gui.builtinContextMenus import itemMutations
from gui.builtinContextMenus import moduleFill
from gui.builtinContextMenus import moduleMutatedExport
from gui.builtinContextMenus import skillAffectors

View File

@@ -5,7 +5,7 @@ from gui import fitCommands as cmd
from gui.contextMenu import ContextMenuUnconditional
from gui.utils.clipboard import fromClipboard
from service.fit import Fit
from service.port.eft import parseAdditions
from service.port.eft import parseAdditions, importGetMutationData, lineIter
_t = wx.GetTranslation
@@ -41,9 +41,12 @@ class AdditionsImport(ContextMenuUnconditional):
def activate(self, callingWindow, fullContext, i):
text = fromClipboard()
items = parseAdditions(text)
lines = list(lineIter(text))
mutaData = importGetMutationData(lines)
text = '\n'.join(lines)
items = parseAdditions(text, mutaData=mutaData)
filterFunc = self.viewSpecMap[self.srcContext][1]
items = [(i.ID, a) for i, a in items if filterFunc(i)]
items = [(i.ID, a, m) for i, a, m in items if filterFunc(i)]
if not items:
return
command = self.viewSpecMap[self.srcContext][2]

View File

@@ -8,7 +8,7 @@ from eos.saveddata.cargo import Cargo as es_Cargo
from eos.saveddata.drone import Drone
from eos.saveddata.fighter import Fighter as es_Fighter
from eos.saveddata.fit import Fit as es_Fit
from gui.contextMenu import ContextMenuSingle
from gui.contextMenu import ContextMenuCombined
from service.fit import Fit
# noinspection PyPackageRequirements
@@ -16,12 +16,12 @@ from service.fit import Fit
_t = wx.GetTranslation
class ChangeItemAmount(ContextMenuSingle):
class ChangeItemAmount(ContextMenuCombined):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, callingWindow, srcContext, mainItem):
def display(self, callingWindow, srcContext, mainItem, selection):
if srcContext not in ("droneItem", "projectedDrone", "cargoItem", "projectedFit", "fighterItem", "projectedFighter"):
return False
@@ -30,10 +30,12 @@ class ChangeItemAmount(ContextMenuSingle):
return True
def getText(self, callingWindow, itmContext, mainItem):
def getText(self, callingWindow, itmContext, mainItem, selection):
if isinstance(mainItem, es_Cargo):
return _t("Change Selection Quantity")
return _t("Change {0} Quantity").format(itmContext)
def activate(self, callingWindow, fullContext, mainItem, i):
def activate(self, callingWindow, fullContext, mainItem, selection, i):
fitID = self.mainFrame.getActiveFit()
srcContext = fullContext[0]
if isinstance(mainItem, es_Fit):
@@ -56,8 +58,12 @@ class ChangeItemAmount(ContextMenuSingle):
cleanInput = int(float(re.sub(r'[^0-9.]', '', dlg.input.GetLineText(0).strip())))
if isinstance(mainItem, es_Cargo):
self.mainFrame.command.Submit(cmd.GuiChangeCargoAmountCommand(
fitID=fitID, itemID=mainItem.itemID, amount=cleanInput))
itemIDs = []
for cargo in selection:
if cargo in fit.cargo:
itemIDs.append(cargo.itemID)
self.mainFrame.command.Submit(cmd.GuiChangeCargosAmountCommand(
fitID=fitID, itemIDs=itemIDs, amount=cleanInput))
elif isinstance(mainItem, Drone):
if srcContext == "projectedDrone":
self.mainFrame.command.Submit(cmd.GuiChangeProjectedDroneAmountCommand(

View File

@@ -1,16 +1,19 @@
# noinspection PyPackageRequirements
import re
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from gui.contextMenu import ContextMenuSingle
from gui.fitCommands import GuiConvertMutatedLocalModuleCommand, GuiRevertMutatedLocalModuleCommand
from gui.fitCommands import (
GuiConvertMutatedLocalModuleCommand, GuiRevertMutatedLocalModuleCommand,
GuiConvertMutatedLocalDroneCommand, GuiRevertMutatedLocalDroneCommand)
from service.fit import Fit
_t = wx.GetTranslation
class ChangeModuleMutation(ContextMenuSingle):
class ChangeItemMutation(ContextMenuSingle):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
@@ -18,10 +21,10 @@ class ChangeModuleMutation(ContextMenuSingle):
def display(self, callingWindow, srcContext, mainItem):
if srcContext != "fittingModule" or self.mainFrame.getActiveFit() is None:
if srcContext not in ("fittingModule", "droneItem") or self.mainFrame.getActiveFit() is None:
return False
if mainItem is None or mainItem.isEmpty:
if mainItem is None or getattr(mainItem, 'isEmpty', False):
return False
if len(mainItem.item.mutaplasmids) == 0 and not mainItem.isMutated:
@@ -42,24 +45,27 @@ class ChangeModuleMutation(ContextMenuSingle):
menu = rootMenu if msw else sub
for item in mainItem.item.mutaplasmids:
label = item.item.name
for mutaplasmid in mainItem.item.mutaplasmids:
id = ContextMenuSingle.nextID()
self.eventIDs[id] = (item, mainItem)
skillItem = wx.MenuItem(menu, id, label)
menu.Bind(wx.EVT_MENU, self.handleMenu, skillItem)
sub.Append(skillItem)
self.eventIDs[id] = (mutaplasmid, mainItem)
mItem = wx.MenuItem(menu, id, mutaplasmid.shortName)
menu.Bind(wx.EVT_MENU, self.handleMenu, mItem)
sub.Append(mItem)
return sub
def handleMenu(self, event):
mutaplasmid, mod = self.eventIDs[event.Id]
mutaplasmid, item = self.eventIDs[event.Id]
fitID = self.mainFrame.getActiveFit()
fit = Fit.getInstance().getFit(fitID)
if mod in fit.modules:
position = fit.modules.index(mod)
if item in fit.modules:
position = fit.modules.index(item)
self.mainFrame.command.Submit(GuiConvertMutatedLocalModuleCommand(
fitID=fitID, position=position, mutaplasmid=mutaplasmid))
elif item in fit.drones:
position = fit.drones.index(item)
self.mainFrame.command.Submit(GuiConvertMutatedLocalDroneCommand(
fitID=fitID, position=position, mutaplasmid=mutaplasmid))
def activate(self, callingWindow, fullContext, mainItem, i):
fitID = self.mainFrame.getActiveFit()
@@ -68,9 +74,13 @@ class ChangeModuleMutation(ContextMenuSingle):
position = fit.modules.index(mainItem)
self.mainFrame.command.Submit(GuiRevertMutatedLocalModuleCommand(
fitID=fitID, position=position))
elif mainItem in fit.drones:
position = fit.drones.index(mainItem)
self.mainFrame.command.Submit(GuiRevertMutatedLocalDroneCommand(
fitID=fitID, position=position))
def getBitmap(self, callingWindow, context, mainItem):
return None
ChangeModuleMutation.register()
ChangeItemMutation.register()

View File

@@ -355,4 +355,5 @@ class ItemParams(wx.Panel):
fvalue = roundDec(value, digits)
else:
fvalue = value
return "%s %s" % (fvalue, unit)
unitSuffix = f' {unit}' if unit is not None else ''
return f'{fvalue}{unitSuffix}'

View File

@@ -18,23 +18,22 @@ _t = wx.GetTranslation
class ItemMutatorPanel(wx.Panel):
def __init__(self, parent, mod):
def __init__(self, parent, stuff):
wx.Panel.__init__(self, parent)
self.stuff = mod
self.stuff = stuff
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
mainSizer = wx.BoxSizer(wx.VERTICAL)
headerSizer = wx.BoxSizer(wx.HORIZONTAL)
headerSizer.AddStretchSpacer()
itemIcon = BitmapLoader.getStaticBitmap(mod.item.iconID, self, "icons")
itemIcon = BitmapLoader.getStaticBitmap(stuff.item.iconID, self, "icons")
if itemIcon is not None:
headerSizer.Add(itemIcon, 0, 0, 0)
mutaIcon = BitmapLoader.getStaticBitmap(mod.mutaplasmid.item.iconID, self, "icons")
mutaIcon = BitmapLoader.getStaticBitmap(stuff.mutaplasmid.item.iconID, self, "icons")
if mutaIcon is not None:
headerSizer.Add(mutaIcon, 0, wx.LEFT, 0)
sourceItemShort = "{} {}".format(mod.mutaplasmid.item.name.split(" ")[0], mod.baseItem.name)
sourceItemText = wx.StaticText(self, wx.ID_ANY, sourceItemShort)
sourceItemText = wx.StaticText(self, wx.ID_ANY, stuff.fullName)
font = parent.GetFont()
font.SetWeight(wx.BOLD)
sourceItemText.SetFont(font)
@@ -43,7 +42,7 @@ class ItemMutatorPanel(wx.Panel):
mainSizer.Add(headerSizer, 0, wx.ALL | wx.EXPAND, 5)
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND, 0)
self.mutaList = ItemMutatorList(self, mod)
self.mutaList = ItemMutatorList(self, stuff)
mainSizer.Add(self.mutaList, 1, wx.EXPAND | wx.ALL, 0)
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND, 0)
@@ -68,13 +67,13 @@ class ItemMutatorPanel(wx.Panel):
class ItemMutatorList(wx.ScrolledWindow):
def __init__(self, parent, mod):
def __init__(self, parent, stuff):
wx.ScrolledWindow.__init__(self, parent)
self.SetScrollRate(0, 15)
self.carryingFitID = gui.mainFrame.MainFrame.getInstance().getActiveFit()
self.initialMutations = {}
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
self.mod = mod
self.stuff = stuff
self.timer = None
self.isModified = False
@@ -91,9 +90,8 @@ class ItemMutatorList(wx.ScrolledWindow):
('Damage Control', 'duration'): True,
('Siege Module', 'siegeLocalLogisticsDurationBonus'): False
}
first = True
for m in sorted(mod.mutators.values(), key=lambda x: x.attribute.displayName):
for m in sorted(stuff.mutators.values(), key=lambda x: x.attribute.displayName):
if m.baseValue == 0:
continue
if not first:
@@ -102,10 +100,10 @@ class ItemMutatorList(wx.ScrolledWindow):
self.initialMutations[m.attrID] = m.value
highIsGood = higOverrides.get((mod.item.group.name, m.attribute.name), m.highIsGood)
highIsGood = higOverrides.get((stuff.item.group.name, m.attribute.name), m.highIsGood)
# Format: [raw value, modifier applied to base raw value, display value]
range1 = (m.minValue, m.attribute.unit.SimplifyValue(m.minValue))
range2 = (m.maxValue, m.attribute.unit.SimplifyValue(m.maxValue))
range1 = (m.minValue, self._simplifyValue(m, m.minValue))
range2 = (m.maxValue, self._simplifyValue(m, m.maxValue))
# minValue/maxValue do not always correspond to min/max, because these are
# just base value multiplied by minMod/maxMod, and in case base is negative
@@ -148,11 +146,11 @@ class ItemMutatorList(wx.ScrolledWindow):
headingSizer.Add(displayName, 3, wx.ALL | wx.EXPAND, 0)
worseVal = ItemParams.FormatValue(*m.attribute.unit.PreformatValue(worseRange[0]), rounding='dec')
worseVal = ItemParams.FormatValue(*self._preformatValue(m, worseRange[0]), rounding='dec')
worseText = wx.StaticText(self, wx.ID_ANY, worseVal)
worseText.SetForegroundColour(badColor)
betterVal = ItemParams.FormatValue(*m.attribute.unit.PreformatValue(betterRange[0]), rounding='dec')
betterVal = ItemParams.FormatValue(*self._preformatValue(m, betterRange[0]), rounding='dec')
betterText = wx.StaticText(self, wx.ID_ANY, betterVal)
betterText.SetForegroundColour(goodColor)
@@ -163,23 +161,38 @@ class ItemMutatorList(wx.ScrolledWindow):
sizer.Add(headingSizer, 0, wx.ALL | wx.EXPAND, 5)
slider = AttributeSlider(parent=self,
baseValue=m.attribute.unit.SimplifyValue(sliderBaseValue),
baseValue=self._simplifyValue(m, sliderBaseValue),
minValue=displayMinRange[1],
maxValue=displayMaxRange[1],
inverse=displayMaxRange is worseRange)
slider.SetValue(m.attribute.unit.SimplifyValue(m.value), False)
slider.SetValue(self._simplifyValue(m, m.value), False)
slider.Bind(EVT_VALUE_CHANGED, self.changeMutatedValue)
self.event_mapping[slider] = m
sizer.Add(slider, 0, wx.RIGHT | wx.LEFT | wx.EXPAND, 10)
self.SetSizer(sizer)
def _simplifyValue(self, mutator, value):
if mutator.attribute.unit is None:
return value
return mutator.attribute.unit.SimplifyValue(value)
def _complicateValue(self, mutator, value):
if mutator.attribute.unit is None:
return value
return mutator.attribute.unit.ComplicateValue(value)
def _preformatValue(self, mutator, value):
if mutator.attribute.unit is None:
return value, None
return mutator.attribute.unit.PreformatValue(value)
def changeMutatedValue(self, evt):
if evt.AffectsModifiedFlag:
self.isModified = True
m = self.event_mapping[evt.Object]
value = evt.Value
value = m.attribute.unit.ComplicateValue(value)
value = self._complicateValue(m, value)
sFit = Fit.getInstance()
sFit.changeMutatedValuePrelim(m, value)
@@ -198,7 +211,7 @@ class ItemMutatorList(wx.ScrolledWindow):
sFit = Fit.getInstance()
for slider, m in self.event_mapping.items():
value = sFit.changeMutatedValuePrelim(m, m.baseValue)
value = m.attribute.unit.SimplifyValue(value)
value = self._simplifyValue(m, value)
slider.SetValue(value, affect_modified_flag=False)
evt.Skip()
@@ -208,7 +221,7 @@ class ItemMutatorList(wx.ScrolledWindow):
for slider, m in self.event_mapping.items():
value = random.uniform(m.minValue, m.maxValue)
value = sFit.changeMutatedValuePrelim(m, value)
value = m.attribute.unit.SimplifyValue(value)
value = self._simplifyValue(m, value)
slider.SetValue(value, affect_modified_flag=False)
evt.Skip()
@@ -218,7 +231,7 @@ class ItemMutatorList(wx.ScrolledWindow):
for slider, m in self.event_mapping.items():
if m.attrID in self.initialMutations:
value = sFit.changeMutatedValuePrelim(m, self.initialMutations[m.attrID])
value = m.attribute.unit.SimplifyValue(value)
value = self._simplifyValue(m, value)
slider.SetValue(value, affect_modified_flag=False)
evt.Skip()
@@ -226,25 +239,34 @@ class ItemMutatorList(wx.ScrolledWindow):
# Submit mutation changes
sFit = Fit.getInstance()
fit = sFit.getFit(self.carryingFitID)
if self.mod in fit.modules:
isCurrentMod = self.stuff in fit.modules
isCurrentDrone = self.stuff in fit.drones
if isCurrentMod or isCurrentDrone:
if self.isModified:
currentMutation = {}
for slider, m in self.event_mapping.items():
# Sliders may have more up-to-date info than mutator in case we changed
# value in slider and without confirming it, decided to close window
value = slider.GetValue()
value = m.attribute.unit.ComplicateValue(value)
value = self._complicateValue(m, value)
if value != m.value:
value = sFit.changeMutatedValuePrelim(m, value)
currentMutation[m.attrID] = value
else:
currentMutation = self.initialMutations
mainFrame = gui.mainFrame.MainFrame.getInstance()
mainFrame.getCommandForFit(self.carryingFitID).Submit(cmd.GuiChangeLocalModuleMutationCommand(
fitID=self.carryingFitID,
position=fit.modules.index(self.mod),
mutation=currentMutation,
oldMutation=self.initialMutations))
if isCurrentMod:
mainFrame.getCommandForFit(self.carryingFitID).Submit(cmd.GuiChangeLocalModuleMutationCommand(
fitID=self.carryingFitID,
position=fit.modules.index(self.stuff),
mutation=currentMutation,
oldMutation=self.initialMutations))
elif isCurrentDrone:
mainFrame.getCommandForFit(self.carryingFitID).Submit(cmd.GuiChangeLocalDroneMutationCommand(
fitID=self.carryingFitID,
position=fit.drones.index(self.stuff),
mutation=currentMutation,
oldMutation=self.initialMutations))
for slider in self.event_mapping:
slider.OnWindowClose()

View File

@@ -37,118 +37,19 @@ class PFEsiPref(PreferenceView):
rbSizer = wx.BoxSizer(wx.HORIZONTAL)
self.rbMode = wx.RadioBox(panel, -1, _t("Login Authentication Method"), wx.DefaultPosition, wx.DefaultSize,
[_t('Local Server'), _t('Manual')], 1, wx.RA_SPECIFY_COLS)
self.rbMode.SetItemToolTip(0, _t("This options starts a local webserver that the web application will call back to"
self.rbMode.SetItemToolTip(0, _t("This option starts a local webserver that EVE SSO Server will call back to"
" with information about the character login."))
self.rbMode.SetItemToolTip(1, _t("This option prompts users to copy and paste information from the web application "
"to allow for character login. Use this if having issues with the local server."))
self.rbSsoMode = wx.RadioBox(panel, -1, _t("SSO Mode"), wx.DefaultPosition, wx.DefaultSize,
[_t('pyfa.io'), _t('Custom application')], 1, wx.RA_SPECIFY_COLS)
self.rbSsoMode.SetItemToolTip(0, _t("This options routes SSO Logins through pyfa.io, allowing you to easily login "
"without any configuration. When in doubt, use this option."))
self.rbSsoMode.SetItemToolTip(1, _t("This option goes through EVE SSO directly, but requires more configuration. Use "
"this if pyfa.io is blocked for some reason, or if you do not wish to route data throguh pyfa.io."))
self.rbMode.SetItemToolTip(1, _t("This option prompts users to copy and paste information to allow for"
" character login. Use this if having issues with the local server."))
self.rbMode.SetSelection(self.settings.get('loginMode'))
self.rbSsoMode.SetSelection(self.settings.get('ssoMode'))
rbSizer.Add(self.rbSsoMode, 1, wx.ALL, 5)
rbSizer.Add(self.rbMode, 1, wx.TOP | wx.RIGHT, 5)
self.rbMode.Bind(wx.EVT_RADIOBOX, self.OnModeChange)
self.rbSsoMode.Bind(wx.EVT_RADIOBOX, self.OnSSOChange)
mainSizer.Add(rbSizer, 1, wx.ALL | wx.EXPAND, 0)
detailsTitle = wx.StaticText(panel, wx.ID_ANY, _t("Custom Application"), wx.DefaultPosition, wx.DefaultSize, 0)
detailsTitle.Wrap(-1)
detailsTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
mainSizer.Add(detailsTitle, 0, wx.ALL, 5)
mainSizer.Add(wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
wx.EXPAND, 5)
fgAddrSizer = wx.FlexGridSizer(2, 2, 0, 0)
fgAddrSizer.AddGrowableCol(1)
fgAddrSizer.SetFlexibleDirection(wx.BOTH)
fgAddrSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
self.stSetID = wx.StaticText(panel, wx.ID_ANY, _t("Client ID:"), wx.DefaultPosition, wx.DefaultSize, 0)
self.stSetID.Wrap(-1)
fgAddrSizer.Add(self.stSetID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.inputClientID = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientID'), wx.DefaultPosition,
wx.DefaultSize, 0)
fgAddrSizer.Add(self.inputClientID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
self.stSetSecret = wx.StaticText(panel, wx.ID_ANY, _t("Client Secret:"), wx.DefaultPosition, wx.DefaultSize, 0)
self.stSetSecret.Wrap(-1)
fgAddrSizer.Add(self.stSetSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
self.inputClientSecret = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientSecret'), wx.DefaultPosition,
wx.DefaultSize, 0)
fgAddrSizer.Add(self.inputClientSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
self.inputClientID.Bind(wx.EVT_TEXT, self.OnClientDetailChange)
self.inputClientSecret.Bind(wx.EVT_TEXT, self.OnClientDetailChange)
mainSizer.Add(fgAddrSizer, 0, wx.EXPAND, 5)
# self.stTimout = wx.StaticText(panel, wx.ID_ANY, "Timeout (seconds):", wx.DefaultPosition, wx.DefaultSize, 0)
# self.stTimout.Wrap(-1)
#
# timeoutSizer.Add(self.stTimout, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
# self.intTimeout = IntCtrl(panel, max=300000, limited=True, value=self.settings.get('timeout'))
# timeoutSizer.Add(self.intTimeout, 0, wx.ALL, 5)
# self.intTimeout.Bind(wx.lib.intctrl.EVT_INT, self.OnTimeoutChange)
#
# mainSizer.Add(timeoutSizer, 0, wx.ALL | wx.EXPAND, 0)
# detailsTitle = wx.StaticText(panel, wx.ID_ANY, "CREST client details", wx.DefaultPosition, wx.DefaultSize, 0)
# detailsTitle.Wrap(-1)
# detailsTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))
#
# mainSizer.Add(detailsTitle, 0, wx.ALL, 5)
# mainSizer.Add(wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
# wx.EXPAND, 5)
# fgAddrSizer = wx.FlexGridSizer(2, 2, 0, 0)
# fgAddrSizer.AddGrowableCol(1)
# fgAddrSizer.SetFlexibleDirection(wx.BOTH)
# fgAddrSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)
#
# self.stSetID = wx.StaticText(panel, wx.ID_ANY, "Client ID:", wx.DefaultPosition, wx.DefaultSize, 0)
# self.stSetID.Wrap(-1)
# fgAddrSizer.Add(self.stSetID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
#
# self.inputClientID = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientID'), wx.DefaultPosition,
# wx.DefaultSize, 0)
#
# fgAddrSizer.Add(self.inputClientID, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
#
# self.stSetSecret = wx.StaticText(panel, wx.ID_ANY, "Client Secret:", wx.DefaultPosition, wx.DefaultSize, 0)
# self.stSetSecret.Wrap(-1)
#
# fgAddrSizer.Add(self.stSetSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
#
# self.inputClientSecret = wx.TextCtrl(panel, wx.ID_ANY, self.settings.get('clientSecret'), wx.DefaultPosition,
# wx.DefaultSize, 0)
#
# fgAddrSizer.Add(self.inputClientSecret, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 5)
#
# self.btnApply = wx.Button(panel, wx.ID_ANY, "Save Client Settings", wx.DefaultPosition, wx.DefaultSize, 0)
# self.btnApply.Bind(wx.EVT_BUTTON, self.OnBtnApply)
#
# mainSizer.Add(fgAddrSizer, 0, wx.EXPAND, 5)
# mainSizer.Add(self.btnApply, 0, wx.ALIGN_RIGHT, 5)
# self.ToggleProxySettings(self.settings.get('loginMode'))
self.ToggleSSOMode(self.settings.get('ssoMode'))
panel.SetSizer(mainSizer)
panel.Layout()
@@ -158,32 +59,6 @@ class PFEsiPref(PreferenceView):
def OnModeChange(self, event):
self.settings.set('loginMode', event.GetInt())
def OnSSOChange(self, event):
self.settings.set('ssoMode', event.GetInt())
self.ToggleSSOMode(event.GetInt())
def ToggleSSOMode(self, mode):
if mode:
self.stSetID.Enable()
self.inputClientID.Enable()
self.stSetSecret.Enable()
self.inputClientSecret.Enable()
self.rbMode.Disable()
else:
self.stSetID.Disable()
self.inputClientID.Disable()
self.stSetSecret.Disable()
self.inputClientSecret.Disable()
self.rbMode.Enable()
def OnClientDetailChange(self, evt):
self.settings.set('clientID', self.inputClientID.GetValue().strip())
self.settings.set('clientSecret', self.inputClientSecret.GetValue().strip())
# sEsi = Esi.getInstance()
# sEsi.delAllCharacters()
#
def getImage(self):
return BitmapLoader.getBitmap("eve", "gui")

View File

@@ -149,6 +149,14 @@ class PFGeneralPref(PreferenceView):
_t('When disabled, reloads charges just in selected modules. Action can be reversed by holding Ctrl or Alt key while changing charge.')))
mainSizer.Add(self.cbReloadAll, 0, wx.ALL | wx.EXPAND, 5)
self.cbExpMutants = wx.CheckBox(panel, wx.ID_ANY, _t("Include more information in names of mutated items"),
wx.DefaultPosition, wx.DefaultSize, 0)
if "wxGTK" not in wx.PlatformInfo:
self.cbExpMutants.SetCursor(helpCursor)
self.cbExpMutants.SetToolTip(wx.ToolTip(
_t('Use short mutaplasmid name and base item name instead of actual item name. Works if EVE data language is set to English.')))
mainSizer.Add(self.cbExpMutants, 0, wx.ALL | wx.EXPAND, 5)
self.rbAddLabels = wx.RadioBox(panel, -1, _t("Extra info in Additions panel tab names"), wx.DefaultPosition, wx.DefaultSize,
[_t("None"), _t("Quantity of active items"), _t("Quantity of all items")], 1, wx.RA_SPECIFY_COLS)
mainSizer.Add(self.rbAddLabels, 0, wx.EXPAND | wx.TOP | wx.RIGHT | wx.BOTTOM, 10)
@@ -169,6 +177,7 @@ class PFGeneralPref(PreferenceView):
self.cbOpenFitInNew.SetValue(self.sFit.serviceFittingOptions["openFitInNew"])
self.cbShowShipBrowserTooltip.SetValue(self.sFit.serviceFittingOptions["showShipBrowserTooltip"])
self.cbReloadAll.SetValue(self.sFit.serviceFittingOptions["ammoChangeAll"])
self.cbExpMutants.SetValue(self.sFit.serviceFittingOptions["expandedMutantNames"])
self.rbAddLabels.SetSelection(self.sFit.serviceFittingOptions["additionsLabels"])
self.cbGlobalChar.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalCharStateChange)
@@ -184,6 +193,7 @@ class PFGeneralPref(PreferenceView):
self.cbOpenFitInNew.Bind(wx.EVT_CHECKBOX, self.onCBOpenFitInNew)
self.cbShowShipBrowserTooltip.Bind(wx.EVT_CHECKBOX, self.onCBShowShipBrowserTooltip)
self.cbReloadAll.Bind(wx.EVT_CHECKBOX, self.onCBReloadAll)
self.cbExpMutants.Bind(wx.EVT_CHECKBOX, self.onCBExpMutants)
self.cbRackLabels.Enable(self.sFit.serviceFittingOptions["rackSlots"] or False)
@@ -266,6 +276,11 @@ class PFGeneralPref(PreferenceView):
def onCBReloadAll(self, event):
self.sFit.serviceFittingOptions["ammoChangeAll"] = self.cbReloadAll.GetValue()
def onCBExpMutants(self, event):
self.sFit.serviceFittingOptions["expandedMutantNames"] = self.cbExpMutants.GetValue()
fitID = self.mainFrame.getActiveFit()
wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID,)))
def OnAddLabelsChange(self, event):
self.sFit.serviceFittingOptions["additionsLabels"] = event.GetInt()
fitID = self.mainFrame.getActiveFit()

View File

@@ -70,7 +70,10 @@ class BaseName(ViewColumn):
stuff = stuff.item
if isinstance(stuff, Drone):
return "%dx %s" % (stuff.amount, stuff.item.name)
if FitSvc.getInstance().serviceFittingOptions["expandedMutantNames"]:
return "%dx %s" % (stuff.amount, stuff.fullName)
else:
return "%dx %s" % (stuff.amount, stuff.item.name)
elif isinstance(stuff, Fighter):
return "%d/%d %s" % \
(stuff.amount, stuff.getModifiedItemAttr("fighterSquadronMaxSize"), stuff.item.name)
@@ -117,7 +120,10 @@ class BaseName(ViewColumn):
if stuff.isEmpty:
return "%s Slot" % FittingSlot(stuff.slot).name.capitalize()
else:
return stuff.item.customName
if FitSvc.getInstance().serviceFittingOptions["expandedMutantNames"]:
return stuff.fullName
else:
return stuff.item.customName
elif isinstance(stuff, Implant):
return stuff.item.name
elif isinstance(stuff, TargetProfile):

View File

@@ -42,6 +42,7 @@ from gui.contextMenu import ContextMenu
from gui.utils.clipboard import fromClipboard, toClipboard
from service.character import Character
from service.esi import Esi
from service.esiAccess import APIException
from service.fit import Fit
from service.market import Market
@@ -888,14 +889,7 @@ class APIView(wx.Panel):
def fetchCallback(e=None):
if e:
pyfalog.warn("Error fetching skill information for character for __fetchCallback")
exc_type, exc_value, exc_trace = e
if config.debug:
exc_value = ''.join(traceback.format_exception(exc_type, exc_value, exc_trace))
pyfalog.warn(exc_value)
wx.MessageBox(
_t("Error fetching skill information"),
_t("Error"), wx.ICON_ERROR | wx.STAY_ON_TOP)
SkillFetchExceptionHandler(e)
else:
wx.MessageBox(
_t("Successfully fetched skills"), _t("Success"), wx.ICON_INFORMATION | wx.STAY_ON_TOP)
@@ -926,3 +920,24 @@ class SecStatusDialog(wx.Dialog):
self.Layout()
self.Center(wx.BOTH)
class SkillFetchExceptionHandler:
def __init__(self, e):
from gui.esiFittings import ESIExceptionHandler
exc_type, exc_value, exc_trace = e
if config.debug:
exc_value = ''.join(traceback.format_exception(exc_type, exc_value, exc_trace))
pyfalog.warn(exc_value)
try:
try:
raise exc_value
except APIException as ex:
pyfalog.error(ex)
ESIExceptionHandler(ex)
except Exception as ex:
pyfalog.error(ex)
wx.MessageBox(
_t("Error fetching skill information"),
_t("Error"), wx.ICON_ERROR | wx.STAY_ON_TOP)

View File

@@ -163,15 +163,9 @@ class CharacterSelection(wx.Panel):
if e is None:
self.refreshCharacterList()
else:
from gui.characterEditor import SkillFetchExceptionHandler
pyfalog.warn("Error fetching skill information for character for refreshAPICallback")
exc_type, exc_value, exc_trace = e
if config.debug:
exc_value = ''.join(traceback.format_exception(exc_type, exc_value, exc_trace))
pyfalog.warn(exc_value)
wx.MessageBox(
_t("Error fetching skill information"),
_t("Error"), wx.ICON_ERROR | wx.STAY_ON_TOP)
SkillFetchExceptionHandler(e)
def charChanged(self, event):
fitID = self.mainFrame.getActiveFit()

View File

@@ -9,6 +9,7 @@ import config
import gui.globalEvents as GE
from eos.db import getItem
from eos.saveddata.cargo import Cargo
import gui.mainFrame
from gui.auxWindow import AuxiliaryFrame
from gui.display import Display
from gui.characterEditor import APIView
@@ -132,7 +133,7 @@ class EveFittings(AuxiliaryFrame):
except APIException as ex:
# Can't do this in a finally because then it obscures the message dialog
del waitDialog # noqa: F821
ESIExceptionHandler(self, ex)
ESIExceptionHandler(ex)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as ex:
@@ -149,6 +150,7 @@ class EveFittings(AuxiliaryFrame):
self.mainFrame._openAfterImport(fits)
def deleteFitting(self, event):
self.statusbar.SetStatusText("")
sEsi = Esi.getInstance()
selection = self.fitView.fitSelection
if not selection:
@@ -164,16 +166,26 @@ class EveFittings(AuxiliaryFrame):
if activeChar is None:
return
try:
sEsi.delFitting(activeChar, data['fitting_id'])
# repopulate the fitting list
self.fitTree.populateSkillTree(self.fittings)
self.fitView.update([])
try:
sEsi.delFitting(activeChar, data['fitting_id'])
# repopulate the fitting list
self.fitTree.populateSkillTree(self.fittings)
self.fitView.update([])
except APIException as ex:
pyfalog.error(ex)
self.statusbar.SetStatusText("Failed to delete fit: ESI error {} received - {}".format(ex.status_code, ex.response["error"]))
try:
ESIExceptionHandler(ex)
except:
# don't need to do anything - we should already have error code in the status
pass
except requests.exceptions.ConnectionError:
msg = _t("Connection error, please check your internet connection")
pyfalog.error(msg)
self.statusbar.SetStatusText(msg)
def deleteAllFittings(self, event):
self.statusbar.SetStatusText("")
sEsi = Esi.getInstance()
activeChar = self.getActiveCharacter()
if activeChar is None:
@@ -186,20 +198,30 @@ class EveFittings(AuxiliaryFrame):
) as dlg:
if dlg.ShowModal() == wx.ID_YES:
try:
for fit in self.fittings:
sEsi.delFitting(activeChar, fit['fitting_id'])
anyDeleted = True
try:
for fit in self.fittings:
sEsi.delFitting(activeChar, fit['fitting_id'])
anyDeleted = True
except APIException as ex:
pyfalog.error(ex)
if anyDeleted:
msg = "Some fits were not deleted: ESI error {} received - {}".format(ex.status_code,
ex.response["error"])
else:
msg = "Failed to delete fits: ESI error {} received - {}".format(ex.status_code,
ex.response["error"])
pyfalog.error(msg)
self.statusbar.SetStatusText(msg)
try:
ESIExceptionHandler(ex)
except:
# don't need to do anything - we should already have error code in the status
pass
except requests.exceptions.ConnectionError:
msg = "Connection error, please check your internet connection"
pyfalog.error(msg)
self.statusbar.SetStatusText(msg)
except APIException as ex:
if anyDeleted:
msg = "Some fits were not deleted: ESI error {} received".format(ex.status_code)
else:
msg = "Failed to delete fits: ESI error {} received".format(ex.status_code)
pyfalog.error(msg)
self.statusbar.SetStatusText(msg)
# repopulate the fitting list
self.fitTree.populateSkillTree(self.fittings)
self.fitView.update([])
@@ -222,15 +244,33 @@ class ESIServerExceptionHandler:
class ESIExceptionHandler:
# todo: make this a generate excetpion handler for all calls
def __init__(self, parentWindow, ex):
if ex.response['error'].startswith('Token is not valid') or ex.response['error'] == 'invalid_token': # todo: this seems messy, figure out a better response
def __init__(self, ex):
# raise ex
if ex.response['error'].startswith('Token is not valid') \
or ex.response['error'] == 'invalid_token' \
or ex.response['error'] == 'invalid_grant': # todo: this seems messy, figure out a better response
pyfalog.error(ex)
with wx.MessageDialog(
parentWindow,
gui.mainFrame.MainFrame.getInstance(),
_t("There was an error validating characters' SSO token. Please try "
"logging into the character again to reset the token."),
_t("Invalid Token"),
wx.OK | wx.ICON_ERROR
wx.OK | wx.ICON_ERROR | wx.CANCEL
) as dlg:
dlg.SetOKLabel("Manage ESI Characters")
ret = dlg.ShowModal()
if ret == wx.ID_OK:
SsoCharacterMgmt.openOne(parent=gui.mainFrame.MainFrame.getInstance())
# todo: spawn manage esi characters
pass
elif ex.response['error'].startswith('Timeout contacting'):
pyfalog.error(ex)
with wx.MessageDialog(
gui.mainFrame.MainFrame.getInstance(),
"HTTP %s: %s\n\n" % (ex.status_code, ex.response['error'])
+ _t("The server took too long to response. Please try again in a moment."),
_t("Timeout"),
wx.OK | wx.ICON_ERROR
) as dlg:
dlg.ShowModal()
else:
@@ -335,9 +375,9 @@ class ExportToEve(AuxiliaryFrame):
pyfalog.warning(msg)
self.statusbar.SetStatusText(msg, 1)
return
res = sEsi.postFitting(activeChar, data)
try:
res = sEsi.postFitting(activeChar, data)
res.raise_for_status()
self.statusbar.SetStatusText("", 0)
self.statusbar.SetStatusText(res.reason, 1)
@@ -346,19 +386,19 @@ class ExportToEve(AuxiliaryFrame):
pyfalog.error(msg)
self.statusbar.SetStatusText(_t("ERROR"), 0)
self.statusbar.SetStatusText(msg, 1)
except ESIExportException as ex:
except APIException as ex:
pyfalog.error(ex)
self.statusbar.SetStatusText(_t("ERROR"), 0)
self.statusbar.SetStatusText("{} - {}".format(res.status_code, res.reason), 1)
except APIException as ex:
self.statusbar.SetStatusText("HTTP {} - {}".format(ex.status_code, ex.response["error"]), 1)
try:
ESIExceptionHandler(self, ex)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as ex:
self.statusbar.SetStatusText(_t("ERROR"), 0)
self.statusbar.SetStatusText("{} - {}".format(res.status_code, res.reason), 1)
pyfalog.error(ex)
ESIExceptionHandler(ex)
except:
# don't need to do anything - we should already get the error in ex.response
pass
except Exception as ex:
self.statusbar.SetStatusText(_t("ERROR"), 0)
self.statusbar.SetStatusText("Unknown error", 1)
pyfalog.error(ex)
class SsoCharacterMgmt(AuxiliaryFrame):

View File

@@ -5,7 +5,7 @@ from .gui.booster.remove import GuiRemoveBoostersCommand
from .gui.booster.sideEffectToggleState import GuiToggleBoosterSideEffectStateCommand
from .gui.booster.toggleStates import GuiToggleBoosterStatesCommand
from .gui.cargo.add import GuiAddCargoCommand
from .gui.cargo.changeAmount import GuiChangeCargoAmountCommand
from .gui.cargo.changeAmount import GuiChangeCargosAmountCommand
from .gui.cargo.changeMetas import GuiChangeCargoMetasCommand
from .gui.cargo.imprt import GuiImportCargosCommand
from .gui.cargo.remove import GuiRemoveCargosCommand
@@ -26,8 +26,12 @@ from .gui.itemsRebase import GuiRebaseItemsCommand
from .gui.localDrone.add import GuiAddLocalDroneCommand
from .gui.localDrone.changeAmount import GuiChangeLocalDroneAmountCommand
from .gui.localDrone.changeMetas import GuiChangeLocalDroneMetasCommand
from .gui.localDrone.changeMutation import GuiChangeLocalDroneMutationCommand
from .gui.localDrone.clone import GuiCloneLocalDroneCommand
from .gui.localDrone.imprt import GuiImportLocalDronesCommand
from .gui.localDrone.mutatedConvert import GuiConvertMutatedLocalDroneCommand
from .gui.localDrone.mutatedImport import GuiImportLocalMutatedDroneCommand
from .gui.localDrone.mutatedRevert import GuiRevertMutatedLocalDroneCommand
from .gui.localDrone.remove import GuiRemoveLocalDronesCommand
from .gui.localDrone.stackSplit import GuiSplitLocalDroneStackCommand
from .gui.localDrone.stacksMerge import GuiMergeLocalDroneStacksCommand

View File

@@ -0,0 +1,51 @@
import wx
from logbook import Logger
from service.fit import Fit
pyfalog = Logger(__name__)
class CalcChangeLocalDroneMutationCommand(wx.Command):
def __init__(self, fitID, position, mutation, oldMutation=None):
wx.Command.__init__(self, True, 'Change Local Drone Mutation')
self.fitID = fitID
self.position = position
self.mutation = mutation
self.savedMutation = oldMutation
def Do(self):
pyfalog.debug('Doing changing of local drone mutation at position {} to {} for fit ID {}'.format(
self.position, self.mutation, self.fitID))
sFit = Fit.getInstance()
fit = sFit.getFit(self.fitID)
drone = fit.drones[self.position]
if not drone.isMutated:
return False
if self.savedMutation is None:
self.savedMutation = {}
for mutator in drone.mutators.values():
self.savedMutation[mutator.attrID] = mutator.value
if self.mutation == self.savedMutation:
return False
for mutator in drone.mutators.values():
if mutator.attrID not in self.mutation:
continue
if mutator.value != self.mutation[mutator.attrID]:
mutator.value = self.mutation[mutator.attrID]
return True
def Undo(self):
pyfalog.debug('Undoing changing of local drone mutation at position {} to {} for fit ID {}'.format(
self.position, self.mutation, self.fitID))
cmd = CalcChangeLocalDroneMutationCommand(
fitID=self.fitID,
position=self.position,
mutation=self.savedMutation)
return cmd.Do()

View File

@@ -10,21 +10,26 @@ from gui.fitCommands.calc.cargo.remove import CalcRemoveCargoCommand
from gui.fitCommands.helpers import CargoInfo, InternalCommandHistory
class GuiChangeCargoAmountCommand(wx.Command):
class GuiChangeCargosAmountCommand(wx.Command):
def __init__(self, fitID, itemID, amount):
def __init__(self, fitID, itemIDs, amount):
wx.Command.__init__(self, True, 'Change Cargo Amount')
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.itemID = itemID
self.itemIDs = itemIDs
self.amount = amount
def Do(self):
results = []
if self.amount > 0:
cmd = CalcChangeCargoAmountCommand(fitID=self.fitID, cargoInfo=CargoInfo(itemID=self.itemID, amount=self.amount))
for itemID in self.itemIDs:
cmd = CalcChangeCargoAmountCommand(fitID=self.fitID, cargoInfo=CargoInfo(itemID=itemID, amount=self.amount))
results.append(self.internalHistory.submit(cmd))
else:
cmd = CalcRemoveCargoCommand(fitID=self.fitID, cargoInfo=CargoInfo(itemID=self.itemID, amount=math.inf))
success = self.internalHistory.submit(cmd)
for itemID in self.itemIDs:
cmd = CalcRemoveCargoCommand(fitID=self.fitID, cargoInfo=CargoInfo(itemID=itemID, amount=math.inf))
results.append(self.internalHistory.submit(cmd))
success = any(results)
eos.db.commit()
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
return success

View File

@@ -14,7 +14,7 @@ class GuiImportCargosCommand(wx.Command):
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.cargos = {}
for itemID, amount in cargos:
for itemID, amount, mutation in cargos:
if itemID not in self.cargos:
self.cargos[itemID] = 0
self.cargos[itemID] += amount

View File

@@ -0,0 +1,44 @@
import wx
import eos.db
import gui.mainFrame
from gui import globalEvents as GE
from gui.fitCommands.calc.drone.localChangeMutation import CalcChangeLocalDroneMutationCommand
from gui.fitCommands.helpers import InternalCommandHistory
from service.fit import Fit
class GuiChangeLocalDroneMutationCommand(wx.Command):
def __init__(self, fitID, position, mutation, oldMutation=None):
wx.Command.__init__(self, True, 'Change Local Drone Mutation')
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.position = position
self.mutation = mutation
self.oldMutation = oldMutation
def Do(self):
cmd = CalcChangeLocalDroneMutationCommand(
fitID=self.fitID,
position=self.position,
mutation=self.mutation,
oldMutation=self.oldMutation)
success = self.internalHistory.submit(cmd)
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
return success
def Undo(self):
success = self.internalHistory.undoAll()
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
return success

View File

@@ -14,15 +14,24 @@ class GuiImportLocalDronesCommand(wx.Command):
wx.Command.__init__(self, True, 'Import Local Drones')
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.drones = drones
self.droneInfos = []
for itemID, amount, mutation in drones:
if mutation:
mutaplasmid, attrs = mutation
self.droneInfos.append(DroneInfo(
itemID=mutaplasmid.resultingItem.ID,
amount=amount,
amountActive=0,
baseItemID=itemID,
mutaplasmidID=mutaplasmid.ID,
mutations=attrs))
else:
self.droneInfos.append(DroneInfo(itemID=itemID, amount=amount, amountActive=0))
def Do(self):
results = []
for itemID, amount in self.drones:
cmd = CalcAddLocalDroneCommand(
fitID=self.fitID,
droneInfo=DroneInfo(itemID=itemID, amount=amount, amountActive=0),
forceNewStack=True)
for info in self.droneInfos:
cmd = CalcAddLocalDroneCommand(fitID=self.fitID, droneInfo=info, forceNewStack=True)
results.append(self.internalHistory.submit(cmd))
success = any(results)
eos.db.flush()

View File

@@ -0,0 +1,65 @@
import math
import wx
import eos.db
import gui.mainFrame
from gui import globalEvents as GE
from gui.fitCommands.calc.drone.localAdd import CalcAddLocalDroneCommand
from gui.fitCommands.calc.drone.localRemove import CalcRemoveLocalDroneCommand
from gui.fitCommands.helpers import DroneInfo, InternalCommandHistory
from service.fit import Fit
class GuiConvertMutatedLocalDroneCommand(wx.Command):
def __init__(self, fitID, position, mutaplasmid):
wx.Command.__init__(self, True, 'Convert Local Drone to Mutated')
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.position = position
self.itemID = mutaplasmid.resultingItem.ID
self.mutaplasmidID = mutaplasmid.ID
def Do(self):
sFit = Fit.getInstance()
fit = sFit.getFit(self.fitID)
try:
drone = fit.drones[self.position]
except IndexError:
return False
if drone.isMutated:
return False
info = DroneInfo(
amount=drone.amount,
amountActive=drone.amountActive,
itemID=self.itemID,
baseItemID=drone.item.ID,
mutaplasmidID=self.mutaplasmidID,
mutations={})
cmdRemove = CalcRemoveLocalDroneCommand(
fitID=self.fitID,
position=self.position,
amount=math.inf)
cmdAdd = CalcAddLocalDroneCommand(
fitID=self.fitID,
droneInfo=info,
forceNewStack=True,
ignoreRestrictions=True)
success = self.internalHistory.submitBatch(cmdRemove, cmdAdd)
eos.db.flush()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
return success
def Undo(self):
success = self.internalHistory.undoAll()
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
return success

View File

@@ -0,0 +1,44 @@
import wx
import eos.db
import gui.mainFrame
from gui import globalEvents as GE
from gui.fitCommands.calc.drone.localAdd import CalcAddLocalDroneCommand
from gui.fitCommands.helpers import InternalCommandHistory, DroneInfo
from service.fit import Fit
class GuiImportLocalMutatedDroneCommand(wx.Command):
def __init__(self, fitID, baseItem, mutaplasmid, mutations, amount):
wx.Command.__init__(self, True, 'Import Local Mutated Drone')
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.newDroneInfo = DroneInfo(
amount=amount,
amountActive=0,
itemID=mutaplasmid.resultingItem.ID,
baseItemID=baseItem.ID,
mutaplasmidID=mutaplasmid.ID,
mutations=mutations)
def Do(self):
cmd = CalcAddLocalDroneCommand(fitID=self.fitID, droneInfo=self.newDroneInfo, forceNewStack=True)
success = self.internalHistory.submit(cmd)
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
return success
def Undo(self):
success = self.internalHistory.undoAll()
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
return success

View File

@@ -0,0 +1,60 @@
import math
import wx
import eos.db
import gui.mainFrame
from gui import globalEvents as GE
from gui.fitCommands.calc.drone.localAdd import CalcAddLocalDroneCommand
from gui.fitCommands.calc.drone.localRemove import CalcRemoveLocalDroneCommand
from gui.fitCommands.helpers import DroneInfo, InternalCommandHistory
from service.fit import Fit
class GuiRevertMutatedLocalDroneCommand(wx.Command):
def __init__(self, fitID, position):
wx.Command.__init__(self, True, 'Revert Local Drone from Mutated')
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.position = position
def Do(self):
sFit = Fit.getInstance()
fit = sFit.getFit(self.fitID)
try:
drone = fit.drones[self.position]
except IndexError:
return False
if not drone.isMutated:
return False
info = DroneInfo(
amount=drone.amount,
amountActive=drone.amountActive,
itemID=drone.baseItemID)
cmdRemove = CalcRemoveLocalDroneCommand(
fitID=self.fitID,
position=self.position,
amount=math.inf)
cmdAdd = CalcAddLocalDroneCommand(
fitID=self.fitID,
droneInfo=info,
forceNewStack=True,
ignoreRestrictions=True)
success = self.internalHistory.submitBatch(cmdRemove, cmdAdd)
eos.db.flush()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
return success
def Undo(self):
success = self.internalHistory.undoAll()
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID,)))
return success

View File

@@ -14,7 +14,7 @@ class GuiImportLocalFightersCommand(wx.Command):
wx.Command.__init__(self, True, 'Import Local Fighters')
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.fighters = fighters
self.fighters = [(i, a) for i, a, m in fighters]
def Do(self):
results = []

View File

@@ -21,7 +21,10 @@ class GuiConvertMutatedLocalModuleCommand(wx.Command):
def Do(self):
sFit = Fit.getInstance()
fit = sFit.getFit(self.fitID)
mod = fit.modules[self.position]
try:
mod = fit.modules[self.position]
except IndexError:
return False
if mod.isEmpty:
return False
if mod.isMutated:

View File

@@ -19,7 +19,10 @@ class GuiRevertMutatedLocalModuleCommand(wx.Command):
def Do(self):
sFit = Fit.getInstance()
fit = sFit.getFit(self.fitID)
mod = fit.modules[self.position]
try:
mod = fit.modules[self.position]
except IndexError:
return False
if mod.isEmpty:
return False
if not mod.isMutated:

View File

@@ -158,8 +158,11 @@ class ModuleInfo:
class DroneInfo:
def __init__(self, itemID, amount, amountActive):
def __init__(self, amount, amountActive, itemID, baseItemID=None, mutaplasmidID=None, mutations=None):
self.itemID = itemID
self.baseItemID = baseItemID
self.mutaplasmidID = mutaplasmidID
self.mutations = mutations
self.amount = amount
self.amountActive = amountActive
@@ -170,22 +173,40 @@ class DroneInfo:
info = cls(
itemID=drone.itemID,
amount=drone.amount,
amountActive=drone.amountActive)
amountActive=drone.amountActive,
baseItemID=drone.baseItemID,
mutaplasmidID=drone.mutaplasmidID,
mutations={m.attrID: m.value for m in drone.mutators.values()})
return info
def toDrone(self):
item = Market.getInstance().getItem(self.itemID, eager=('attributes', 'group.category'))
mkt = Market.getInstance()
item = mkt.getItem(self.itemID, eager=('attributes', 'group.category'))
if self.baseItemID and self.mutaplasmidID:
baseItem = mkt.getItem(self.baseItemID, eager=('attributes', 'group.category'))
mutaplasmid = eos.db.getDynamicItem(self.mutaplasmidID)
else:
baseItem = None
mutaplasmid = None
try:
drone = Drone(item)
drone = Drone(item, baseItem=baseItem, mutaplasmid=mutaplasmid)
except ValueError:
pyfalog.warning('Invalid item: {}'.format(self.itemID))
return None
if self.mutations is not None:
for attrID, mutator in drone.mutators.items():
if attrID in self.mutations:
mutator.value = self.mutations[attrID]
drone.amount = self.amount
drone.amountActive = self.amountActive
return drone
def __repr__(self):
return makeReprStr(self, ['itemID', 'amount', 'amountActive'])
return makeReprStr(self, [
'itemID', 'amount', 'amountActive',
'baseItemID', 'mutaplasmidID', 'mutations'])
class FighterInfo:

View File

@@ -22,6 +22,7 @@ import wx
import config
import gui.mainFrame
from eos.saveddata.drone import Drone
from eos.saveddata.module import Module
from gui.auxWindow import AuxiliaryFrame
from gui.bitmap_loader import BitmapLoader
@@ -165,7 +166,7 @@ class ItemStatsContainer(wx.Panel):
self.traits = ItemTraits(self.nbContainer, stuff, item)
self.nbContainer.AddPage(self.traits, _t("Traits"))
if isinstance(stuff, Module) and stuff.isMutated:
if isinstance(stuff, (Module, Drone)) and stuff.isMutated:
self.mutator = ItemMutatorPanel(self.nbContainer, stuff)
self.nbContainer.AddPage(self.mutator, _t("Mutations"))

View File

@@ -762,28 +762,33 @@ class MainFrame(wx.Frame):
if importType == "FittingItem":
baseItem, mutaplasmidItem, mutations = importData[0]
if mutaplasmidItem:
self.command.Submit(cmd.GuiImportLocalMutatedModuleCommand(activeFit, baseItem, mutaplasmidItem, mutations))
if baseItem.isDrone:
self.command.Submit(cmd.GuiImportLocalMutatedDroneCommand(
activeFit, baseItem, mutaplasmidItem, mutations, amount=1))
else:
self.command.Submit(cmd.GuiImportLocalMutatedModuleCommand(
activeFit, baseItem, mutaplasmidItem, mutations))
else:
self.command.Submit(cmd.GuiAddLocalModuleCommand(activeFit, baseItem.ID))
return
if importType == "AdditionsDrones":
if self.command.Submit(cmd.GuiImportLocalDronesCommand(activeFit, [(i.ID, a) for i, a in importData[0]])):
if self.command.Submit(cmd.GuiImportLocalDronesCommand(activeFit, [(i.ID, a, m) for i, a, m in importData[0]])):
self.additionsPane.select("Drones")
return
if importType == "AdditionsFighters":
if self.command.Submit(cmd.GuiImportLocalFightersCommand(activeFit, [(i.ID, a) for i, a in importData[0]])):
if self.command.Submit(cmd.GuiImportLocalFightersCommand(activeFit, [(i.ID, a, m) for i, a, m in importData[0]])):
self.additionsPane.select("Fighters")
return
if importType == "AdditionsImplants":
if self.command.Submit(cmd.GuiImportImplantsCommand(activeFit, [(i.ID, a) for i, a in importData[0]])):
if self.command.Submit(cmd.GuiImportImplantsCommand(activeFit, [(i.ID, a, m) for i, a, m in importData[0]])):
self.additionsPane.select("Implants")
return
if importType == "AdditionsBoosters":
if self.command.Submit(cmd.GuiImportBoostersCommand(activeFit, [(i.ID, a) for i, a in importData[0]])):
if self.command.Submit(cmd.GuiImportBoostersCommand(activeFit, [(i.ID, a, m) for i, a, m in importData[0]])):
self.additionsPane.select("Boosters")
return
if importType == "AdditionsCargo":
if self.command.Submit(cmd.GuiImportCargosCommand(activeFit, [(i.ID, a) for i, a in importData[0]])):
if self.command.Submit(cmd.GuiImportCargosCommand(activeFit, [(i.ID, a, m) for i, a, m in importData[0]])):
self.additionsPane.select("Cargo")
return
except (KeyboardInterrupt, SystemExit):

View File

@@ -38,7 +38,7 @@ class SsoLogin(wx.Dialog):
from service.esi import Esi
self.sEsi = Esi.getInstance()
uri = self.sEsi.getLoginURI(None)
uri = self.sEsi.get_login_uri(None)
webbrowser.open(uri)
@@ -53,7 +53,7 @@ class SsoLoginServer(wx.Dialog):
self.sEsi = Esi.getInstance()
serverAddr = self.sEsi.startServer(port)
uri = self.sEsi.getLoginURI(serverAddr)
uri = self.sEsi.get_login_uri(serverAddr)
bSizer1 = wx.BoxSizer(wx.VERTICAL)
self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.OnLogin)