Files
pyfa/gui/mainFrame.py
2010-12-05 20:06:46 +02:00

439 lines
15 KiB
Python

#===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
import service
import config
from gui import bitmapLoader
from gui.mainMenuBar import MainMenuBar
from gui.additionsPane import AdditionsPane
from gui.marketBrowser import MarketBrowser
from gui.multiSwitch import MultiSwitch
from gui.statsPane import StatsPane
from gui.shipBrowser import ShipBrowser, FitSelected
from wx.lib.wordwrap import wordwrap
from gui.characterEditor import CharacterEditor
from gui.characterSelection import CharacterSelection
from gui.patternEditor import DmgPatternEditorDlg
from gui.preferenceDialog import PreferenceDialog
from gui.graphFrame import GraphFrame
from gui.copySelectDialog import CopySelectDialog
import aboutData
from wx._core import PyDeadObjectError
import os.path
import gui.chromeTabs
from util import toClipboard, fromClipboard
from builtinViews import *
from gui.fleetBrowser import FleetBrowser
#dummy panel no paint no erasebk
class PFPanel(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnBkErase)
def OnPaint(self, event):
event.Skip()
def OnBkErase(self, event):
pass
class MainFrame(wx.Frame):
__instance = None
@classmethod
def getInstance(cls):
return cls.__instance if cls.__instance is not None else MainFrame()
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, title="pyfa - Python Fitting Assistant")
MainFrame.__instance = self
self.LoadMainFrameAttribs()
if 'wxMSW' in wx.PlatformInfo:
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
i = wx.IconFromBitmap(bitmapLoader.getBitmap("pyfa", "icons"))
self.SetIcon(i)
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
self.splitter = wx.SplitterWindow(self, style = wx.SP_LIVE_UPDATE)
mainSizer.Add(self.splitter,1,wx.EXPAND | wx.LEFT, 2)
self.FitviewAdditionsPanel = PFPanel(self.splitter)
faSizer = wx.BoxSizer(wx.VERTICAL)
self.fitMultiSwitch = MultiSwitch(self.FitviewAdditionsPanel)
faSizer.Add(self.fitMultiSwitch,1,wx.EXPAND)
self.additionsPane = AdditionsPane(self.FitviewAdditionsPanel)
faSizer.Add(self.additionsPane, 0, wx.EXPAND)
self.FitviewAdditionsPanel.SetSizer(faSizer)
self.notebookBrowsers = gui.chromeTabs.PFNotebook(self.splitter, False)
self.marketBrowser = MarketBrowser(self.notebookBrowsers)
self.notebookBrowsers.AddPage(self.marketBrowser, "Market", showClose = False)
self.shipBrowser = ShipBrowser(self.notebookBrowsers)
self.notebookBrowsers.AddPage(self.shipBrowser, "Ships", showClose = False)
self.fleetBrowser = FleetBrowser(self.notebookBrowsers)
self.notebookBrowsers.AddPage(self.fleetBrowser, "Fleets", showClose = False)
self.notebookBrowsers.SetSelection(1)
self.splitter.SplitVertically(self.notebookBrowsers, self.FitviewAdditionsPanel)
self.splitter.SetMinimumPaneSize(200)
self.splitter.SetSashPosition(300)
cstatsSizer = wx.BoxSizer(wx.VERTICAL)
self.charSelection = CharacterSelection(self)
cstatsSizer.Add(self.charSelection, 0, wx.EXPAND)
self.statsPane = StatsPane(self)
cstatsSizer.Add(self.statsPane, 0, wx.EXPAND)
mainSizer.Add(cstatsSizer, 0 , wx.EXPAND)
self.SetSizer(mainSizer)
self.addPageId = wx.NewId()
self.closePageId = wx.NewId()
self.graphFrame = None
self.statsWnds = []
self.activeStatsWnd = None
#Add menu
self.SetMenuBar(MainMenuBar())
#self.SetToolBar(MainToolBar(self))
self.registerMenu()
self.Bind(wx.EVT_CLOSE, self.OnClose)
#Show ourselves
self.Show()
def LoadMainFrameAttribs(self):
mainFrameDefaultAttribs = {"wnd_width":1000, "wnd_height": 700}
self.mainFrameAttribs = service.SettingsProvider.getInstance().getSettings("pyfaMainWindowAttribs", mainFrameDefaultAttribs)
width = self.mainFrameAttribs["wnd_width"]
height = self.mainFrameAttribs["wnd_height"]
self.SetSize((width, height))
self.SetMinSize((mainFrameDefaultAttribs["wnd_width"], mainFrameDefaultAttribs["wnd_height"]))
def UpdateMainFrameAttribs(self):
if self.IsIconized():
return
width,height = self.GetSize()
x,y = self.GetPosition()
self.mainFrameAttribs["wnd_width"] = width
self.mainFrameAttribs["wnd_height"] = height
def SetActiveStatsWindow(self, wnd):
self.activeStatsWnd = wnd
def GetActiveStatsWindow(self):
if self.activeStatsWnd in self.statsWnds:
return self.activeStatsWnd
if len(self.statsWnds) > 0:
return self.statsWnds[len(self.statsWnds) - 1]
else:
return None
def RegisterStatsWindow(self, wnd):
self.statsWnds.append(wnd)
def UnregisterStatsWindow(self, wnd):
self.statsWnds.remove(wnd)
def getActiveFit(self):
p = self.fitMultiSwitch.GetSelectedPage()
m = getattr(p, "getActiveFit", None)
return m() if m is not None else None
def getActiveView(self):
sel = self.fitMultiSwitch.GetSelectedPage()
def CloseCurrentPage(self, evt):
ms = self.fitMultiSwitch
page = ms.GetSelection()
if page is not None:
ms.DeletePage(page)
def OnClose(self, event):
self.UpdateMainFrameAttribs()
service.SettingsProvider.getInstance().saveAll()
event.Skip()
def ExitApp(self, event):
self.Close()
event.Skip()
def ShowAboutBox(self, evt):
info = wx.AboutDialogInfo()
info.Name = "pyfa"
info.Version = aboutData.versionString
info.Description = wordwrap(aboutData.description + "\n\n\nDevelopers: " + ", ".join(aboutData.developers) + "\n\nAdditional credits:\n " + "\n ".join(aboutData.credits) + "\n\nLicense: " + aboutData.license + " - see included " + aboutData.licenseLocation,
550, wx.ClientDC(self))
info.WebSite = ("http://www.evefit.org/Pyfa", "pyfa home page")
wx.AboutBox(info)
def showCharacterEditor(self, event):
dlg=CharacterEditor(self)
dlg.Show()
def showDamagePatternEditor(self, event):
dlg=DmgPatternEditorDlg(self)
dlg.ShowModal()
dlg.Destroy()
def showImportDialog(self, event):
fits = []
sFit = service.Fit.getInstance()
dlg=wx.FileDialog(
self,
"Open One Or More Fitting Files",
wildcard = "EFT text fitting files (*.cfg)|*.cfg|EvE XML fitting files (*.xml)|*.xml|All Files (*)|*",
style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE)
if (dlg.ShowModal() == wx.ID_OK):
try:
for importPath in dlg.GetPaths():
fits += sFit.importFit(importPath)
IDs = sFit.saveImportedFits(fits)
self._openAfterImport(len(fits), IDs)
except:
wx.MessageBox("Error importing from file.", "Error", wx.OK | wx.ICON_ERROR, self)
dlg.Destroy()
def _openAfterImport(self, importCount, fitIDs):
if importCount == 1:
if self.getActiveFit() != fitIDs[0]:
wx.PostEvent(self, FitSelected(fitID=fitIDs[0]))
self.shipBrowser.RefreshContent()
def showExportDialog(self, event):
dlg=wx.FileDialog(
self,
"Save Fitting As...",
wildcard = "EFT text fitting files (*.cfg)|*.cfg|EvE XML fitting files (*.xml)|*.xml",
style = wx.FD_SAVE)
if (dlg.ShowModal() == wx.ID_OK):
sFit = service.Fit.getInstance()
format = dlg.GetFilterIndex()
output = ""
path = dlg.GetPath()
if (format == 0):
output = sFit.exportFit(self.getActiveFit())
if '.' not in os.path.basename(path):
path += ".cfg"
elif (format == 1):
output = sFit.exportXml(self.getActiveFit())
if '.' not in os.path.basename(path):
path += ".xml"
else:
print "oops, invalid fit format %d" % format
dlg.Destroy()
return
file = open(path, "w")
file.write(output)
file.close()
dlg.Destroy()
def showPreferenceDialog(self, event):
dlg = PreferenceDialog(self)
dlg.ShowModal()
dlg.Destroy()
def registerMenu(self):
menuBar = self.GetMenuBar()
# Quit
self.Bind(wx.EVT_MENU, self.ExitApp, id=wx.ID_EXIT)
# Widgets Inspector
if config.debug:
self.Bind(wx.EVT_MENU, self.openWXInspectTool, id=911)
# About
self.Bind(wx.EVT_MENU, self.ShowAboutBox, id=wx.ID_ABOUT)
# Char editor
self.Bind(wx.EVT_MENU, self.showCharacterEditor, id=menuBar.characterEditorId)
# Damage pattern editor
self.Bind(wx.EVT_MENU, self.showDamagePatternEditor, id=menuBar.damagePatternEditorId)
# Import dialog
self.Bind(wx.EVT_MENU, self.showImportDialog, id=wx.ID_OPEN)
# Export dialog
self.Bind(wx.EVT_MENU, self.showExportDialog, id=wx.ID_SAVEAS)
# Import from Clipboard
self.Bind(wx.EVT_MENU, self.importFromClipboard, id=wx.ID_PASTE)
# Backup fits
self.Bind(wx.EVT_MENU, self.backupToXml, id=menuBar.backupFitsId)
# Preference dialog
self.Bind(wx.EVT_MENU, self.showPreferenceDialog, id=wx.ID_PREFERENCES)
#Clipboard exports
self.Bind(wx.EVT_MENU, self.exportToClipboard, id=wx.ID_COPY)
#Graphs
self.Bind(wx.EVT_MENU, self.openGraphFrame, id=menuBar.graphFrameId)
toggleShipMarketId = wx.NewId()
# Close Page
self.Bind(wx.EVT_MENU, self.CloseCurrentPage, id=self.closePageId)
self.Bind(wx.EVT_MENU, self.HAddPage, id = self.addPageId)
self.Bind(wx.EVT_MENU, self.toggleShipMarket, id = toggleShipMarketId)
actb = [(wx.ACCEL_CTRL, ord('T'), self.addPageId),
(wx.ACCEL_CMD, ord('T'), self.addPageId),
(wx.ACCEL_CTRL, ord("W"), self.closePageId),
(wx.ACCEL_CMD, ord("W"), self.closePageId),
(wx.ACCEL_CTRL, ord(" "), toggleShipMarketId),
(wx.ACCEL_CMD, ord(" "), toggleShipMarketId)]
atable = wx.AcceleratorTable(actb)
self.SetAcceleratorTable(atable)
def HAddPage(self,event):
self.fitMultiSwitch.AddPage(wx.Panel(self, size = (0,0)), "Empty Tab")
def toggleShipMarket(self, event):
sel = self.notebookBrowsers.GetSelection()
self.notebookBrowsers.SetSelection(0 if sel == 1 else 1)
def clipboardEft(self):
sFit = service.Fit.getInstance()
toClipboard(sFit.exportFit(self.getActiveFit()))
def clipboardDna(self):
sFit = service.Fit.getInstance()
toClipboard(sFit.exportDna(self.getActiveFit()))
def clipboardXml(self):
sFit = service.Fit.getInstance()
toClipboard(sFit.exportXml(self.getActiveFit()))
def importFromClipboard(self, event):
sFit = service.Fit.getInstance()
try:
fits = sFit.importFitFromBuffer(fromClipboard())
IDs = sFit.saveImportedFits(fits)
self._openAfterImport(len(fits), IDs)
except:
pass
def exportToClipboard(self, event):
CopySelectDict = {CopySelectDialog.copyFormatEft: self.clipboardEft,
CopySelectDialog.copyFormatXml: self.clipboardXml,
CopySelectDialog.copyFormatDna: self.clipboardDna}
dlg = CopySelectDialog(self)
dlg.ShowModal()
selected = dlg.GetSelected()
try:
CopySelectDict[selected]()
except:
pass
dlg.Destroy()
def backupToXml(self, event):
sFit = service.Fit.getInstance()
saveDialog = wx.FileDialog(
self,
"Save Backup As...",
wildcard = "EvE XML fitting file (*.xml)|*.xml",
style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
if (saveDialog.ShowModal() == wx.ID_OK):
filePath = saveDialog.GetPath()
if '.' not in os.path.basename(filePath):
filePath += ".xml"
self.waitDialog = WaitDialog(self)
sFit.backupFits(filePath, self.closeWaitDialog)
self.waitDialog.ShowModal()
saveDialog.Destroy()
def closeWaitDialog(self):
if self.waitDialog.timer.IsRunning():
self.waitDialog.timer.Stop()
self.waitDialog.Destroy()
def openGraphFrame(self, event):
if not gui.graphFrame.enabled:
return
if not self.graphFrame:
self.graphFrame = GraphFrame(self)
self.graphFrame.Show()
else:
self.graphFrame.SetFocus()
def toggleShipBrowser(self, event):
self.GetToolBar().toggleShipBrowser(event)
def openWXInspectTool(self,event):
from wx.lib.inspection import InspectionTool
if not InspectionTool().initialized:
InspectionTool().Init()
# Find a widget to be selected in the tree. Use either the
# one under the cursor, if any, or this frame.
wnd = wx.FindWindowAtPointer()
if not wnd:
wnd = self
InspectionTool().Show(wnd, True)
class WaitDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__ (self, parent, id=wx.ID_ANY, title=u"Please wait ...", size=(200,30),
style=wx.NO_BORDER)
mainSizer = wx.BoxSizer( wx.HORIZONTAL )
self.progress = wx.Gauge( self, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.GA_HORIZONTAL | wx.GA_SMOOTH )
mainSizer.Add( self.progress, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 0 )
self.progress.SetRange(20)
self.progress.SetValue(0)
self.cycle = 0
self.SetSizer( mainSizer )
self.Layout()
self.timer = wx.Timer(self,wx.ID_ANY)
self.timer.Start(100)
self.Bind(wx.EVT_CLOSE,self.OnClose)
self.Bind(wx.EVT_TIMER,self.OnTimer)
self.CenterOnParent()
def OnTimer(self, event):
self.cycle += 1
if self.cycle > self.progress.GetRange():
self.cycle = 0
self.progress.SetValue(self.cycle)
def OnClose(self, event):
pass