diff --git a/gui/builtinPreferenceViews/pyfaGeneralPreferences.py b/gui/builtinPreferenceViews/pyfaGeneralPreferences.py index 4b9c4c3e0..3e1a3bc1d 100644 --- a/gui/builtinPreferenceViews/pyfaGeneralPreferences.py +++ b/gui/builtinPreferenceViews/pyfaGeneralPreferences.py @@ -16,6 +16,7 @@ class PFGeneralPref ( PreferenceView): def populatePanel( self, panel ): self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.dirtySettings = False + self.openFitsSettings = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []}) mainSizer = wx.BoxSizer( wx.VERTICAL ) @@ -39,10 +40,13 @@ class PFGeneralPref ( PreferenceView): self.cbCompactSkills = wx.CheckBox( panel, wx.ID_ANY, u"Compact skills needed tooltip", wx.DefaultPosition, wx.DefaultSize, 0 ) mainSizer.Add( self.cbCompactSkills, 0, wx.ALL|wx.EXPAND, 5 ) - + self.cbFitColorSlots = wx.CheckBox( panel, wx.ID_ANY, u"Color fitting view by slot", wx.DefaultPosition, wx.DefaultSize, 0 ) mainSizer.Add( self.cbFitColorSlots, 0, wx.ALL|wx.EXPAND, 5 ) + self.cbReopenFits = wx.CheckBox( panel, wx.ID_ANY, u"Reopen previous fits on startup", wx.DefaultPosition, wx.DefaultSize, 0 ) + mainSizer.Add( self.cbReopenFits, 0, wx.ALL|wx.EXPAND, 5 ) + self.cbRackSlots = wx.CheckBox( panel, wx.ID_ANY, u"Separate Racks", wx.DefaultPosition, wx.DefaultSize, 0 ) mainSizer.Add( self.cbRackSlots, 0, wx.ALL|wx.EXPAND, 5 ) @@ -51,10 +55,6 @@ class PFGeneralPref ( PreferenceView): labelSizer.Add( self.cbRackLabels, 0, wx.ALL|wx.EXPAND, 5 ) mainSizer.Add( labelSizer, 0, wx.LEFT|wx.EXPAND, 30 ) - # Needs to be implemented - save active fittings and reapply when starting pyfa - #self.cbReopenFits = wx.CheckBox( panel, wx.ID_ANY, u"Reopen Fits", wx.DefaultPosition, wx.DefaultSize, 0 ) - #mainSizer.Add( self.cbReopenFits, 0, wx.ALL|wx.EXPAND, 5 ) - defCharSizer = wx.BoxSizer( wx.HORIZONTAL ) self.sFit = service.Fit.getInstance() @@ -66,6 +66,7 @@ class PFGeneralPref ( PreferenceView): self.cbRackSlots.SetValue(self.sFit.serviceFittingOptions["rackSlots"] or False) self.cbRackLabels.SetValue(self.sFit.serviceFittingOptions["rackLabels"] or False) self.cbCompactSkills.SetValue(self.sFit.serviceFittingOptions["compactSkills"] or False) + self.cbReopenFits.SetValue(self.openFitsSettings["enabled"]) self.cbGlobalChar.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalCharStateChange) self.cbGlobalDmgPattern.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalDmgPatternStateChange) @@ -74,7 +75,8 @@ class PFGeneralPref ( PreferenceView): self.cbRackSlots.Bind(wx.EVT_CHECKBOX, self.onCBGlobalRackSlots) self.cbRackLabels.Bind(wx.EVT_CHECKBOX, self.onCBGlobalRackLabels) self.cbCompactSkills.Bind(wx.EVT_CHECKBOX, self.onCBCompactSkills) - + self.cbReopenFits.Bind(wx.EVT_CHECKBOX, self.onCBReopenFits) + self.cbRackLabels.Enable(self.sFit.serviceFittingOptions["rackSlots"] or False) panel.SetSizer( mainSizer ) @@ -116,12 +118,15 @@ class PFGeneralPref ( PreferenceView): def OnCBGlobalDmgPatternStateChange(self, event): self.sFit.serviceFittingOptions["useGlobalDamagePattern"] = self.cbGlobalDmgPattern.GetValue() event.Skip() - + def onCBCompactSkills(self, event): self.sFit.serviceFittingOptions["compactSkills"] = self.cbCompactSkills.GetValue() event.Skip() - + + def onCBReopenFits(self, event): + self.openFitsSettings["enabled"] = self.cbReopenFits.GetValue() + def getImage(self): return bitmapLoader.getBitmap("prefs_settings", "icons") -PFGeneralPref.register() \ No newline at end of file +PFGeneralPref.register() diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 1d45f09e8..444ad9ad4 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -44,21 +44,20 @@ class FitSpawner(gui.multiSwitch.TabSpawner): def fitSelected(self, event): count = -1 - if self.multiSwitch.GetPageCount() == 0: - self.multiSwitch.AddPage() for index, page in enumerate(self.multiSwitch.pages): try: if page.activeFitID == event.fitID: - count +=1 + count += 1 self.multiSwitch.SetSelection(index) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=event.fitID)) break except: pass - if count <0: + if count < 0: + startup = getattr(event, "startup", False) # see OpenFitsThread in gui.mainFrame mstate = wx.GetMouseState() - if mstate.CmdDown() or mstate.MiddleDown(): + if mstate.CmdDown() or mstate.MiddleDown() or startup: self.multiSwitch.AddPage() view = FittingView(self.multiSwitch) @@ -281,13 +280,15 @@ class FittingView(d.Display): def fitSelected(self, event): if self.parent.IsActive(self): fitID = event.fitID + startup = getattr(event, "startup", False) self.activeFitID = fitID - self.Show(fitID is not None) - self.slotsChanged() sFit = service.Fit.getInstance() - sFit.switchFit(fitID) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) self.updateTab() + if not startup or startup == 2: # see OpenFitsThread in gui.mainFrame + self.Show(fitID is not None) + self.slotsChanged() + sFit.switchFit(fitID) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID)) event.Skip() @@ -562,11 +563,17 @@ class FittingView(d.Display): self.itemRect = self.GetItemRect(0) if 'wxMac' in wx.PlatformInfo: - self.MakeSnapshot() + try: + self.MakeSnapshot() + except: + pass def OnShow(self, event): if not event.GetShow(): - self.MakeSnapshot() + try: + self.MakeSnapshot() + except: + pass event.Skip() def Snapshot(self): diff --git a/gui/mainFrame.py b/gui/mainFrame.py index da598fa04..dad54971d 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -22,12 +22,14 @@ import os.path import sqlalchemy import wx +import time from wx._core import PyDeadObjectError from wx.lib.wordwrap import wordwrap import service import config +import threading import gui.aboutData import gui.chromeTabs @@ -64,6 +66,30 @@ class PFPanel(wx.Panel): def OnBkErase(self, event): pass +class OpenFitsThread(threading.Thread): + def __init__(self, fits, callback): + threading.Thread.__init__(self) + self.mainFrame = MainFrame.getInstance() + self.callback = callback + self.fits = fits + self.start() + + def run(self): + time.sleep(0.5) # Give GUI some time to finish drawing + + # `startup` tells FitSpawner that we are loading fits are startup, and + # has 3 values: + # False = Set as default in FitSpawner itself, never set here + # 1 = Create new fit page, but do not calculate page + # 2 = Create new page and calculate + # We use 1 for all fits except the last one where we use 2 so that we + # have correct calculations displayed at startup + for fitID in self.fits[:-1]: + wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID, startup=1)) + + wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fits[-1], startup=2)) + wx.CallAfter(self.callback) + class MainFrame(wx.Frame): __instance = None @classmethod @@ -149,19 +175,18 @@ class MainFrame(wx.Frame): self.SetMenuBar(MainMenuBar()) self.registerMenu() - - #Internal vars to keep track of other windows (graphing/stats) self.graphFrame = None self.statsWnds = [] self.activeStatsWnd = None - self.Bind(wx.EVT_CLOSE, self.OnClose) #Show ourselves self.Show() + self.LoadPreviousOpenFits() + #Check for updates self.sUpdate = service.Update.getInstance() self.sUpdate.CheckUpdate(self.ShowUpdateBox) @@ -171,8 +196,21 @@ class MainFrame(wx.Frame): dlg.ShowModal() dlg.Destroy() - def LoadMainFrameAttribs(self): + def LoadPreviousOpenFits(self): + self.prevOpenFits = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []}) + fits = self.prevOpenFits['pyfaOpenFits'] + if not self.prevOpenFits['enabled'] or len(fits) is 0: + # add blank page if there are no fits to be loaded + self.fitMultiSwitch.AddPage() + return + + self.waitDialog = animUtils.WaitDialog(self, title="Opening previous fits") + OpenFitsThread(fits, self.closeWaitDialog) + self.waitDialog.ShowModal() + + + def LoadMainFrameAttribs(self): mainFrameDefaultAttribs = {"wnd_width":1000, "wnd_height": 700, "wnd_maximized": False} self.mainFrameAttribs = service.SettingsProvider.getInstance().getSettings("pyfaMainWindowAttribs", mainFrameDefaultAttribs) @@ -200,7 +238,6 @@ class MainFrame(wx.Frame): self.activeStatsWnd = wnd def GetActiveStatsWindow(self): - if self.activeStatsWnd in self.statsWnds: return self.activeStatsWnd @@ -232,6 +269,15 @@ class MainFrame(wx.Frame): def OnClose(self, event): self.UpdateMainFrameAttribs() + + # save open fits + self.prevOpenFits['pyfaOpenFits'] = [] # clear old list + for page in self.fitMultiSwitch.pages: + m = getattr(page, "getActiveFit", None) + if m is not None: + self.prevOpenFits['pyfaOpenFits'].append(m()) + + # save all teh settingz service.SettingsProvider.getInstance().saveAll() event.Skip() diff --git a/gui/multiSwitch.py b/gui/multiSwitch.py index dd37e9d56..91532785d 100644 --- a/gui/multiSwitch.py +++ b/gui/multiSwitch.py @@ -17,14 +17,14 @@ # along with pyfa. If not, see . #=============================================================================== -import wx import gui.chromeTabs import gui.builtinViews.emptyView + class MultiSwitch(gui.chromeTabs.PFNotebook): def __init__(self, parent): gui.chromeTabs.PFNotebook.__init__(self, parent) - self.AddPage() + #self.AddPage() # now handled by mainFrame self.handlers = handlers = [] for type in TabSpawner.tabTypes: handlers.append(type(self)) @@ -35,21 +35,22 @@ class MultiSwitch(gui.chromeTabs.PFNotebook): if h: h(type, info) - def AddPage(self, tabWnd=None, tabTitle="Empty Tab", tabImage=None): + def AddPage(self, tabWnd=None, tabTitle="Empty Tab", tabImage=None): if tabWnd is None: tabWnd = gui.builtinViews.emptyView.BlankPage(self) tabWnd.handleDrag = lambda type, info: self.handleDrag(type, info) gui.chromeTabs.PFNotebook.AddPage(self, tabWnd, tabTitle, tabImage, True) - def DeletePage(self, n, *args, **kwargs): gui.chromeTabs.PFNotebook.DeletePage(self, n, *args, **kwargs) if self.GetPageCount() == 0: self.AddPage() + class TabSpawner(object): tabTypes = [] + @classmethod def register(cls): TabSpawner.tabTypes.append(cls) diff --git a/service/settings.py b/service/settings.py index f77a946b0..ed7d0225e 100644 --- a/service/settings.py +++ b/service/settings.py @@ -186,50 +186,50 @@ class ProxySettings(): return self.autodetect() if self.getMode() == 2: return (self.getAddress(), int(self.getPort())) - - - + + + """ Settings used by the HTML export feature. -""" +""" class HTMLExportSettings(): _instance = None - + @classmethod def getInstance(cls): if cls._instance == None: cls._instance = HTMLExportSettings() - return cls._instance + return cls._instance def __init__(self): serviceHTMLExportDefaultSettings = {"enabled": False, "path": config.pyfaPath + os.sep + 'pyfaFits.html' } self.serviceHTMLExportSettings = SettingsProvider.getInstance().getSettings("pyfaServiceHTMLExportSettings", serviceHTMLExportDefaultSettings) - + def getEnabled(self): return self.serviceHTMLExportSettings["enabled"] - + def setEnabled(self, enabled): self.serviceHTMLExportSettings["enabled"] = enabled - + def getPath(self): return self.serviceHTMLExportSettings["path"] - + def setPath(self, path): self.serviceHTMLExportSettings["path"] = path - + """ Settings used by update notification -""" +""" class UpdateSettings(): _instance = None - + @classmethod def getInstance(cls): if cls._instance == None: cls._instance = UpdateSettings() - return cls._instance + return cls._instance def __init__(self): # Settings @@ -238,9 +238,12 @@ class UpdateSettings(): # version - Set to release tag that user does not want notifications for serviceUpdateDefaultSettings = { "all": False, "prerelease": True, 'version': None } self.serviceUpdateSettings = SettingsProvider.getInstance().getSettings("pyfaServiceUpdateSettings", serviceUpdateDefaultSettings) - + def get(self, type): return self.serviceUpdateSettings[type] - + def set(self, type, value): - self.serviceUpdateSettings[type] = value \ No newline at end of file + self.serviceUpdateSettings[type] = value + +# @todo: "reopen fits" setting class +# @todo: migrate fit settings (from fit service) here?