class MainWindow(wx.Frame): def __init__(self, parent, id): wx.Frame.__init__(self, parent, id, 'Planet Hunt', size=(1400, 600)) self.splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE) # The passing references to panels and controsl to each other # seems a bit sloppy and I want to do away with it. Not sure how yet. data_display_panel = DataDisplayPanel(self.splitter) data_modify_panel = DataModifyPanel(self.splitter, data_display_panel) data_search_panel = DataSearchPanel(self.splitter, data_display_panel, data_modify_panel) self.splitter.AppendWindow(data_search_panel, sashPos=150) self.splitter.AppendWindow(data_display_panel, sashPos=1050) self.splitter.AppendWindow(data_modify_panel) status_bar = self.CreateStatusBar() menubar_main = wx.MenuBar() file_menu = wx.Menu() edit_menu = wx.Menu() file_menu.Append(wx.NewIdRef(), 'Connect...', 'Connect to a new server') file_menu.Append(wx.NewIdRef(), 'Close', 'Quit the application') menubar_main.Append(file_menu, 'File') menubar_main.Append(edit_menu, 'Edit') self.SetMenuBar(menubar_main) self.SetStatusBar(status_bar) def force_update(self): # Jiggle the splitter 'sash' around to force a redraw. # No, I don't like having to do this but I can't figure out the # proper way to make the matplotlib graphs actually show up. sp = self.splitter.GetSashPosition(0) self.splitter.SetSashPosition(0, sp+1) self.splitter.SetSashPosition(0, sp+0) def close_window(self, event): self.Destroy()
class PanelMiners(wx.Panel): lock = threading.RLock() def __init__(self, parent, frame, num_miners=4): wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY) self.parent = parent self.frame = frame self.resize_lock = False self.num_miners = num_miners self.devicesJson = self.loadDevices() self.splitter = MultiSplitterWindow(self, id=wx.ID_ANY, style=wx.SP_LIVE_UPDATE) self.splitter.SetOrientation(wx.HORIZONTAL) self.splitter.SetMinimumPaneSize(1) self.miner0 = PMI.PanelMinerInstance(self.splitter, self, "Miner #0", self.devicesJson['miner0'], self.devicesJson['miner0num'], self.devicesJson['devices']) self.miner1 = PMI.PanelMinerInstance(self.splitter, self, "Miner #1", self.devicesJson['miner1'], self.devicesJson['miner1num'], self.devicesJson['devices']) self.miner2 = PMI.PanelMinerInstance(self.splitter, self, "Miner #2", self.devicesJson['miner2'], self.devicesJson['miner2num'], self.devicesJson['devices']) self.miner3 = PMI.PanelMinerInstance(self.splitter, self, "Miner #3", self.devicesJson['miner3'], self.devicesJson['miner3num'], self.devicesJson['devices']) self.splitter.AppendWindow(self.miner0) self.splitter.AppendWindow(self.miner1) self.splitter.AppendWindow(self.miner2) self.splitter.AppendWindow(self.miner3) self.splitter.Bind(wx.EVT_SIZE, self.resizeMinerPanels) #self.splitter.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGING, self.sashChanging) #self.splitter.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.resizeMinerPanels) self.collapsePanel = CollapsePanel(self, self.devicesJson['resize'], self.devicesJson['transfer']) sizer = wx.BoxSizer(wx.HORIZONTAL) sizerW = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(self.splitter, 1, wx.EXPAND) sizerW.Add(self.collapsePanel, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, -1) sizer.Add(sizerW, 0, wx.EXPAND | wx.TOP, 1) self.SetSizer(sizer) def loadDevices(self): f = open(DEVICES_FILE) data = f.read() f.close() return json.loads(data) def saveDevices(self): sel0 = self.miner0.handler.deviceCombo.GetValue() sel1 = self.miner1.handler.deviceCombo.GetValue() sel2 = self.miner2.handler.deviceCombo.GetValue() sel3 = self.miner3.handler.deviceCombo.GetValue() num0 = self.miner0.handler.deviceNum.GetValue() num1 = self.miner1.handler.deviceNum.GetValue() num2 = self.miner2.handler.deviceNum.GetValue() num3 = self.miner3.handler.deviceNum.GetValue() self.devicesJson['miner0'] = sel0 self.devicesJson['miner1'] = sel1 self.devicesJson['miner2'] = sel2 self.devicesJson['miner3'] = sel3 self.devicesJson['miner0num'] = num0 self.devicesJson['miner1num'] = num1 self.devicesJson['miner2num'] = num2 self.devicesJson['miner3num'] = num3 self.devicesJson['resize'] = self.collapsePanel.resizeBtn.GetValue() self.devicesJson['transfer'] = self.collapsePanel.transferBtn.GetValue( ) io.open(DEVICES_FILE, 'wt', encoding='utf-8').write(unicode(json.dumps(self.devicesJson))) def deviceChanged(self): if self.collapsePanel.transferBtn.GetValue(): devices = [ self.miner0.handler.getDevice(), self.miner1.handler.getDevice(), self.miner2.handler.getDevice(), self.miner3.handler.getDevice() ] self.frame.notebook.broadcastEventToAllTabs(event_id="miner", event_value=devices) def executeAlgo(self, maxAlgo, switch): if switch: self.stopMiners() else: self.stopCrashedMiners() ret0 = self.miner0.executeAlgo(maxAlgo, switch) ret1 = self.miner1.executeAlgo(maxAlgo, switch) ret2 = self.miner2.executeAlgo(maxAlgo, switch) ret3 = self.miner3.executeAlgo(maxAlgo, switch) if (ret0 is None and ret1 is None and ret2 is None and ret3 is None): return None return ret0 or ret1 or ret2 or ret3 def stopMiners(self, wait=False, exit=False): self.miner0.stopMiner(exit) self.miner1.stopMiner(exit) self.miner2.stopMiner(exit) self.miner3.stopMiner(exit) if exit: self.stopLoop(self.checkMinersExited) elif wait: self.stopLoop(self.checkMinersReady) self.frame.notebook.broadcastEventToAllTabs(event_id="stop_mining") def stopCrashedMiners(self): if self.miner0.minerStatus() == PMI.STATUS_CRASHED: self.miner0.stopMiner() if self.miner1.minerStatus() == PMI.STATUS_CRASHED: self.miner1.stopMiner() if self.miner2.minerStatus() == PMI.STATUS_CRASHED: self.miner2.stopMiner() if self.miner3.minerStatus() == PMI.STATUS_CRASHED: self.miner3.stopMiner() def stopLoop(self, endFunction): success = False i = 0 str_ini = "Waiting for miners to die " from miner import PanelMinerInstance while i < PanelMinerInstance.MAX_ITERATIONS: if not endFunction(): time.sleep(0.5) i += 1 str_out = str_ini + str(i) print str_out else: str_out = "MINERS done, Bye!" print str_out #time.sleep(2) success = True break print "Miners: Exited with success = " + str(success) if not success: str_out = "MINERS Dammit" print str_out time.sleep(5) def checkMinerCrashed(self): if self.miner0.minerStatus() == PMI.STATUS_CRASHED or \ self.miner1.minerStatus() == PMI.STATUS_CRASHED or \ self.miner2.minerStatus() == PMI.STATUS_CRASHED or \ self.miner3.minerStatus() == PMI.STATUS_CRASHED: return False return True def checkMinersReady(self): if ( self.miner0.minerStatus() in (PMI.STATUS_READY, PMI.STATUS_DISABLED, PMI.STATUS_CRASHED, PMI.STATUS_EXITED, PMI.STATUS_EXITING ) ) and \ ( self.miner1.minerStatus() in (PMI.STATUS_READY, PMI.STATUS_DISABLED, PMI.STATUS_CRASHED, PMI.STATUS_EXITED, PMI.STATUS_EXITING ) ) and \ ( self.miner2.minerStatus() in (PMI.STATUS_READY, PMI.STATUS_DISABLED, PMI.STATUS_CRASHED, PMI.STATUS_EXITED, PMI.STATUS_EXITING ) ) and \ ( self.miner3.minerStatus() in (PMI.STATUS_READY, PMI.STATUS_DISABLED, PMI.STATUS_CRASHED, PMI.STATUS_EXITED, PMI.STATUS_EXITING ) ): return True return False def checkMinersExited(self): if ( self.miner0.minerStatus() == PMI.STATUS_EXITED ) and \ ( self.miner1.minerStatus() == PMI.STATUS_EXITED ) and \ ( self.miner2.minerStatus() == PMI.STATUS_EXITED ) and \ ( self.miner3.minerStatus() == PMI.STATUS_EXITED ): return True return False def checkMinersSelected(self): if ( self.miner0.minerStatus() == PMI.STATUS_DISABLED ) and \ ( self.miner1.minerStatus() == PMI.STATUS_DISABLED ) and \ ( self.miner2.minerStatus() == PMI.STATUS_DISABLED ) and \ ( self.miner3.minerStatus() == PMI.STATUS_DISABLED ): return False return True def resizeMinerPanels(self, event=None, slide=False, forceResize=False): try: if not self.collapsePanel.resizeBtn.GetValue() and not forceResize: event.Skip() return width = self.parent.GetSize()[0] best = width / self.num_miners num_ready = sum( 1 for miner in [self.miner0, self.miner1, self.miner2, self.miner3] if miner.minerStatus() is not PMI.STATUS_DISABLED) #num_rinning = sum(1 for miner in [self.miner0, self.miner1, self.miner2, self.miner3] if miner.minerStatus() == PMI.STATUS_RUNNING) factor = 1.5 factor = factor if num_ready == 0 else factor + ( float(num_ready * 1.5) / 10) #factor = 1.5 if num_ready == 0 else 1.5 * ( 1 + ( self.num_miners - float(num_ready) - 1 ) / 10 ) num_not_ready = self.num_miners - num_ready if num_ready == 0 or num_not_ready == 0 or forceResize: wide = narrow = best else: factored_num_ready = num_ready * factor factored_total = factored_num_ready + num_not_ready factor_ready = float(factored_num_ready) / factored_total factor_not_ready = float(num_not_ready) / factored_total wide = (factor_ready * width) / num_ready narrow = (factor_not_ready * width) / num_not_ready #no slide effect allowed for resize event triggered calls to the function for performance reasons. if not slide: self.splitter.SetSashPosition( 0, int(wide if self.miner0.minerStatus() != PMI. STATUS_DISABLED else narrow)) self.splitter.SetSashPosition( 1, int(wide if self.miner1.minerStatus() != PMI. STATUS_DISABLED else narrow)) self.splitter.SetSashPosition( 2, int(wide if self.miner2.minerStatus() != PMI. STATUS_DISABLED else narrow)) self.splitter.SetSashPosition( 3, int(wide if self.miner3.minerStatus() != PMI. STATUS_DISABLED else narrow)) if event: event.Skip() return thread = threading.Thread(target=self.resizeMinerPanelsThread, args=(wide, narrow)) thread.start() except (PyDeadObjectError, AttributeError): pass def resizeMinerPanelsThread(self, wide, narrow): try: #with PanelMiners.lock: if self.resize_lock: time.sleep(0.5) if not self.resize_lock: self.resize_lock = True target0 = int(wide if self.miner0.minerStatus() != PMI. STATUS_DISABLED else narrow) target1 = int(wide if self.miner1.minerStatus() != PMI. STATUS_DISABLED else narrow) target2 = int(wide if self.miner2.minerStatus() != PMI. STATUS_DISABLED else narrow) target3 = int(wide if self.miner3.minerStatus() != PMI. STATUS_DISABLED else narrow) steps = 15 for w in range(1, steps): #if self.resize_lock == False: # break delta0 = target0 - self.splitter.GetSashPosition(0) delta1 = target1 - self.splitter.GetSashPosition(1) delta2 = target2 - self.splitter.GetSashPosition(2) delta3 = target3 - self.splitter.GetSashPosition(3) pct = float(w) / steps self.splitter.SetSashPosition( 0, self.splitter.GetSashPosition(0) + pct * delta0) self.splitter.SetSashPosition( 1, self.splitter.GetSashPosition(1) + pct * delta1) self.splitter.SetSashPosition( 2, self.splitter.GetSashPosition(2) + pct * delta2) self.splitter.SetSashPosition( 3, self.splitter.GetSashPosition(3) + pct * delta3) time.sleep(0.01) self.resize_lock = False except PyDeadObjectError: pass def setButtonExpanded(self, expanded): self.collapsePanel.setButtonExpanded(expanded) def getExpansionStatus(self): return self.collapsePanel.collapseBtn.GetValue()