import time import webbrowser import json import wx import requests from service.crest import CrestModes from service.crest import Crest from service.fit import Fit from eos.types import Cargo from eos.db import getItem import gui.display as d import gui.globalEvents as GE class CrestFittings(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Browse EVE Fittings", pos=wx.DefaultPosition, size=wx.Size(550, 450), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL) self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) self.mainFrame = parent mainSizer = wx.BoxSizer(wx.VERTICAL) sCrest = Crest.getInstance() characterSelectSizer = wx.BoxSizer(wx.HORIZONTAL) if sCrest.settings.get('mode') == CrestModes.IMPLICIT: self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s" % sCrest.implicitCharacter.name, wx.DefaultPosition, wx.DefaultSize) self.stLogged.Wrap(-1) characterSelectSizer.Add(self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) else: self.charChoice = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, []) characterSelectSizer.Add(self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) self.updateCharList() self.fetchBtn = wx.Button(self, wx.ID_ANY, u"Fetch Fits", wx.DefaultPosition, wx.DefaultSize, 5) characterSelectSizer.Add(self.fetchBtn, 0, wx.ALL, 5) mainSizer.Add(characterSelectSizer, 0, wx.EXPAND, 5) self.sl = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) mainSizer.Add(self.sl, 0, wx.EXPAND | wx.ALL, 5) contentSizer = wx.BoxSizer(wx.HORIZONTAL) browserSizer = wx.BoxSizer(wx.VERTICAL) self.fitTree = FittingsTreeView(self) browserSizer.Add(self.fitTree, 1, wx.ALL | wx.EXPAND, 5) contentSizer.Add(browserSizer, 1, wx.EXPAND, 0) fitSizer = wx.BoxSizer(wx.VERTICAL) self.fitView = FitView(self) fitSizer.Add(self.fitView, 1, wx.ALL | wx.EXPAND, 5) btnSizer = wx.BoxSizer(wx.HORIZONTAL) self.importBtn = wx.Button(self, wx.ID_ANY, u"Import to pyfa", wx.DefaultPosition, wx.DefaultSize, 5) self.deleteBtn = wx.Button(self, wx.ID_ANY, u"Delete from EVE", wx.DefaultPosition, wx.DefaultSize, 5) btnSizer.Add(self.importBtn, 1, wx.ALL, 5) btnSizer.Add(self.deleteBtn, 1, wx.ALL, 5) fitSizer.Add(btnSizer, 0, wx.EXPAND) contentSizer.Add(fitSizer, 1, wx.EXPAND, 0) mainSizer.Add(contentSizer, 1, wx.EXPAND, 5) self.fetchBtn.Bind(wx.EVT_BUTTON, self.fetchFittings) self.importBtn.Bind(wx.EVT_BUTTON, self.importFitting) self.deleteBtn.Bind(wx.EVT_BUTTON, self.deleteFitting) self.mainFrame.Bind(GE.EVT_SSO_LOGOUT, self.ssoLogout) self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.ssoLogin) self.Bind(wx.EVT_CLOSE, self.OnClose) self.statusbar = wx.StatusBar(self) self.statusbar.SetFieldsCount() self.SetStatusBar(self.statusbar) self.cacheTimer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.updateCacheStatus, self.cacheTimer) self.SetSizer(mainSizer) self.Layout() self.Centre(wx.BOTH) def ssoLogin(self, event): self.updateCharList() event.Skip() def updateCharList(self): sCrest = Crest.getInstance() chars = sCrest.getCrestCharacters() if len(chars) == 0: self.Close() self.charChoice.Clear() for char in chars: self.charChoice.Append(char.name, char.ID) self.charChoice.SetSelection(0) def updateCacheStatus(self, event): t = time.gmtime(self.cacheTime - time.time()) if t < 0: self.cacheTimer.Stop() else: sTime = time.strftime("%H:%M:%S", t) self.statusbar.SetStatusText("Cached for %s" % sTime, 0) def ssoLogout(self, event): if event.type == CrestModes.IMPLICIT: self.Close() else: self.updateCharList() event.Skip() # continue event def OnClose(self, event): self.mainFrame.Unbind(GE.EVT_SSO_LOGOUT, handler=self.ssoLogout) self.mainFrame.Unbind(GE.EVT_SSO_LOGIN, handler=self.ssoLogin) event.Skip() def getActiveCharacter(self): sCrest = Crest.getInstance() if sCrest.settings.get('mode') == CrestModes.IMPLICIT: return sCrest.implicitCharacter.ID selection = self.charChoice.GetCurrentSelection() return self.charChoice.GetClientData(selection) if selection is not None else None def fetchFittings(self, event): sCrest = Crest.getInstance() try: waitDialog = wx.BusyInfo("Fetching fits, please wait...", parent=self) fittings = sCrest.getFittings(self.getActiveCharacter()) self.cacheTime = fittings.get('cached_until') self.updateCacheStatus(None) self.cacheTimer.Start(1000) self.fitTree.populateSkillTree(fittings) except requests.exceptions.ConnectionError: self.statusbar.SetStatusText("Connection error, please check your internet connection") finally: del waitDialog def importFitting(self, event): selection = self.fitView.fitSelection if not selection: return data = self.fitTree.fittingsTreeCtrl.GetPyData(selection) sFit = Fit.getInstance() fits = sFit.importFitFromBuffer(data) self.mainFrame._openAfterImport(fits) def deleteFitting(self, event): sCrest = Crest.getInstance() selection = self.fitView.fitSelection if not selection: return data = json.loads(self.fitTree.fittingsTreeCtrl.GetPyData(selection)) dlg = wx.MessageDialog(self, "Do you really want to delete %s (%s) from EVE?" % (data['name'], data['ship']['name']), "Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION) if dlg.ShowModal() == wx.ID_YES: try: sCrest.delFitting(self.getActiveCharacter(), data['fittingID']) except requests.exceptions.ConnectionError: self.statusbar.SetStatusText("Connection error, please check your internet connection") class ExportToEve(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Export fit to EVE", pos=wx.DefaultPosition, size=(wx.Size(350, 100)), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL) self.mainFrame = parent self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) sCrest = Crest.getInstance() mainSizer = wx.BoxSizer(wx.VERTICAL) hSizer = wx.BoxSizer(wx.HORIZONTAL) if sCrest.settings.get('mode') == CrestModes.IMPLICIT: self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s" % sCrest.implicitCharacter.name, wx.DefaultPosition, wx.DefaultSize) self.stLogged.Wrap(-1) hSizer.Add(self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) else: self.charChoice = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, []) hSizer.Add(self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) self.updateCharList() self.charChoice.SetSelection(0) self.exportBtn = wx.Button(self, wx.ID_ANY, u"Export Fit", wx.DefaultPosition, wx.DefaultSize, 5) hSizer.Add(self.exportBtn, 0, wx.ALL, 5) mainSizer.Add(hSizer, 0, wx.EXPAND, 5) self.exportBtn.Bind(wx.EVT_BUTTON, self.exportFitting) self.statusbar = wx.StatusBar(self) self.statusbar.SetFieldsCount(2) self.statusbar.SetStatusWidths([100, -1]) self.mainFrame.Bind(GE.EVT_SSO_LOGOUT, self.ssoLogout) self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.ssoLogin) self.Bind(wx.EVT_CLOSE, self.OnClose) self.SetSizer(hSizer) self.SetStatusBar(self.statusbar) self.Layout() self.Centre(wx.BOTH) def updateCharList(self): sCrest = Crest.getInstance() chars = sCrest.getCrestCharacters() if len(chars) == 0: self.Close() self.charChoice.Clear() for char in chars: self.charChoice.Append(char.name, char.ID) self.charChoice.SetSelection(0) def ssoLogin(self, event): self.updateCharList() event.Skip() def ssoLogout(self, event): if event.type == CrestModes.IMPLICIT: self.Close() else: self.updateCharList() event.Skip() # continue event def OnClose(self, event): self.mainFrame.Unbind(GE.EVT_SSO_LOGOUT, handler=self.ssoLogout) event.Skip() def getActiveCharacter(self): sCrest = Crest.getInstance() if sCrest.settings.get('mode') == CrestModes.IMPLICIT: return sCrest.implicitCharacter.ID selection = self.charChoice.GetCurrentSelection() return self.charChoice.GetClientData(selection) if selection is not None else None def exportFitting(self, event): sFit = Fit.getInstance() fitID = self.mainFrame.getActiveFit() self.statusbar.SetStatusText("", 0) if fitID is None: self.statusbar.SetStatusText("Please select an active fitting in the main window", 1) return self.statusbar.SetStatusText("Sending request and awaiting response", 1) sCrest = Crest.getInstance() try: data = sFit.exportCrest(fitID) res = sCrest.postFitting(self.getActiveCharacter(), data) self.statusbar.SetStatusText("%d: %s" % (res.status_code, res.reason), 0) try: text = json.loads(res.text) self.statusbar.SetStatusText(text['message'], 1) except ValueError: self.statusbar.SetStatusText("", 1) except requests.exceptions.ConnectionError: self.statusbar.SetStatusText("Connection error, please check your internet connection", 1) class CrestMgmt(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="CREST Character Management", pos=wx.DefaultPosition, size=wx.Size(550, 250), style=wx.DEFAULT_DIALOG_STYLE) self.mainFrame = parent mainSizer = wx.BoxSizer(wx.HORIZONTAL) self.lcCharacters = wx.ListCtrl(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT) self.lcCharacters.InsertColumn(0, heading='Character') self.lcCharacters.InsertColumn(1, heading='Refresh Token') self.popCharList() mainSizer.Add(self.lcCharacters, 1, wx.ALL | wx.EXPAND, 5) btnSizer = wx.BoxSizer(wx.VERTICAL) self.addBtn = wx.Button(self, wx.ID_ANY, u"Add Character", wx.DefaultPosition, wx.DefaultSize, 0) btnSizer.Add(self.addBtn, 0, wx.ALL | wx.EXPAND, 5) self.deleteBtn = wx.Button(self, wx.ID_ANY, u"Revoke Character", wx.DefaultPosition, wx.DefaultSize, 0) btnSizer.Add(self.deleteBtn, 0, wx.ALL | wx.EXPAND, 5) mainSizer.Add(btnSizer, 0, wx.EXPAND, 5) self.addBtn.Bind(wx.EVT_BUTTON, self.addChar) self.deleteBtn.Bind(wx.EVT_BUTTON, self.delChar) self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.ssoLogin) self.SetSizer(mainSizer) self.Layout() self.Centre(wx.BOTH) def ssoLogin(self, event): self.popCharList() event.Skip() def popCharList(self): sCrest = Crest.getInstance() chars = sCrest.getCrestCharacters() self.lcCharacters.DeleteAllItems() for index, char in enumerate(chars): self.lcCharacters.InsertStringItem(index, char.name) self.lcCharacters.SetStringItem(index, 1, char.refresh_token) self.lcCharacters.SetItemData(index, char.ID) self.lcCharacters.SetColumnWidth(0, wx.LIST_AUTOSIZE) self.lcCharacters.SetColumnWidth(1, wx.LIST_AUTOSIZE) def addChar(self, event): sCrest = Crest.getInstance() uri = sCrest.startServer() webbrowser.open(uri) def delChar(self, event): item = self.lcCharacters.GetFirstSelected() if item > -1: charID = self.lcCharacters.GetItemData(item) sCrest = Crest.getInstance() sCrest.delCrestCharacter(charID) self.popCharList() class FittingsTreeView(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, id=wx.ID_ANY) self.parent = parent pmainSizer = wx.BoxSizer(wx.VERTICAL) tree = self.fittingsTreeCtrl = wx.TreeCtrl(self, wx.ID_ANY, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT) pmainSizer.Add(tree, 1, wx.EXPAND | wx.ALL, 0) self.root = tree.AddRoot("Fits") self.populateSkillTree(None) self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.displayFit) self.SetSizer(pmainSizer) self.Layout() def populateSkillTree(self, data): if data is None: return root = self.root tree = self.fittingsTreeCtrl tree.DeleteChildren(root) dict = {} fits = data['items'] for fit in fits: if fit['ship']['name'] not in dict: dict[fit['ship']['name']] = [] dict[fit['ship']['name']].append(fit) for name, fits in dict.iteritems(): shipID = tree.AppendItem(root, name) for fit in fits: fitId = tree.AppendItem(shipID, fit['name']) tree.SetPyData(fitId, json.dumps(fit)) tree.SortChildren(root) def displayFit(self, event): selection = self.fittingsTreeCtrl.GetSelection() fit = json.loads(self.fittingsTreeCtrl.GetPyData(selection)) list = [] for item in fit['items']: try: cargo = Cargo(getItem(item['type']['id'])) cargo.amount = item['quantity'] list.append(cargo) except: pass self.parent.fitView.fitSelection = selection self.parent.fitView.update(list) class FitView(d.Display): DEFAULT_COLS = ["Base Icon", "Base Name"] def __init__(self, parent): d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL) self.fitSelection = None