class QtTest(unittest.TestCase): def setUp(self): """ Initialize our QApplication :return: None """ # We need to be able to test our code without a real device. So we setup # our Mock server here. Then we connect our client to that mock server. self.server = MockServer(('localhost', 0), MockHandler) self.listen_ip, self.listen_port = self.server.server_address self.server_thread = threading.Thread(target=self.server.serve_forever) self.server_thread.daemon = False self.server_thread.start() self.app = QApplication.instance() if self.app is None: self.app = QApplication([]) self.main_window = MainWindow(None) def tearDown(self): self.server.shutdown() self.main_window.clean_up() def testNames(self): self.cnt = 0 def _watch(msg): self.cnt += 1 # We know our mock server should emit 3 messages to the message_signal. So # we can use this as a way to count that all 3 have been sent before trying # to verify that our names list was updated correctly. self.main_window.network_manager.message_signal.connect(_watch) # This is how we normally would start the connection. Just now we are pointing # to our mock server. self.main_window.start_api(self.listen_ip, self.listen_port) # We know our mock server is going to send 3 names. So keep processing # until all 3 have been sent. while self.cnt < 3: if self.app.hasPendingEvents(): self.app.processEvents() # Finally, assert that our end goal has been met. assert self.main_window.names_list.count() == 3
class QtTest(unittest.TestCase, QObject): done = Signal() def __init__(self, *args, **kwargs): super(QtTest, self).__init__(*args, **kwargs) QObject.__init__(self) def setUp(self): """ Initialize our QApplication :return: None """ self.app = QApplication.instance() if self.app is None: self.app = QApplication([]) self.main_window = MainWindow(None) def tearDown(self): self.main_window.clean_up() def testGreeting(self): self.main_window.name_text.setText('Ryan') self.main_window.submit_button.click() assert self.main_window.hello_label.text() == u"{} {}".format(GREETING, 'Ryan') def testNamesList(self): self.done.connect(self.main_window.name_manager_thread.quit) self.main_window.name_text.setText('Ryan') self.main_window.submit_button.click() self.main_window.name_text.setText('Meg') self.main_window.submit_button.click() assert self.main_window.names_list.count() == 2 assert self.main_window.names_list.item(0).text() == 'Ryan' assert self.main_window.names_list.item(1).text() == 'Meg' assert wait_for(lambda: len(self.main_window.name_manager.names) == 2, 2) is True def testClearList(self): self.main_window.name_text.setText('Ryan') self.main_window.submit_button.click() self.main_window.name_text.setText('Meg') self.main_window.submit_button.click() self.main_window.clear_list_button.click() assert self.main_window.names_list.count() == 0 def testRestoreList(self): """ Using this method to test the Restore List procedure, we need to know exactly how many signals are going to be emitted. This could change over time without affecting our desired functionality. :return: """ self.main_window.name_text.setText('Ryan') self.main_window.submit_button.click() self.main_window.name_text.setText('Meg') self.main_window.submit_button.click() assert self.main_window.names_list.count() == 2 assert wait_for(lambda: len(self.main_window.name_manager.names) == 2, 2) is True self.main_window.clear_list_button.click() assert self.main_window.names_list.count() == 0 # This is running in another thread and we can't test # it the same way we tested other methods! self.main_window.restore_list_button.click() # First a signal is emitted to the NameManager thread to # get all the names. We have to process this event manually. self.app.processEvents() # The NameManager thread emits all the names to its names_signal. # We have to process this event as well! self.app.processEvents() # There must be a better way assert self.main_window.names_list.count() == 2 def testRestoreListBetter(self): """ Now we just keep processing events until we run out of work to do. Then we should have a deterministic state that we can test. :return: """ self.main_window.name_text.setText('Ryan') self.main_window.submit_button.click() self.main_window.name_text.setText('Meg') self.main_window.submit_button.click() assert self.main_window.names_list.count() == 2 assert wait_for(lambda: len(self.main_window.name_manager.names) == 2, 2) is True self.main_window.clear_list_button.click() assert self.main_window.names_list.count() == 0 # Simulate our restore button click self.main_window.restore_list_button.click() # While there is work to do, do it. while self.app.hasPendingEvents(): self.app.processEvents() # Now let's see what our state is assert self.main_window.names_list.count() == 2
class QtSupport( QtEditorModule ): _name = "qt" _dependency = [] statusWindow = None currentTheme = None def setupMainWindow( self ): self.mainWindow = QtMainWindow(None) self.mainWindow.setBaseSize( 800, 600 ) self.mainWindow.resize( 800, 600 ) self.mainWindow.setFixedSize(0,0) self.mainWindow.show() self.mainWindow.raise_() #bring app to front self.mainWindow.hide() self.mainWindow.module = self self.sharedMenuBar = QMenuBar( None ) self.mainWindow.setMenuWidget( self.sharedMenuBar ) self.menu = self.addMenuBar( 'main', self.sharedMenuBar ) self.menu.addChild('&File').addChild([ '----', 'Main Editor|F2', 'Asset Editor|F3', '----', 'Open Project', '----', 'E&xit', ] ) self.menu.addChild('&Edit').addChild( [ 'Undo|Ctrl+Z', 'Redo|Ctrl+Shift+Z', '----', ] ) self.menu.addChild('&Asset') self.menu.addChild( dict( name = 'preview', label = 'Game' ) ) self.menu.addChild('&Entity') self.menu.addChild('&View').addChild([ '----', 'Default Theme', 'Dark Theme', 'Robot Theme', '----', ] ) self.menu.addChild('&Window') # self.menu.addChild('&Help') def getSharedMenubar( self ): return self.sharedMenuBar def showSystemStatusWindow( self ): pass # this method use gii def setActiveWindow(self, window): self.qtApp.setActiveWindow(window) def getMainWindow( self ): return self.mainWindow def getQtSettingObject( self ): return self.qtSetting ##----------------------------------------------------------------## def openProject( self ): fileName, filt = QFileDialog.getOpenFileName(self.mainWindow, "Open Project File", "~", "Project file (*.json )") if fileName: path = os.path.dirname( fileName ) self.getApp().openProject( path ) def useStyle( self, style = "" ): self.currentTheme = style self.applyTheme() def applyTheme( self ): if self.currentTheme == "": self.qtApp.setStyleSheet("") else: self.qtApp.setStyleSheet( themes.load_stylesheet(self.currentTheme) ) ##----------------------------------------------------------------## def onLoad( self ): QLocale.setDefault(QLocale(QLocale.C)) locale.setlocale(locale.LC_ALL, 'C') QCoreApplication.setOrganizationName("CloudTeam") QCoreApplication.setOrganizationDomain("cloudteam.pro") QCoreApplication.setApplicationName("juma-moai-editor") self.qtApp = QApplication( sys.argv ) self.qtSetting = QSettings() self.setupMainWindow() self.initialized = True self.running = False return True def onStart( self ): eventFilter = QtSupportEventFilter( self.qtApp ) eventFilter.app = self self.qtApp.installEventFilter(eventFilter) def needUpdate( self ): return True def onUpdate( self ): if not self.qtApp.hasPendingEvents(): return self.qtApp.processEvents( QEventLoop.AllEvents, 4 ) def onStart( self ): self.restoreWindowState( self.mainWindow ) self.getApp().openProject( self.qtSetting.value("project/path", '~') ) self.currentTheme = self.qtSetting.value("theme/style", 'robotstyle') self.applyTheme() self.qtApp.processEvents( QEventLoop.AllEvents ) def onStop( self ): self.qtSetting.setValue("theme/style", self.currentTheme) self.qtSetting.setValue("project/path", self.getProject().path ) self.saveWindowState( self.mainWindow ) def onUnload( self ): print Style.RESET_ALL + '' def onMenu(self, node): name = node.name if name == 'exit': self.getApp().stop() if name == 'open_project': self.openProject() elif name == 'default_theme': self.useStyle() elif name == 'dark_theme': self.useStyle( 'darkstyle' ) elif name == 'robot_theme': self.useStyle( 'robotstyle' ) elif name == 'main_editor': self.getModule('main_editor').setFocus() elif name == 'asset_editor': self.getModule('asset_editor').setFocus() elif name == 'copy': print 'copy' elif name == 'paste': print 'paste' elif name == 'cut': print 'cut' elif name == 'undo': stack = EditorCommandRegistry.get().getCommandStack( 'main_editor' ) stack.undoCommand() elif name == 'redo': stack = EditorCommandRegistry.get().getCommandStack( 'main_editor' ) stack.redoCommand()