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
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 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()