示例#1
0
    def new(self):
        self.all_sprites = pg.sprite.Group()
        self.walls = pg.sprite.Group()
        self.enemies = pg.sprite.Group()
        self.inters = pg.sprite.Group()
        self.spells = pg.sprite.Group()
        self.playerg = pg.sprite.Group()
        self.screens = pg.sprite.Group()
        self.player = Player(self, 8, 8)
        self.log = LogWindow(self, 3, 15)
        self.inventory = Inventory(self, 0, 0)

        # first floor (TODO start screen)
        self.current_floor = Floor(self, 1)
        self.current_floor.populate_floor()

        # put the player in a random place
        gx, gy = self.current_floor.get_valid_pos()
        self.player.update_global_position(gx, gy)

        # start the engines
        self.tick = True

        # TODO remove
        self.save_map()
示例#2
0
    def createDockWindows(self):
        """
        Create the dock windows: dropbar, log, properties, interfaces, routes.
        """
        self.log = LogWindow(self.tr("Log"), self)
        self.log.append("Welcome to %s %s!\n" %
                        (Core.globals.PROG_NAME, Core.globals.PROG_VERSION))
        self.log.append(
            "To open an existing topology, please click the 'Open' icon from the tray above canvas!"
        )
        self.log.setGeometry(QtCore.QRect(0, 0, 800, 114))
        mainWidgets["log"] = self.log

        self.dropbar = DropBar(self.tr("Components"), self)
        self.dropbar.setGeometry(QtCore.QRect(0, 0, 129, 390))
        mainWidgets["drop"] = self.dropbar

        self.properties = PropertiesWindow(self)
        self.properties.setWindowTitle("Properties")
        mainWidgets["properties"] = self.properties

        self.interfaces = InterfacesWindow(self)
        self.interfaces.setWindowTitle("Interfaces")
        mainWidgets["interfaces"] = self.interfaces

        self.routes = RoutesWindow(self.interfaces, self)
        self.routes.setWindowTitle("Routes")
        mainWidgets["routes"] = self.routes

        self.tm = TaskManagerWindow(self)
        self.tm.setWindowTitle("Task Manager")
        mainWidgets["tm"] = self.tm

        self.debugWindow = QtGui.QDockWidget(self.tr("Debug Window"))
        self.debugWindow.setWidget(DebugWindow(self))

        self.docks = {
            "Components": self.dropbar,
            "Log": self.log,
            "Properties": self.properties,
            "Interfaces": self.interfaces,
            "Routes": self.routes,
            "Task Manager": self.tm
        }

        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dropbar)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.log)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.properties)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.interfaces)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.routes)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.tm)

        self.tm.setFloating(True)
        self.routes.setFloating(True)
        self.debugWindow.setFloating(True)
示例#3
0
文件: mainp.py 项目: rjaffk/shop
def create_database():
    try:
        cursor.execute("CREATE DATABASE {} DEFAULT CHARACTER SET 'utf8'".format(db_name))
        cursor.execute("USE {}".format(db_name))
        cursor.execute("""CREATE TABLE IF NOT EXISTS `users` (id INT(2) AUTO_INCREMENT,
            name VARCHAR(30) NOT NULL UNIQUE, password VARCHAR(20) NOT NULL,
                role TINYINT NOT NULL, PRIMARY KEY(id))""")
        cursor.execute("""INSERT INTO users (name, password,role)
            values('Ivan', '1234',1), ('Anna', 'qwert', 2), ('Jane', '123qwe',2)""")
        con.commit()
        LogWindow.logwin()


    except mysql.connector.Error as err:
        if err.errno == errorcode.ER_DB_CREATE_EXISTS:
            LogWindow.logwin()
        else:
            print("Failed creating database: {}".format(err))
示例#4
0
    def createDockWindows(self):
        """
        Create the dock windows: dropbar, log, properties, interfaces, routes.
        """
        self.log = LogWindow(self.tr("Log"), self)
        self.log.append("Welcome to %s %s!\n" % (Core.globals.PROG_NAME, Core.globals.PROG_VERSION))
        self.log.setGeometry(QtCore.QRect(0, 0, 800, 114))
        mainWidgets["log"] = self.log

        self.dropbar = DropBar(self.tr("Components"), self)
        self.dropbar.setGeometry(QtCore.QRect(0, 0, 129, 390))
        mainWidgets["drop"] = self.dropbar

        self.properties = PropertiesWindow(self)
        self.properties.setWindowTitle("Properties")
        mainWidgets["properties"] = self.properties

        self.interfaces = InterfacesWindow(self)
        self.interfaces.setWindowTitle("Interfaces")
        mainWidgets["interfaces"] = self.interfaces

        self.routes = RoutesWindow(self.interfaces, self)
        self.routes.setWindowTitle("Routes")
        mainWidgets["routes"] = self.routes

        self.tm = TaskManagerWindow(self)
        self.tm.setWindowTitle("Task Manager")
        mainWidgets["tm"] = self.tm

        self.debugWindow = QtGui.QDockWidget(self.tr("Debug Window"))
        self.debugWindow.setWidget(DebugWindow(self))

        self.docks = {
            "Components": self.dropbar,
            "Log": self.log,
            "Properties": self.properties,
            "Interfaces": self.interfaces,
            "Routes": self.routes,
            "Task Manager": self.tm,
        }

        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dropbar)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.log)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.properties)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.interfaces)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.routes)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.tm)

        self.tm.setFloating(True)
        self.routes.setFloating(True)
        self.debugWindow.setFloating(True)
示例#5
0
    def initWechat(self):

        self.LogWin = LogWindow.LogWindow()
        self.MainWin = MainWindow.mainWindow()
        self.MainWin.sendMessage.connect(self.sendMsg)  # 发送输入消息
        self.MainWin.selectFriend.connect(
            self.changeChattingFriend)  # 鼠标点击左侧朋友
        self.MainWin.imgHeadRequest.connect(self.userHeadRespond)  # 相应头像请求
        self.MainWin.friendAutoReply.connect(self.setFriendAutoReply)
        self.LogWin.mainButton.clicked.connect(self.slotButtonGetQR)

        self.LogWin.show()

        self.LogWin.setWindowIcon(QIcon('0qrc/icon.png'))

        self.MainWin.hide()
        self.rTime = None
示例#6
0
文件: MainWindow.py 项目: aallai/gini
class MainWindow(Systray):
    
    def __init__(self, app):
        """
        Create a main window for the given application.
        """
        defaultOptions["palette"] = app.palette()
        Systray.__init__(self)

        self.expansions = 0
        self.client = None
        self.server = None
        self.running = False
        self.recovery = False
        mainWidgets["main"] = self
        mainWidgets["app"] = app
        
        self.canvas = Canvas(self)
        mainWidgets["canvas"] = self.canvas

        self.tabWidget = TabWidget(self)
        mainWidgets["tab"] = self.tabWidget

        self.setCentralWidget(self.tabWidget)
        #self.setCentralWidget(self.canvas)
        
        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.createDockWindows()
        self.createConfigWindows()
        self.createPopupWindows()
        self.createProgressBar()
    
        self.newScene()
        
        self.debugWindow.hide()
        self.tm.hide()
        self.routes.hide()

        self.setVisible(True)
        self.center()
        self.saveLayout(environ["config"] + "defaultLayout")
        
        self.defaultLayout = True
        if options["restore"]:
            self.loadLayout()
            self.defaultLayout = False
            
        self.loadProject()        

    def center(self):
        """
        Center the window.
        """
        screen = QtGui.QDesktopWidget().screenGeometry()
        rect = self.geometry()
        self.move((screen.width()-rect.width())/2, (screen.height()-rect.height())/2)
        self.show()
    
    def getProject(self):
        """
        Return the project.
        """
        return self.project

    def startTutorial(self):
        """
        Start the interactive tutorial.
        """
        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append("You are already doing the tutorial!  If you would like to stop or restart, select 'Close' from the File menu now.")
            return

        if not self.closeTopology():
            return
        
        self.project = "Tutorial"
        self.filename = ""
        
        self.canvas = Tutorial(self)
        mainWidgets["canvas"] = self.canvas

        self.tabWidget.removeTab(0)
        self.tabWidget.addTab(self.canvas, "Tutorial")
        self.canvas.start()

        for nodeType in nodeTypes.keys():
            itemTypes = nodeTypes[nodeType]
            itemTypes[nodeType] = 0

        self.properties.clear()
        self.interfaces.clear()
        self.routes.clear()

        self.resetLayout(True)
        self.lockDocks()

    def lockDocks(self):
        """
        Lock the dock windows so they cannot be moved, closed or resized.
        """
        self.tm.hide()
        for dock in self.docks.values():
            dock.setFeatures(dock.NoDockWidgetFeatures)

    def unlockDocks(self):
        """
        Unlock the dock windows.
        """
        self.tm.show()
        for dock in self.docks.values():
            dock.setFeatures(dock.DockWidgetClosable | dock.DockWidgetMovable | dock.DockWidgetFloatable)
                             
    def faq(self):
        """
        Open the FAQ in the default browser.
        """
        olddir = os.getcwd()
        os.chdir(environ["doc"])
        loadpath = os.getcwd()
        os.chdir(olddir)

        if environ["os"] == "Windows":
            url = QtCore.QUrl("file:///" + loadpath + "/FAQ.html")
        else:
            url = QtCore.QUrl("file://" + loadpath + "/FAQ.html")
        QtGui.QDesktopServices.openUrl(url)

    def closeTopology(self):
        """
        Close the current topology.
        """
        if self.running:
            self.log.append("You cannot close a topology when one is still running!")
            return False

        scene = self.canvas.scene()
        if scene and scene.items():
            reply = QtGui.QMessageBox.warning(self, self.tr(Core.globals.PROG_NAME), self.tr("Save before closing?"), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel)
            if reply == QtGui.QMessageBox.Yes:
                if not self.saveTopology():
                    return False
            elif reply == QtGui.QMessageBox.No:
                pass
            else:
                return False
        
        if isinstance(mainWidgets["canvas"], Tutorial):
            self.canvas = Canvas(self)
            mainWidgets["canvas"] = self.canvas
            self.tabWidget.removeTab(0)
            self.tabWidget.addTab(self.canvas, "Default Project")
            self.project = ""
            self.unlockDocks()
                
        self.filename = ""
        scene = Scene(self.canvas)
        scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex)
        self.canvas.setScene(scene)
        self.expansions = 0
        
        for nodeType in nodeTypes.keys():
            itemTypes = nodeTypes[nodeType]
            itemTypes[nodeType] = 0

        self.properties.clear()
        self.interfaces.clear()
        self.routes.clear()
        
        return True

    def sendFile(self):
        """
        Start a process to select and send a file to the server.
        """
        if not self.server or self.server.poll() != None:
            self.log.append("Please start the server first!")
            return
        if not self.client or not self.client.isConnected():
            self.startClient()
            
        filename = self.loadFile("All Files (*.*)")
        if not filename:
            return
        
        self.sendWindow.setFilename(filename)
        self.sendWindow.show()
        
    def newScene(self):
        """
        Close the current topology and create a new one.
        """
        if self.running:
            self.log.append("You cannot create a new topology when one is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append("You cannot create a new topology during the tutorial!")
            return

        if not self.closeTopology():
            return

        self.expandScene()

    def expandScene(self):
        """
        Expand the scene based on number of expansions.
        """
        x = 175 + self.expansions * 30
        y = 160 + self.expansions * 20
        scene = self.canvas.scene()
        item = QtGui.QGraphicsLineItem(-x, -y, x, y)
        scene.addItem(item)
        scene.removeItem(item)
        self.expansions += 1

    def newProject(self):
        """
        Create a new project for device sharing.
        """
        if self.running:
            self.log.append("You cannot create a new project when one is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append("You cannot create a new project during the tutorial!")
            return
        
        filename = self.saveFile("gproj")
        if filename.isEmpty():
            return

        projectname = str(filename).split("/")[-1].strip(".gproj")
        from Core.Item import nodeTypes
        for nodeType in nodeTypes:
            if projectname.startswith(nodeType + "_"):
                self.popup.setWindowTitle("Invalid Project Name")
                self.popup.setText("You cannot name a project starting with the name of a device and underscore!")
                self.popup.show()
                return

        self.project = str(filename)
        file = QtCore.QFile(filename)
        if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(self, self.tr("Save Error"),
                                      self.tr("Cannot write file %1:\n%2.")
                                      .arg(self.filename)
                                      .arg(file.errorString()))
            return
        
        out = QtCore.QTextStream(file)
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
        
        if options["username"]:
            out << "username="******"username"] + "\n"
        else:
            self.log.append("Warning, no username is specified!")
            
        if options["session"]:
            out << "session=" + options["session"] + "\n"
        elif options["server"]:
            out << "server=" + options["server"] + "\n"
        else:
            self.log.append("Warning, no server or session name is specified!")

        QtGui.QApplication.restoreOverrideCursor()

        self.tabWidget.addTab(self.canvas, projectname)

    def openProject(self):
        """
        Load an existing project for device sharing.
        """
        if self.running:
            self.log.append("You cannot open a project when one is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append("You cannot open a project during the tutorial!")
            return
        
        filename = self.loadFile("GPROJ (*.gproj)")
        if filename.isEmpty():
            return

        self.project = str(filename)
        self.loadProject()

    def loadProject(self):
        """
        Load project file data into options.
        """

        if not self.project:
            self.tabWidget.addTab(self.canvas, "Default Project")
            return
        
        file = QtCore.QFile(self.project)
        if not file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(self, self.tr("Load Error"),
                                      self.tr("Cannot read file %1:\n%2.")
                                      .arg(self.project)
                                      .arg(file.errorString()))
            self.tabWidget.addTab(self.canvas, "Default Project")
            return
        
        _in = QtCore.QTextStream(file)
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)

        while not _in.atEnd():
            line = str(_in.readLine())
            option, value = line.split("=", 1)
            options[option] = value
            
        self.configWindow.updateSettings()

        QtGui.QApplication.restoreOverrideCursor()
        projectname = self.project.split("/")[-1].strip(".gproj")
        self.tabWidget.addTab(self.canvas, projectname)

    def closeProject(self):
        """
        Close the current project.
        """
        if self.running:
            self.log.append("You cannot close a project when it is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append("You cannot close a project during the tutorial!")
            return
        
        if self.tabWidget.count() == 1:
            self.tabWidget.addTab(self.canvas, "Default Project")
            self.project = ""
        else:
            self.tabWidget.removeTab(0)
        
    def export(self):
        """
        Open an export window to generate an image from the canvas.
        """
        self.exportWindow.show()
        
    def startBackend(self):
        """
        Start the backend server.
        """
        self.startServer()
        #self.startClient()

    def setRecovery(self, recovery):
        """
        Set the recovering state of the topology.
        """
        self.recovery = recovery
        
    def isRunning(self):
        """
        Returns whether a topology is running or not.
        """
        return self.running
    
    def startServer(self):
        """
        Start the server backend of gbuilder, which controls running topologies.
        """
        if self.server and self.server.poll() == None:
            self.log.append("A server is already running!")
            return
        
        base = "ssh -t " 
	if options["username"] :
		base += options['username'] + "@"
	base += options["server"]

        tunnel = " -L " + options["localPort"] + ":localhost:" + options["remotePort"]
        server = "bash -c -i 'gserver " + options["remotePort"] + "' || sleep 5"
        command = ""
        
        if environ["os"] == "Windows":
            startpath = environ["tmp"] + "gserver.start"
            try:
                startFile = open(startpath, "w")
                startFile.write("echo -ne \"\\033]0;gserver\\007\"\n")
                startFile.write(server)
                startFile.close()
            except:
                self.log.append("Failed to write to start file!")
                return
            
            command += "putty -"
            if options["session"]:
                command += "load " + options["session"] + " -l " + options["username"] + " -t"
            else:
                command += base
            command += tunnel + " -m \"" + startpath + "\""
        else:
            command += "xterm -T gserver -e " + base + tunnel + " \" " + server + "\""

        self.server = subprocess.Popen(str(command), shell=True)

    def startClient(self):
        """
        Start the client of gbuilder, which communicates with the server.
        """
        self.client = Client(self)
        self.client.connectTo("localhost", int(options["localPort"]), 10)
        #self.client.start()
        mainWidgets["client"] = self.client

    def compile(self):
        """
        Compile the current topology.
        """
        if self.running:
            self.log.append("You cannot compile a topology when one is still running!")
            return False

        if self.saveTopology() == False:
            return False
        
        scene = self.canvas.scene()
        compiler = Compiler(scene.items(), self.filename)
        xmlFile = compiler.compile()

        self.properties.display()
        self.interfaces.display()
        self.routes.display()
        
        if xmlFile:
            self.statusBar().showMessage(self.tr("Compiled '%1'").arg(xmlFile), 2000)
            return True
        else:
            self.statusBar().showMessage(self.tr("Compile failed"), 2000)
            return False

    def run(self):
        """
        Run the current topology.
        """
        if not self.server or self.server.poll() != None:
            self.log.append("Please start the server first!")
            return
        if not self.client or not self.client.isConnected():
            self.startClient()
            
        if self.isRunning() and not self.recovery:
            self.log.append("A topology is already running, please stop it first!")
            return

        scene = self.canvas.scene()
        items = scene.items()
        if items:
            if self.recovery:
                self.recovery = False
            elif options["autocompile"] and not self.compile():
                return
        else:
            self.log.append("Please create or load a topology first!")
            return

        options["elasticMode"] = False

        xmlFile = self.filename.replace(".gsav", ".xml")

        if not os.access(xmlFile, os.F_OK):
            self.log.append("Please compile the topology first!")
            return

        self.tm.show()
        
        #self.progressBar.setValue(0)
        self.client.process("file . " + xmlFile)
        self.client.send("init " + self.project.split("/")[-1].strip(".gproj"))
        self.client.send("canvas %d,%d" % (scene.width(), scene.height()))
        for item in items:
            if item.type == "Mobile" or item.type == "Wireless_access_point":
                x = item.pos().x()
                y = item.pos().y()
                self.client.send("mobile %s %d,%d" % (item.getName(), x, y))
        self.client.process("start " + xmlFile)

        self.running = True
        self.canvas.setAcceptDrops(False)
        scene = self.canvas.scene()
        scene.startRefresh()
        scene.clearSelection()
        
        self.properties.clear()
        self.interfaces.clear()
        self.routes.clear()
        
    def stop(self):
        """
        Stop the current running topology.
        """
        if not self.server or self.server.poll() != None:
            self.log.append("Please start the server first!")
            return
        if not self.client or not self.client.isConnected():
            self.startClient()

        if self.recovery:
            self.recovery = False
            
        scene = self.canvas.scene()
        activeDevices = False
        from Core.Device import Device
        for item in scene.items():
            if not isinstance(item, Device):
                continue
            if item.type == "Router":
                item.stop()
            if item.status:
                activeDevices = True

        if not activeDevices:
            self.stopped()
        elif not scene.isRefreshing():
            scene.startRefresh()
            
        self.client.process("stop")

    def stopped(self):
        """
        Handle a fully stopped topology.
        """
        self.running = False
        self.canvas.scene().stopRefresh()
        self.tm.hide()
        self.canvas.setAcceptDrops(True)
        
        olddir = os.getcwd()
        os.chdir(environ["tmp"])
        for tmpfile in os.listdir("."):
            if tmpfile.startswith("."):
                continue
            try:
                os.remove(tmpfile)
            except:
                continue
        os.chdir(olddir)

    def loadFile(self, filetype):
        """
        Load a file through a file dialog.
        """
        # Qt is very picky in the filename structure but python is not, so we use python
        # to form the correct path which will work for both Windows and Linux        
        olddir = os.getcwd()
        os.chdir(environ["sav"])
        loadpath = os.getcwd()
        os.chdir(olddir)
        
        filename = QtGui.QFileDialog.getOpenFileName(self,
                    self.tr("Choose a file name"), loadpath,
                    self.tr(filetype))

        return filename
        
    def loadTopology(self):
        """
        Load a topology.
        """
        if self.running:
            self.log.append("You cannot load a topology when one is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append("You cannot load a topology during the tutorial!")
            return
        
        def loadIntoScene(line):
            scene = self.canvas.scene()
            itemType,arg = line.split(":")
            args = str(arg).strip("()").split(",")

            if itemType == "edge":
                source = scene.findItem(args[0])
                dest = scene.findItem(args[1])
                if source.type == "Mobile" or dest.type == "Mobile":
                    item = Wireless_Connection(source, dest)
                else:
                    item = Connection(source, dest)
                scene.addItem(item)
            else:
                devType, index = str(itemType).rsplit("_", 1)
                item = deviceTypes[devType]()
                item.setIndex(int(index))
                scene.addItem(item)
                item.setPos(float(args[0]), float(args[1]))
                item.nudge()

            return item

        def loadProperties(itemDict):
            currentInterfaceTarget = None
            currentRouteSubnet = None
            
            for item, properties in itemDict.iteritems():
                for line in properties:
                    count = 0
                    while line.find("\t") == 0:
                        line = line[1:]
                        count += 1

                    prop, value = line.split(":", 1)
                    if count == 1:
                        item.setProperty(prop, value)
                    elif count == 2:
                        currentInterfaceTarget = self.canvas.scene().findItem(value)
                    elif count == 3:
                        item.setInterfaceProperty(prop, value, currentInterfaceTarget)
                    elif count == 4:
                        currentRouteSubnet = value
                        item.addEntry("", "", value, currentInterfaceTarget)
                    elif count == 5:
                        item.setEntryProperty(prop, value, currentRouteSubnet, currentInterfaceTarget)

        filename = self.loadFile("GSAV (*.gsav)")
        if filename.isEmpty():
            return

        file = QtCore.QFile(filename)
        if not file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(self, self.tr("Load Error"),
                                      self.tr("Cannot read file %1:\n%2.")
                                      .arg(filename)
                                      .arg(file.errorString()))
            return

        self.newScene()
        self.filename = str(filename)

        _in = QtCore.QTextStream(file)
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)

        itemDict = {}
        
        line = str(_in.readLine())
        lines = []
        while not _in.atEnd():
            item = loadIntoScene(line)
            line = str(_in.readLine())
            while line.find("\t") == 0:
                lines.append(line)
                line = str(_in.readLine())
            itemDict[item] = lines
            lines = []

        loadProperties(itemDict)
        
        QtGui.QApplication.restoreOverrideCursor()
        
        self.statusBar().showMessage(self.tr("Loaded '%1'").arg(filename), 2000)

    def saveFile(self, filetype):
        """
        Save a file through a file dialog.
        """
        olddir = os.getcwd()
        os.chdir(environ["sav"])
        savepath = os.getcwd()
        os.chdir(olddir)
        
        filename = QtGui.QFileDialog.getSaveFileName(self,
                    self.tr("Choose a file name"), savepath,
                    self.tr(filetype.upper() + " (*.%s)" % filetype))

        if filename.isEmpty():
            return filename
        
        if not filename.toLower().endsWith("." + filetype):
            filename += "." + filetype
        
        return filename
    
    def saveTopologyAs(self):
        """
        Save a topology under a given filename.
        """
        if not self.canvas.scene().items():
            self.log.append("There is nothing to save!")
            return False

        filename = self.saveFile("gsav")
        if filename.isEmpty():
            return False
            
        self.filename = str(filename)
        
        return self.saveTopology()
        
    def saveTopology(self):
        """
        Save a topology.
        """
        if not self.canvas.scene().items():
            self.log.append("There is nothing to save!")
            return False

        # for first time use
        if not self.filename:
            return self.saveTopologyAs()

        file = QtCore.QFile(self.filename)
        if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(self, self.tr("Save Error"),
                                      self.tr("Cannot write file %1:\n%2.")
                                      .arg(self.filename)
                                      .arg(file.errorString()))
            return False
        
        out = QtCore.QTextStream(file)
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)

        scene = self.canvas.scene()
        outstring = ""
        for item in scene.items():
            if isinstance(item, Node):
                outstring += item.toString()
        
        for item in scene.items():
            if isinstance(item, Edge):
                outstring += item.toString()

        out << outstring
        QtGui.QApplication.restoreOverrideCursor()
        
        self.statusBar().showMessage(self.tr("Saved '%1'").arg(self.filename), 2000)

        return True

    def copy(self):
        """
        Copy selected text from the log into the paste buffer.
        """
        self.log.copy()

    def config(self):
        """
        Open the options window.
        """
        self.configWindow.show()

    def arrange(self):
        """
        Rearrange the topology based on the distance between nodes.
        """
        if self.isRunning():
            self.log.append("Cannot arrange while running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            mainWidgets["log"].append("Cannot arrange during the tutorial!")
            return
        
        options["elasticMode"] = not options["elasticMode"]
        
    def about(self):
        """
        Show the about window.
        """
        QtGui.QMessageBox.about(self, 
                                self.tr("About %s %s" 
                                    % (Core.globals.PROG_NAME,
                                       Core.globals.PROG_VERSION)),
                                self.tr("<b>%s %s</b><br>Written by Daniel Ng<br>under the supervision of Muthucumaru Maheswaran" 
                                    % (Core.globals.PROG_NAME, 
                                       Core.globals.PROG_VERSION)))
    
    def createActions(self):
        """
        Create the actions used in the menus and toolbars.
        """
        self.newSceneAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "new.png"), self.tr("&New"), self)
        self.newSceneAct.setShortcut(self.tr("Ctrl+N"))
        self.newSceneAct.setStatusTip(self.tr("Create a new topology"))
        self.connect(self.newSceneAct, QtCore.SIGNAL("triggered()"), self.newScene)

        self.closeAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "close.png"), self.tr("&Close"), self)
        self.closeAct.setShortcut(self.tr("Ctrl+W"))
        self.closeAct.setStatusTip(self.tr("Close the current topology"))
        self.connect(self.closeAct, QtCore.SIGNAL("triggered()"), self.closeTopology)
        
        self.loadAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "open.png"), self.tr("&Open..."), self)
        self.loadAct.setShortcut(self.tr("Ctrl+O"))
        self.loadAct.setStatusTip(self.tr("Load a topology"))
        self.connect(self.loadAct, QtCore.SIGNAL("triggered()"), self.loadTopology)
        
        self.saveAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "save.png"), self.tr("&Save..."), self)
        self.saveAct.setShortcut(self.tr("Ctrl+S"))
        self.saveAct.setStatusTip(self.tr("Save the current topology"))
        self.connect(self.saveAct, QtCore.SIGNAL("triggered()"), self.saveTopology)

        self.saveAsAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "save.png"), self.tr("&Save As..."), self)
        self.saveAsAct.setShortcut(self.tr("Ctrl+Shift+S"))
        self.saveAsAct.setStatusTip(self.tr("Save the current topology under a given filename"))
        self.connect(self.saveAsAct, QtCore.SIGNAL("triggered()"), self.saveTopologyAs)

        self.sendFileAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "send.png"), self.tr("&Send File..."), self)
        self.sendFileAct.setShortcut(self.tr("Ctrl+F"))
        self.sendFileAct.setStatusTip(self.tr("Choose a file to send to the server"))
        self.connect(self.sendFileAct, QtCore.SIGNAL("triggered()"), self.sendFile)
        
        self.exportAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "export.png"), self.tr("&Export..."), self)
        self.exportAct.setShortcut(self.tr("Ctrl+P"))
        self.exportAct.setStatusTip(self.tr("Export the current topology as an image"))
        self.connect(self.exportAct, QtCore.SIGNAL("triggered()"), self.export)

        self.copyAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "copy.png"), self.tr("&Copy"), self)
        self.copyAct.setShortcut(self.tr("Ctrl+C"))
        self.copyAct.setStatusTip(self.tr("Copy the selected text"))
        self.connect(self.copyAct, QtCore.SIGNAL("triggered()"), self.copy)

        self.compileAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "compile.png"), self.tr("&Compile"), self)
        self.compileAct.setShortcut(self.tr("Ctrl+E"))
        self.compileAct.setStatusTip(self.tr("Compile the current topology"))
        self.connect(self.compileAct, QtCore.SIGNAL("triggered()"), self.compile)
        
        self.runAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "run.png"), self.tr("&Run"), self)
        self.runAct.setShortcut(self.tr("Ctrl+R"))
        self.runAct.setStatusTip(self.tr("Run the current topology"))
        self.connect(self.runAct, QtCore.SIGNAL("triggered()"), self.run)

        self.stopAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "stop.png"), self.tr("&Stop"), self)
        self.stopAct.setShortcut(self.tr("Ctrl+D"))
        self.stopAct.setStatusTip(self.tr("Stop the current topology"))
        self.connect(self.stopAct, QtCore.SIGNAL("triggered()"), self.stop)

        self.startServerAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "startServer.png"), self.tr("&Start Server"), self)
        self.startServerAct.setShortcut(self.tr("Ctrl+T"))
        self.startServerAct.setStatusTip(self.tr("Start the server"))
        self.connect(self.startServerAct, QtCore.SIGNAL("triggered()"), self.startBackend)

        self.optionsAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "options.png"), self.tr("&Options"), self)
        self.optionsAct.setShortcut(self.tr("F2"))
        self.optionsAct.setStatusTip(self.tr("Show the options window"))
        self.connect(self.optionsAct, QtCore.SIGNAL("triggered()"), self.config)

        self.arrangeAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "arrange.png"), self.tr("&Arrange"), self)
        self.arrangeAct.setShortcut(self.tr("Ctrl+A"))
        self.arrangeAct.setStatusTip(self.tr("Arranges the current topology"))
        self.connect(self.arrangeAct, QtCore.SIGNAL("triggered()"), self.arrange)

        self.resetLayoutAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "layout.png"), self.tr("Reset Layout"), self)
        self.resetLayoutAct.setStatusTip(self.tr("Reset dock windows to the saved layout"))
        self.connect(self.resetLayoutAct, QtCore.SIGNAL("triggered()"), self.resetLayout)

        self.expandSceneAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "expand.png"), self.tr("Expand Scene"), self)
        self.expandSceneAct.setStatusTip(self.tr("Expand the scene for more space"))
        self.connect(self.expandSceneAct, QtCore.SIGNAL("triggered()"), self.expandScene)
        
        self.quitAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "exit.png"), self.tr("&Quit"), self)
        self.quitAct.setShortcut(self.tr("Ctrl+Q"))
        self.quitAct.setStatusTip(self.tr("Quit the application"))
        self.connect(self.quitAct, QtCore.SIGNAL("triggered()"), self.quit)

        self.newProjectAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "new.png"), self.tr("&New"), self)
        self.newProjectAct.setShortcut(self.tr("Ctrl+Shift+N"))
        self.newProjectAct.setStatusTip(self.tr("Create a new project"))
        self.connect(self.newProjectAct, QtCore.SIGNAL("triggered()"), self.newProject)

        self.openProjectAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "open.png"), self.tr("&Open"), self)
        self.openProjectAct.setShortcut(self.tr("Ctrl+Shift+O"))
        self.openProjectAct.setStatusTip(self.tr("Open an existing project"))
        self.connect(self.openProjectAct, QtCore.SIGNAL("triggered()"), self.openProject)

        self.closeProjectAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "close.png"), self.tr("&Close"), self)
        self.closeProjectAct.setShortcut(self.tr("Ctrl+Shift+W"))
        self.closeProjectAct.setStatusTip(self.tr("Close the current project"))
        self.connect(self.closeProjectAct, QtCore.SIGNAL("triggered()"), self.closeProject)
        
        self.tutorialAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "tutorial.png"), self.tr("&Tutorial"), self)
        self.connect(self.tutorialAct, QtCore.SIGNAL("triggered()"), self.startTutorial)

        self.faqAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "help.png"), self.tr("&FAQ"), self)
        self.connect(self.faqAct, QtCore.SIGNAL("triggered()"), self.faq)
        
        self.aboutAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "giniLogo.png"), self.tr("&About"), self)
        self.aboutAct.setStatusTip(self.tr("Show the application's About box"))
        self.connect(self.aboutAct, QtCore.SIGNAL("triggered()"), self.about)

        self.aboutQtAct = QtGui.QAction(self.tr("About &Qt"), self)
        self.aboutQtAct.setStatusTip(self.tr("Show the Qt library's About box"))
        self.connect(self.aboutQtAct, QtCore.SIGNAL("triggered()"),
                     QtGui.qApp, QtCore.SLOT("aboutQt()"))

    def createMenus(self):
        """
        Create the menus with actions.
        """
        self.fileMenu = self.menuBar().addMenu(self.tr("&File"))
        self.fileMenu.setPalette(defaultOptions["palette"])
        self.fileMenu.addAction(self.newSceneAct)
        self.fileMenu.addAction(self.loadAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addAction(self.sendFileAct)
        self.fileMenu.addAction(self.exportAct)
        self.fileMenu.addAction(self.closeAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.quitAct)

        self.projectMenu = self.menuBar().addMenu(self.tr("&Project"))
        self.projectMenu.setPalette(defaultOptions["palette"])
        self.projectMenu.addAction(self.newProjectAct)
        self.projectMenu.addAction(self.openProjectAct)
        self.projectMenu.addAction(self.closeProjectAct)
        
        self.editMenu = self.menuBar().addMenu(self.tr("&Edit"))
        self.editMenu.setPalette(defaultOptions["palette"])
        self.editMenu.addAction(self.copyAct)
        self.editMenu.addAction(self.arrangeAct)
        self.editMenu.addAction(self.resetLayoutAct)
        self.editMenu.addAction(self.expandSceneAct)

        self.runMenu = self.menuBar().addMenu(self.tr("&Run"))
        self.runMenu.setPalette(defaultOptions["palette"])
        self.runMenu.addAction(self.compileAct)
        self.runMenu.addAction(self.runAct)
        self.runMenu.addAction(self.stopAct)
        self.runMenu.addAction(self.startServerAct)
        
        self.configMenu = self.menuBar().addMenu(self.tr("&Config"))
        self.configMenu.setPalette(defaultOptions["palette"])
        self.configMenu.addAction(self.optionsAct)
        
        self.menuBar().addSeparator()
        
        self.helpMenu = self.menuBar().addMenu(self.tr("&Help"))
        self.helpMenu.setPalette(defaultOptions["palette"])
        self.helpMenu.addAction(self.tutorialAct)
        self.helpMenu.addAction(self.faqAct)
        self.helpMenu.addAction(self.aboutAct)
        self.helpMenu.addAction(self.aboutQtAct)

    def createPopupMenu(self):
        """
        Customize the popup menu so that it is visible.
        """
        popupMenu = QtGui.QMainWindow.createPopupMenu(self)
        popupMenu.setPalette(defaultOptions["palette"])
        return popupMenu

    def createToolBars(self):
        """
        Create the toolbars with actions.
        """
        self.fileToolBar = self.addToolBar(self.tr("File"))
        self.fileToolBar.addAction(self.newSceneAct)
        self.fileToolBar.addAction(self.loadAct)
        self.fileToolBar.addAction(self.saveAct)
        self.fileToolBar.addAction(self.sendFileAct)
        self.fileToolBar.addAction(self.exportAct)
        self.fileToolBar.addAction(self.closeAct)
        
        self.editToolBar = self.addToolBar(self.tr("Edit"))
        self.editToolBar.addAction(self.copyAct)
        self.editToolBar.addAction(self.resetLayoutAct)
        self.editToolBar.addAction(self.expandSceneAct)

        self.runToolBar = self.addToolBar(self.tr("Run"))
        self.runToolBar.addAction(self.compileAct)
        self.runToolBar.addAction(self.runAct)
        self.runToolBar.addAction(self.stopAct)
        self.runToolBar.addAction(self.startServerAct)
        
    def createStatusBar(self):
        """
        Create the status bar.
        """
        self.statusBar().showMessage(self.tr("Ready"))

    def createProgressBar(self):
        """
        Create the progress bar.
        """
        self.progressBar = QtGui.QProgressBar()
        self.progressBar.setRange(0, 10000)
        self.progressBar.setValue(0)

        self.statusBar().addPermanentWidget(self.progressBar)
        self.progressBar.show()

    def getDeviceCount(self, alive=False):
        """
        Return the interfaceable device count, or the alive ones if alive=True.
        """
        from Core.Interfaceable import Interfaceable
        
        count = 0.0
        for item in self.canvas.scene().items():
            if isinstance(item, Interfaceable):
                if alive and item.status in ("", "dead"):
                    continue
                count += 1.0

        return count

    def updateProgressBar(self):
        """
        Update the progress bar.
        """
        maxVal = self.progressBar.maximum()
        finalVal = (self.getDeviceCount(True) / self.getDeviceCount()) * maxVal

        if finalVal < 0:
            finalVal = 0
            
        self.progressBar.setValue(finalVal)

        if finalVal == 0:
            return True

        return False
    
    def createConfigWindows(self):
        """
        Create the options window.
        """
        self.configWindow = ConfigDialog(self)

    def createDockWindows(self):
        """
        Create the dock windows: dropbar, log, properties, interfaces, routes.
        """
        self.log = LogWindow(self.tr("Log"), self)
        self.log.append("Welcome to %s %s!\n" 
                % (Core.globals.PROG_NAME, Core.globals.PROG_VERSION))
        self.log.setGeometry(QtCore.QRect(0, 0, 800, 114))
        mainWidgets["log"] = self.log

        self.dropbar = DropBar(self.tr("Components"), self)
        self.dropbar.setGeometry(QtCore.QRect(0, 0, 129, 390))
        mainWidgets["drop"] = self.dropbar
        
        self.properties = PropertiesWindow(self)
        self.properties.setWindowTitle("Properties")
        mainWidgets["properties"] = self.properties

        self.interfaces = InterfacesWindow(self)
        self.interfaces.setWindowTitle("Interfaces")
        mainWidgets["interfaces"] = self.interfaces
        
        self.routes = RoutesWindow(self.interfaces, self)
        self.routes.setWindowTitle("Routes")
        mainWidgets["routes"] = self.routes
        
        self.tm = TaskManagerWindow(self)
        self.tm.setWindowTitle("Task Manager")
        mainWidgets["tm"] = self.tm
        
        self.debugWindow = QtGui.QDockWidget(self.tr("Debug Window"))
        self.debugWindow.setWidget(DebugWindow(self))
        
        self.docks = {"Components":self.dropbar, "Log":self.log, "Properties":self.properties, "Interfaces":self.interfaces, "Routes":self.routes, "Task Manager":self.tm}
        
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dropbar)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.log)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.properties)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.interfaces)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.routes)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.tm)

        self.tm.setFloating(True)
        self.routes.setFloating(True)
        self.debugWindow.setFloating(True)

    def createPopupWindows(self):
        """
        Create the different popup windows.
        """
        self.exportWindow = ExportWindow(self)
        self.sendWindow = SendDirectoryWindow(self)
        
        self.popup = QtGui.QMessageBox(self)
        self.popup.setIcon(QtGui.QMessageBox.Warning)
        self.popup.setWindowIcon(QtGui.QIcon(environ["images"]+"giniLogo.png"))
        mainWidgets["popup"] = self.popup

    def keyPressEvent(self, event):
        """
        Handle specific shortcut keys.
        """
        key = event.key()
        scene = self.canvas.scene()
        if key == QtCore.Qt.Key_Escape:
            scene.clearSelection()
        elif key == QtCore.Qt.Key_Delete:
            for item in scene.selectedItems():
                item.delete()
        elif key == QtCore.Qt.Key_C:
            items = scene.items()
            if not items:
                return
            selected = scene.selectedItems()
            scene.clearSelection()
            if selected:
                index = items.index(selected[0])
                items[index - 1].setSelected(True)
            else:
                items[0].setSelected(True)
        elif key == QtCore.Qt.Key_H:
            for dock in self.docks.values():
                dock.setFloating(not dock.isFloating())
        elif key == QtCore.Qt.Key_F10:
            self.debugWindow.show()
示例#7
0
class MainWindow(Systray):
    def __init__(self, app):
        """
        Create a main window for the given application.
        """

        defaultOptions["palette"] = app.palette()
        Systray.__init__(self)

        self.expansions = 0
        self.client = None
        self.server = None
        self.running = False
        self.recovery = False
        mainWidgets["main"] = self
        mainWidgets["app"] = app

        self.canvas = Canvas(self)
        mainWidgets["canvas"] = self.canvas

        self.tabWidget = TabWidget(self)
        mainWidgets["tab"] = self.tabWidget

        self.setCentralWidget(self.tabWidget)
        #self.setCentralWidget(self.canvas)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.createDockWindows()
        self.createConfigWindows()
        self.createPopupWindows()
        self.createProgressBar()

        self.newScene()

        self.debugWindow.hide()
        self.tm.hide()
        self.routes.hide()

        self.setVisible(True)
        self.center()
        self.saveLayout(environ["config"] + "defaultLayout")

        self.defaultLayout = True
        if options["restore"]:
            self.loadLayout()
            self.defaultLayout = False

        self.loadProject()
        atexit.register(self.cleanup)

    def center(self):
        """
        Center the window.
        """
        screen = QtGui.QDesktopWidget().screenGeometry()
        rect = self.geometry()
        self.move((screen.width() - rect.width()) / 2,
                  (screen.height() - rect.height()) / 2)
        self.show()

    def getProject(self):
        """
        Return the project.
        """
        return self.project

    def startTutorial(self):
        """
        Start the interactive tutorial.
        """
        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append(
                "You are already doing the tutorial!  If you would like to stop or restart, select 'Close' from the File menu now."
            )
            return

        if not self.closeTopology():
            return

        self.project = "Tutorial"
        self.filename = ""

        self.canvas = Tutorial(self)
        mainWidgets["canvas"] = self.canvas

        self.tabWidget.removeTab(0)
        self.tabWidget.addTab(self.canvas, "Tutorial")
        self.canvas.start()

        for nodeType in nodeTypes.keys():
            itemTypes = nodeTypes[nodeType]
            itemTypes[nodeType] = 0

        self.properties.clear()
        self.interfaces.clear()
        self.routes.clear()

        self.resetLayout(True)
        self.lockDocks()

    def lockDocks(self):
        """
        Lock the dock windows so they cannot be moved, closed or resized.
        """
        self.tm.hide()
        for dock in self.docks.values():
            dock.setFeatures(dock.NoDockWidgetFeatures)

    def unlockDocks(self):
        """
        Unlock the dock windows.
        """
        self.tm.show()
        for dock in self.docks.values():
            dock.setFeatures(dock.DockWidgetClosable | dock.DockWidgetMovable
                             | dock.DockWidgetFloatable)

    def faq(self):
        """
        Open the FAQ in the default browser.
        """
        olddir = os.getcwd()
        os.chdir(environ["doc"])
        loadpath = os.getcwd()
        os.chdir(olddir)

        if environ["os"] == "Windows":
            url = QtCore.QUrl("file:///" + loadpath + "/FAQ.html")
        else:
            url = QtCore.QUrl("file://" + loadpath + "/FAQ.html")
        QtGui.QDesktopServices.openUrl(url)

    def closeTopology(self):
        """
        Close the current topology.
        """
        if self.running:
            self.log.append(
                "You cannot close a topology when one is still running!")
            return False

        scene = self.canvas.scene()
        if scene and scene.items():
            reply = QtGui.QMessageBox.warning(
                self, self.tr(Core.globals.PROG_NAME),
                self.tr("Save before closing?"), QtGui.QMessageBox.Yes
                | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel)
            if reply == QtGui.QMessageBox.Yes:
                if not self.saveTopology():
                    return False
            elif reply == QtGui.QMessageBox.No:
                pass
            else:
                return False

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.canvas = Canvas(self)
            mainWidgets["canvas"] = self.canvas
            self.tabWidget.removeTab(0)
            self.tabWidget.addTab(self.canvas, "Default Project")
            self.project = ""
            self.unlockDocks()

        self.filename = ""
        scene = Scene(self.canvas)
        scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex)
        self.canvas.setScene(scene)
        self.expansions = 0

        for nodeType in nodeTypes.keys():
            itemTypes = nodeTypes[nodeType]
            itemTypes[nodeType] = 0

        self.properties.clear()
        self.interfaces.clear()
        self.routes.clear()

        return True

    def sendFile(self):
        """
        Start a process to select and send a file to the server.
        """
        if not self.server or self.server.poll() != None:
            self.log.append("Please start the server first!")
            return
        if not self.client or not self.client.isConnected():
            self.startClient()

        filename = self.loadFile("All Files (*.*)")
        if not filename:
            return

        self.sendWindow.setFilename(filename)
        self.sendWindow.show()

    def newScene(self):
        """
        Close the current topology and create a new one.
        """
        if self.running:
            self.log.append(
                "You cannot create a new topology when one is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append(
                "You cannot create a new topology during the tutorial!")
            return

        if not self.closeTopology():
            return

        self.expandScene()

    def expandScene(self):
        """
        Expand the scene based on number of expansions.
        """
        x = 175 + self.expansions * 30
        y = 160 + self.expansions * 20
        scene = self.canvas.scene()
        item = QtGui.QGraphicsLineItem(-x, -y, x, y)
        scene.addItem(item)
        scene.removeItem(item)
        self.expansions += 1

    def newProject(self):
        """
        Create a new project for device sharing.
        """
        if self.running:
            self.log.append(
                "You cannot create a new project when one is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append(
                "You cannot create a new project during the tutorial!")
            return

        filename = self.saveFile("gproj")
        if filename.isEmpty():
            return

        projectname = str(filename).split("/")[-1].strip(".gproj")
        from Core.Item import nodeTypes
        for nodeType in nodeTypes:
            if projectname.startswith(nodeType + "_"):
                self.popup.setWindowTitle("Invalid Project Name")
                self.popup.setText(
                    "You cannot name a project starting with the name of a device and underscore!"
                )
                self.popup.show()
                return

        self.project = str(filename)
        file = QtCore.QFile(filename)
        if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(
                self, self.tr("Save Error"),
                self.tr("Cannot write file %1:\n%2.").arg(self.filename).arg(
                    file.errorString()))
            return

        out = QtCore.QTextStream(file)
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)

        if options["username"]:
            out << "username="******"username"] + "\n"
        else:
            self.log.append("Warning, no username is specified!")

        if options["session"]:
            out << "session=" + options["session"] + "\n"
        elif options["server"]:
            out << "server=" + options["server"] + "\n"
        else:
            self.log.append("Warning, no server or session name is specified!")

        QtGui.QApplication.restoreOverrideCursor()

        self.tabWidget.addTab(self.canvas, projectname)

    def openProject(self):
        """
        Load an existing project for device sharing.
        """
        if self.running:
            self.log.append(
                "You cannot open a project when one is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append("You cannot open a project during the tutorial!")
            return

        filename = self.loadFile("GPROJ (*.gproj)")
        if filename.isEmpty():
            return

        self.project = str(filename)
        self.loadProject()

    def loadProject(self):
        """
        Load project file data into options.
        """

        if not self.project:
            self.tabWidget.addTab(self.canvas, "Default Project")
            return

        file = QtCore.QFile(self.project)
        if not file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(
                self, self.tr("Load Error"),
                self.tr("Cannot read file %1:\n%2.").arg(self.project).arg(
                    file.errorString()))
            self.tabWidget.addTab(self.canvas, "Default Project")
            return

        _in = QtCore.QTextStream(file)
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)

        while not _in.atEnd():
            line = str(_in.readLine())
            option, value = line.split("=", 1)
            options[option] = value

        self.configWindow.updateSettings()

        QtGui.QApplication.restoreOverrideCursor()
        projectname = self.project.split("/")[-1].strip(".gproj")
        self.tabWidget.addTab(self.canvas, projectname)

    def closeProject(self):
        """
        Close the current project.
        """
        if self.running:
            self.log.append(
                "You cannot close a project when it is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append("You cannot close a project during the tutorial!")
            return

        if self.tabWidget.count() == 1:
            self.tabWidget.addTab(self.canvas, "Default Project")
            self.project = ""
        else:
            self.tabWidget.removeTab(0)

    def export(self):
        """
        Open an export window to generate an image from the canvas.
        """
        self.exportWindow.show()

    def startBackend(self):
        """
        Start the backend server.
        """
        self.startServer()
        #self.startClient()

    def setRecovery(self, recovery):
        """
        Set the recovering state of the topology.
        """
        self.recovery = recovery

    def isRunning(self):
        """
        Returns whether a topology is running or not.
        """
        return self.running

    def startServer(self):
        """
        Start the server backend of gbuilder, which controls running topologies.
        """
        if self.server and self.server.poll() == None:
            self.log.append("A server is already running!")
            return

        base = "ssh -t " + options["username"] + "@" + options["server"]
        tunnel = " -L " + options["localPort"] + ":localhost:" + options[
            "remotePort"]
        server = "bash -c -i 'gserver " + options["remotePort"] + "' || sleep 5"
        command = ""
        gserver = "gserver"

        if environ["os"] == "Windows":
            startpath = environ["tmp"] + "gserver.start"
            try:
                startFile = open(startpath, "w")
                startFile.write("echo -ne \"\\033]0;" + gserver + "\\007\"\n")
                startFile.write(server)
                startFile.close()
            except:
                self.log.append("Failed to write to start file!")
                return

            command += "putty -"
            if options["session"]:
                command += "load " + options["session"] + " -l " + options[
                    "username"] + " -t"
            else:
                command += base
            command += tunnel + " -m \"" + startpath + "\""
        else:
            command += "rxvt -T \"" + gserver + "\" -e " + base + tunnel + " \" " + server + "\""

        self.server = subprocess.Popen(str(command),
                                       shell=True,
                                       preexec_fn=os.setpgrp)

    def startClient(self):
        """
        Start the client of gbuilder, which communicates with the server.
        """
        self.client = Client(self)
        self.client.connectTo("localhost", int(options["localPort"]), 10)
        #self.client.start()
        mainWidgets["client"] = self.client

    def compile(self):
        """
        Compile the current topology.
        """
        if self.running:
            self.log.append(
                "You cannot compile a topology when one is still running!")
            return False

        if self.saveTopology() == False:
            return False

        scene = self.canvas.scene()
        compiler = Compiler(scene.items(), self.filename)
        xmlFile = compiler.compile()

        self.properties.display()
        self.interfaces.display()
        self.routes.display()

        if xmlFile:
            self.statusBar().showMessage(
                self.tr("Compiled '%1'").arg(xmlFile), 2000)
            return True
        else:
            self.statusBar().showMessage(self.tr("Compile failed"), 2000)
            return False

    def run(self):
        """
        Run the current topology.
        """
        if not self.server or self.server.poll() != None:
            self.log.append("Please start the server first!")
            return
        if not self.client or not self.client.isConnected():
            self.startClient()

        if self.isRunning() and not self.recovery:
            self.log.append(
                "A topology is already running, please stop it first!")
            return

        scene = self.canvas.scene()
        items = scene.items()
        if items:
            if self.recovery:
                self.recovery = False
            elif options["autocompile"] and not self.compile():
                return
        else:
            self.log.append("Please create or load a topology first!")
            return

        options["elasticMode"] = False

        xmlFile = self.filename.replace(".gsav", ".xml")

        if not os.access(xmlFile, os.F_OK):
            self.log.append("Please compile the topology first!")
            return

        self.tm.show()

        #self.progressBar.setValue(0)
        self.client.process("file . " + xmlFile)
        self.client.send("init " + self.project.split("/")[-1].strip(".gproj"))
        self.client.send("canvas %d,%d" % (scene.width(), scene.height()))
        for item in items:
            if item.device_type == "Mobile" or item.device_type == "Wireless_access_point":
                x = item.pos().x()
                y = item.pos().y()
                self.client.send("mobile %s %d,%d" % (item.getName(), x, y))
        self.client.process("start " + xmlFile)

        self.running = True
        self.canvas.setAcceptDrops(False)
        scene = self.canvas.scene()
        scene.startRefresh()
        scene.clearSelection()

        self.properties.clear()
        self.interfaces.clear()
        self.routes.clear()

    def stop(self):
        """
        Stop the current running topology.
        """
        if not self.server or self.server.poll() != None:
            self.log.append("Please start the server first!")
            return
        if not self.client or not self.client.isConnected():
            self.startClient()

        if self.recovery:
            self.recovery = False

        scene = self.canvas.scene()
        activeDevices = False
        from Core.Device import Device
        for item in scene.items():
            if not isinstance(item, Device):
                continue
            if item.device_type == "Router":
                item.stop()
            if item.status:
                activeDevices = True

        if not activeDevices:
            self.stopped()
        elif not scene.isRefreshing():
            scene.startRefresh()

        self.client.process("stop")

    def stopped(self):
        """
        Handle a fully stopped topology.
        """
        self.running = False
        self.canvas.scene().stopRefresh()
        self.tm.hide()
        self.canvas.setAcceptDrops(True)

        olddir = os.getcwd()
        os.chdir(environ["tmp"])
        for tmpfile in os.listdir("."):
            if tmpfile.startswith("."):
                continue
            try:
                os.remove(tmpfile)
            except:
                continue
        os.chdir(olddir)

    def loadFile(self, filetype):
        """
        Load a file through a file dialog.
        """
        # Qt is very picky in the filename structure but python is not, so we use python
        # to form the correct path which will work for both Windows and Linux
        olddir = os.getcwd()
        os.chdir(environ["sav"])
        loadpath = os.getcwd()
        os.chdir(olddir)

        filename = QtGui.QFileDialog.getOpenFileName(
            self, self.tr("Choose a file name"), loadpath, self.tr(filetype))

        return filename

    def loadTopology(self):
        """
        Load a topology.
        """
        if self.running:
            self.log.append(
                "You cannot load a topology when one is still running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            self.log.append("You cannot load a topology during the tutorial!")
            return

        def loadIntoScene(line):
            scene = self.canvas.scene()
            itemType, arg = line.split(":")
            args = str(arg).strip("()").split(",")

            if itemType == "edge":
                source = scene.findItem(args[0])
                dest = scene.findItem(args[1])
                if source.device_type == "Mobile" or dest.device_type == "Mobile":
                    item = Wireless_Connection(source, dest)
                else:
                    item = Connection(source, dest)
                scene.addItem(item)
            else:
                devType, index = str(itemType).rsplit("_", 1)
                item = deviceTypes[devType]()
                item.setIndex(int(index))
                scene.addItem(item)
                item.setPos(float(args[0]), float(args[1]))
                item.nudge()

            return item

        def loadProperties(itemDict):
            currentInterfaceTarget = None
            currentRouteSubnet = None

            for item, properties in itemDict.iteritems():
                for line in properties:
                    count = 0
                    while line.find("\t") == 0:
                        line = line[1:]
                        count += 1

                    prop, value = line.split(":", 1)
                    if count == 1:
                        item.setProperty(prop, value)
                    elif count == 2:
                        currentInterfaceTarget = self.canvas.scene().findItem(
                            value)
                    elif count == 3:
                        item.setInterfaceProperty(prop, value,
                                                  currentInterfaceTarget)
                    elif count == 4:
                        currentRouteSubnet = value
                        item.addEntry("", "", value, currentInterfaceTarget)
                    elif count == 5:
                        item.setEntryProperty(prop, value, currentRouteSubnet,
                                              currentInterfaceTarget)

        filename = self.loadFile("GSAV (*.gsav)")
        if filename.isEmpty():
            return

        file = QtCore.QFile(filename)
        if not file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(
                self, self.tr("Load Error"),
                self.tr("Cannot read file %1:\n%2.").arg(filename).arg(
                    file.errorString()))
            return

        self.newScene()
        self.filename = str(filename)

        _in = QtCore.QTextStream(file)
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)

        itemDict = {}

        line = str(_in.readLine())
        lines = []
        while not _in.atEnd():
            item = loadIntoScene(line)
            line = str(_in.readLine())
            while line.find("\t") == 0:
                lines.append(line)
                line = str(_in.readLine())
            itemDict[item] = lines
            lines = []

        loadProperties(itemDict)

        QtGui.QApplication.restoreOverrideCursor()

        self.statusBar().showMessage(
            self.tr("Loaded '%1'").arg(filename), 2000)

    def saveFile(self, filetype):
        """
        Save a file through a file dialog.
        """
        olddir = os.getcwd()
        os.chdir(environ["sav"])
        savepath = os.getcwd()
        os.chdir(olddir)

        filename = QtGui.QFileDialog.getSaveFileName(
            self, self.tr("Choose a file name"), savepath,
            self.tr(filetype.upper() + " (*.%s)" % filetype))

        if filename.isEmpty():
            return filename

        if not filename.toLower().endsWith("." + filetype):
            filename += "." + filetype

        return filename

    def saveTopologyAs(self):
        """
        Save a topology under a given filename.
        """
        if not self.canvas.scene().items():
            self.log.append("There is nothing to save!")
            return False

        filename = self.saveFile("gsav")
        if filename.isEmpty():
            return False

        self.filename = str(filename)

        return self.saveTopology()

    def saveTopology(self):
        """
        Save a topology.
        """
        if not self.canvas.scene().items():
            self.log.append("There is nothing to save!")
            return False

        # for first time use
        if not self.filename:
            return self.saveTopologyAs()

        file = QtCore.QFile(self.filename)
        if not file.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(
                self, self.tr("Save Error"),
                self.tr("Cannot write file %1:\n%2.").arg(self.filename).arg(
                    file.errorString()))
            return False

        out = QtCore.QTextStream(file)
        QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)

        scene = self.canvas.scene()
        outstring = ""
        for item in scene.items():
            if isinstance(item, Node):
                outstring += item.toString()

        for item in scene.items():
            if isinstance(item, Edge):
                outstring += item.toString()

        out << outstring
        QtGui.QApplication.restoreOverrideCursor()

        self.statusBar().showMessage(
            self.tr("Saved '%1'").arg(self.filename), 2000)

        return True

    def copy(self):
        """
        Copy selected text from the log into the paste buffer.
        """
        self.log.copy()

    def config(self):
        """
        Open the options window.
        """
        self.configWindow.show()

    def arrange(self):
        """
        Rearrange the topology based on the distance between nodes.
        """
        if self.isRunning():
            self.log.append("Cannot arrange while running!")
            return

        if isinstance(mainWidgets["canvas"], Tutorial):
            mainWidgets["log"].append("Cannot arrange during the tutorial!")
            return

        options["elasticMode"] = not options["elasticMode"]

    def about(self):
        """
        Show the about window.
        """
        QtGui.QMessageBox.about(
            self,
            self.tr("About %s %s" %
                    (Core.globals.PROG_NAME, Core.globals.PROG_VERSION)),
            self.
            tr("<b>%s %s</b><br>Written by Daniel Ng<br>under the supervision of Muthucumaru Maheswaran"
               % (Core.globals.PROG_NAME, Core.globals.PROG_VERSION)))

    def createActions(self):
        """
        Create the actions used in the menus and toolbars.
        """
        self.newSceneAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "new.png"), self.tr("&New"), self)
        self.newSceneAct.setShortcut(self.tr("Ctrl+N"))
        self.newSceneAct.setStatusTip(self.tr("Create a new topology"))
        self.connect(self.newSceneAct, QtCore.SIGNAL("triggered()"),
                     self.newScene)

        self.closeAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "close.png"), self.tr("&Close"),
            self)
        self.closeAct.setShortcut(self.tr("Ctrl+W"))
        self.closeAct.setStatusTip(self.tr("Close the current topology"))
        self.connect(self.closeAct, QtCore.SIGNAL("triggered()"),
                     self.closeTopology)

        self.loadAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "open.png"), self.tr("&Open..."),
            self)
        self.loadAct.setShortcut(self.tr("Ctrl+O"))
        self.loadAct.setStatusTip(self.tr("Load a topology"))
        self.connect(self.loadAct, QtCore.SIGNAL("triggered()"),
                     self.loadTopology)

        self.saveAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "save.png"), self.tr("&Save..."),
            self)
        self.saveAct.setShortcut(self.tr("Ctrl+S"))
        self.saveAct.setStatusTip(self.tr("Save the current topology"))
        self.connect(self.saveAct, QtCore.SIGNAL("triggered()"),
                     self.saveTopology)

        self.saveAsAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "save.png"),
            self.tr("&Save As..."), self)
        self.saveAsAct.setShortcut(self.tr("Ctrl+Shift+S"))
        self.saveAsAct.setStatusTip(
            self.tr("Save the current topology under a given filename"))
        self.connect(self.saveAsAct, QtCore.SIGNAL("triggered()"),
                     self.saveTopologyAs)

        self.sendFileAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "send.png"),
            self.tr("&Send File..."), self)
        self.sendFileAct.setShortcut(self.tr("Ctrl+F"))
        self.sendFileAct.setStatusTip(
            self.tr("Choose a file to send to the server"))
        self.connect(self.sendFileAct, QtCore.SIGNAL("triggered()"),
                     self.sendFile)

        self.exportAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "export.png"),
            self.tr("&Export..."), self)
        self.exportAct.setShortcut(self.tr("Ctrl+P"))
        self.exportAct.setStatusTip(
            self.tr("Export the current topology as an image"))
        self.connect(self.exportAct, QtCore.SIGNAL("triggered()"), self.export)

        self.copyAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "copy.png"), self.tr("&Copy"),
            self)
        self.copyAct.setShortcut(self.tr("Ctrl+C"))
        self.copyAct.setStatusTip(self.tr("Copy the selected text"))
        self.connect(self.copyAct, QtCore.SIGNAL("triggered()"), self.copy)

        self.compileAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "compile.png"),
            self.tr("&Compile"), self)
        self.compileAct.setShortcut(self.tr("Ctrl+E"))
        self.compileAct.setStatusTip(self.tr("Compile the current topology"))
        self.connect(self.compileAct, QtCore.SIGNAL("triggered()"),
                     self.compile)

        self.runAct = QtGui.QAction(QtGui.QIcon(environ["images"] + "run.png"),
                                    self.tr("&Run"), self)
        self.runAct.setShortcut(self.tr("Ctrl+R"))
        self.runAct.setStatusTip(self.tr("Run the current topology"))
        self.connect(self.runAct, QtCore.SIGNAL("triggered()"), self.run)

        self.stopAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "stop.png"), self.tr("&Stop"),
            self)
        self.stopAct.setShortcut(self.tr("Ctrl+D"))
        self.stopAct.setStatusTip(self.tr("Stop the current topology"))
        self.connect(self.stopAct, QtCore.SIGNAL("triggered()"), self.stop)

        self.startServerAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "startServer.png"),
            self.tr("&Start Server"), self)
        self.startServerAct.setShortcut(self.tr("Ctrl+T"))
        self.startServerAct.setStatusTip(self.tr("Start the server"))
        self.connect(self.startServerAct, QtCore.SIGNAL("triggered()"),
                     self.startBackend)

        self.optionsAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "options.png"),
            self.tr("&Options"), self)
        self.optionsAct.setShortcut(self.tr("F2"))
        self.optionsAct.setStatusTip(self.tr("Show the options window"))
        self.connect(self.optionsAct, QtCore.SIGNAL("triggered()"),
                     self.config)

        self.arrangeAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "arrange.png"),
            self.tr("&Arrange"), self)
        self.arrangeAct.setShortcut(self.tr("Ctrl+A"))
        self.arrangeAct.setStatusTip(self.tr("Arranges the current topology"))
        self.connect(self.arrangeAct, QtCore.SIGNAL("triggered()"),
                     self.arrange)

        self.resetLayoutAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "layout.png"),
            self.tr("Reset Layout"), self)
        self.resetLayoutAct.setStatusTip(
            self.tr("Reset dock windows to the saved layout"))
        self.connect(self.resetLayoutAct, QtCore.SIGNAL("triggered()"),
                     self.resetLayout)

        self.expandSceneAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "expand.png"),
            self.tr("Expand Scene"), self)
        self.expandSceneAct.setStatusTip(
            self.tr("Expand the scene for more space"))
        self.connect(self.expandSceneAct, QtCore.SIGNAL("triggered()"),
                     self.expandScene)

        self.quitAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "exit.png"), self.tr("&Quit"),
            self)
        self.quitAct.setShortcut(self.tr("Ctrl+Q"))
        self.quitAct.setStatusTip(self.tr("Quit the application"))
        self.connect(self.quitAct, QtCore.SIGNAL("triggered()"), self.quit)

        self.newProjectAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "new.png"), self.tr("&New"), self)
        self.newProjectAct.setShortcut(self.tr("Ctrl+Shift+N"))
        self.newProjectAct.setStatusTip(self.tr("Create a new project"))
        self.connect(self.newProjectAct, QtCore.SIGNAL("triggered()"),
                     self.newProject)

        self.openProjectAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "open.png"), self.tr("&Open"),
            self)
        self.openProjectAct.setShortcut(self.tr("Ctrl+Shift+O"))
        self.openProjectAct.setStatusTip(self.tr("Open an existing project"))
        self.connect(self.openProjectAct, QtCore.SIGNAL("triggered()"),
                     self.openProject)

        self.closeProjectAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "close.png"), self.tr("&Close"),
            self)
        self.closeProjectAct.setShortcut(self.tr("Ctrl+Shift+W"))
        self.closeProjectAct.setStatusTip(self.tr("Close the current project"))
        self.connect(self.closeProjectAct, QtCore.SIGNAL("triggered()"),
                     self.closeProject)

        self.tutorialAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "tutorial.png"),
            self.tr("&Tutorial"), self)
        self.connect(self.tutorialAct, QtCore.SIGNAL("triggered()"),
                     self.startTutorial)

        self.faqAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "help.png"), self.tr("&FAQ"), self)
        self.connect(self.faqAct, QtCore.SIGNAL("triggered()"), self.faq)

        self.aboutAct = QtGui.QAction(
            QtGui.QIcon(environ["images"] + "giniLogo.png"), self.tr("&About"),
            self)
        self.aboutAct.setStatusTip(self.tr("Show the application's About box"))
        self.connect(self.aboutAct, QtCore.SIGNAL("triggered()"), self.about)

        self.aboutQtAct = QtGui.QAction(self.tr("About &Qt"), self)
        self.aboutQtAct.setStatusTip(
            self.tr("Show the Qt library's About box"))
        self.connect(self.aboutQtAct, QtCore.SIGNAL("triggered()"), QtGui.qApp,
                     QtCore.SLOT("aboutQt()"))

    def createMenus(self):
        """
        Create the menus with actions.
        """
        self.fileMenu = self.menuBar().addMenu(self.tr("&File"))
        self.fileMenu.setPalette(defaultOptions["palette"])
        self.fileMenu.addAction(self.newSceneAct)
        self.fileMenu.addAction(self.loadAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addAction(self.sendFileAct)
        self.fileMenu.addAction(self.exportAct)
        self.fileMenu.addAction(self.closeAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.quitAct)

        self.projectMenu = self.menuBar().addMenu(self.tr("&Project"))
        self.projectMenu.setPalette(defaultOptions["palette"])
        self.projectMenu.addAction(self.newProjectAct)
        self.projectMenu.addAction(self.openProjectAct)
        self.projectMenu.addAction(self.closeProjectAct)

        self.editMenu = self.menuBar().addMenu(self.tr("&Edit"))
        self.editMenu.setPalette(defaultOptions["palette"])
        self.editMenu.addAction(self.copyAct)
        self.editMenu.addAction(self.arrangeAct)
        self.editMenu.addAction(self.resetLayoutAct)
        self.editMenu.addAction(self.expandSceneAct)

        self.runMenu = self.menuBar().addMenu(self.tr("&Run"))
        self.runMenu.setPalette(defaultOptions["palette"])
        self.runMenu.addAction(self.compileAct)
        self.runMenu.addAction(self.runAct)
        self.runMenu.addAction(self.stopAct)
        self.runMenu.addAction(self.startServerAct)

        self.configMenu = self.menuBar().addMenu(self.tr("&Config"))
        self.configMenu.setPalette(defaultOptions["palette"])
        self.configMenu.addAction(self.optionsAct)

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu(self.tr("&Help"))
        self.helpMenu.setPalette(defaultOptions["palette"])
        self.helpMenu.addAction(self.tutorialAct)
        self.helpMenu.addAction(self.faqAct)
        self.helpMenu.addAction(self.aboutAct)
        self.helpMenu.addAction(self.aboutQtAct)

    def createPopupMenu(self):
        """
        Customize the popup menu so that it is visible.
        """
        popupMenu = QtGui.QMainWindow.createPopupMenu(self)
        popupMenu.setPalette(defaultOptions["palette"])
        return popupMenu

    def createToolBars(self):
        """
        Create the toolbars with actions.
        """
        self.fileToolBar = self.addToolBar(self.tr("File"))
        self.fileToolBar.addAction(self.newSceneAct)
        self.fileToolBar.addAction(self.loadAct)
        self.fileToolBar.addAction(self.saveAct)
        self.fileToolBar.addAction(self.sendFileAct)
        self.fileToolBar.addAction(self.exportAct)
        self.fileToolBar.addAction(self.closeAct)

        self.editToolBar = self.addToolBar(self.tr("Edit"))
        self.editToolBar.addAction(self.copyAct)
        self.editToolBar.addAction(self.resetLayoutAct)
        self.editToolBar.addAction(self.expandSceneAct)

        self.runToolBar = self.addToolBar(self.tr("Run"))
        self.runToolBar.addAction(self.compileAct)
        self.runToolBar.addAction(self.runAct)
        self.runToolBar.addAction(self.stopAct)
        self.runToolBar.addAction(self.startServerAct)

    def createStatusBar(self):
        """
        Create the status bar.
        """
        self.statusBar().showMessage(self.tr("Ready"))

    def createProgressBar(self):
        """
        Create the progress bar.
        """
        self.progressBar = QtGui.QProgressBar()
        self.progressBar.setRange(0, 10000)
        self.progressBar.setValue(0)

        self.statusBar().addPermanentWidget(self.progressBar)
        self.progressBar.show()

    def getDeviceCount(self, alive=False):
        """
        Return the interfaceable device count, or the alive ones if alive=True.
        """
        from Core.Interfaceable import Interfaceable

        count = 0.0
        for item in self.canvas.scene().items():
            if isinstance(item, Interfaceable):
                if item.device_type != "REALM":
                    if alive and item.status in ("", "dead"):
                        continue
                    count += 1.0

        return count

    def updateProgressBar(self):
        """
        Update the progress bar.
        """
        maxVal = self.progressBar.maximum()
        finalVal = (self.getDeviceCount(True) / self.getDeviceCount()) * maxVal

        if finalVal < 0:
            finalVal = 0

        self.progressBar.setValue(finalVal)

        if finalVal == 0:
            return True

        return False

    def createConfigWindows(self):
        """
        Create the options window.
        """
        self.configWindow = ConfigDialog(self)

    def createDockWindows(self):
        """
        Create the dock windows: dropbar, log, properties, interfaces, routes.
        """
        self.log = LogWindow(self.tr("Log"), self)
        self.log.append("Welcome to %s %s!\n" %
                        (Core.globals.PROG_NAME, Core.globals.PROG_VERSION))
        self.log.setGeometry(QtCore.QRect(0, 0, 800, 114))
        mainWidgets["log"] = self.log

        self.dropbar = DropBar(self.tr("Components"), self)
        self.dropbar.setGeometry(QtCore.QRect(0, 0, 129, 390))
        mainWidgets["drop"] = self.dropbar

        self.properties = PropertiesWindow(self)
        self.properties.setWindowTitle("Properties")
        mainWidgets["properties"] = self.properties

        self.interfaces = InterfacesWindow(self)
        self.interfaces.setWindowTitle("Interfaces")
        mainWidgets["interfaces"] = self.interfaces

        self.routes = RoutesWindow(self.interfaces, self)
        self.routes.setWindowTitle("Routes")
        mainWidgets["routes"] = self.routes

        self.tm = TaskManagerWindow(self)
        self.tm.setWindowTitle("Task Manager")
        mainWidgets["tm"] = self.tm

        self.debugWindow = QtGui.QDockWidget(self.tr("Debug Window"))
        self.debugWindow.setWidget(DebugWindow(self))

        self.docks = {
            "Components": self.dropbar,
            "Log": self.log,
            "Properties": self.properties,
            "Interfaces": self.interfaces,
            "Routes": self.routes,
            "Task Manager": self.tm
        }

        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dropbar)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.log)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.properties)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.interfaces)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.routes)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.tm)

        self.tm.setFloating(True)
        self.routes.setFloating(True)
        self.debugWindow.setFloating(True)

    def createPopupWindows(self):
        """
        Create the different popup windows.
        """
        self.exportWindow = ExportWindow(self)
        self.sendWindow = SendDirectoryWindow(self)

        self.popup = QtGui.QMessageBox(self)
        self.popup.setIcon(QtGui.QMessageBox.Warning)
        self.popup.setWindowIcon(
            QtGui.QIcon(environ["images"] + "giniLogo.png"))
        mainWidgets["popup"] = self.popup

    def keyPressEvent(self, event):
        """
        Handle specific shortcut keys.
        """
        key = event.key()
        scene = self.canvas.scene()
        if key == QtCore.Qt.Key_Escape:
            scene.clearSelection()
        elif key == QtCore.Qt.Key_Delete:
            for item in scene.selectedItems():
                item.delete()
        elif key == QtCore.Qt.Key_C:
            items = scene.items()
            if not items:
                return
            selected = scene.selectedItems()
            scene.clearSelection()
            if selected:
                index = items.index(selected[0])
                items[index - 1].setSelected(True)
            else:
                items[0].setSelected(True)
        elif key == QtCore.Qt.Key_H:
            for dock in self.docks.values():
                dock.setFloating(not dock.isFloating())
        elif key == QtCore.Qt.Key_F10:
            self.debugWindow.show()

    def cleanup(self):
        if self.server != None:
            self.server.kill()
示例#8
0
class Game:
    def __init__(self):
        pg.init()

        self.screen = pg.display.set_mode((WIDTH, HEIGHT), flags=DOUBLEBUF)
        self.screen.set_alpha(None)

        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()
        pg.key.set_repeat(SPRINT_DELAY, SPRINT_SPEED)
        self.current_floor = None
        self.view = None
        self.load_data()
        self.show_grid = True
        self.log = None
        self.tick = False
        self.show_inventory = False
        self.godmode = GODMODE

        pg.event.set_allowed([QUIT, KEYDOWN, KEYUP])

    def load_data(self):
        pass

    def new(self):
        self.all_sprites = pg.sprite.Group()
        self.walls = pg.sprite.Group()
        self.enemies = pg.sprite.Group()
        self.inters = pg.sprite.Group()
        self.spells = pg.sprite.Group()
        self.playerg = pg.sprite.Group()
        self.screens = pg.sprite.Group()
        self.player = Player(self, 8, 8)
        self.log = LogWindow(self, 3, 15)
        self.inventory = Inventory(self, 0, 0)

        # first floor (TODO start screen)
        self.current_floor = Floor(self, 1)
        self.current_floor.populate_floor()

        # put the player in a random place
        gx, gy = self.current_floor.get_valid_pos()
        self.player.update_global_position(gx, gy)

        # start the engines
        self.tick = True

        # TODO remove
        self.save_map()

    def run(self):
        # game loop - set self.playing = False to end the game
        self.playing = True
        self.log.init()
        while self.playing:
            self.dt = self.clock.tick(FPS) / 1000
            self.events()
            self.update()
            self.draw()
        return self.playing

    def save_map(self):
        map_string = ""
        fl = self.current_floor.layout
        px = self.player.gx
        py = self.player.gy
        for y in range(0, MAP_HEIGHT):
            for x in range(0, MAP_WIDTH):
                if x == px and y == py:
                    map_string += "@"
                elif fl[x][y] == 9:
                    map_string += "^"
                elif fl[x][y] == 0:
                    map_string += "."
                else:
                    map_string += str(fl[x][y])
            map_string += '\n'
        if not os.path.exists("scraps"):
            os.makedirs("scraps")
        with open("scraps/last_map.txt", 'w') as f:
            f.write(map_string)
        print("level map saved in scraps/last_map.txt!")

    def quit(self, save_map=False):
        if save_map:
            self.save_map()
        pg.quit()
        sys.exit()

    def update(self):
        # only update on tick
        # (currently just player movement)
        if not self.player.still:
            self.tick = True

        if self.show_inventory:
            self.inventory.update()
        elif self.tick:  # NOTE: might be able to toggle turn based here...
            # use the global position of the player to decide what to draw
            cur_g_x = self.player.gx
            cur_g_y = self.player.gy

            self.playerg.update()
            self.walls.update()
            self.spells.update()
            self.enemies.update()
            self.inters.update()
            self.current_floor.update_viewport(cur_g_x, cur_g_y)
            self.player.still = True
            self.tick = False
            self.player.dx = 0
            self.player.dy = 0
        self.log.update()

        if not self.player.state.alive:
            self.playing = False

    def draw_grid(self):
        for x in range(0, WIDTH, TILESIZE):
            pg.draw.line(self.screen, DARKGREY, (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, TILESIZE):
            pg.draw.line(self.screen, DARKGREY, (0, y), (WIDTH, y))

    def draw(self):
        if self.show_inventory:
            self.inventory.drawt(self.screen)
        else:
            self.screen.fill(BGCOLOR)
            for wall in self.walls:
                wall.drawt(self.screen)
            for enemy in self.enemies:
                enemy.drawt(self.screen)
            for inter in self.inters:
                inter.drawt(self.screen)
            for spell in self.spells:
                spell.drawt(self.screen)
            if self.show_grid:
                self.draw_grid()
            self.player.drawt(self.screen)
        self.log.draw(self.screen)
        pg.display.flip()

    def events(self):
        # catch all events here
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.quit()
            if self.show_inventory:
                if event.type == pg.KEYDOWN:
                    if event.key == pg.K_i:
                        self.show_inventory = False
                elif event.type == pg.MOUSEBUTTONUP and event.button == 1:
                    mouse_pos = pg.mouse.get_pos()
                    self.inventory.check(mouse_pos)
            else:
                if event.type == pg.KEYDOWN:
                    if event.key == pg.K_ESCAPE:
                        self.quit()
                    if event.key == pg.K_m:
                        self.quit(save_map=True)
                    if event.key == pg.K_a:
                        self.player.move(dx=-1)
                    if event.key == pg.K_d:
                        self.player.move(dx=1)
                    if event.key == pg.K_w:
                        self.player.move(dy=-1)
                    if event.key == pg.K_s:
                        self.player.move(dy=1)
                    if event.key == pg.K_SPACE:
                        # if not self.player.is_firing: TODO maybe limit this?
                        self.tick = True
                        mouse_pos = pg.mouse.get_pos()
                        self.player.fire_spell(mouse_pos)
                    if event.key == pg.K_RETURN:
                        self.tick = True
                    if event.key == pg.K_RSHIFT or event.key == pg.K_LSHIFT:
                        self.player.use_item()
                    if event.key == pg.K_g:
                        self.show_grid = not self.show_grid
                    if event.key == pg.K_l:
                        self.godmode = not self.godmode
                        self.log.info(f"GODMODE ON: {self.godmode}")
                    if event.key == pg.K_i:
                        self.show_inventory = True
                    if event.key == pg.K_o:
                        print(f"group num walls = {len(self.walls)}")
                    if event.key == pg.K_DOWN:
                        self.log.update_place(change=1)
                    if event.key == pg.K_UP:
                        self.log.update_place(change=-1)
                elif event.type == pg.MOUSEBUTTONUP and event.button == 1:
                    mouse_pos = pg.mouse.get_pos()
                    self.player.inspect_space(mouse_pos)
                    self.tick = True
                elif event.type == pg.MOUSEBUTTONUP and event.button == 3:
                    mouse_pos = pg.mouse.get_pos()
                    self.player.interact_space(mouse_pos)

    def get_sprite_at(self, x, y):
        for sprite in self.all_sprites:
            try:
                if sprite.x == x and sprite.y == y:
                    return sprite
            except:
                pass
        return None

    def object_in_view(self, gx, gy):
        """
        gx and gy are global quards
        """
        # use the global position of the player to decide what to draw
        cur_g_x = self.player.gx
        cur_g_y = self.player.gy

        # need to massage the indexes so that (xmin, ymin) is (0, 0) on the view
        xmin = cur_g_x - 6
        xmax = cur_g_x + 10
        ymin = cur_g_y - 6
        ymax = cur_g_y + 10

        # if we are out of sight, despawn
        if gx < xmin or gx > xmax or gy < ymin or gy > ymax:
            return False
        return True

    def show_start_screen(self):
        pass

    def show_go_screen(self):
        pass