From 9a2408741e36f3e49e540d88eb0bd0319a929205 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Fri, 23 May 2014 21:31:36 -0400 Subject: [PATCH 1/3] Feature: reopen previous fits on startup --- .../pyfaGeneralPreferences.py | 23 +++++++----- gui/builtinViews/fittingView.py | 2 +- gui/mainFrame.py | 32 ++++++++++++++-- service/settings.py | 37 ++++++++++--------- 4 files changed, 63 insertions(+), 31 deletions(-) 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..89e5018cc 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -56,7 +56,7 @@ class FitSpawner(gui.multiSwitch.TabSpawner): except: pass if count <0: - mstate = wx.GetMouseState() + mstate = getattr(event, "mstate", wx.GetMouseState()) if mstate.CmdDown() or mstate.MiddleDown(): self.multiSwitch.AddPage() diff --git a/gui/mainFrame.py b/gui/mainFrame.py index da598fa04..da83bbbd0 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -149,8 +149,6 @@ class MainFrame(wx.Frame): self.SetMenuBar(MainMenuBar()) self.registerMenu() - - #Internal vars to keep track of other windows (graphing/stats) self.graphFrame = None self.statsWnds = [] @@ -159,6 +157,10 @@ class MainFrame(wx.Frame): self.Bind(wx.EVT_CLOSE, self.OnClose) + self.prevOpenFits = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False,"pyfaOpenFits": []}) + if self.prevOpenFits['enabled']: + self.LoadPreviousOpenFits() + #Show ourselves self.Show() @@ -171,8 +173,22 @@ class MainFrame(wx.Frame): dlg.ShowModal() dlg.Destroy() - def LoadMainFrameAttribs(self): + def LoadPreviousOpenFits(self): + fits = self.prevOpenFits['pyfaOpenFits'] + if len(fits) > 0: + # open first fit in same tab (which should be empty) + wx.PostEvent(self, FitSelected(fitID=fits[0])) + + # set mouse state to pass to FitSpawner via event + mstate = wx.GetMouseState() + mstate.SetMiddleDown(True) + + # open the rest of the fits with an mstate override (to open in new tabs) + for fitID in fits[1:]: + wx.PostEvent(self, FitSelected(fitID=fitID, mstate=mstate)) + + def LoadMainFrameAttribs(self): mainFrameDefaultAttribs = {"wnd_width":1000, "wnd_height": 700, "wnd_maximized": False} self.mainFrameAttribs = service.SettingsProvider.getInstance().getSettings("pyfaMainWindowAttribs", mainFrameDefaultAttribs) @@ -200,7 +216,6 @@ class MainFrame(wx.Frame): self.activeStatsWnd = wnd def GetActiveStatsWindow(self): - if self.activeStatsWnd in self.statsWnds: return self.activeStatsWnd @@ -232,6 +247,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/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? From 2d82eb7c929d4ba796ec7dc21c415e33a7539e82 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Sat, 24 May 2014 22:20:26 -0400 Subject: [PATCH 2/3] Add thread for opening fits on startup, which allows us of wait dialog Wait dialog doesn't actually move as the GUI thread is locked when opening the fits, but at least it shows that -something- is happening. --- gui/builtinViews/fittingView.py | 4 +-- gui/mainFrame.py | 47 ++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 89e5018cc..96101be72 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -49,13 +49,13 @@ class FitSpawner(gui.multiSwitch.TabSpawner): 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: mstate = getattr(event, "mstate", wx.GetMouseState()) if mstate.CmdDown() or mstate.MiddleDown(): diff --git a/gui/mainFrame.py b/gui/mainFrame.py index da83bbbd0..9625df43e 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 + + # open first fit in same tab (which should be empty) + wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fits[0])) + + # set mouse state to pass to FitSpawner via event + mstate = wx.GetMouseState() + mstate.SetMiddleDown(True) + + # open the rest of the fits with an mstate override (to open in new tabs) + for fitID in self.fits[1:]: + wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID, mstate=mstate)) + + wx.CallAfter(self.callback) + class MainFrame(wx.Frame): __instance = None @classmethod @@ -154,16 +180,15 @@ class MainFrame(wx.Frame): self.statsWnds = [] self.activeStatsWnd = None - self.Bind(wx.EVT_CLOSE, self.OnClose) + #Show ourselves + self.Show() + self.prevOpenFits = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False,"pyfaOpenFits": []}) if self.prevOpenFits['enabled']: self.LoadPreviousOpenFits() - #Show ourselves - self.Show() - #Check for updates self.sUpdate = service.Update.getInstance() self.sUpdate.CheckUpdate(self.ShowUpdateBox) @@ -175,18 +200,10 @@ class MainFrame(wx.Frame): def LoadPreviousOpenFits(self): fits = self.prevOpenFits['pyfaOpenFits'] - if len(fits) > 0: - # open first fit in same tab (which should be empty) - wx.PostEvent(self, FitSelected(fitID=fits[0])) - - # set mouse state to pass to FitSpawner via event - mstate = wx.GetMouseState() - mstate.SetMiddleDown(True) - - # open the rest of the fits with an mstate override (to open in new tabs) - for fitID in fits[1:]: - wx.PostEvent(self, FitSelected(fitID=fitID, mstate=mstate)) + self.waitDialog = animUtils.WaitDialog(self, title = "Opening previous fits") + thread = OpenFitsThread(fits, self.closeWaitDialog) + self.waitDialog.ShowModal() def LoadMainFrameAttribs(self): mainFrameDefaultAttribs = {"wnd_width":1000, "wnd_height": 700, "wnd_maximized": False} From a1416e6bece09a6037c79ed63f2ddf7963ee56aa Mon Sep 17 00:00:00 2001 From: blitzmann Date: Sun, 25 May 2014 02:55:28 -0400 Subject: [PATCH 3/3] Improves on fit loading on startup by only calculating the last fit that is opened. Issue with FittingView.MakeSnapshot() need an exception catch. --- gui/builtinViews/fittingView.py | 27 ++++++++++++++--------- gui/mainFrame.py | 39 +++++++++++++++++++-------------- gui/multiSwitch.py | 9 ++++---- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 96101be72..444ad9ad4 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -44,8 +44,6 @@ 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: @@ -56,9 +54,10 @@ class FitSpawner(gui.multiSwitch.TabSpawner): except: pass if count < 0: - mstate = getattr(event, "mstate", wx.GetMouseState()) + 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 9625df43e..dad54971d 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -77,17 +77,17 @@ class OpenFitsThread(threading.Thread): def run(self): time.sleep(0.5) # Give GUI some time to finish drawing - # open first fit in same tab (which should be empty) - wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fits[0])) - - # set mouse state to pass to FitSpawner via event - mstate = wx.GetMouseState() - mstate.SetMiddleDown(True) - - # open the rest of the fits with an mstate override (to open in new tabs) - for fitID in self.fits[1:]: - wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID, mstate=mstate)) + # `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): @@ -185,9 +185,7 @@ class MainFrame(wx.Frame): #Show ourselves self.Show() - self.prevOpenFits = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False,"pyfaOpenFits": []}) - if self.prevOpenFits['enabled']: - self.LoadPreviousOpenFits() + self.LoadPreviousOpenFits() #Check for updates self.sUpdate = service.Update.getInstance() @@ -199,11 +197,18 @@ class MainFrame(wx.Frame): dlg.Destroy() def LoadPreviousOpenFits(self): + self.prevOpenFits = service.SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []}) fits = self.prevOpenFits['pyfaOpenFits'] - if len(fits) > 0: - self.waitDialog = animUtils.WaitDialog(self, title = "Opening previous fits") - thread = OpenFitsThread(fits, self.closeWaitDialog) - self.waitDialog.ShowModal() + + 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} 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)