class HiveMasterWindow(qtgui.QMainWindow, AbstractBeeMaster): # this constructor should never be called directly, use an alternate def __init__(self): qtgui.QMainWindow.__init__(self) AbstractBeeMaster.__init__(self) # set defaults settings = qtcore.QSettings("BeeDraw", "Hive") self.config["port"], ok = settings.value("port", 8333).toInt() self.config["width"], ok = settings.value("width", 600).toInt() self.config["height"], ok = settings.value("height", 400).toInt() self.config["networkhistorysize"], ok = settings.value("networkhistorysize", 20).toInt() self.config["password"] = settings.value("password").toString() self.config["autolog"] = False # Initialize values self.nextclientid = 1 self.nextclientidmutex = qtcore.QMutex() self.passwordlock = qtcore.QReadWriteLock() # setup interface self.ui = Ui_HiveMasterSpec() self.ui.setupUi(self) self.show() # setup queues used for all thread communication self.routinginput = Queue(0) self.routingthread = HiveRoutingThread(self) self.routingthread.start() # this will be keyed on the client ids and values will be queue objects self.clientwriterqueues = {} self.socketsmap = {} self.readerthreads = {} self.writerthreads = {} # this dictionary will be keyed on id and map to the username self.clientnames = {} # set up client list mutex for messing with either of the above 2 dictinoaries self.clientslistmutex = qtcore.QReadWriteLock() # default value stuff that needs to be here self.fgcolor = qtgui.QColor(0, 0, 0) self.bgcolor = qtgui.QColor(255, 255, 255) # drawing window which holds the current state of the network session self.curwindow = None self.serverthread = None # restore window position self.restoreGeometry(settings.value("geometry").toByteArray()) self.restoreState(settings.value("windowState").toByteArray()) def getHistorySize(self): return self.config["networkhistorysize"] # since there should only be one window just return 1 def getNextWindowId(self): return 1 def getWindowById(self, id): return self.curwindow def getToolClassByName(self, name): return self.toolbox.getToolDescByName(name) def registerReaderThread(self, id, thread): lock = qtcore.QWriteLocker(self.clientslistmutex) self.readerthreads[id] = thread def registerWriterThread(self, id, thread): lock = qtcore.QWriteLocker(self.clientslistmutex) self.writerthreads[id] = thread def registerClient(self, username, id, socket): lock = qtcore.QWriteLocker(self.clientslistmutex) for name in self.clientnames.values(): if name == username: return False self.clientwriterqueues[id] = Queue(100) self.clientnames[id] = username self.ui.clientsList.addItem(username) self.socketsmap[id] = socket command = (DrawingCommandTypes.networkcontrol, NetworkControlCommandTypes.resyncrequest) self.curwindow.addResyncRequestToQueue(id) return True def unregisterClient(self, id): # print_debug("unregistering client: %d" % id) lock = qtcore.QWriteLocker(self.clientslistmutex) if not id in self.clientnames: return # remove from dictionary of clients username = self.clientnames[id] del self.clientnames[id] if id in self.writerthreads: del self.writerthreads[id] if id in self.readerthreads: del self.readerthreads[id] # remove from list of outgoing queues del self.clientwriterqueues[id] # remove from gui items = self.ui.clientsList.findItems(username, qtcore.Qt.MatchFixedString) for item in items: index = self.ui.clientsList.row(item) self.ui.clientsList.takeItem(index) # set layers owned by that client to unowned lock = qtcore.QWriteLocker(self.curwindow.layerslistlock) for layer in self.curwindow.layers: if layer.owner == id: # print_debug("setting layer %d to unowned" % layer.key) self.curwindow.addGiveUpLayerToQueue(layer.key, id) del self.socketsmap[id] def closeEvent(self, event): if self.serverthread: result = qtgui.QMessageBox.question( self, "Ready to Quit?", "Are you sure you'd like to exit the whole application?\nThe currently running server will be terminated.", qtgui.QMessageBox.Ok, qtgui.QMessageBox.Cancel, ) if result != qtgui.QMessageBox.Ok: event.ignore() return settings = qtcore.QSettings("BeeDraw", "Hive") settings.setValue("geometry", self.saveGeometry()) settings.setValue("windowState", self.saveState()) qtgui.QMainWindow.closeEvent(self, event) # self.stopServer() def resetState(self): # only do this if the server isn't running if not self.serverthread: self.curwindow = HiveSessionState( self, self.config["width"], self.config["height"], WindowTypes.standaloneserver, 20 ) self.curwindow.startRemoteDrawingThreads() def startServer(self): # make sure the state exists if not self.curwindow: self.resetState() # make sure no other instance is running self.stopServer() self.serverthread = HiveServerThread(self, self.config["port"], sockettype=BeeSocketTypes.python) self.serverthread.start() def event(self, event): if event.type() == BeeCustomEventTypes.hiveserverstatus: if event.status == HiveServerStatusTypes.running: self.changeStatusLabel("Serving on port: %d" % self.config["port"]) elif event.status == HiveServerStatusTypes.starterror: if event.errorstring: body = event.errorstring else: body = ( "Failed to start server on port %d.\nMake sure port is not already in use." % self.config["port"] ) qtgui.QMessageBox.critical(self, "Could not start server", body) self.changeStatusLabel("Failed to start on port %d" % self.config["port"]) elif event.status == HiveServerStatusTypes.stopped: self.changeStatusLabel("Server not running") print "changed status to server not running" return qtgui.QMainWindow.event(self, event) def changeStatusLabel(self, text): self.ui.statusLabel.setText(text) def stopServer(self): if self.serverthread: self.serverthread.stopServerThread() # self.serverthread.terminate() # self.serverthread.quit() # self.serverthread.exit() # self.serverthread.wait() self.serverthread = None self.ui.statusLabel.setText("Serving not running") def on_kick_button_pressed(self): curselection = self.ui.clientsList.selectedIndexes() # if there are any items in the list that means that something was selected if curselection: target = curselection[0].data().toString() self.kickClient(target) def kickClient(self, name): for i in self.clientnames.keys(): if self.clientnames[i] == name: self.socketsmap[i].disconnect() self.routinginput.put(((DrawingCommandTypes.quit,), 0 - i)) def on_actionStart_triggered(self, accept=True): if accept: self.startServer() def on_actionStop_triggered(self, accept=True): if accept: self.stopServer() def getPassword(self): lock = qtcore.QReadLocker(self.passwordlock) return self.config["password"] def setPassword(self, newpass): lock = qtcore.QWriteLocker(self.passwordlock) self.config["password"] = newpass def on_actionOptions_triggered(self, accept=True): if not accept: return dialog = qtgui.QDialog() dialog.ui = Ui_HiveOptionsDialog() dialog.ui.setupUi(dialog) dialog.ui.port_box.setValue(self.config["port"]) dialog.ui.history_size_box.setValue(self.config["networkhistorysize"]) dialog.ui.password_entry.setText(self.config["password"]) dialog.ui.width_box.setValue(self.config["width"]) dialog.ui.height_box.setValue(self.config["height"]) ok = dialog.exec_() if not ok: return self.config["port"] = dialog.ui.port_box.value() self.config["password"] = str(dialog.ui.password_entry.text()) self.config["width"] = dialog.ui.width_box.value() self.config["height"] = dialog.ui.height_box.value() self.config["networkhistorysize"] = dialog.ui.history_size_box.value() settings = qtcore.QSettings("BeeDraw", "Hive") settings.setValue("port", self.config["port"]) settings.setValue("password", self.config["password"]) settings.setValue("width", self.config["width"]) settings.setValue("height", self.config["height"]) settings.setValue("networkhistorysize", self.config["networkhistorysize"])
class HiveMasterWindow(qtgui.QMainWindow): # this constructor should never be called directly, use an alternate def __init__(self,app): qtgui.QMainWindow.__init__(self) self.app=app # Initialize values self.connections=[] self.nextclientid=1 self.nextclientidmutex=qtcore.QMutex() self.password="" # setup interface self.ui=Ui_HiveMasterSpec() self.ui.setupUi(self) self.show() # setup queues used for all thread communication self.routinginput=Queue(0) self.routingthread=HiveRoutingThread(self) self.routingthread.start() # this will be keyed on the client ids and values will be queue objects self.clientwriterqueues={} # this dictionary will be keyed on id and map to the username self.clientnames={} self.toolbox=BeeToolBox() # drawing window which holds the current state of the network session self.window=BeeDrawingWindow(self,600,400,False,WindowTypes.standaloneserver) def getToolClassByName(self,name): self.toolbox.getToolClassByName(name) def getCurToolInst(self,window): curtool=self.getCurToolDesc() return curtool.setupTool(window) def getCurToolDesc(self): return self.toolbox.getCurToolDesc() # alternate constuctor to create a standalone server def standAloneServer(app): master=HiveMasterWindow(app) master.standalonemode=True # this serves as both the window and the master master.master=master master.layers=[] master.serverthread=None standAloneServer=staticmethod(standAloneServer) def registerClient(self,username): lock=qtcore.QMutexLocker(self.nextclientidmutex) newid=self.nextclientid self.nextclientid+=1 lock.unlock() self.clientwriterqueues[newid]=Queue(100) self.clientnames[newid]=username return newid def closeEvent(self,event): qtgui.QMainWindow.closeEvent(self,event) # self.stopServer() def startServer(self): # make sure no other instance is running self.stopServer() self.serverthread=HiveServerThread(self) print "starting thread:" self.serverthread.start() def stopServer(self): if self.serverthread: self.serverthread.terminate() self.serverthread.wait() self.serverthread=None def on_actionStart_triggered(self): self.startServer()