from collections import OrderedDict from itertools import chain # noinspection PyPackageRequirements import wx import gui.globalEvents as GE import gui.mainFrame from gui.contextMenu import ContextMenuUnconditional from service.fit import Fit from service.targetProfile import TargetProfile as svc_TargetProfile class TargetProfileSwitcher(ContextMenuUnconditional): def __init__(self): self.mainFrame = gui.mainFrame.MainFrame.getInstance() def display(self, callingWindow, srcContext): if self.mainFrame.getActiveFit() is None or srcContext != 'firepowerViewFull': return False sTR = svc_TargetProfile.getInstance() self.profiles = list(chain(sTR.getBuiltinTargetProfileList(), sTR.getUserTargetProfileList())) self.profiles.sort(key=lambda p: (p.name in ['None'], p.name)) return len(self.profiles) > 0 def getText(self, callingWindow, itmContext): # We take into consideration just target resists, so call menu item accordingly return 'Target Resists' def handleResistSwitch(self, event): profile = self.profileEventMap.get(event.Id, False) if profile is False: event.Skip() return sFit = Fit.getInstance() fitID = self.mainFrame.getActiveFit() sFit.setTargetProfile(fitID, profile) wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID,))) def _addProfile(self, parentMenu, profile, name): id = ContextMenuUnconditional.nextID() self.profileEventMap[id] = profile menuItem = wx.MenuItem(parentMenu, id, name, kind=wx.ITEM_CHECK) parentMenu.Bind(wx.EVT_MENU, self.handleResistSwitch, menuItem) # determine active profile sFit = Fit.getInstance() fitID = self.mainFrame.getActiveFit() checked = sFit.getFit(fitID).targetProfile is profile return menuItem, checked def _addCategory(self, parentMenu, name): id = ContextMenuUnconditional.nextID() menuItem = wx.MenuItem(parentMenu, id, name) parentMenu.Bind(wx.EVT_MENU, self.handleResistSwitch, menuItem) return menuItem def getSubMenu(self, callingWindow, context, rootMenu, i, pitem): self.profileEventMap = {} self.items = (OrderedDict(), OrderedDict()) for profile in self.profiles: remainingName = profile.name.strip() container = self.items while True: start, end = remainingName.find('['), remainingName.find(']') if start == -1 or end == -1: container[0][remainingName] = profile break container = container[1].setdefault(remainingName[start + 1:end], (OrderedDict(), OrderedDict())) remainingName = remainingName[end + 1:].strip() # Category as menu item - expands further msw = "wxMSW" in wx.PlatformInfo def makeMenu(container, parentMenu, first=False): menu = wx.Menu() if first: mitem, checked = self._addProfile(rootMenu if msw else parentMenu, None, 'No Profile') menu.Append(mitem) mitem.Check(checked) menu.AppendSeparator() for name, pattern in container[0].items(): menuItem, checked = self._addProfile(rootMenu if msw else parentMenu, pattern, name) menu.Append(menuItem) menuItem.Check(checked) for name, subcontainer in container[1].items(): menuItem = self._addCategory(rootMenu if msw else parentMenu, name) subMenu = makeMenu(subcontainer, menu) menuItem.SetSubMenu(subMenu) menu.Append(menuItem) menu.Bind(wx.EVT_MENU, self.handleResistSwitch) return menu subMenu = makeMenu(self.items, rootMenu, first=True) return subMenu TargetProfileSwitcher.register()