def start_q_watcher(app, emu_window, proc_comms_q_to_em, proc_comms_q_from_em): # need to spawn a worker thread that watches the proc_comms_q # need to seperate queue function from queue thread # http://stackoverflow.com/questions/4323678/threading-and-signals-problem # -in-pyqt q_watcher = QueueWatcher(app, emu_window, proc_comms_q_to_em, proc_comms_q_from_em) q_watcher_thread = QThread() q_watcher.moveToThread(q_watcher_thread) q_watcher_thread.started.connect(q_watcher.check_queue) # now that we've set up the thread, let's set up rest of signals/slots q_watcher.set_out_enable.connect(emu_window.set_output_enable) q_watcher.set_out_disable.connect(emu_window.set_output_disable) q_watcher.get_in.connect(emu_window.get_input) q_watcher.get_out.connect(emu_window.get_output) emu_window.send_output.connect(q_watcher.send_get_out_pin_result) emu_window.send_input.connect(q_watcher.send_get_in_pin_result) emu_window.interrupt_flagger.connect(q_watcher.handle_interrupt) # not sure why this doesn't work by connecting to q_watcher_thread.quit def about_to_quit(): q_watcher_thread.quit() app.aboutToQuit.connect(about_to_quit) q_watcher_thread.start()
class QApplicationRunner(QObject): """ Application runner starts application in own thread """ def __init__(self): QObject.__init__(self) self._thread = QThread() self.moveToThread(self._thread) self._thread.started.connect(self.start) self._ev = Event() self._app = None self._thread.start() @Slot() def start(self): self.app = Application() self._ev.set() self.app.exec_() def exit(self): self.app.exit() # perform polite disposal of resources if self._thread.isRunning(): self._thread.wait(1000) # wait 1 sec self._thread.terminate() # no-way @property def app(self): if not self._ev.isSet(): self._ev.wait() return self._app @app.setter def app(self, app): self._app = app
def _btnTransferClicked(self): 'Transfer Dives' idx = self._cbxComputer.currentIndex() dc = self._cbxComputer.itemData(idx, Qt.UserRole+0) if self._logbook.session.dirty: print "Flushing dirty session" self._logbook.rollback() self._txtLogbook.setEnabled(False) self._btnBrowse.setEnabled(False) self._cbxComputer.setEnabled(False) self._btnAddComputer.setEnabled(False) self._btnRemoveComputer.setEnabled(False) self._btnTransfer.setEnabled(False) self._btnExit.setEnabled(False) self._txtStatus.clear() thread = QThread(self) #FIXME: ZOMG HAX: Garbage Collector will eat TransferWorker when moveToThread is called #NOTE: Qt.QueuedConnection is important... self.worker = None self.worker = TransferWorker(dc) thread.started.connect(self.worker.start, Qt.QueuedConnection) self.worker.moveToThread(thread) self.worker.finished.connect(self._transferFinished, Qt.QueuedConnection) self.worker.finished.connect(self.worker.deleteLater, Qt.QueuedConnection) self.worker.finished.connect(thread.deleteLater, Qt.QueuedConnection) self.worker.progress.connect(self._transferProgress, Qt.QueuedConnection) self.worker.started.connect(self._transferStart, Qt.QueuedConnection) self.worker.status.connect(self._transferStatus, Qt.QueuedConnection) thread.start()
def _refresh(self): 'Refresh the list of Computers' self._btnRefresh.setEnabled(False) self._btnRefresh.setText('Scanning...') self._model.clear() typ = self.wizard().field('type') if typ == len(ComputerTypes): # Custom Computer Type didx = self.wizard().field('driver') drvr = list_drivers().keys()[didx] dopt = self.wizard().field('driveropt') else: # Predefined Computer Type drvr = ComputerTypes[typ]['driver'] dopt = ComputerTypes[typ]['driveropt'] dclass = list_drivers()[drvr]['class'] doptions = [] if dopt == '' else dopt.split(':') thread = QThread(self) #FIXME: ZOMG HAX: Garbage Collector will eat DiscoveryWorker when moveToThread is called #NOTE: Qt.QueuedConnection is important... self.worker = None self.worker = DiscoveryWorker(dclass, doptions) self.worker.moveToThread(thread) thread.started.connect(self.worker.start, Qt.QueuedConnection) self.worker.foundDevice.connect(self._model.addItem, Qt.QueuedConnection) self.worker.finished.connect(self._discoverFinished, Qt.QueuedConnection) self.worker.finished.connect(self.worker.deleteLater, Qt.QueuedConnection) self.worker.finished.connect(thread.deleteLater, Qt.QueuedConnection) thread.start()
def start_q_watcher(app, emu_window, proc_comms_q_to_em, proc_comms_q_from_em): # need to spawn a worker thread that watches the proc_comms_q # need to seperate queue function from queue thread # http://stackoverflow.com/questions/4323678/threading-and-signals-problem # -in-pyqt q_watcher = QueueWatcher( app, emu_window, proc_comms_q_to_em, proc_comms_q_from_em) q_watcher_thread = QThread() q_watcher.moveToThread(q_watcher_thread) q_watcher_thread.started.connect(q_watcher.check_queue) # now that we've set up the thread, let's set up rest of signals/slots q_watcher.set_out_enable.connect(emu_window.set_output_enable) q_watcher.set_out_disable.connect(emu_window.set_output_disable) q_watcher.get_in.connect(emu_window.get_input) q_watcher.get_out.connect(emu_window.get_output) emu_window.send_output.connect(q_watcher.send_get_out_pin_result) emu_window.send_input.connect(q_watcher.send_get_in_pin_result) emu_window.interrupt_flagger.connect(q_watcher.handle_interrupt) # not sure why this doesn't work by connecting to q_watcher_thread.quit def about_to_quit(): q_watcher_thread.quit() app.aboutToQuit.connect(about_to_quit) q_watcher_thread.start()
class QWebPageRunner(QObject): """ Web page runner starts WebPage instances in one separate thread and implements custom event loop. """ #FIXME: consider using QEventLoop instead def __init__(self, app): QObject.__init__(self) self._thread = QThread() self.moveToThread(self._thread) self._thread.started.connect(self.start) self._destroying = Event() self._destroying.clear() self._result = None self._commandQueue = Queue() self._app = app self._thread.start() @Slot() def start(self): try: while not self._destroying.is_set(): self._app.processEvents() try: cmd = self._commandQueue.get(timeout=0.1) args = () if isinstance(cmd, tuple): if not len(cmd): continue args = cmd[1:] cmd = cmd[0] if isinstance(cmd, NewPage): args = (self._app,) if isinstance(cmd, Command): cmd(*args) else: raise ValueError('Unknown command %s(%s).' % (cmd, args)) except Empty: pass except Exception as e: logger.exception(e) def exit(self): self._destroying.set() if self._thread.isRunning(): self._thread.wait(1000) # wait 1 sec self._thread.terminate() # no-way def invoke(self, cmd, *args): if isinstance(cmd, type) and issubclass(cmd, Command): cmd = cmd() if not isinstance(cmd, Command): cmd = Command(cmd) cmd.event.clear() self._commandQueue.put((cmd,)+args) while not cmd.event.is_set(): self._app.processEvents() cmd.event.wait(0.1) return cmd.result
class RendererExecutorGui(QObject): """A class to execute a rendering engine in Graphical User Interface mode. This class is designed to run a renderer in a separate thread, keeping GUI responsive. Meanwhile, stdout/stderr are piped to FreeCAD console, in such a way it is possible to follow the evolution of the rendering. To achieve that, renderer is executed in a separate thread, using **QThread**. Nota: in this class, it is assumed that Qt GUI is up, so it is not tested anywhere. """ def __init__(self, cmd, img): """Initialize executor. Args: cmd -- command to execute (str) img -- path to resulting image (the renderer output) (str) """ super().__init__(QCoreApplication.instance()) self.thread = QThread() self.worker = Worker(cmd, img) self.thread.setObjectName("fcd-renderexec") def start(self): """Start executor.""" # Move worker to thread self.worker.moveToThread(self.thread) # Connect signals and slots # pylint: disable=no-member self.thread.started.connect(self.worker.run) self.worker.finished.connect(self.thread.quit) self.worker.finished.connect(self.worker.deleteLater) self.worker.finished.connect(self.thread.exit) self.thread.finished.connect(self.thread.deleteLater) # self.thread.finished.connect(lambda: print("Thread finished")) # Dbg self.worker.result_ready.connect(display_image) # Start the thread self.thread.start() def join(self): """Join thread. This method is provided for consistency with CLI executor, but it should not be of much use in GUI context. """ loop = QEventLoop() self.thread.finished.connect(loop.quit) # pylint: disable=no-member if not self.thread.isFinished(): loop.exec_(flags=QEventLoop.ExcludeUserInputEvents)
def main(): loadtesterplugins() qt.mainthread = QThread.currentThread() # Store current thread qt.initialize_view() # Get the view ready dispatch_thread = QThread() # The QThread to put the dispatcher on qt.maindispatch = QTDispatcher(qt.mainview) # Set up the dispatcher qt.qapp.lastWindowClosed.connect(dispatch_thread.quit) # Connect the close signal to the thread quit signal qt.maindispatch.moveToThread(dispatch_thread) # Move the dispatcher to the new thread dispatch_thread.start() # Start the thread qt.mainview.show() # Show the main window res = qt.qapp.exec_() # Start the event loop, exits when the last window has been closed dispatch_thread.wait() # Wait for the dispatcher thread to finish sys.exit(res)
def start_input_watcher(app, emu_window): input_watcher = InputWatcher() input_watcher_thread = QThread() input_watcher.moveToThread(input_watcher_thread) input_watcher_thread.started.connect(input_watcher.check_inputs) # signal / slots input_watcher.set_in_enable.connect(emu_window.set_input_enable) input_watcher.set_in_disable.connect(emu_window.set_input_disable) # qyit setup def about_to_quit(): input_watcher_thread.quit() app.aboutToQuit.connect(about_to_quit) input_watcher_thread.start()
def start_interface_message_handler( app, emu_window, proc_comms_q_to_em, proc_comms_q_from_em): # need to spawn a worker thread that watches the proc_comms_q # need to seperate queue function from queue thread # http://stackoverflow.com/questions/4323678/threading-and-signals-problem # -in-pyqt handler_start = threading.Barrier(2) intface_msg_hand = InterfaceMessageHandler( app, proc_comms_q_to_em, proc_comms_q_from_em, handler_start) intface_msg_hand_thread = QThread() intface_msg_hand.moveToThread(intface_msg_hand_thread) intface_msg_hand_thread.started.connect(intface_msg_hand.check_queue) # now that we've set up the thread, let's set up rest of signals/slots intface_msg_hand.set_viewport_corner.connect( emu_window.slot_set_viewport_corner) intface_msg_hand.set_cursor.connect(emu_window.slot_set_cursor) intface_msg_hand.set_message.connect(emu_window.slot_set_message) intface_msg_hand.set_display_enable.connect( emu_window.slot_set_display_enable) intface_msg_hand.set_backlight_enable.connect( emu_window.slot_set_backlight_enable) intface_msg_hand.set_cursor_enable.connect( emu_window.slot_set_cursor_enable) intface_msg_hand.set_blink_enable.connect( emu_window.slot_set_blink_enable) intface_msg_hand.get_switch.connect(emu_window.slot_get_switch) intface_msg_hand.get_cursor.connect(emu_window.slot_get_cursor) intface_msg_hand.get_viewport_corner.connect( emu_window.slot_get_viewport_corner) intface_msg_hand.move_left.connect(emu_window.slot_move_left) intface_msg_hand.move_right.connect(emu_window.slot_move_right) intface_msg_hand.home.connect(emu_window.slot_home) intface_msg_hand.clear.connect(emu_window.slot_clear) intface_msg_hand.see_cursor.connect(emu_window.slot_see_cursor) emu_window.send_switch.connect(intface_msg_hand.send_get_switch_result) emu_window.send_cursor.connect(intface_msg_hand.send_get_cursor_result) emu_window.send_viewport_corner.connect( intface_msg_hand.send_get_viewport_corner_result) def about_to_quit(): intface_msg_hand_thread.quit() app.aboutToQuit.connect(about_to_quit) intface_msg_hand_thread.start() handler_start.wait()
def start_input_watcher(app, emu_window): input_watcher = InputWatcher(emu_window) input_watcher_thread = QThread() input_watcher.moveToThread(input_watcher_thread) input_watcher_thread.started.connect(input_watcher.check_inputs) # signal / slots input_watcher.set_in_enable.connect(emu_window.set_input_enable) input_watcher.set_in_disable.connect(emu_window.set_input_disable) # quit setup def about_to_quit(): input_watcher.stop_checking_inputs() input_watcher_thread.quit() app.aboutToQuit.connect(about_to_quit) input_watcher_thread.start()
def start_blinker(app, emu_window): # need to spawn a worker thread that watches the proc_comms_q # need to seperate queue function from queue thread # http://stackoverflow.com/questions/4323678/threading-and-signals-problem # -in-pyqt blinker_start = threading.Barrier(2) blinker = Blinker(emu_window, blinker_start) blinker_thread = QThread() blinker.moveToThread(blinker_thread) blinker_thread.started.connect(blinker.blink) blinker.blink_signal.connect(emu_window.blink) # not sure why this doesn't work by connecting to blinker_thread.quit def about_to_quit(): blinker_thread.quit() app.aboutToQuit.connect(about_to_quit) blinker_thread.start() blinker_start.wait()
def main(argv = None): if argv is None: argv = sys.argv version = '20130216' # modification date in yyyymmdd format connmgr = ConnectionManager() comm = SerialComm(connmgr) app = QApplication(argv) appwindow = MainWindow(connmgr, 'Projector Control Panel') commthread = QThread() comm.enumerateSerialPorts() comm.moveToThread(commthread) commthread.start() appwindow.show() appwindow.writeToLog('Software version ' + version + '.') result = app.exec_() commthread.quit() commthread.wait() return result
class SyncWindow(QMainWindow): """ Application main window. This class is meant to handle every widget needed by the application, as well as other needed global objects and behavior. """ failedLogIn = Signal() syncStarted = Signal() loginRequested = Signal(( str, str, )) statusChanged = Signal(( str, str, int, )) def __init__(self, parent=None): super(SyncWindow, self).__init__(parent) # Sets up several UI aspects self.tray = QSystemTrayIcon(self) self.tray.setIcon(QIcon(QPixmap(':/resources/icon.png'))) self.tray.show() self.setStyleSheet('SyncWindow {background: white}') self.setWindowTitle('IQBox') self.setWindowIcon(QIcon(QPixmap(':/resources/logobar.png'))) self.statusBar().setFont(View.labelsFont()) self.syncThread = None # Initializes the window with a `LoginView` widget. self.loginView() def loginView(self): """ Initializes a `LoginView` object and sets it up as the main window's central widget. """ login = LoginView() login.login.connect(self.onLogin) self.failedLogIn.connect(login.onFailedLogIn) self.setCentralWidget(login) self.setFixedSize(login.size()) self.statusBar().hide() def syncView(self): """ Initializes a `SyncView` object and sets it up as the main window's central widget. """ syncview = SyncView() self.setCentralWidget(syncview) self.setFixedSize(syncview.size()) self.statusBar().show() self.statusChanged.connect(syncview.status.setMessage) syncview.sync.connect(self.onSync) @Slot(str, str, str, bool) def onLogin(self, host, username, passwd, ssl): """ Slot. Triggers a log in request to the server. :param host: Indicates the hostname of the FTP server :param username: Username to log in into the FTP server :param passwd: Password to log in into the FTP server :param ssl: Indicates whether the FTP needs SSL support """ self.sync = Sync(host, ssl) self.syncStarted.connect(self.sync.initQueue) self.sync.server.downloadProgress.connect(self.onDownloadProgress) self.sync.server.uploadProgress.connect(self.onUploadProgress) self.sync.server.fileEvent.connect(self.onFileEvent) self.sync.server.badFilenameFound.connect(self.badNameWarning) self.sync.server.loginCompleted.connect(self.onLoginCompleted) self.sync.server.fileEventCompleted.connect(self.onFileEventCompleted) self.sync.server.ioError.connect(self.onIOError) # Added by Si self.sync.server.textStatus.connect(self.setStatus) self.sync.statusChanged.connect(self.setStatus) self.loginRequested.connect(self.sync.server.onLogin) self.syncThread = QThread() self.sync.moveToThread(self.syncThread) self.syncThread.start() QApplication.instance().lastWindowClosed.connect(self.syncThread.quit) self.loginRequested.emit(username, passwd) @Slot(bool, str) def onLoginCompleted(self, ok, msg): if not ok: self.showMessageBox(msg) self.failedLogIn.emit() else: self.syncView() @Slot() def onFileEventCompleted(self): # Workaround because there's an exception # when there's a file IO error # Ideally it should be managed elsewhere # But I don't know the code intimately enough yet. try: self.currentFile except AttributeError: self.currentFile = '' self.statusChanged.emit('Completed', self.currentFile, 100) @Slot(str) def onSync(self, localdir): """ Slot. Triggers a server checkout. :param localdir: Absolute local directory path where to keep the files """ self.sync.setLocalDir(localdir) self.sync.local.ioError.connect(self.onIOError) self.syncStarted.emit() self.setStatus('Syncing') def showMessageBox(self, msg): warning = QMessageBox(self) warning.setFont(View.labelsFont()) warning.setStyleSheet('QMessageBox {background: white}') warning.setWindowTitle("Error") warning.setText(msg) warning.setIcon(QMessageBox.Warning) warning.addButton("Ok", QMessageBox.AcceptRole).setFont(View.editsFont()) warning.exec_() @Slot(int, int) def onProgress(self, action, total, progress): """ Slot. Triggers download progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ if progress <= 0: return else: percent = (progress * 100) / total self.statusChanged.emit(action, self.currentFile, percent) @Slot(str) def setStatus(self, msg): self.statusChanged.emit(msg, '', 0) @Slot(int, int) def onDownloadProgress(self, total, progress): """ Slot. Triggers upload progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ self.onProgress('Downloading', total, progress) @Slot(int, int) def onUploadProgress(self, total, progress): """ Slot. Triggers download progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ self.onProgress('Uploading', total, progress) @Slot(str) def onFileEvent(self, filename): """ Slot. Updates the current download filename to be used in the UI :param filename: Name of the file that is being downloaded """ self.currentFile = filename @Slot(str) def onIOError(self, filename): self.showMessageBox('Error reading: "{}"'.format(filename)) @Slot(str) def badNameWarning(self, filename): self.showMessageBox( 'Will not sync "{}". Invalid filename'.format(filename))
debug_thread("rx_thread", rx_thread) if USE_DERIVED: # receiver = Derived() # receiver = DerivedTwo() # receiver = DerivedThree() # receiver = RelayDerived() receiver = DerivedFromNoSlot() else: receiver = Base() # receiver = RelayBase() # receiver = NoSlotBase() debug_object(receiver) receiver.moveToThread(rx_thread) debug_object(receiver) # Signals: startup tx_thread.started.connect(transmitter.start) rx_thread.started.connect(receiver.start) # ... shutdown transmitter.finished.connect(tx_thread.quit) tx_thread.finished.connect(rx_thread.quit) rx_thread.finished.connect(app.quit) # ... action transmitter.transmit.connect(receiver.receive) # Go rx_thread.start() tx_thread.start() report("Starting app") app.exec_()
class UnlockDialog(QDialog, Ui_Dialog): signal = QtCore.Signal(str, str) def __init__(self, fileName=None, parent=None): super(UnlockDialog, self).__init__(parent) if not admin.isUserAdmin(): admin.runAsAdmin() # end the current instance of the program because it isn't uac. Results in two app windows otherwise. sys.exit(0) self.setupUi(self) # print psutil.Process(os.getpid()).parent fileArgPos = self._getRelevantCmdArgument(sys.argv) if fileArgPos != None: self.fileName = sys.argv[fileArgPos] self.stackedWidget.setCurrentIndex(0) self.setUnlockTextLabel(self.fileName) self.sameLocation = False # elif self._checkScriptNameInFolder(): # parentProcessName = psutil.Process(os.getpid()).parent().exe() # if parentProcessName != "python.exe": # scriptName = os.path.basename(parentProcessName) # else: # scriptName = os.path.basename(__file__) # # get the script name without file extension # scriptName = os.path.splitext(scriptName)[0] + ".exelocker" # self.fileName = os.path.basename(scriptName) # self.sameLocation = False # self.setUnlockTextLabel(self.fileName) # self.stackedWidget.setCurrentIndex(0) else: self.fileName = None self.sameLocation = True self.stackedWidget.setCurrentIndex(1) if self._argsHasDirectory(): index = self._getRelevantDirectoryArg() self.fillListWidget(sys.argv[index]) else: self.fillListWidget() self.setWindowFlags(QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint) self.setFixedSize(self.width(), self.height()) # connect the unlock button self.unlockButton.clicked.connect(self.unlockFile) # self.passwordLineEdit.returnPressed.connect(self.unlockFile) # <-- This line of code ruined my whole f*****g day # The above line made two events fire when the exelocker filename is same as the script name. I don't f*****g understand it. F**K self.browseButton.clicked.connect(self.browseFiles) self.listWidgetUnlockButton.clicked.connect(self.listWidgetSelectedEvent) # connect with the thread self.signal.connect(self.fileUnlockedEvent) def _argsHasDirectory(self): """" Check if the argument has a directory """ for index, args in enumerate(sys.argv): if os.path.isdir(args): return True return None def _getRelevantDirectoryArg(self): """ Return the index of the argument which is a directory """ for index, args in enumerate(sys.argv): if os.path.isdir(args): return index return None def _checkScriptNameInFolder(self): parentProcessName = psutil.Process(os.getpid()).parent().name() if parentProcessName != "python.exe": scriptName = parentProcessName else: scriptName = os.path.basename(__file__) # get script name without extension scriptName = os.path.splitext(scriptName)[0] # change extension of script name to lock to .exelocker scriptName = scriptName + ".exelocker" # print scriptName fileList = self._getRelevantFilesInFolder() try: index = fileList.index(scriptName) print index except ValueError: index = None if index != None: return True else: return False def listWidgetSelectedEvent(self): self.fileName = self.listWidget.currentItem().text() self.setUnlockTextLabel(self.fileName) self.stackedWidget.setCurrentIndex(0) self.setUnlockTextLabel(self.fileName) def setUnlockTextLabel(self, fileName): if fileName and len(fileName): fileName = os.path.basename(fileName) string = u"Enter password for " + fileName + ":" self.unlockTextLabel.setText(string) def fillListWidget(self, location = None): if location != None: filteredList = self._getRelevantFilesInFolder(location) else: filteredList = self._getRelevantFilesInFolder() self.listWidget.addItems(filteredList) def _getRelevantFilesInFolder(self, location = None): if location == None: files = os.listdir('.') else: files = os.listdir(location) filteredList = [] for f in files: if os.path.isfile(f): extension = os.path.splitext(f)[1] if extension == ".exelocker": filteredList.append(f) return filteredList def browseFiles(self): dir = "." file = QFileDialog.getOpenFileName(self, "Select .exelocker file", dir, "EXE Locker file (*.exelocker)") if len(file[0]): self.fileName = file[0] self.stackedWidget.setCurrentIndex(0) self.setUnlockTextLabel(self.fileName) def fileUnlockedEvent(self, success, decryptedFileName): if success == 'True': QMessageBox.information(self, __appname__, "File Unlocked Successfully.") else: os.remove(decryptedFileName) EncryptedFile.replaceWithUnlockDialog(EncryptedFile.CALLER_LOCATION, decryptedFileName) QMessageBox.information(self, __appname__, "Wrong password. Couldn't unlock file.") def unlockFile(self): if EncryptedFile.isValidFile(self.fileName): eFile = EncryptedFile(self.fileName) unhashedPassword = self.passwordLineEdit.text() password = EncryptionHelper.generateKeyHash(unhashedPassword) self.thread = QThread() self.worker = Worker(eFile, password, self.signal, self.sameLocation) self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.run) self.worker.signal.connect(self.thread.quit) self.worker.signal.connect(self.worker.deleteLater) self.thread.finished.connect(self.thread.deleteLater) self.thread.start() else: QMessageBox.information(self, __appname__, "Invalid .exelocker file.") self.passwordLineEdit.setText("") def _getRelevantCmdArgument(self, args): for arg in args: if EncryptedFile.isValidFile(arg): return args.index(arg) return None
class Progress(QWidget, ProgressGui.Ui_Progress): # Signals completeProcessSig = Signal(str) endProcessEarlySig = Signal() """ -------------------------------------------------------------------------------------------------------------------- Constructor method -------------------------------------------------------------------------------------------------------------------- """ def __init__(self, mode, algo_type, key, keysize, ciphertext_file_path, plaintext_file_path, parent=None): super(Progress, self).__init__(parent) self.setupUi(self) self.setWindowTitle(ApplicationStrings.APPLICATION_NAME) self.setFixedSize(500, 135) # set values from those passed in self.mode = mode self.algo_type = algo_type self.key = key self.keysize = keysize self.ciphertext_file_path = ciphertext_file_path self.plaintext_file_path = plaintext_file_path # create empty holders self.init_vector = None self.cipher = None self.cipher_process = None self.monitor_progress_thread = None self.progress_monitor = None # create Values to be shared between processes self.end_process_early = Value('i', 0) self.percent_done = Value('d', 0.0) self.pause_requested = Value('i', 0) self.paused = Value('i', 0) self.pause_sig_sent = Value('i', 0) # connect cancel btn signal and slot self.cancel_btn.clicked.connect(self.requestPause) # create the Value objects shared between processes self.setGuiValues() # create the initialization vector self.createInitVector() # create an instance of the appropriate cipher self.createCipher() # create and setup the monitor class self.setupMonitor() # create the Process that the Cipher will run in self.createCipherProcess() """ -------------------------------------------------------------------------------------------------------------------- Set the Gui Labels from data passed into constructor -------------------------------------------------------------------------------------------------------------------- """ def setGuiLabels(self): if self.mode == 'encryption': self.title_label.setText('Encrypting File: %s' \ % self.plaintext_file_path[:3]+'.../'+self.plaintext_file_path.split('/')[-1]) elif self.mode == 'decryption': self.title_label.setText('Decrypting File: %s' \ % self.ciphertext_file_path[:3]+'.../'+self.ciphertext_file_path.split('/')[-1]) self.key_label.setText('Key: %s' % binascii.hexlify(self.key).decode()) self.progress_bar.reset() """ -------------------------------------------------------------------------------------------------------------------- Create the Initialization vector -------------------------------------------------------------------------------------------------------------------- """ def createInitVector(self): if kr.getFromKeyring('iv_source', 'admin') is None: self.init_vector = 1 else: self.init_vector = int(kr.getFromKeyring('iv_source', 'admin')) + 1 kr.saveToKeyring('iv_source', 'admin', str(self.init_vector)) self.init_vector = hashlib.sha256(str(self.init_vector).encode('utf-8')).hexdigest() self.init_vector = bytearray.fromhex(self.init_vector)[:16] """ -------------------------------------------------------------------------------------------------------------------- Create the Cipher Algorithm -------------------------------------------------------------------------------------------------------------------- """ def createCipher(self): if self.algo_type == 'aes': self.cipher = AesCipher(self.keysize, self.plaintext_file_path, self.ciphertext_file_path, self.init_vector, self.key) elif self.algo_type == '3es': print('3es') elif self.algo_type == 'des': print('des') """ -------------------------------------------------------------------------------------------------------------------- Setup the monitor class and move to its own thread -------------------------------------------------------------------------------------------------------------------- """ def setupMonitor(self): self.monitor_progress_thread = QThread() self.progress_monitor = ProgressMonitor(self.percent_done, self.paused, self.pause_sig_sent, self.end_process_early) self.progress_monitor.moveToThread(self.monitor_progress_thread) # connect signals and slots self.monitor_progress_thread.started.connect(self.progress_monitor.beginMonitoring) self.progress_monitor.updateProcessSig.connect(self.update) self.progress_monitor.endProcessEarlySig.connect(self.endEarly) self.progress_monitor.endProcessSig.connect(self.complete) self.progress_monitor.pauseSig.connect(self.showCancelMessage) """ -------------------------------------------------------------------------------------------------------------------- Create the Cipher Process and set the target to the appropriate method in the Cipher instance -------------------------------------------------------------------------------------------------------------------- """ def createCipherProcess(self): if self.mode == 'encryption': self.cipher_process = Process(target=self.cipher.encrypt, args=(self.percent_done, self.pause_requested, self.paused)) elif self.mode == 'decryption': self.cipher_process = Process(target=self.cipher.decrypt, args=(self.percent_done, self.pause_requested, self.paused)) """ -------------------------------------------------------------------------------------------------------------------- Begin the encryption/decryption process and start the monitoring thread -------------------------------------------------------------------------------------------------------------------- """ def begin(self): self.monitor_progress_thread.start() self.cipher_process.start() """ -------------------------------------------------------------------------------------------------------------------- Update the progress bar with values from the encryption/decryption process -------------------------------------------------------------------------------------------------------------------- """ def update(self, percent_done): self.progress_bar.setValue(percent_done) """ -------------------------------------------------------------------------------------------------------------------- request the process to pause -------------------------------------------------------------------------------------------------------------------- """ def requestPause(self): self.pause_requested.value = 1 """ -------------------------------------------------------------------------------------------------------------------- show the cancel message -------------------------------------------------------------------------------------------------------------------- """ def showCancelMessage(self): msgBox = QMessageBox() msgBox.setText("Are You Sure You Want To Cancel %s" % self.mode) msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) msgBox.setDefaultButton(QMessageBox.Cancel) ret = msgBox.exec_() if ret == QMessageBox.Ok: self.end_process_early.value = 1 elif ret == QMessageBox.Cancel: self.paused.value = 0 self.pause_requested.value = 0 self.pause_sig_sent.value = 0 self.pause_requested.value = 0 """ -------------------------------------------------------------------------------------------------------------------- Complete encryption / decryption when done -------------------------------------------------------------------------------------------------------------------- """ def complete(self): self.cipher = None # terminate the update progress thread self.monitor_progress_thread.terminate() while self.monitor_progress_thread.isRunning(): time.sleep(0.01) # terminate the cipher process self.cipher_process.terminate() while self.cipher_process.is_alive(): time.sleep(0.01) self.close() # create the filepath to send back to the message box fp = '' if self.mode == 'encryption': fp = self.ciphertext_file_path elif self.mode == 'decryption': fp = self.plaintext_file_path # emit Signal self.completeProcessSig.emit(fp) """ -------------------------------------------------------------------------------------------------------------------- Cancel the encryption / decryption before completion -------------------------------------------------------------------------------------------------------------------- """ def endEarly(self): self.cipher = None # terminate the update progress thread self.monitor_progress_thread.terminate() while self.monitor_progress_thread.isRunning(): time.sleep(0.01) # terminate the cipher process self.cipher_process.terminate() while self.cipher_process.is_alive(): time.sleep(0.01) self.close() # emit Signal self.endProcessEarlySig.emit()
def start(self): QThread.start(self) loop=QEventLoop() self._init.connect(loop.quit) loop.exec_()
class UnlockDialog(QDialog, Ui_Dialog): signal = QtCore.Signal(str, str) def __init__(self, fileName=None, parent=None): super(UnlockDialog, self).__init__(parent) if not admin.isUserAdmin(): admin.runAsAdmin() # end the current instance of the program because it isn't uac. Results in two app windows otherwise. sys.exit(0) self.setupUi(self) # print psutil.Process(os.getpid()).parent fileArgPos = self._getRelevantCmdArgument(sys.argv) if fileArgPos != None: self.fileName = sys.argv[fileArgPos] self.stackedWidget.setCurrentIndex(0) self.setUnlockTextLabel(self.fileName) self.sameLocation = False # elif self._checkScriptNameInFolder(): # parentProcessName = psutil.Process(os.getpid()).parent().exe() # if parentProcessName != "python.exe": # scriptName = os.path.basename(parentProcessName) # else: # scriptName = os.path.basename(__file__) # # get the script name without file extension # scriptName = os.path.splitext(scriptName)[0] + ".exelocker" # self.fileName = os.path.basename(scriptName) # self.sameLocation = False # self.setUnlockTextLabel(self.fileName) # self.stackedWidget.setCurrentIndex(0) else: self.fileName = None self.sameLocation = True self.stackedWidget.setCurrentIndex(1) if self._argsHasDirectory(): index = self._getRelevantDirectoryArg() self.fillListWidget(sys.argv[index]) else: self.fillListWidget() self.setWindowFlags(QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint) self.setFixedSize(self.width(), self.height()) # connect the unlock button self.unlockButton.clicked.connect(self.unlockFile) # self.passwordLineEdit.returnPressed.connect(self.unlockFile) # <-- This line of code ruined my whole f*****g day # The above line made two events fire when the exelocker filename is same as the script name. I don't f*****g understand it. F**K self.browseButton.clicked.connect(self.browseFiles) self.listWidgetUnlockButton.clicked.connect( self.listWidgetSelectedEvent) # connect with the thread self.signal.connect(self.fileUnlockedEvent) def _argsHasDirectory(self): """" Check if the argument has a directory """ for index, args in enumerate(sys.argv): if os.path.isdir(args): return True return None def _getRelevantDirectoryArg(self): """ Return the index of the argument which is a directory """ for index, args in enumerate(sys.argv): if os.path.isdir(args): return index return None def _checkScriptNameInFolder(self): parentProcessName = psutil.Process(os.getpid()).parent().name() if parentProcessName != "python.exe": scriptName = parentProcessName else: scriptName = os.path.basename(__file__) # get script name without extension scriptName = os.path.splitext(scriptName)[0] # change extension of script name to lock to .exelocker scriptName = scriptName + ".exelocker" # print scriptName fileList = self._getRelevantFilesInFolder() try: index = fileList.index(scriptName) print index except ValueError: index = None if index != None: return True else: return False def listWidgetSelectedEvent(self): self.fileName = self.listWidget.currentItem().text() self.setUnlockTextLabel(self.fileName) self.stackedWidget.setCurrentIndex(0) self.setUnlockTextLabel(self.fileName) def setUnlockTextLabel(self, fileName): if fileName and len(fileName): fileName = os.path.basename(fileName) string = u"Enter password for " + fileName + ":" self.unlockTextLabel.setText(string) def fillListWidget(self, location=None): if location != None: filteredList = self._getRelevantFilesInFolder(location) else: filteredList = self._getRelevantFilesInFolder() self.listWidget.addItems(filteredList) def _getRelevantFilesInFolder(self, location=None): if location == None: files = os.listdir('.') else: files = os.listdir(location) filteredList = [] for f in files: if os.path.isfile(f): extension = os.path.splitext(f)[1] if extension == ".exelocker": filteredList.append(f) return filteredList def browseFiles(self): dir = "." file = QFileDialog.getOpenFileName(self, "Select .exelocker file", dir, "EXE Locker file (*.exelocker)") if len(file[0]): self.fileName = file[0] self.stackedWidget.setCurrentIndex(0) self.setUnlockTextLabel(self.fileName) def fileUnlockedEvent(self, success, decryptedFileName): if success == 'True': QMessageBox.information(self, __appname__, "File Unlocked Successfully.") else: os.remove(decryptedFileName) EncryptedFile.replaceWithUnlockDialog( EncryptedFile.CALLER_LOCATION, decryptedFileName) QMessageBox.information(self, __appname__, "Wrong password. Couldn't unlock file.") def unlockFile(self): if EncryptedFile.isValidFile(self.fileName): eFile = EncryptedFile(self.fileName) unhashedPassword = self.passwordLineEdit.text() password = EncryptionHelper.generateKeyHash(unhashedPassword) self.thread = QThread() self.worker = Worker(eFile, password, self.signal, self.sameLocation) self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.run) self.worker.signal.connect(self.thread.quit) self.worker.signal.connect(self.worker.deleteLater) self.thread.finished.connect(self.thread.deleteLater) self.thread.start() else: QMessageBox.information(self, __appname__, "Invalid .exelocker file.") self.passwordLineEdit.setText("") def _getRelevantCmdArgument(self, args): for arg in args: if EncryptedFile.isValidFile(arg): return args.index(arg) return None
class MainWindow(QMainWindow): start_acq = Signal(str) start_rec = Signal(str) collect_frame = Signal(object) collect_threshed = Signal(object) def __init__(self, parent=None): ''' sets up the whole main window ''' #standard init super(MainWindow, self).__init__(parent) #set the window title self.setWindowTitle('Open Ephys Control GUI') self.window_height = 700 self.window_width = 1100 self.screen2 = QDesktopWidget().screenGeometry(0) self.move( self.screen2.left() + (self.screen2.width() - self.window_width) / 2., self.screen2.top() + (self.screen2.height() - self.window_height) / 2.) self.get_info() self.noinfo = True while self.noinfo: loop = QEventLoop() QTimer.singleShot(500., loop.quit) loop.exec_() subprocess.Popen('start %s' % open_ephys_path, shell=True) self.collect_frame.connect(self.update_frame) self.collect_threshed.connect(self.update_threshed) self.acquiring = False self.recording = False self.video_height = self.window_height * .52 self.video_width = self.window_width * .48 self.resize(self.window_width, self.window_height) #create QTextEdit window 'terminal' for receiving stdout and stderr self.terminal = QTextEdit(self) #set the geometry self.terminal.setGeometry( QRect(self.window_width * .02, self.window_height * .15 + self.video_height, self.video_width * .96, 150)) #make widgets self.setup_video_frames() self.setup_thresh_buttons() self.overlay = True #create thread and worker for video processing self.videoThread = QThread(self) self.videoThread.start() self.videoproc_worker = VideoWorker(self) self.videoproc_worker.moveToThread(self.videoThread) self.vt_file = None """""" """""" """""" """""" """""" """""" """""" """ set up menus """ """""" """""" """""" """""" """""" """""" """""" #create a QMenuBar and set geometry self.menubar = QMenuBar(self) self.menubar.setGeometry( QRect(0, 0, self.window_width * .5, self.window_height * .03)) #set the QMenuBar as menu bar for main window self.setMenuBar(self.menubar) #create a QStatusBar statusbar = QStatusBar(self) #set it as status bar for main window self.setStatusBar(statusbar) #create icon toolbar with default image iconToolBar = self.addToolBar("iconBar.png") #create a QAction for the acquire button self.action_Acq = QAction(self) #make it checkable self.action_Acq.setCheckable(True) #grab an icon for the button acq_icon = self.style().standardIcon(QStyle.SP_MediaPlay) #set the icon for the action self.action_Acq.setIcon(acq_icon) #when the button is pressed, call the Acquire function self.action_Acq.triggered.connect(self.Acquire) #create a QAction for the record button self.action_Record = QAction(self) #make it checkable self.action_Record.setCheckable(True) #grab an icon for the button record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton) #set the icon for the action self.action_Record.setIcon(record_icon) #when the button is pressed, call advanced_settings function self.action_Record.triggered.connect(self.Record) #create QAction for stop button action_Stop = QAction(self) #grab close icon stop_icon = self.style().standardIcon(QStyle.SP_MediaStop) #set icon for action action_Stop.setIcon(stop_icon) #when button pressed, close window action_Stop.triggered.connect(self.Stop) #show tips for each action in the status bar self.action_Acq.setStatusTip("Start acquiring") self.action_Record.setStatusTip("Start recording") action_Stop.setStatusTip("Stop acquiring/recording") #add actions to icon toolbar iconToolBar.addAction(self.action_Acq) iconToolBar.addAction(self.action_Record) iconToolBar.addAction(action_Stop) # self.sort_button = QPushButton('Sort Now',self) # self.sort_button.setGeometry(QRect(self.window_width*.85,0,self.window_width*.15,self.window_height*.05)) # self.sort_button.clicked.connect(self.sort_now) #show the window if minimized by windows self.showMinimized() self.showNormal() """""" """""" """""" """""" """""" """""" """""" """""" """""" """""" "" """""" """""" """""" """""" """""" """""" """""" """""" """""" """""" "" #this function acts as a slot to accept 'message' signal @Slot(str) def print_message(self, message): ''' print stdout and stderr to terminal window ''' #move terminal cursor to end self.terminal.moveCursor(QTextCursor.End) #write message to terminal self.terminal.insertPlainText(message) def setup_thresh_buttons(self): ''' set up buttons for overlay/clearing thresh view ''' self.button_frame = QFrame(self) self.button_frame.setGeometry( QRect(self.window_width * .52, self.window_height * .13 + self.video_height, self.video_width * .98, 50)) button_layout = QHBoxLayout() self.button_frame.setLayout(button_layout) self.clear_button = QPushButton('Clear') self.overlay_button = QPushButton('Overlay') button_layout.addWidget(self.clear_button) button_layout.addWidget(self.overlay_button) self.clear_button.setEnabled(False) self.clear_button.clicked.connect(self.clear_threshed) self.overlay_button.setEnabled(False) self.overlay_button.clicked.connect(self.overlay_threshed) def setup_video_frames(self): ''' set up spots for playing video frames ''' filler_frame = np.zeros((360, 540, 3)) filler_frame = qimage2ndarray.array2qimage(filler_frame) self.raw_frame = QFrame(self) self.raw_label = QLabel() self.raw_label.setText('raw') self.raw_frame.setGeometry( QRect(self.window_width * .01, self.window_height * .15, self.video_width, self.video_height)) self.raw_frame raw_layout = QVBoxLayout() self.raw_frame.setLayout(raw_layout) raw_layout.addWidget(self.raw_label) self.threshed_frame = QFrame(self) self.threshed_label = QLabel() self.threshed_label.setText('Threshed') self.threshed_frame.setGeometry( QRect(self.window_width * .51, self.window_height * .15, self.video_width, self.video_height)) threshed_layout = QVBoxLayout() self.threshed_frame.setLayout(threshed_layout) threshed_layout.addWidget(self.threshed_label) self.label_frame = QFrame(self) self.label_frame.setGeometry( QRect(self.window_width * .01, self.window_height * .11, self.video_width * 2, 50)) self.label_rawlabel = QLabel() self.label_rawlabel.setText('Raw Video') self.label_threshedlabel = QLabel() self.label_threshedlabel.setText('Threshold View') label_layout = QHBoxLayout() self.label_frame.setLayout(label_layout) label_layout.addWidget(self.label_rawlabel) label_layout.addWidget(self.label_threshedlabel) self.raw_label.setPixmap(QPixmap.fromImage(filler_frame)) self.threshed_label.setPixmap(QPixmap.fromImage(filler_frame)) def Acquire(self): if self.action_Acq.isChecked(): self.vidbuffer = [] if self.recording: while 1: try: self.sock.send('StopRecord') self.sock.recv() except: continue break self.recording = False else: #create and start a thread to transport a worker to later self.workerThread = QThread(self) self.workerThread.start() #create a worker object based on Worker class and move it to our #worker thread self.worker = Worker(self) self.worker.moveToThread(self.workerThread) try: self.start_acq.disconnect() except: pass while 1: try: self.sock.send('StartAcquisition') self.sock.recv() except: continue break self.acquiring = True self.start_acq.connect(self.worker.acquire) self.start_acq.emit('start!') self.action_Acq.setEnabled(False) self.action_Record.setChecked(False) self.action_Record.setEnabled(True) record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton) #set the icon for the action self.action_Record.setIcon(record_icon) def Record(self): if self.action_Record.isChecked(): if not self.acquiring: self.workerThread = QThread(self) self.workerThread.start() self.worker = Worker(self) self.worker.moveToThread(self.workerThread) try: self.start_rec.disconnect() except: pass while 1: try: self.sock.send('StartAcquisition') self.sock.recv() except: continue break while 1: try: self.sock.send('StartRecord') self.sock.recv() except: continue break self.vidbuffer = [] self.start_rec.connect(self.worker.acquire) self.recording = True self.start_rec.emit('start!') else: while 1: try: self.sock.send('StartRecord') self.sock.recv() except: continue break self.vidbuffer = [] self.recording = True record_icon = self.style().standardIcon(QStyle.SP_DialogNoButton) #set the icon for the action self.action_Record.setIcon(record_icon) self.action_Record.setEnabled(False) self.action_Acq.setChecked(False) self.action_Acq.setEnabled(True) def Stop(self): self.acquiring = False self.recording = False while 1: try: self.sock.send('isRecording') rec = self.sock.recv() except: continue break if rec == '1': while 1: try: self.sock.send('StopRecord') self.sock.recv() except: continue break self.action_Record.setEnabled(True) self.action_Record.setChecked(False) while 1: try: self.sock.send('isAcquiring') acq = self.sock.recv_string() except: continue break if acq == '1': while 1: try: self.sock.send('StopAcquisition') self.sock.recv() except: continue break self.action_Acq.setEnabled(True) self.action_Acq.setChecked(False) try: #open a csv file for saving tracking data with open(self.vt_file, 'a') as csvfile: #create a writer vidwriter = csv.writer(csvfile, dialect='excel-tab') #check if it's an empty file for row in self.vidbuffer: vidwriter.writerow(row) except: pass record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton) #set the icon for the action self.action_Record.setIcon(record_icon) def update_frame(self, image): self.raw_label.setPixmap(QPixmap.fromImage(image)) def update_threshed(self, threshed_image): self.threshed_label.setPixmap(QPixmap.fromImage(threshed_image)) def clear_threshed(self): self.green_frame = np.zeros_like(self.green_frame) self.red_frame = np.zeros_like(self.red_frame) def overlay_threshed(self): if self.overlay: self.overlay = False elif not self.overlay: self.overlay = True # def sort_now(self): # # if self.recdir is not None: # os.chdir('./kilosort_control') # #create and show the main window # self.sort_frame = kilosort_control.sort_gui.MainWindow() # self.sort_frame.show() # # #set up stream for stdout and stderr based on outputStream class # self.outputStream = kilosort_control.sort_gui.outputStream() # #when outputStream sends messages, connect to appropriate function for # #writing to terminal window # self.outputStream.message.connect(self.sort_frame.print_message) # # #connect stdout and stderr to outputStream # sys.stdout = self.outputStream # sys.stderr = self.outputStream # # self.sort_frame.run_now(self.recdir) # # self.close() def get_info(self): self.info_window = QWidget() self.info_window.resize(400, 350) #set title self.info_window.setWindowTitle('Session Info') #give layout info_layout = QVBoxLayout(self.info_window) with open('info_fields.pickle', 'rb') as f: default_fields = pickle.load(f) f.close() #set label for pic_resolution setting experimenter_label = QLabel('Experimenter:') #make a QLineEdit box for displaying/editing settings experimenter = QComboBox(self.info_window) experimenter.setEditable(True) experimenter.addItems(default_fields['experimenter']) #add label and box to current window info_layout.addWidget(experimenter_label) info_layout.addWidget(experimenter) #set label for pic_resolution setting whose_animal_label = QLabel('Whose animal?') #make a QLineEdit box for displaying/editing settings whose_animal = QComboBox(self.info_window) whose_animal.setEditable(True) whose_animal.addItems(default_fields['whose_animal']) #add label and box to current window info_layout.addWidget(whose_animal_label) info_layout.addWidget(whose_animal) animal_number_label = QLabel('Animal number:') animal_number = QComboBox(self.info_window) animal_number.setEditable(True) animal_number.addItems(default_fields['animal_number']) info_layout.addWidget(animal_number_label) info_layout.addWidget(animal_number) session_number_label = QLabel('Session number:') session_number = QTextEdit(self.info_window) session_number.setText('1') info_layout.addWidget(session_number_label) info_layout.addWidget(session_number) session_type_label = QLabel('Session type:') session_type = QComboBox(self.info_window) session_type.setEditable(True) session_type.addItems(default_fields['session_type']) info_layout.addWidget(session_type_label) info_layout.addWidget(session_type) def save_info(self): info_fields = {} info_fields['experimenter'] = [ experimenter.itemText(i) for i in range(experimenter.count()) ] info_fields['whose_animal'] = [ whose_animal.itemText(i) for i in range(whose_animal.count()) ] info_fields['animal_number'] = [ animal_number.itemText(i) for i in range(animal_number.count()) ] info_fields['session_type'] = [ session_type.itemText(i) for i in range(session_type.count()) ] with open('info_fields.pickle', 'wb') as f: pickle.dump(info_fields, f, protocol=2) f.close() current_experimenter = str(experimenter.currentText()) current_whose_animal = str(whose_animal.currentText()) current_animal_number = str(animal_number.currentText()) current_session_number = str(session_number.toPlainText()) current_session_type = str(session_type.currentText()) recdir = data_save_dir + current_whose_animal + '/' + current_animal_number if not os.path.exists(recdir): os.makedirs(recdir) self.experiment_info = '###### Experiment Info ######\r\n' self.experiment_info += 'Experimenter: %s\r\n' % current_experimenter self.experiment_info += 'Whose animal? %s\r\n' % current_whose_animal self.experiment_info += 'Animal number: %s\r\n' % current_animal_number self.experiment_info += 'Session number: %s\r\n' % current_session_number self.experiment_info += 'Session type: %s\r\n' % current_session_type self.experiment_info = self.experiment_info.encode() config_file = config_path + '/' + current_animal_number + '.xml' if not os.path.exists(config_file): shutil.copy(default_config, config_file) tree = et.parse(config_file) root = tree.getroot() for child in root: if child.tag == 'CONTROLPANEL': child.attrib['recordPath'] = recdir.replace('/', '\\') tree.write(config_file) tree.write(default_config) self.info_window.close() self.noinfo = False ready_button = QPushButton('Ready!') ready_button.clicked.connect(lambda: save_info(self)) info_layout.addWidget(ready_button) self.info_window.show()
class MainWindow(QMainWindow, Ui_MainWindow): add_name_signal = Signal(unicode) def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) # Create the name manager instance and move it to another thread. # This will cause all the slots to be run in that other thread # instead of our GUI thread. self.name_manager = NameManager() self.name_manager_thread = QThread() self.name_manager.moveToThread(self.name_manager_thread) self.name_manager_thread.start() # Create our network manager self.network_manager = NetworkManager() # When the name manager emits it's full name list, we want to # repopulate our list. self.name_manager.names_signal.connect(self.populate_list) # When the restore list button is clicked, let the name manager # know we need all the names in long term storage self.restore_list_button.clicked.connect(self.name_manager.get_all_names) self.add_name_signal.connect(self.name_manager.store_name) self.add_name_signal.connect(self.cache_name) self.submit_button.clicked.connect(self.say_hello) self.clear_list_button.clicked.connect(self.clear_list) def clean_up(self): """ You can't rely on __del__ properly closing down all your threads. So use a clean_up method that will be called manually. :return: """ if hasattr(self, 'network_manager_thread'): self.network_manager.api.end_connection() self.network_manager.api.join() self.network_manager_thread.quit() self.name_manager_thread.quit() def start_api(self, ip, port): """ Connect to an external API service which will send us names :param ip: IP address of server :param port: Port of service :return: """ self.network_manager_thread = QThread() self.network_manager.moveToThread(self.network_manager_thread) self.network_manager.message_signal.connect(self.handle_message) self.network_manager_thread.start() self.network_manager.connect_signal.emit(ip, port) @Slot() def handle_message(self, message): """ Handle incoming names from the API. We simply want to follow the established procedure to add a new name. So we just emit on that signal. :param message: String name :return: """ self.add_name_signal.emit(message) @Slot() def say_hello(self): self.add_name_signal.emit(self.name_text.text()) self.hello_label.setText(u"{} {}".format(GREETING, self.name_text.text())) self.name_text.setText('') @Slot() def cache_name(self, name): self.names_list.addItem(name) @Slot() def clear_list(self): self.names_list.clear() @Slot() def populate_list(self, names): """ Clears and repopulates the list with the given list :param names: List of names :return: """ self.clear_list() for name in names: self.names_list.addItem(name)
class SyncWindow(QMainWindow): """ Application main window. This class is meant to handle every widget needed by the application, as well as other needed global objects and behavior. """ failedLogIn = Signal() syncStarted = Signal() loginRequested = Signal((str, str,)) statusChanged = Signal((str, str, int,)) def __init__(self, parent=None): super(SyncWindow, self).__init__(parent) # Sets up several UI aspects self.tray = QSystemTrayIcon(self) self.tray.setIcon(QIcon(QPixmap(':/resources/icon.png'))) self.tray.show() self.setStyleSheet('SyncWindow {background: white}') self.setWindowTitle('IQBox') self.setWindowIcon(QIcon(QPixmap(':/resources/logobar.png'))) self.statusBar().setFont(View.labelsFont()) self.syncThread = None # Initializes the window with a `LoginView` widget. self.loginView() def loginView(self): """ Initializes a `LoginView` object and sets it up as the main window's central widget. """ login = LoginView() login.login.connect(self.onLogin) self.failedLogIn.connect(login.onFailedLogIn) self.setCentralWidget(login) self.setFixedSize(login.size()) self.statusBar().hide() def syncView(self): """ Initializes a `SyncView` object and sets it up as the main window's central widget. """ syncview = SyncView() self.setCentralWidget(syncview) self.setFixedSize(syncview.size()) self.statusBar().show() self.statusChanged.connect(syncview.status.setMessage) syncview.sync.connect(self.onSync) @Slot(str, str, str, bool) def onLogin(self, host, username, passwd, ssl): """ Slot. Triggers a log in request to the server. :param host: Indicates the hostname of the FTP server :param username: Username to log in into the FTP server :param passwd: Password to log in into the FTP server :param ssl: Indicates whether the FTP needs SSL support """ self.sync = Sync(host, ssl) self.syncStarted.connect(self.sync.initQueue) self.sync.server.downloadProgress.connect(self.onDownloadProgress) self.sync.server.uploadProgress.connect(self.onUploadProgress) self.sync.server.fileEvent.connect(self.onFileEvent) self.sync.server.badFilenameFound.connect(self.badNameWarning) self.sync.server.loginCompleted.connect(self.onLoginCompleted) self.sync.server.fileEventCompleted.connect(self.onFileEventCompleted) self.sync.server.ioError.connect(self.onIOError) # Added by Si self.sync.server.textStatus.connect(self.setStatus) self.sync.statusChanged.connect(self.setStatus) self.loginRequested.connect(self.sync.server.onLogin) self.syncThread = QThread() self.sync.moveToThread(self.syncThread) self.syncThread.start() QApplication.instance().lastWindowClosed.connect(self.syncThread.quit) self.loginRequested.emit(username, passwd) @Slot(bool, str) def onLoginCompleted(self, ok, msg): if not ok: self.showMessageBox(msg) self.failedLogIn.emit() else: self.syncView() @Slot() def onFileEventCompleted(self): # Workaround because there's an exception # when there's a file IO error # Ideally it should be managed elsewhere # But I don't know the code intimately enough yet. try: self.currentFile except AttributeError: self.currentFile = '' self.statusChanged.emit('Completed', self.currentFile, 100) @Slot(str) def onSync(self, localdir): """ Slot. Triggers a server checkout. :param localdir: Absolute local directory path where to keep the files """ self.sync.setLocalDir(localdir) self.sync.local.ioError.connect(self.onIOError) self.syncStarted.emit() self.setStatus('Syncing') def showMessageBox(self, msg): warning = QMessageBox(self) warning.setFont(View.labelsFont()) warning.setStyleSheet('QMessageBox {background: white}') warning.setWindowTitle("Error") warning.setText(msg) warning.setIcon(QMessageBox.Warning) warning.addButton("Ok", QMessageBox.AcceptRole).setFont(View.editsFont()) warning.exec_() @Slot(int, int) def onProgress(self, action, total, progress): """ Slot. Triggers download progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ if progress <= 0: return else: percent = (progress * 100) / total self.statusChanged.emit(action, self.currentFile, percent) @Slot(str) def setStatus(self, msg): self.statusChanged.emit(msg, '', 0) @Slot(int, int) def onDownloadProgress(self, total, progress): """ Slot. Triggers upload progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ self.onProgress('Downloading', total, progress) @Slot(int, int) def onUploadProgress(self, total, progress): """ Slot. Triggers download progress update in the UI. :param total: Total size of the download in bytes :param progress: Current downdload progress in bytes """ self.onProgress('Uploading', total, progress) @Slot(str) def onFileEvent(self, filename): """ Slot. Updates the current download filename to be used in the UI :param filename: Name of the file that is being downloaded """ self.currentFile = filename @Slot(str) def onIOError(self, filename): self.showMessageBox('Error reading: "{}"'.format(filename)) @Slot(str) def badNameWarning(self, filename): self.showMessageBox( 'Will not sync "{}". Invalid filename'.format(filename))