11 Commits

9 changed files with 455 additions and 21 deletions

View File

@@ -23,7 +23,7 @@ rm -rf build dist
echo "Building binary with PyInstaller..."
uv run pyinstaller pyfa.spec
cp oleacc* dist/pyfa/
# cp oleacc* dist/pyfa/
echo ""
echo "Build complete! Binary is located at: dist/pyfa/pyfa.exe"

View File

@@ -79,7 +79,7 @@ class ChangeAffectingSkills(ContextMenuSingle):
label = _t("Level %s") % i
id = ContextMenuSingle.nextID()
self.skillIds[id] = (skill, i)
self.skillIds[id] = (skill, i, False) # False = not "up" for individual skills
menuItem = wx.MenuItem(rootMenu, id, label, kind=wx.ITEM_RADIO)
rootMenu.Bind(wx.EVT_MENU, self.handleSkillChange, menuItem)
return menuItem
@@ -89,6 +89,40 @@ class ChangeAffectingSkills(ContextMenuSingle):
self.skillIds = {}
sub = wx.Menu()
# When rootMenu is None (direct menu access), use sub for binding on Windows
bindMenu = rootMenu if (rootMenu is not None and msw) else (sub if msw else None)
# Add "All" entry
allItem = wx.MenuItem(sub, ContextMenuSingle.nextID(), _t("All"))
grandSubAll = wx.Menu()
allItem.SetSubMenu(grandSubAll)
# For "All", only show levels 1-5 (not "Not Learned")
for i in range(1, 6):
id = ContextMenuSingle.nextID()
self.skillIds[id] = (None, i, False) # None indicates "All" was selected, False = not "up"
label = _t("Level %s") % i
menuItem = wx.MenuItem(bindMenu if bindMenu else grandSubAll, id, label, kind=wx.ITEM_RADIO)
grandSubAll.Bind(wx.EVT_MENU, self.handleSkillChange, menuItem)
grandSubAll.Append(menuItem)
# Add separator
grandSubAll.AppendSeparator()
# Add "Up Level 1..5" entries
for i in range(1, 6):
id = ContextMenuSingle.nextID()
self.skillIds[id] = (None, i, True) # None indicates "All" was selected, True = "up" only
label = _t("Up Level %s") % i
menuItem = wx.MenuItem(bindMenu if bindMenu else grandSubAll, id, label, kind=wx.ITEM_RADIO)
grandSubAll.Bind(wx.EVT_MENU, self.handleSkillChange, menuItem)
grandSubAll.Append(menuItem)
sub.Append(allItem)
# Add separator
sub.AppendSeparator()
for skill in self.skills:
skillItem = wx.MenuItem(sub, ContextMenuSingle.nextID(), skill.item.name)
grandSub = wx.Menu()
@@ -99,7 +133,7 @@ class ChangeAffectingSkills(ContextMenuSingle):
skillItem.SetBitmap(bitmap)
for i in range(-1, 6):
levelItem = self.addSkill(rootMenu if msw else grandSub, skill, i)
levelItem = self.addSkill(bindMenu if bindMenu else grandSub, skill, i)
grandSub.Append(levelItem)
if (not skill.learned and i == -1) or (skill.learned and skill.level == i):
levelItem.Check(True)
@@ -108,9 +142,24 @@ class ChangeAffectingSkills(ContextMenuSingle):
return sub
def handleSkillChange(self, event):
skill, level = self.skillIds[event.Id]
skill, level, up = self.skillIds[event.Id]
if skill is None: # "All" was selected
for s in self.skills:
if up:
# Only increase skill if it's below the target level
if not s.learned or s.level < level:
self.sChar.changeLevel(self.charID, s.item.ID, level)
else:
self.sChar.changeLevel(self.charID, s.item.ID, level)
else:
if up:
# Only increase skill if it's below the target level
if not skill.learned or skill.level < level:
self.sChar.changeLevel(self.charID, skill.item.ID, level)
else:
self.sChar.changeLevel(self.charID, skill.item.ID, level)
self.sChar.changeLevel(self.charID, skill.item.ID, level)
fitID = self.mainFrame.getActiveFit()
self.sFit.changeChar(fitID, self.charID)

View File

@@ -0,0 +1,220 @@
# noinspection PyPackageRequirements
import wx
import itertools
import gui.mainFrame
from eos.saveddata.character import Skill
from eos.saveddata.fighter import Fighter as es_Fighter
from eos.saveddata.module import Module as es_Module
from eos.saveddata.ship import Ship
from gui.utils.clipboard import toClipboard
from gui.utils.numberFormatter import formatAmount
from service.fit import Fit
_t = wx.GetTranslation
class ItemSkills(wx.Panel):
def __init__(self, parent, stuff, item):
wx.Panel.__init__(self, parent)
self.stuff = stuff
self.item = item
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
leftPanel = wx.Panel(self)
leftSizer = wx.BoxSizer(wx.VERTICAL)
leftPanel.SetSizer(leftSizer)
header = wx.StaticText(leftPanel, wx.ID_ANY, _t("Components"))
font = header.GetFont()
font.SetWeight(wx.FONTWEIGHT_BOLD)
header.SetFont(font)
leftSizer.Add(header, 0, wx.ALL, 5)
self.checkboxes = {}
components = [
("Ship", "ship"),
("Modules", "modules"),
("Drones", "drones"),
("Fighters", "fighters"),
("Cargo", "cargo"),
("Implants", "appliedImplants"),
("Boosters", "boosters"),
("Necessary", "necessary"),
]
for label, key in components:
cb = wx.CheckBox(leftPanel, wx.ID_ANY, label)
cb.SetValue(True)
cb.Bind(wx.EVT_CHECKBOX, self.onCheckboxChange)
self.checkboxes[key] = cb
leftSizer.Add(cb, 0, wx.ALL, 2)
leftSizer.AddStretchSpacer()
mainSizer.Add(leftPanel, 0, wx.EXPAND | wx.ALL, 5)
rightPanel = wx.Panel(self)
rightSizer = wx.BoxSizer(wx.VERTICAL)
rightPanel.SetSizer(rightSizer)
headerRight = wx.StaticText(rightPanel, wx.ID_ANY, _t("Skills"))
fontRight = headerRight.GetFont()
fontRight.SetWeight(wx.FONTWEIGHT_BOLD)
headerRight.SetFont(fontRight)
rightSizer.Add(headerRight, 0, wx.ALL, 5)
self.skillsText = wx.TextCtrl(rightPanel, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_DONTWRAP)
font = wx.Font(9, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
self.skillsText.SetFont(font)
rightSizer.Add(self.skillsText, 1, wx.EXPAND | wx.ALL, 5)
mainSizer.Add(rightPanel, 1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(mainSizer)
self.nbContainer = parent if isinstance(parent, wx.Notebook) else None
if self.nbContainer:
self.nbContainer.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onTabChanged)
self.updateSkills()
def onCheckboxChange(self, event):
self.updateSkills()
self._copyToClipboard()
def updateSkills(self):
fitID = gui.mainFrame.MainFrame.getInstance().getActiveFit()
if fitID is None:
self.skillsText.SetValue("")
self._updateCheckboxStates(None)
return
sFit = Fit.getInstance()
fit = sFit.getFit(fitID)
if fit is None:
self.skillsText.SetValue("")
self._updateCheckboxStates(None)
return
if not fit.calculated:
fit.calculate()
self._updateCheckboxStates(fit)
char = fit.character
skillsMap = {}
items = []
if self.checkboxes["ship"].GetValue():
items.append(fit.ship)
if self.checkboxes["modules"].GetValue():
items.extend(fit.modules)
if self.checkboxes["drones"].GetValue():
items.extend(fit.drones)
if self.checkboxes["fighters"].GetValue():
items.extend(fit.fighters)
if self.checkboxes["cargo"].GetValue():
items.extend(fit.cargo)
if self.checkboxes["appliedImplants"].GetValue():
items.extend(fit.appliedImplants)
if self.checkboxes["boosters"].GetValue():
items.extend(fit.boosters)
for thing in items:
self._collectAffectingSkills(thing, char, skillsMap)
if self.checkboxes["necessary"].GetValue():
self._collectRequiredSkills(items, char, skillsMap)
skillsList = ""
for skillName in sorted(skillsMap):
charLevel = skillsMap[skillName]
for level in range(1, charLevel + 1):
skillsList += "%s %d\n" % (skillName, level)
self.skillsText.SetValue(skillsList)
self._copyToClipboard()
def _copyToClipboard(self):
skillsText = self.skillsText.GetValue()
if skillsText:
toClipboard(skillsText)
def onTabChanged(self, event):
if self.nbContainer:
pageIndex = self.nbContainer.FindPage(self)
if pageIndex != -1 and event.GetSelection() == pageIndex:
self.updateSkills()
event.Skip()
def _updateCheckboxStates(self, fit):
if fit is None:
for cb in self.checkboxes.values():
cb.Enable(False)
return
self.checkboxes["ship"].Enable(True)
self.checkboxes["modules"].Enable(len(fit.modules) > 0)
self.checkboxes["drones"].Enable(len(fit.drones) > 0)
self.checkboxes["fighters"].Enable(len(fit.fighters) > 0)
self.checkboxes["cargo"].Enable(len(fit.cargo) > 0)
self.checkboxes["appliedImplants"].Enable(len(fit.appliedImplants) > 0)
self.checkboxes["boosters"].Enable(len(fit.boosters) > 0)
self.checkboxes["necessary"].Enable(True)
def _collectAffectingSkills(self, thing, char, skillsMap):
for attr in ("item", "charge"):
if attr == "charge" and isinstance(thing, es_Fighter):
continue
subThing = getattr(thing, attr, None)
if subThing is None:
continue
if isinstance(thing, es_Fighter) and attr == "charge":
continue
if attr == "charge":
cont = getattr(thing, "chargeModifiedAttributes", None)
else:
cont = getattr(thing, "itemModifiedAttributes", None)
if cont is not None:
for attrName in cont.iterAfflictions():
for fit, afflictors in cont.getAfflictions(attrName).items():
for afflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors:
if isinstance(afflictor, Skill) and afflictor.character == char:
skillName = afflictor.item.name
if skillName not in skillsMap:
skillsMap[skillName] = afflictor.level
elif skillsMap[skillName] < afflictor.level:
skillsMap[skillName] = afflictor.level
def _collectRequiredSkills(self, items, char, skillsMap):
"""Collect required skills from items (necessary to use them)"""
for thing in items:
for attr in ("item", "charge"):
if attr == "charge" and isinstance(thing, es_Fighter):
continue
subThing = getattr(thing, attr, None)
if subThing is None:
continue
if isinstance(thing, es_Fighter) and attr == "charge":
continue
if hasattr(subThing, "requiredSkills"):
for reqSkill, level in subThing.requiredSkills.items():
skillName = reqSkill.name
charSkill = char.getSkill(reqSkill) if char else None
charLevel = charSkill.level if charSkill else 0
if charLevel > 0:
if skillName not in skillsMap:
skillsMap[skillName] = charLevel
elif skillsMap[skillName] < charLevel:
skillsMap[skillName] = charLevel
else:
if skillName not in skillsMap:
skillsMap[skillName] = level
elif skillsMap[skillName] < level:
skillsMap[skillName] = level

View File

@@ -23,6 +23,7 @@ class ItemView(Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
"Price",
"attr:power,,,True",
"attr:cpu,,,True"]

View File

@@ -20,6 +20,7 @@
# noinspection PyPackageRequirements
import wx
from eos.gamedata import Item
from eos.saveddata.cargo import Cargo
from eos.saveddata.drone import Drone
from eos.saveddata.fighter import Fighter
@@ -53,7 +54,14 @@ class Price(ViewColumn):
self.imageId = fittingView.imageList.GetImageIndex("totalPrice_small", "gui")
def getText(self, stuff):
if stuff.item is None or stuff.item.group.name == "Ship Modifiers":
if isinstance(stuff, Item):
item = stuff
else:
if not hasattr(stuff, "item") or stuff.item is None:
return ""
item = stuff.item
if item.group.name == "Ship Modifiers":
return ""
if hasattr(stuff, "isEmpty"):
@@ -63,7 +71,7 @@ class Price(ViewColumn):
if isinstance(stuff, Module) and stuff.isMutated:
return ""
priceObj = stuff.item.price
priceObj = item.price
if not priceObj.isValid():
return False
@@ -79,7 +87,11 @@ class Price(ViewColumn):
display.SetItem(colItem)
sPrice.getPrices([mod.item], callback, waitforthread=True)
if isinstance(mod, Item):
item = mod
else:
item = mod.item
sPrice.getPrices([item], callback, waitforthread=True)
def getImageId(self, mod):
return -1

View File

@@ -668,6 +668,21 @@ class FittingView(d.Display):
contexts.append(fullContext)
contexts.append(("fittingShip", _t("Ship") if not fit.isStructure else _t("Citadel")))
# Check if shift is held for direct skills menu access
if wx.GetKeyState(wx.WXK_SHIFT):
from gui.builtinContextMenus.skillAffectors import ChangeAffectingSkills
for fullContext in contexts:
srcContext = fullContext[0]
itemContext = fullContext[1] if len(fullContext) > 1 else None
skillsMenu = ChangeAffectingSkills()
if skillsMenu.display(self, srcContext, mainMod):
# On Windows, menu items need to be bound to the menu shown with PopupMenu
# We pass None as rootMenu so items are bound to their parent submenus
sub = skillsMenu.getSubMenu(self, srcContext, mainMod, None, 0, None)
if sub:
self.PopupMenu(sub)
return
menu = ContextMenu.getMenu(self, mainMod, selection, *contexts)
self.PopupMenu(menu)

View File

@@ -29,7 +29,7 @@ import config
import gui.globalEvents as GE
import gui.mainFrame
from gui.bitmap_loader import BitmapLoader
from gui.utils.clipboard import toClipboard
from gui.utils.clipboard import toClipboard, fromClipboard
from service.character import Character
from service.fit import Fit
@@ -49,6 +49,10 @@ class CharacterSelection(wx.Panel):
# cache current selection to fall back in case we choose to open char editor
self.charCache = None
# history for Shift-Tab navigation
self.charHistory = []
self._updatingFromHistory = False
self.charChoice = wx.Choice(self)
mainSizer.Add(self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 3)
@@ -92,7 +96,7 @@ class CharacterSelection(wx.Panel):
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
if not fit or not self.needsSkills:
if not fit:
return
pos = wx.GetMousePosition()
@@ -100,17 +104,23 @@ class CharacterSelection(wx.Panel):
menu = wx.Menu()
grantItem = menu.Append(wx.ID_ANY, _t("Grant Missing Skills"))
self.Bind(wx.EVT_MENU, self.grantMissingSkills, grantItem)
if self.needsSkills:
grantItem = menu.Append(wx.ID_ANY, _t("Grant Missing Skills"))
self.Bind(wx.EVT_MENU, self.grantMissingSkills, grantItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills"))
self.Bind(wx.EVT_MENU, self.exportSkills, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills"))
self.Bind(wx.EVT_MENU, self.exportSkills, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (condensed)"))
self.Bind(wx.EVT_MENU, self.exportSkillsCondensed, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (condensed)"))
self.Bind(wx.EVT_MENU, self.exportSkillsCondensed, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (EVEMon)"))
self.Bind(wx.EVT_MENU, self.exportSkillsEveMon, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (EVEMon)"))
self.Bind(wx.EVT_MENU, self.exportSkillsEveMon, exportItem)
menu.AppendSeparator()
importItem = menu.Append(wx.ID_ANY, _t("Import Skills from Clipboard"))
self.Bind(wx.EVT_MENU, self.importSkillsFromClipboard, importItem)
self.PopupMenu(menu, pos)
@@ -189,6 +199,13 @@ class CharacterSelection(wx.Panel):
sFit = Fit.getInstance()
sFit.changeChar(fitID, charID)
self.charCache = self.charChoice.GetCurrentSelection()
if not self._updatingFromHistory and charID is not None:
currentChar = self.getActiveCharacter()
if currentChar is not None:
if not self.charHistory or self.charHistory[-1] != currentChar:
self.charHistory.append(currentChar)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID,)))
def toggleRefreshButton(self):
@@ -210,6 +227,29 @@ class CharacterSelection(wx.Panel):
return True
return False
def selectPreviousChar(self):
currentChar = self.getActiveCharacter()
if currentChar is None:
return
if not self.charHistory:
return
if self.charHistory and self.charHistory[-1] == currentChar:
self.charHistory.pop()
if not self.charHistory:
return
prevChar = self.charHistory.pop()
if currentChar != prevChar:
self.charHistory.append(currentChar)
self._updatingFromHistory = True
if self.selectChar(prevChar):
self.charChanged(None)
self._updatingFromHistory = False
def fitChanged(self, event):
"""
@@ -222,7 +262,7 @@ class CharacterSelection(wx.Panel):
self.charChoice.Enable(activeFitID is not None)
choice = self.charChoice
sFit = Fit.getInstance()
currCharID = choice.GetClientData(choice.GetCurrentSelection())
currCharID = choice.GetClientData(choice.GetCurrentSelection()) if choice.GetCurrentSelection() != -1 else None
fit = sFit.getFit(activeFitID)
newCharID = fit.character.ID if fit is not None else None
@@ -256,6 +296,9 @@ class CharacterSelection(wx.Panel):
self.selectChar(sChar.all5ID())
elif currCharID != newCharID:
if currCharID is not None and not self._updatingFromHistory:
if not self.charHistory or self.charHistory[-1] != currCharID:
self.charHistory.append(currCharID)
self.selectChar(newCharID)
if not fit.calculated:
self.charChanged(None)
@@ -289,6 +332,83 @@ class CharacterSelection(wx.Panel):
toClipboard(list)
def importSkillsFromClipboard(self, evt):
charID = self.getActiveCharacter()
if charID is None:
return
sChar = Character.getInstance()
char = sChar.getCharacter(charID)
text = fromClipboard()
if not text:
with wx.MessageDialog(self, _t("Clipboard is empty"), _t("Error"), wx.OK | wx.ICON_ERROR) as dlg:
dlg.ShowModal()
return
try:
lines = text.strip().splitlines()
imported = 0
errors = []
for line in lines:
line = line.strip()
if not line:
continue
try:
parts = line.rsplit(None, 1)
if len(parts) != 2:
errors.append(_t("Invalid format: {}").format(line))
continue
skillName = parts[0]
levelStr = parts[1]
try:
level = int(levelStr)
except ValueError:
try:
level = roman.fromRoman(levelStr.upper())
except (roman.InvalidRomanNumeralError, ValueError):
errors.append(_t("Invalid level format: {}").format(line))
continue
if level < 0 or level > 5:
errors.append(_t("Level must be between 0 and 5: {}").format(line))
continue
skill = char.getSkill(skillName)
sChar.changeLevel(charID, skill.item.ID, level)
imported += 1
except KeyError as e:
errors.append(_t("Skill not found: {}").format(skillName))
pyfalog.error("Skill not found: '{}'", skillName)
except Exception as e:
errors.append(_t("Error processing line '{}': {}").format(line, str(e)))
pyfalog.error("Error importing skill from line '{}': {}", line, e)
if imported > 0:
self.refreshCharacterList()
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
fitID = self.mainFrame.getActiveFit()
if fitID is not None:
wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID,)))
if errors:
errorMsg = _t("Imported {} skill(s). Errors:\n{}").format(imported, "\n".join(errors))
with wx.MessageDialog(self, errorMsg, _t("Import Skills"), wx.OK | wx.ICON_WARNING) as dlg:
dlg.ShowModal()
elif imported > 0:
with wx.MessageDialog(self, _t("Successfully imported {} skill(s)").format(imported), _t("Import Skills"), wx.OK) as dlg:
dlg.ShowModal()
except Exception as e:
pyfalog.error("Error importing skills from clipboard: {}", e)
with wx.MessageDialog(self, _t("Error importing skills. Please check the log file."), _t("Error"), wx.OK | wx.ICON_ERROR) as dlg:
dlg.ShowModal()
def _buildSkillsTooltip(self, reqs, currItem="", tabulationLevel=0):
tip = ""
sCharacter = Character.getInstance()

View File

@@ -24,6 +24,7 @@ import config
import gui.mainFrame
from eos.saveddata.drone import Drone
from eos.saveddata.module import Module
from eos.saveddata.ship import Ship
from gui.auxWindow import AuxiliaryFrame
from gui.bitmap_loader import BitmapLoader
from gui.builtinItemStatsViews.itemAffectedBy import ItemAffectedBy
@@ -35,6 +36,7 @@ from gui.builtinItemStatsViews.itemEffects import ItemEffects
from gui.builtinItemStatsViews.itemMutator import ItemMutatorPanel
from gui.builtinItemStatsViews.itemProperties import ItemProperties
from gui.builtinItemStatsViews.itemRequirements import ItemRequirements
from gui.builtinItemStatsViews.itemSkills import ItemSkills
from gui.builtinItemStatsViews.itemTraits import ItemTraits
from service.market import Market
@@ -156,6 +158,8 @@ class ItemStatsContainer(wx.Panel):
def __init__(self, parent, stuff, item, context=None):
wx.Panel.__init__(self, parent)
sMkt = Market.getInstance()
self.stuff = stuff
self.context = context
mainSizer = wx.BoxSizer(wx.VERTICAL)
@@ -196,6 +200,10 @@ class ItemStatsContainer(wx.Panel):
self.affectedby = ItemAffectedBy(self.nbContainer, stuff, item)
self.nbContainer.AddPage(self.affectedby, _t("Affected by"))
if stuff is not None and isinstance(stuff, Ship):
self.skills = ItemSkills(self.nbContainer, stuff, item)
self.nbContainer.AddPage(self.skills, _t("Skills"))
if config.debug:
self.properties = ItemProperties(self.nbContainer, stuff, item, context)
self.nbContainer.AddPage(self.properties, _t("Properties"))

View File

@@ -578,6 +578,7 @@ class MainFrame(wx.Frame):
toggleShipMarketId = wx.NewId()
ctabnext = wx.NewId()
ctabprev = wx.NewId()
charPrevId = wx.NewId()
# Close Page
self.Bind(wx.EVT_MENU, self.CloseCurrentPage, id=self.closePageId)
@@ -587,6 +588,7 @@ class MainFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.toggleShipMarket, id=toggleShipMarketId)
self.Bind(wx.EVT_MENU, self.CTabNext, id=ctabnext)
self.Bind(wx.EVT_MENU, self.CTabPrev, id=ctabprev)
self.Bind(wx.EVT_MENU, self.selectPreviousCharacter, id=charPrevId)
actb = [(wx.ACCEL_CTRL, ord('T'), self.addPageId),
(wx.ACCEL_CMD, ord('T'), self.addPageId),
@@ -620,7 +622,10 @@ class MainFrame(wx.Frame):
(wx.ACCEL_CMD, wx.WXK_PAGEDOWN, ctabnext),
(wx.ACCEL_CMD, wx.WXK_PAGEUP, ctabprev),
(wx.ACCEL_CMD | wx.ACCEL_SHIFT, ord("Z"), wx.ID_REDO)
(wx.ACCEL_CMD | wx.ACCEL_SHIFT, ord("Z"), wx.ID_REDO),
# Shift+Tab for previous character
(wx.ACCEL_SHIFT, wx.WXK_TAB, charPrevId)
]
# Ctrl/Cmd+# for addition pane selection
@@ -746,6 +751,9 @@ class MainFrame(wx.Frame):
def CTabPrev(self, event):
self.fitMultiSwitch.PrevPage()
def selectPreviousCharacter(self, event):
self.charSelection.selectPreviousChar()
def HAddPage(self, event):
self.fitMultiSwitch.AddPage()
@@ -855,7 +863,8 @@ class MainFrame(wx.Frame):
char = fit.character
skillsMap = {}
for thing in itertools.chain(fit.modules, fit.drones, fit.fighters, [fit.ship], fit.appliedImplants, fit.boosters, fit.cargo):
# for thing in itertools.chain(fit.modules, fit.drones, fit.fighters, [fit.ship], fit.appliedImplants, fit.boosters, fit.cargo):
for thing in itertools.chain(fit.modules, fit.drones, fit.fighters, fit.appliedImplants, fit.boosters, fit.cargo):
self._collectAffectingSkills(thing, char, skillsMap)
skillsList = ""