def createLayout(self):
     #Left side of screen: List of availabe games
     #Right side of screen: TabWidget showing all the games in which the player is participating
     self.horizontalLayout = QtGui.QHBoxLayout()
     self.mainWidget = QtGui.QWidget(self)
     self.mainWidget.setLayout(self.horizontalLayout)
     
     self.networkLobby = NetworkLobbyWidget(self)
     QtCore.QObject.connect(self.networkLobby, QtCore.SIGNAL("joinGameClicked(PyQt_PyObject, QString)"), self.joinGame)
     QtCore.QObject.connect(self.networkLobby, QtCore.SIGNAL("addGame()"), self.createNewGame)
     self.leftLayout = QtGui.QVBoxLayout()
     self.leftLayout.addWidget(self.networkLobby)
     
     self.tabWidget = QtGui.QTabWidget(self)
     self.tabWidget.setTabsClosable(True)
     self.tabWidget.tabCloseRequested.connect(self.tabCloseClicked)
     
     self.horizontalLayout.addLayout(self.leftLayout, 2)
     self.horizontalLayout.addWidget(self.tabWidget, 15)
     self.setCentralWidget(self.mainWidget)
class MainWindow(QtGui.QMainWindow):
    def __init__(self, win_parent = None):
        QtGui.QMainWindow.__init__(self, win_parent)
        
        self.games = []
        
        #ensure threading safety:
        self.lock = threading.Condition()
        
        #GUI
        self.createLayout()
        self.createMenu()
        self.showMaximized()
        self.succesBox = QtGui.QMessageBox(QtGui.QMessageBox.Information, "Success", "Service started successfully", QtGui.QMessageBox.Ok, self)
        self.errorBox = QtGui.QMessageBox(QtGui.QMessageBox.Critical, "Error", "Service registration failed, please restart.", QtGui.QMessageBox.Ok, self)
        
        playerAddWidget = PlayerAddWidget(self)
        localPlayerName = playerAddWidget.getPlayerInfo()
        self.localPlayer = Player(str(localPlayerName))
        
        #Network
        self.manyInARowService = ManyInARowService(self.localPlayer, self.serviceRegisteredCallback, self.serviceRegistrationFailedCallback,
                                                   self.serviceUnregisteredCallback, self.peerServiceDiscoveredCallback,
                                                   self.peerServiceRemovedCallback, self.playerAddedCallback, self.playerUpdatedCallback,
                                                   self.playerLeftCallback, self.gameAddedCallback,
                                                   self.gameUpdatedCallback, self.gameEmptyCallback)
        
        self.manyInARowService.start()
        
    def closeEvent(self, event):
        with self.lock:
            self.manyInARowService.kill()
            for i in range(len(self.games)):
                self.games[i].close()
                
            event.accept()
        
    def createLayout(self):
        #Left side of screen: List of availabe games
        #Right side of screen: TabWidget showing all the games in which the player is participating
        self.horizontalLayout = QtGui.QHBoxLayout()
        self.mainWidget = QtGui.QWidget(self)
        self.mainWidget.setLayout(self.horizontalLayout)
        
        self.networkLobby = NetworkLobbyWidget(self)
        QtCore.QObject.connect(self.networkLobby, QtCore.SIGNAL("joinGameClicked(PyQt_PyObject, QString)"), self.joinGame)
        QtCore.QObject.connect(self.networkLobby, QtCore.SIGNAL("addGame()"), self.createNewGame)
        self.leftLayout = QtGui.QVBoxLayout()
        self.leftLayout.addWidget(self.networkLobby)
        
        self.tabWidget = QtGui.QTabWidget(self)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.tabCloseRequested.connect(self.tabCloseClicked)
        
        self.horizontalLayout.addLayout(self.leftLayout, 2)
        self.horizontalLayout.addWidget(self.tabWidget, 15)
        self.setCentralWidget(self.mainWidget)
        
    def createMenu(self):
        gameMenu = QtGui.QMenu("&Game", self)
        newGameAct = QtGui.QAction("Start &new", gameMenu)
        newGameAct.triggered.connect(self.createNewGame)
        quitAct = QtGui.QAction("&Close", gameMenu)
        quitAct.triggered.connect(self.close)
        gameMenu.addAction(newGameAct)
        gameMenu.addAction(quitAct)
        self.menuBar().addMenu(gameMenu)
        
    def tabCloseClicked(self, tabIndex):
        gameWidget = self.tabWidget.widget(tabIndex)
        gameWidget.close()
        self.tabWidget.removeTab(tabIndex)
        
    def createNewGame(self):
        newGameDialog = NewGameDialog(self)
        (gameName, gameComment, numRows, numCols, waitTime) = newGameDialog.getGameInfo()
        if(gameName != None):
            self.games.append(GameWidget(GameWidget.CREATE_NEW_GAME, {'rows' : numRows, 'cols' : numCols, 'name' : gameName, 'comment' : gameComment, 'waitTime' : waitTime}, self.localPlayer, self.manyInARowService, self.tabWidget))
            self.tabWidget.addTab(self.games[len(self.games) - 1], gameName)
    
    def joinGame(self, UUID, name):
        # Is called when the user chooses to join a network game. This functions makes sure a new tab is created and the game joining is intiated. 
        with self.lock:
            info = self.networkLobby.getGameInfo(UUID)
            self.games.append(GameWidget(GameWidget.JOIN_GAME, info , self.localPlayer, self.manyInARowService, self.tabWidget))
            self.tabWidget.addTab(self.games[len(self.games) - 1], name)
        
    def serviceRegisteredCallback(self, name, regtype, port):
        """with self.lock:
            self.succesBox.exec_()
        """
    def serviceRegistrationFailedCallback(self, name, errorCode, errorMessage):
        with self.lock:
            self.errorBox.setText(str(errorCode) + ": " + str(errorMessage))
            self.errorBox.exec_()
            self.close()
    
    def serviceUnregisteredCallback(self, serviceName, serviceType, port):
        pass
    
    def peerServiceDiscoveredCallback(self, serviceName, interfaceIndex, ip, port):
        with self.lock:
            self.networkLobby.addPeer(serviceName, interfaceIndex, ip, port)
    
    def peerServiceRemovedCallback(self, serviceName, interfaceIndex):
        with self.lock:
            self.networkLobby.removePeer(serviceName, interfaceIndex)
        
    def playerAddedCallback(self, player):
        with self.lock:
            self.networkLobby.addPlayer(player)
    
    def playerUpdatedCallback(self, player):
        with self.lock:
            self.networkLobby.updatePlayer(player)
    
    def playerLeftCallback(self, player):
        with self.lock:
            self.networkLobby.removePlayer(player)
    
    def gameAddedCallback(self, gameUUID, newGame):
        with self.lock:
            self.networkLobby.addGame(newGame, gameUUID)
    
    def gameUpdatedCallback(self, updatedGame):
        pass
    
    def gameEmptyCallback(self, emptyGameUUID, UUID):
        with self.lock:
            self.networkLobby.removeGame(emptyGameUUID)