| 
					
				 | 
			
			
				@@ -0,0 +1,119 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import sys,os,subprocess,time,traceback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import random 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from PySide2 import QtCore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from PySide2.QtWidgets import * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from PySide2.QtGui import * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class Worker(QtCore.QRunnable): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Worker thread for running background tasks.""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def __init__(self, fn, *args, **kwargs): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        super(Worker, self).__init__() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # Store constructor arguments (re-used for processing) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.fn = fn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.args = args 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.kwargs = kwargs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.signals = WorkerSignals() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.kwargs['progress_callback'] = self.signals.progress 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @QtCore.Slot() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def run(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result = self.fn( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                *self.args, **self.kwargs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        except: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            traceback.print_exc() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            exctype, value = sys.exc_info()[:2] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.signals.error.emit((exctype, value, traceback.format_exc())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.signals.result.emit(result) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        finally: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.signals.finished.emit() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class WorkerSignals(QtCore.QObject): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Defines the signals available from a running worker thread. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Supported signals are: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    finished 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        No data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        `tuple` (exctype, value, traceback.format_exc() ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        `object` data returned from processing, anything 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    finished = QtCore.Signal() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    error = QtCore.Signal(tuple) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = QtCore.Signal(object) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    progress = QtCore.Signal(int) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class App(QDialog): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """GUI Application using PySide2 widgets""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def __init__(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        QDialog.__init__(self) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.setAttribute(QtCore.Qt.WA_DeleteOnClose) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.setGeometry(QtCore.QRect(200, 200, 500, 500)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.threadpool = QtCore.QThreadPool() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        layout = QVBoxLayout(self) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.setLayout(layout) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.startbutton = QPushButton('START') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.startbutton.clicked.connect(self.run) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        layout.addWidget(self.startbutton) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.stopbutton = QPushButton('STOP') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.stopbutton.clicked.connect(self.stop) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        layout.addWidget(self.stopbutton) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.progressbar = QProgressBar(self) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.progressbar.setRange(0,1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        layout.addWidget(self.progressbar) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.info = QTextEdit(self) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.info.append('Hello') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        layout.addWidget(self.info) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def progress_fn(self, msg): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        """Update progress""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.info.append(str(msg))         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def run_threaded_process(self, process, progress_fn, on_complete): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        """Execute a function in the background with a worker""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        worker = Worker(fn=process) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.threadpool.start(worker) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        worker.signals.finished.connect(on_complete) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        worker.signals.progress.connect(progress_fn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.progressbar.setRange(0,0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def run(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        """call process""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.stopped = False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.run_threaded_process(self.test, self.progress_fn, self.completed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def stop(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.stopped=True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def completed(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.progressbar.setRange(0,1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def test(self, progress_callback): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        """Do some process here""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        total = 500 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for i in range(0,total): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            time.sleep(.2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            x = random.randint(1,1e4) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            progress_callback.emit(x) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if self.stopped == True: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+app = QApplication([]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+xapp = App() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+xapp.show() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+sys.exit(app.exec_()) 
			 |