class SerialThread(QThread): # define a signal, when cam opens, emit this signal def __init__(self): super(SerialThread, self).__init__() # self.tnum = num self.isstop = True self.cond = QWaitCondition() self.mutex = QMutex() # self.sensor = ControlBoard() def __del__(self): # 线程状态改变与线程终止 self.isstop = True self.quit() def pause(self): # print("thread pause") self.isstop = True def resume(self): self.isstop = False self.cond.wakeAll() def run(self): pass
class LoadingBarThread(QThread): change_value = pyqtSignal(int) def __init__(self, parent, limit): QThread.__init__(self) self.cond = QWaitCondition() self.mutex = QMutex() self.is_running = True self.limit = limit self.parent = parent def __del__(self): self.wait() def run(self): self.cnt = 0 while True: self.mutex.lock() if not self.is_running: self.cond.wait(self.mutex) if self.cnt == self.limit: self.toggle_status() self.cnt += 1 self.change_value.emit(self.cnt) self.msleep(10) self.mutex.unlock() def toggle_status(self): self.is_running = not self.is_running if self.is_running: self.cond.wakeAll()
class ConsoleInitThread(QObject): initialized = pyqtSignal(object, object) def __init__(self, *args, **kwargs): super(ConsoleInitThread, self).__init__(*args, **kwargs) self.mutex = QMutex() self.wait_condition = QWaitCondition() def run(self): self.mutex.lock() kernel_manager = QtKernelManager(kernel_name="""python3""") kernel_manager.start_kernel() kernel_client = kernel_manager.client() kernel_client.start_channels() # notify to update ui self.initialized.emit(kernel_manager, kernel_client) # wait for exit self.wait_condition.wait(self.mutex) self.mutex.unlock() # stop channels and kernel kernel_client.stop_channels() kernel_manager.shutdown_kernel() def stop(self): self.wait_condition.wakeAll()
class SharedData: """ Provides access to shared data between Window and Classifier """ def __init__(self): self._mutex = QMutex() self._data = None self._data_available = QWaitCondition() def consume(self): self._mutex.lock() if self._data is None: self._data_available.wait(self._mutex) result = self._data self._data = None self._mutex.unlock() return result def provide(self, data): self._mutex.lock() self._data = data self._data_available.wakeAll() self._mutex.unlock()
class WorkerThread(QThread): def __init__(self): QThread.__init__(self) self.cond = QWaitCondition() self.mutex = QMutex() self._status = False self.userID = "" def __del__(self): self.wait() def run(self): while True: self.mutex.lock() print("start thread") if not self._status: self.cond.wait(self.mutex) #print(userID) recordingSnd.recording(self.userID) print("going to another work") self.msleep(100) self.mutex.unlock() def toggle_status(self, userID): self.userID = userID self._status = not self._status if self._status: self.cond.wakeAll() @property def status(self): return self._status
class Thread(QThread): valueChange = pyqtSignal(int) def __init__(self, *args, **kwargs): super(Thread, self).__init__(*args, **kwargs) self._isPause = False self._value = 0 self.cond = QWaitCondition() self.mutex = QMutex() def pause(self): self._isPause = True def resume(self): self._isPause = False self.cond.wakeAll() def run(self): while 1: self.mutex.lock() if self._isPause: self.cond.wait(self.mutex) if self._value > 100: self._value = 0 self._value += 1 self.valueChange.emit(self._value) self.msleep(100) self.mutex.unlock()
class Thread(QThread): signal_update = pyqtSignal() def __init__(self, window): QThread.__init__(self) self.cond = QWaitCondition() self.mutex = QMutex() self.cnt = 0 self._status = True self.window = window self.logger = Logger(window) def __del__(self): self.wait() def run(self): while True: self.mutex.lock() if not self._status: self.cond.wait(self.mutex) # self.logger.print_log("working auto bot") self.msleep(1000) # ※주의 QThread에서 제공하는 sleep을 사용 self.signal_update.emit() self.mutex.unlock() def toggle_status(self): self._status = not self._status if self._status: self.cond.wakeAll() @property def status(self): return self._status
class DownloadManager(QThread): imagesLoaded = QtCore.pyqtSignal(list) downloadFailed = QtCore.pyqtSignal(list) allDownloaded = QtCore.pyqtSignal() downloadPaused = QtCore.pyqtSignal() downloadResumed = QtCore.pyqtSignal() exceptionRaised = QtCore.pyqtSignal(str) def __init__(self, app_state): super().__init__() self.mutex = QMutex() self.download_paused = False self.wait_condition = QWaitCondition() self.stateful_downloader = StatefulDownloader(app_state) self._has_started = False def run(self): try: self._has_started = True stateful_downloader = self.stateful_downloader for result in stateful_downloader: self.imagesLoaded.emit(result.succeeded_urls) self.downloadFailed.emit(result.failed_urls) if self.download_paused: self.downloadPaused.emit() self.mutex.lock() self.wait_condition.wait(self.mutex) self.mutex.unlock() self.allDownloaded.emit() except WordNetIdsUnavailableError: msg = 'Failed to fetch a list of WordNet ids. ' \ 'Check if ImageNet server can be reached' self.exceptionRaised.emit(msg) def pause_download(self): self.mutex.lock() self.download_paused = True self.mutex.unlock() def resume_download(self): if not self._has_started: self.start() return self.mutex.lock() self.download_paused = False self.mutex.unlock() self.wait_condition.wakeAll() self.downloadResumed.emit()
class ProjectedImageBuffer(object): """ Class for synchronizing processing threads from different cameras. """ def __init__(self, drop_if_full=True, buffer_size=8): self.drop_if_full = drop_if_full self.buffer = Buffer(buffer_size) self.sync_devices = set() self.wc = QWaitCondition() self.mutex = QMutex() self.arrived = 0 self.current_frames = dict() def bind_thread(self, thread): with QMutexLocker(self.mutex): self.sync_devices.add(thread.device_id) name = thread.camera_model.camera_name shape = settings.project_shapes[name] self.current_frames[thread.device_id] = np.zeros( shape[::-1] + (3, ), np.uint8) thread.proc_buffer_manager = self def get(self): return self.buffer.get() def set_frame_for_device(self, device_id, frame): if device_id not in self.sync_devices: raise ValueError( "Device not held by the buffer: {}".format(device_id)) self.current_frames[device_id] = frame def sync(self, device_id): # only perform sync if enabled for specified device/stream self.mutex.lock() if device_id in self.sync_devices: # increment arrived count self.arrived += 1 # we are the last to arrive: wake all waiting threads if self.arrived == len(self.sync_devices): self.buffer.add(self.current_frames, self.drop_if_full) self.wc.wakeAll() # still waiting for other streams to arrive: wait else: self.wc.wait(self.mutex) # decrement arrived count self.arrived -= 1 self.mutex.unlock() def wake_all(self): with QMutexLocker(self.mutex): self.wc.wakeAll() def __contains__(self, device_id): return device_id in self.sync_devices def __str__(self): return (self.__class__.__name__ + ":\n" + \ "devices: {}\n".format(self.sync_devices))
class SerialReadThread(QThread): """ 시리얼 연결이 성공하면 항상 데이터를 수신할 수 있어야 하므로 스레드로 만들어야 한다. """ # 사용자 정의 시그널 선언 # 받은 데이터 그대로를 전달 해주기 위해 QByteArray 형태로 전달 received_data = pyqtSignal(QByteArray, name="receivedData") def __init__(self, serial): QThread.__init__(self) self.cond = QWaitCondition() self._status = False self.mutex = QMutex() self.serial = serial def __del__(self): self.wait() def run(self): """ 들어온 데이터가 있다면 시그널을 발생 :return: """ while True: self.mutex.lock() if not self._status: self.cond.wait(self.mutex) buf = self.serial.readAll() if buf: #print(buf) buf = bytes("Received : ", "utf-8") + binascii.hexlify(buf) + bytes( [0x0A]) # '0x0A(LF)' self.received_data.emit(buf) self.usleep(1) #buf = bytes([0x0A]) #self.received_data.emit(buf) self.mutex.unlock() def toggle_status(self): self._status = not self._status if self._status: self.cond.wakeAll() @pyqtSlot(bool, name='setStatus') def set_status(self, status): self._status = status if self._status: self.cond.wakeAll()
class Classifier(QThread): signal_classify_done = pyqtSignal(str) def __init__(self): super().__init__() self._mutex = QMutex() self._abort = False self._condition = QWaitCondition() self.cur_img = None # load model and default graph self.classifier = keras.models.load_model('resnet_512.h5') self.graph = tf.get_default_graph() # REALLY IMPORTANT def __del__(self): self._abort = True self.wait() def activate(self, img_np_arr): self.cur_img = img_np_arr print(type(self.cur_img)) print(self.cur_img.shape) self._condition.wakeAll() def run(self): while True: if self._abort: return self._mutex.lock() self._condition.wait(self._mutex) # Doing thing if self.cur_img is None: continue # classify top3 x = np.asarray([self.cur_img]) res = '' with self.graph.as_default(): predictions = self.classifier.predict( x, batch_size=1)[0] # note that predictions is a 2D array idx_max = np.argsort(predictions) top3 = idx_max[-1:-4:-1] for idx in top3: res += '%s:%.2f,' % (classes_reader[idx], predictions[idx]) # emit signal self.signal_classify_done.emit(res) # DONE DOING THING self._mutex.unlock()
class ThreadCapture(QThread): """ 단순히 0부터 100까지 카운트만 하는 쓰레드 값이 변경되면 그 값을 change_value 시그널에 값을 emit 한다. """ # 사용자 정의 시그널 선언 captured_screen = pyqtSignal(QPixmap, name="capturedScreen") def __init__(self): QThread.__init__(self, parent=None) self.cond = QWaitCondition() self.mutex = QMutex() self.cnt = 0 self._status = True def __del__(self): self.wait() def run(self): while True: self.mutex.lock() if not self._status: self.cond.wait(self.mutex) pixmap = self.capture() self.captured_screen(pixmap) self.msleep(100) # ※주의 QThread에서 제공하는 sleep을 사용 self.mutex.unlock() def capture(self): screen: QScreen = QGuiApplication.primaryScreen() window: QWindow = self.windowHandle() if window: screen = window.screen() if not screen: return pixmap = screen.grabWindow(0) return pixmap def toggle_status(self): self._status = not self._status if self._status: self.cond.wakeAll() @property def status(self): return self._status
class SerialWriteThread(QThread): # ######################################################################################### # initialize # ######################################################################################### def __init__(self, serial, write_queue: queue.Queue): QThread.__init__(self) self.cond = QWaitCondition() self.mutex = QMutex() self._status = False self.serial = serial self.write_queue = write_queue def __del__(self): self.wait() # ######################################################################################### # 쓰레드 시작 # ######################################################################################### def run(self): while True: self.mutex.lock() if not self._status: # 하위 실행 안됨 self.cond.wait(self.mutex) if not self.write_queue.empty(): self.serial.write(self.write_queue.get()) self.usleep(1) self.mutex.unlock() # ######################################################################################### # 쓰레드 활성/비화성 # ######################################################################################### @pyqtSlot(bool) def set_status(self, status): self._status = status if self._status: self.cond.wakeAll()
class SchedImportThread(QThread): message = pyqtSignal() def __init__(self, config): super(self.__class__, self).__init__() self.working = True self._config = config hh_mm = config.get('sched', 'time', fallback='18:00') x = hh_mm.split(':') self.hour = int(x[0]) self.minute = int(x[1]) self.cond = QWaitCondition() self.mutex = QMutex() def stop(self): if self.working: self.working = False self.cond.wakeAll() self.wait() def __del__(self): self.stop() def next_time_delta(self): now = Datetime.now() next_time = Datetime(now.year, now.month, now.day, self.hour, self.minute) if next_time < now: current_date = Datetime(now.year, now.month, now.day) if current_date.day_of_week() == 5: next_time = next_time + TimeDelta(3) else: next_time = next_time + TimeDelta(1) return (next_time, next_time - now) @hku_catch() def run(self): self.mutex.tryLock() next_datetime, delta = self.next_time_delta() self.logger.info("下次导入时间:{}".format(next_datetime)) delta = int(delta.total_milliseconds()) while self.working and not self.cond.wait(self.mutex, int(delta)): self.message.emit() next_datetime, delta = self.next_time_delta() self.logger.info("下次导入时间:{}".format(next_datetime)) delta = int(delta.total_milliseconds())
class RecordWindow(WindowBase, WindowUI): def __init__(self, parent=None): WindowBase.__init__(self, parent) self.mutex = QMutex() self.condition = QWaitCondition() self.mutex.lock() self.setupUi(self) self.recording = False logging.info("Initializing Manager......") self.manager = Manager(self.mutex, self.condition) logging.info("Connecting events.......") self.startStopButton.clicked.connect(self.onStartStopButtonPress) self.manager.connectEvents(timerEvent=self.timerEvent, videoFrameEvent=self.setFrame) self.manager.startVideo() def onStartStopButtonPress(self): if self.recording: self.manager.stopRecording() self.startStopButton.setText('start recording') else: self.manager.startRecording() self.startStopButton.setText("stop recording") self.recording = not self.recording def setFrame(self, frame): self.mutex.lock() try: w = self.videoScreen.width() - 1 h = self.videoScreen.height() - 1 pixmap = QtGui.QPixmap.fromImage(frame) self.videoScreen.setPixmap( pixmap.scaled(w, h, QtCore.Qt.KeepAspectRatio, QtCore.Qt.FastTransformation)) self.videoScreen.setMinimumSize(1, 1) finally: self.mutex.unlock() self.condition.wakeAll() def timerEvent(self): elapsedTime = self.manager.getElapsedTime() self.timerWindow.setText(elapsedTime.toString("mm:ss:zzz")[:8])
class SerialReadThread(QThread): """ Should use QThread, because data always are transferred after connecting serial communication """ #Custom Signal #transfer QByteArray type for communicating received data with same type def __init__(self, serial): QThread.__init__(self) self.cond = QWaitCondition() self._status = False self.mutex = QMutex() self.serial = serial def __del__(self): self.wait() def run(self): """ if there is input data, generate signal :return: """ while True: self.mutex.lock() if not self._status(): self.cond.wait(self.mutex) buf = self.serial.readAll() if buf: self.received_data.emit(buf) self.usleep(1) self.mutex.unlock() def toggle_status(self): self._status = not self._status if self._status: self.cond.wakeAll() @pyqtSlot(bool, name='setStatus') def set_status(self, status): self._status = status if self._status: self.cond.wakeAll()
class LoadingBarThread(QThread): change_value = pyqtSignal(int) complete = pyqtSignal() def __init__(self, parent): QThread.__init__(self) self.cond = QWaitCondition() self.mutex = QMutex() self._status = True self.parent = parent def __del__(self): self.wait() def run(self): self.cnt = 0 while True: self.mutex.lock() if not self._status: self.cond.wait(self.mutex) if 50 == self.cnt: self.toggle_status() if 100 == self.cnt: self.cnt = 0 self.complete.emit() self.cnt += 1 self.change_value.emit(self.cnt) self.msleep(10) self.mutex.unlock() def toggle_status(self): self._status = not self._status if self._status: self.cond.wakeAll() @property def status(self): return self._status
class EventThread(QThread): exeCnt = 0 event = None def __init__(self, event): QThread.__init__(self) self.cond = None self.mutex = None self._status = True self.event = event def __del__(self): self.wait() def run(self): self.cond = QWaitCondition() self.mutex = QMutex() self.mutex.lock() # self.msleep(100) if not self._status: self.cond.wait(self.mutex) try: self.event() except Exception as e: print(e) finally: self.mutex.unlock() def toggle_status(self): self._status = not self._status if self._status: self.cond.wakeAll() @property def status(self): return self._status def stop(self): self.terminate()
class Thread(QThread): """ # 단순히 0부터 100까지 카운트만 하는 쓰레드 # 값이 변경되면 그 값을 change_value 시그널에 값을 emit 한다. """ # 사용자 정의 시그널 선언 change_value = pyqtSignal(int) def __init__(self): # QThread.__init__(self) super().__init__() self.cond = QWaitCondition() self.mutex = QMutex() self.cnt = 0 self._status = True def __del__(self): self.wait() def run(self): while True: self.mutex.lock() if not self._status: self.cond.wait(self.mutex) if 100 == self.cnt: self.cnt = 0 self.cnt += 1 self.change_value.emit(self.cnt) self.msleep(100) # ※주의 QThread에서 제공하는 sleep을 사용 self.mutex.unlock() def toggle_status(self): self._status = not self._status if self._status: self.cond.wakeAll() @property def status(self): return self._status
class ReturnValue(Generic[T]): """Pass a return value from a slot back to the signal emitting thread. The ReturnValue has to be send with the signal, the receiving thread than calls .send() to set the value, while the calling thread calls .receive() to wait until the value arrives.""" def __init__(self) -> None: self._mutex = QMutex() self._wait_condition = QWaitCondition() self._value: Optional[T] = None def receive(self) -> T: self._mutex.lock() while self._value is None: self._wait_condition.wait(self._mutex) self._mutex.unlock() return self._value def send(self, value: T) -> None: self._value = value self._wait_condition.wakeAll()
class Thread(QThread): valueChange = pyqtSignal(int) id_pipLine = pyqtSignal(list) task_finished = pyqtSignal() def __init__(self, results, *args, **kwargs): super(Thread, self).__init__(*args, **kwargs) # results 是从raw_datas查询的所有数据 一般以城市为条件查询 self.results = results self._isPause = True self._value = 1 self.cond = QWaitCondition() self.mutex = QMutex() def next(self): print("下一组数据") self._isPause = False self.cond.wakeAll() self._isPause = True def run(self): while True: self.mutex.lock() if self._isPause: for i in self.results: id = i[0] company_id = i[1] job_id = i[2] item = [id, company_id, job_id] # print(item) self.id_pipLine.emit(item) self.cond.wait(self.mutex) if self._value == len(self.results): self.task_finished.emit() print('第{}组'.format(self._value)) self.valueChange.emit(self._value) self._value += 1 self.mutex.unlock()
class WaitingData: def __init__(self): self.logger = logging.getLogger(constants.General.NAME) self.__mutex = QMutex() self.__condition = QWaitCondition() self.__data = None def wait(self): self.__mutex.lock() self.logger.debug(f'Lock: {self}') self.__condition.wait(self.__mutex) def wakeup(self, *args): self.__condition.wakeAll() self.__data = args self.logger.debug(f'Unlock: {self}. Data: {args}') def get_data(self) -> Optional[tuple]: return self.__data
class LogMultiThread(QThread): logViewFinished = pyqtSignal(list) logPagingFinished = pyqtSignal() def __init__(self, ip, tp, guid='', icnt_list=[]): QThread.__init__(self) self.cond = None self.mutex = None self._status = True self.ip = ip self.tp = tp self.guid = guid self.icnt_list = icnt_list def __del__(self): self.wait() def run(self): self.cond = QWaitCondition() #self.mutex = QMutex() #self.mutex.lock() #if not self._status: # self.cond.wait(self.mutex) try: log_view = [] for ix, icnt in enumerate(self.icnt_list): swgs_url = 'http://172.31.196.21:8060/websquare/Service/SVC?commonsvc=0&rtcode=0&Trx_code=ZORDSCOM06020_TR01&ScreenName=ZORDSCOM06020&fCloseAccount=0&LogLvlGbn=&G_BizCd=null&G_Biz_Start_Time=null&__smReqSeq=5&_useLayout=true' payload = {"input1": [{"fcnt": "0", "flag": "L", "guid": self.guid, "icnt": icnt, "ip_addr": self.ip, "rowStatus": "C", "tp_id": self.tp, "prod_skip": "N"}], "HEAD": {"Trx_Code": "ZORDSCOM06020_TR01", "Ngms_UserId": "1000852323", "Ngms_LogInId": "ENJOYHAN", "Ngms_EmpNum": "", "Ngms_OrgId": "A000700000", "Ngms_HrOrgCd": "", "Ngms_PostOrgCd": "A000700000", "Ngms_PostSaleOrgCd": "A000700000", "Ngms_SupSaleOrgCd": "A010890000", "Ngms_IpAddr": "150.28.65.76", "Ngms_BrTypCd": "450", "Ngms_AuthId": "", "Ngms_ConnOrgId": "A000700000", "Ngms_ConnOrgCd": "A000700000", "Ngms_ConnSaleOrgId": "A000700000", "Ngms_ConnSaleOrgCd": "A000700000", "Ngms_AuthTypPermCd": "EQ", "Ngms_PostSaleOrgId": "A000700000", "Ngms_SupSaleOrgId": "A010890000", "Term_Type": "0", "User_Term_Type": "", "St_Stop": "0", "St_Trace": "", "Stx_Dt": "", "Stx_Tm": "", "Etx_Dt": "", "Etx_Tm": "", "Rt_Cd": "", "Screen_Name": "ZORDSCOM06020", "Msg_Cnt": "0", "Handle_Id": "863017520 ", "Ngms_Filler1": "", "Ngms_CoClCd": "T", "Screen_Call_Trace": "Top-ZORDSCOM06020-ZORDSCOM06020_TR01", "rowStatus": "C"}} log_view_result = requests.get(swgs_url, json=payload) log_view_temp = log_view_result.json() log_view.extend(log_view_temp['output1']) self.logPagingFinished.emit() print('{}번 조회완료'.format(icnt)) except Exception as e: print('log woker error') print(e) finally: self.logViewFinished.emit(log_view) pass def toggle_status(self): self._status = not self._status if self._status: self.cond.wakeAll() @property def status(self): return self._status def stop(self): self.terminate()
class VcsStatusMonitorThread(QThread): """ Class implementing the VCS status monitor thread base class. @signal vcsStatusMonitorData(list of str) emitted to update the VCS status @signal vcsStatusMonitorStatus(str, str) emitted to signal the status of the monitoring thread (ok, nok, op) and a status message """ vcsStatusMonitorData = pyqtSignal(list) vcsStatusMonitorStatus = pyqtSignal(str, str) def __init__(self, interval, project, vcs, parent=None): """ Constructor @param interval new interval in seconds (integer) @param project reference to the project object (Project) @param vcs reference to the version control object @param parent reference to the parent object (QObject) """ super(VcsStatusMonitorThread, self).__init__(parent) self.setObjectName("VcsStatusMonitorThread") self.setTerminationEnabled(True) self.projectDir = project.getProjectPath() self.project = project self.vcs = vcs self.interval = interval self.autoUpdate = False self.statusList = [] self.reportedStates = {} self.shouldUpdate = False self.monitorMutex = QMutex() self.monitorCondition = QWaitCondition() self.__stopIt = False def run(self): """ Public method implementing the tasks action. """ while not self.__stopIt: # perform the checking task self.statusList = [] self.vcsStatusMonitorStatus.emit( "wait", self.tr("Waiting for lock")) try: locked = self.vcs.vcsExecutionMutex.tryLock(5000) except TypeError: locked = self.vcs.vcsExecutionMutex.tryLock() if locked: try: self.vcsStatusMonitorStatus.emit( "op", self.tr("Checking repository status")) res, statusMsg = self._performMonitor() finally: self.vcs.vcsExecutionMutex.unlock() if res: status = "ok" else: status = "nok" self.vcsStatusMonitorStatus.emit( "send", self.tr("Sending data")) self.vcsStatusMonitorData.emit(self.statusList) self.vcsStatusMonitorStatus.emit(status, statusMsg) else: self.vcsStatusMonitorStatus.emit( "timeout", self.tr("Timed out waiting for lock")) if self.autoUpdate and self.shouldUpdate: self.vcs.vcsUpdate(self.projectDir, True) continue # check again self.shouldUpdate = False # wait until interval has expired checking for a stop condition self.monitorMutex.lock() if not self.__stopIt: self.monitorCondition.wait( self.monitorMutex, self.interval * 1000) self.monitorMutex.unlock() self._shutdown() self.exit() def setInterval(self, interval): """ Public method to change the monitor interval. @param interval new interval in seconds (integer) """ locked = self.monitorMutex.tryLock() self.interval = interval self.monitorCondition.wakeAll() if locked: self.monitorMutex.unlock() def getInterval(self): """ Public method to get the monitor interval. @return interval in seconds (integer) """ return self.interval def setAutoUpdate(self, auto): """ Public method to enable the auto update function. @param auto status of the auto update function (boolean) """ self.autoUpdate = auto def getAutoUpdate(self): """ Public method to retrieve the status of the auto update function. @return status of the auto update function (boolean) """ return self.autoUpdate def checkStatus(self): """ Public method to wake up the status monitor thread. """ locked = self.monitorMutex.tryLock() self.monitorCondition.wakeAll() if locked: self.monitorMutex.unlock() def stop(self): """ Public method to stop the monitor thread. """ locked = self.monitorMutex.tryLock() self.__stopIt = True self.monitorCondition.wakeAll() if locked: self.monitorMutex.unlock() def clearCachedState(self, name): """ Public method to clear the cached VCS state of a file/directory. @param name name of the entry to be cleared (string) """ key = self.project.getRelativePath(name) try: del self.reportedStates[key] except KeyError: pass def _performMonitor(self): """ Protected method implementing the real monitoring action. This method must be overridden and populate the statusList member variable with a list of strings giving the status in the first column and the path relative to the project directory starting with the third column. The allowed status flags are: <ul> <li>"A" path was added but not yet comitted</li> <li>"M" path has local changes</li> <li>"O" path was removed</li> <li>"R" path was deleted and then re-added</li> <li>"U" path needs an update</li> <li>"Z" path contains a conflict</li> <li>" " path is back at normal</li> </ul> @ireturn tuple of flag indicating successful operation (boolean) and a status message in case of non successful operation (string) @exception RuntimeError to indicate that this method must be implemented by a subclass """ raise RuntimeError('Not implemented') def _shutdown(self): """ Protected method performing shutdown actions. The default implementation does nothing. """ pass
class ValueLabelGui(QWidget): start_signal = QtCore.pyqtSignal() stop_signal = QtCore.pyqtSignal() def __init__(self, parent=None, window=None, devicewrapper=None): """ """ super(ValueLabelGui, self).__init__(parent=parent) self._init_ui(window) self._init_worker_thread(devicewrapper) def _init_ui(self, mainwindow): self.central_wid = QWidget(mainwindow) self._set_central_wid_properties() self.mainwindow = mainwindow self.mainwindow.setCentralWidget(self.central_wid) # grid layout to put all widgets self.wid_layout = QGridLayout() # ===================================================================== # control panel # ===================================================================== self.graphics_layout = QGridLayout() self.vl = pg.ValueLabel(formatStr='{avgValue:0.2f} {suffix}') self.vl.setValue(-1) self.graphics_layout.addWidget(self.vl, 0, 0, 4, 4) # ===================================================================== # control panel # ===================================================================== self.controls_layout = QGridLayout() # ===================================================================== # control buttons - layout # ===================================================================== self.startBtn = QPushButton('START') self.controls_layout.addWidget(self.startBtn, 0, 0, 1, 1) self.stopBtn = QPushButton('STOP') self.controls_layout.addWidget(self.stopBtn, 1, 0, 1, 1) # ===================================================================== # control buttons - connections # ===================================================================== self.startBtn.clicked.connect(self.start_thread) self.stopBtn.clicked.connect(self.stop_thread) # ============================================================ # put everything together # ============================================================ self.wid_layout.addItem(self.graphics_layout, 0, 0, 2, 2) self.wid_layout.addItem(self.controls_layout, 0, 2, 2, 2) # self.wid_layout.setColumnStretch(0, 10) # self.wid_layout.setColumnStretch(8, 2) self.central_wid.setLayout(self.wid_layout) def _set_central_wid_properties(self): """ """ self.central_wid.setAutoFillBackground(True) p = self.central_wid.palette() p.setColor(self.central_wid.backgroundRole(), QtCore.Qt.darkGray) self.central_wid.setPalette(p) def _init_worker_thread(self, devicewrapper): """ """ # Setup QWaitCondition self.mutex = QMutex() self.cond = QWaitCondition() # Setup the measurement engine # self.mthread = QtCore.QThread() self.worker = TimePlotWorker(devicewrapper, self.mutex, self.cond) # connect signal and slots self.start_signal.connect(self.worker.start) self.stop_signal.connect(self.worker.stop) self.worker.reading.connect(self.newReading) return def start_thread(self): self.start_signal.emit() def stop_thread(self): self.stop_signal.emit() def update_ValueLabel(self, val): """ """ self.vl.setValue(val) @QtCore.pyqtSlot(float) def newReading(self, val): """ """ pg.QtGui.QApplication.processEvents() self.update_ValueLabel(val) time.sleep(0.1) # necessary to avoid worker to freeze self.cond.wakeAll() # wake worker thread up return def closeEvent(self, event): reply = QMessageBox.question(self, 'Message', "Are you sure to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: event.accept() else: event.ignore()
class MyWidget(QWidget): def __init__(self): super(MyWidget, self).__init__() self.cur_path = os.path.split(os.path.realpath(__file__))[0] self.im_original = None self.mutex = QMutex() self.condition = QWaitCondition() self.cam_thread = CamThread(mutex=self.mutex, condition=self.condition) self.cam_thread.signal_im_ready.connect(self.set_im) self.cam_thread.signal_original_im_ready.connect(self.set_original_im) self.x0 = 0 self.y0 = 0 self.x1 = 0 self.y1 = 0 self.is_moving = False self.is_resizing = False self.is_capture = False self.confidence = 0.5 """ controls """ # layout self.hbox_main = QHBoxLayout(self) self.vbox_btns = QVBoxLayout(self) self.vbox_im = QHBoxLayout(self) self.hbox_who = QHBoxLayout(self) # button self.btn_save_image = QPushButton('Save Image', self) self.btn_train = QPushButton('Train', self) self.btn_load_image = QPushButton('Load Image \n And Recognize', self) self.btn_start_camera = QPushButton('Start Camera', self) self.btn_stop_camera = QPushButton('Stop Camera', self) self.btn_test = QPushButton('Test', self) size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.btn_save_image.setSizePolicy(size_policy) self.btn_train.setSizePolicy(size_policy) self.btn_load_image.setSizePolicy(size_policy) self.btn_start_camera.setSizePolicy(size_policy) self.btn_stop_camera.setSizePolicy(size_policy) self.btn_test.setSizePolicy(size_policy) # line text self.txb_who = QLineEdit("", self) # label self.lb_realtime = QLabel("", self) self.lb_template = QLabel("", self) self.lb_result = QLabel("", self) self.lb_who = QLabel('Who:', self) """ place controls to layout """ self.hbox_who.addWidget(self.lb_who) self.hbox_who.addWidget(self.txb_who) self.vbox_im.addWidget(self.lb_realtime, alignment=Qt.AlignTop) self.vbox_btns.addLayout(self.hbox_who) self.vbox_btns.addWidget(self.btn_save_image) self.vbox_btns.addWidget(self.btn_train) self.vbox_btns.addWidget(self.btn_load_image) self.vbox_btns.addWidget(self.btn_start_camera) self.vbox_btns.addWidget(self.btn_stop_camera) self.vbox_btns.addWidget(self.btn_test) self.hbox_main.addLayout(self.vbox_im) self.hbox_main.addLayout(self.vbox_btns) self.hbox_main.addWidget(self.lb_template, alignment=Qt.AlignHCenter) self.hbox_main.addWidget(self.lb_result, alignment=Qt.AlignHCenter) self.setLayout(self.hbox_main) """ connect signal and slot """ self.btn_save_image.clicked.connect(self.on_btn_save_image_clicked) self.btn_train.clicked.connect(self.on_btn_train_clicked) self.btn_load_image.clicked.connect(self.on_btn_load_image_clicked) self.btn_start_camera.clicked.connect(self.on_btn_start_camera_clicked) self.btn_stop_camera.clicked.connect(self.on_btn_stop_camera_clicked) self.btn_test.clicked.connect(self.on_btn_test_clicked) self.lb_realtime.mousePressEvent = self.on_lb_realtime_mouse_press self.lb_realtime.mouseMoveEvent = self.on_lb_realtime_mouse_move self.lb_realtime.mouseReleaseEvent = self.on_lb_realtime_mouse_release self.setWindowTitle('qt face recognition') self.show() self.btn_test.setVisible(False) @pyqtSlot('QImage') def set_im(self, image): self.mutex.lock() try: self.lb_realtime.setPixmap(QPixmap.fromImage(image)) finally: self.mutex.unlock() self.condition.wakeAll() @pyqtSlot(object) def set_original_im(self, cv_im): self.im_original = cv_im def on_lb_realtime_mouse_move(self, event): try: is_moving = True self.x1 = event.x() self.y1 = event.y() self.cam_thread.updateDrawingData(self.x0, self.y0, self.x1, self.y1, is_moving) except Exception as e: print(e) def on_lb_realtime_mouse_press(self, event): try: self.is_moving = False self.x0 = event.x() self.y0 = event.y() self.cam_thread.updateDrawingData(self.x0, self.y0, self.x1, self.y1, self.is_moving) except Exception as e: print(e) def on_lb_realtime_mouse_release(self, event): pass def closeEvent(self, event): print("[INFO] closed") self.cam_thread.update_is_capture(False) event.accept() def on_btn_load_image_clicked(self, _): self.load_image_and_recognize() def on_btn_save_image_clicked(self, _): if self.is_capture: self.save_image() else: print("[INFO] please start camera first") def on_btn_train_clicked(self, _): self.is_capture = False self.cam_thread.update_is_capture(self.is_capture) self.train() def on_btn_start_camera_clicked(self, _): if not self.is_capture: self.mutex.lock() self.is_capture = True self.cam_thread.update_is_capture(self.is_capture) self.cam_thread.my_face_recognizer.load_face_recognize_models() self.cam_thread.my_face_recognizer.load_face_detect_model() self.cam_thread.start() def on_btn_stop_camera_clicked(self, _): self.is_capture = False self.cam_thread.update_is_capture(self.is_capture) def on_btn_test_clicked(self, _): # self.cam_thread.my_face_recognizer.load_face_detect_model() # self.cam_thread.my_face_recognizer.load_face_recognize_models() pass def load_image_and_recognize(self): try: filter_by = "Image files (*.jpg *.jpeg *.png *.bmp *.tif *.tiff)" fname = QFileDialog.getOpenFileName(self, "Open file", os.getcwd(), filter_by)[0] if not fname == "": img = cv2.imread(fname, cv2.IMREAD_COLOR) img = imutils.resize(img, width=600) (h, w) = img.shape[:2] image_blob = cv2.dnn.blobFromImage( cv2.resize(img, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0), swapRB=False, crop=False) face_recognizer = FaceRecognizer() face_recognizer.load_face_recognize_models() face_recognizer.load_face_detect_model() detected_faces = face_recognizer.detect_faces(image_blob) index_face = 0 confidence = detected_faces[0, 0, index_face, 2] if confidence > face_recognizer.get_min_confidence(): box = detected_faces[0, 0, index_face, 3:7] * np.array([w, h, w, h]) (startX, startY, endX, endY) = box.astype("int") # extract the face ROI face = img[startY:endY, startX:endX] # (fH, fW) = face.shape[:2] # # ensure the face width and height are sufficiently large # if fW < 20 or fH < 20: # continue face_blob = cv2.dnn.blobFromImage(face, 1.0 / 255, (96, 96), (0, 0, 0), swapRB=True, crop=False) name, proba = face_recognizer.predict_name(face_blob) self.txb_who.setText(name) # draw the bounding box and probability text = "{}: {:.2f}%".format(name, proba * 100) y = startY - 10 if startY - 10 > 10 else startY + 10 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) cv2.rectangle(img, (startX, startY), (endX, endY), (255, 0, 0), 2) cv2.putText(img, text, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (255, 0, 0), 2) else: img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) q_img = QImage(img.data, img.shape[1], img.shape[0], QImage.Format_RGB888) q_img = q_img.scaled(640, 480, Qt.KeepAspectRatio) self.lb_realtime.setPixmap(QPixmap.fromImage(q_img)) self.lb_realtime.update() except Exception as e: print(e) def save_image(self): folder_path = self.cur_path + '/face_recognition_dataset/' + self.txb_who.text() if not os.path.exists(folder_path): os.makedirs(folder_path) num_images = 0 for (dirpath, dirnames, filenames) in walk(folder_path): for filename in filenames: filetype = filename.split(".")[-1] if filetype == "jpg": num_images += 1 str_number = '{:0>5d}'.format(num_images) image_path = folder_path + '/' + self.txb_who.text() + str_number + '.jpg' cv2.imwrite(image_path, self.im_original) print("[INFO] saved " + image_path) def train(self): self.cam_thread.my_face_recognizer.train_with_bo()
class VcsStatusMonitorThread(QThread): """ Class implementing the VCS status monitor thread base class. @signal vcsStatusMonitorData(list of str) emitted to update the VCS status @signal vcsStatusMonitorStatus(str, str) emitted to signal the status of the monitoring thread (ok, nok, op) and a status message @signal vcsStatusMonitorInfo(str) emitted to signal some info of the monitoring thread """ vcsStatusMonitorData = pyqtSignal(list) vcsStatusMonitorStatus = pyqtSignal(str, str) vcsStatusMonitorInfo = pyqtSignal(str) def __init__(self, interval, project, vcs, parent=None): """ Constructor @param interval new interval in seconds (integer) @param project reference to the project object (Project) @param vcs reference to the version control object @param parent reference to the parent object (QObject) """ super(VcsStatusMonitorThread, self).__init__(parent) self.setObjectName("VcsStatusMonitorThread") self.setTerminationEnabled(True) self.projectDir = project.getProjectPath() self.project = project self.vcs = vcs self.interval = interval self.autoUpdate = False self.statusList = [] self.reportedStates = {} self.shouldUpdate = False self.monitorMutex = QMutex() self.monitorCondition = QWaitCondition() self.__stopIt = False def run(self): """ Public method implementing the tasks action. """ while not self.__stopIt: # perform the checking task self.statusList = [] self.vcsStatusMonitorStatus.emit( "wait", QCoreApplication.translate("VcsStatusMonitorThread", "Waiting for lock")) try: locked = self.vcs.vcsExecutionMutex.tryLock(5000) except TypeError: locked = self.vcs.vcsExecutionMutex.tryLock() if locked: try: self.vcsStatusMonitorStatus.emit( "op", QCoreApplication.translate( "VcsStatusMonitorThread", "Checking repository status")) res, statusMsg = self._performMonitor() infoMsg = self._getInfo() finally: self.vcs.vcsExecutionMutex.unlock() if res: status = "ok" else: status = "nok" self.vcsStatusMonitorStatus.emit( "send", QCoreApplication.translate("VcsStatusMonitorThread", "Sending data")) self.vcsStatusMonitorData.emit(self.statusList) self.vcsStatusMonitorStatus.emit(status, statusMsg) self.vcsStatusMonitorInfo.emit(infoMsg) else: self.vcsStatusMonitorStatus.emit( "timeout", QCoreApplication.translate("VcsStatusMonitorThread", "Timed out waiting for lock")) self.vcsStatusMonitorInfo.emit("") if self.autoUpdate and self.shouldUpdate: self.vcs.vcsUpdate(self.projectDir, True) continue # check again self.shouldUpdate = False # wait until interval has expired checking for a stop condition self.monitorMutex.lock() if not self.__stopIt: self.monitorCondition.wait(self.monitorMutex, self.interval * 1000) self.monitorMutex.unlock() self._shutdown() self.exit() def setInterval(self, interval): """ Public method to change the monitor interval. @param interval new interval in seconds (integer) """ locked = self.monitorMutex.tryLock() self.interval = interval self.monitorCondition.wakeAll() if locked: self.monitorMutex.unlock() def getInterval(self): """ Public method to get the monitor interval. @return interval in seconds (integer) """ return self.interval def setAutoUpdate(self, auto): """ Public method to enable the auto update function. @param auto status of the auto update function (boolean) """ self.autoUpdate = auto def getAutoUpdate(self): """ Public method to retrieve the status of the auto update function. @return status of the auto update function (boolean) """ return self.autoUpdate def checkStatus(self): """ Public method to wake up the status monitor thread. """ locked = self.monitorMutex.tryLock() self.monitorCondition.wakeAll() if locked: self.monitorMutex.unlock() def stop(self): """ Public method to stop the monitor thread. """ locked = self.monitorMutex.tryLock() self.__stopIt = True self.monitorCondition.wakeAll() if locked: self.monitorMutex.unlock() def clearCachedState(self, name): """ Public method to clear the cached VCS state of a file/directory. @param name name of the entry to be cleared (string) """ key = self.project.getRelativePath(name) try: del self.reportedStates[key] except KeyError: pass def _performMonitor(self): """ Protected method implementing the real monitoring action. This method must be overridden and populate the statusList member variable with a list of strings giving the status in the first column and the path relative to the project directory starting with the third column. The allowed status flags are: <ul> <li>"A" path was added but not yet comitted</li> <li>"M" path has local changes</li> <li>"O" path was removed</li> <li>"R" path was deleted and then re-added</li> <li>"U" path needs an update</li> <li>"Z" path contains a conflict</li> <li>" " path is back at normal</li> </ul> @return tuple of flag indicating successful operation (boolean) and a status message in case of non successful operation (string) @exception RuntimeError to indicate that this method must be implemented by a subclass """ raise RuntimeError('Not implemented') return () def _getInfo(self): """ Protected method implementing the real info action. This method should be overridden and create a short info message to be shown in the main window status bar right next to the status indicator. @return short info message @rtype str """ return "" def _shutdown(self): """ Protected method performing shutdown actions. The default implementation does nothing. """ pass
class Thread(QThread): """The downloading is handled in a separate thread in order for the progress bar and the pause button to work""" change_value = pyqtSignal(int) done = pyqtSignal(int) log = pyqtSignal(str) is_cancelled = False done_cards = [] def __init__(self, cards, mw, config): QThread.__init__(self) self.cond = QWaitCondition() self.mutex = QMutex() self.cnt = 0 self._status = True self.cards = cards self.mw = mw self.skipped_cards = 0 self.failed: List[FailedDownload] = [] self.config: Config = config def __del__(self): self.wait() def run(self): from . import log_dir skip_existing = self.config.get_config_object( "skipExistingBulkAdd").value card: Card for card in self.cards: """Go through all cards that are selected in the editor""" # self.mutex.lock() if self.is_cancelled: Forvo.cleanup() return if not self._status: # If download is paused, wait self.cond.wait(self.mutex) try: # use try to avoid stopping the entire thread because of a single exception # Get fields from config query_field = self.config.get_note_type_specific_config_object( "searchField", card.note_type()["id"]).value audio_field = self.config.get_note_type_specific_config_object( "audioField", card.note_type()["id"]).value if query_field not in card.note(): raise FieldNotFoundException(query_field) if audio_field not in card.note(): raise FieldNotFoundException(audio_field) query = card.note( )[query_field] # Get query string from card's note using field name language = self.config.get_deck_specific_config_object( "language", card.did).value self.log.emit("[Next Card] Query: %s; Language: %s" % (query, language)) if skip_existing and len(card.note()[audio_field]) > 0: """Skip cards that already have something in the audio field if the setting is turned on""" self.skipped_cards += 1 continue # Get language from config for the card's deck # Get the results results = Forvo(query, language, self.mw) \ .load_search_query() \ .get_pronunciations().pronunciations results.sort(key=lambda result: result.votes) # sort by votes top: Pronunciation = results[ len(results) - 1] # get most upvoted pronunciation self.log.emit("Selected pronunciation by %s with %s votes" % (top.user, str(top.votes))) top.download_pronunciation() # download that self.log.emit("Downloaded pronunciation") if self.config.get_config_object("appendAudio").value: card.note( )[audio_field] += "[sound:%s]" % top.audio # set audio field content to the respective sound self.log.emit("Appended sound string to field content") else: card.note( )[audio_field] = "[sound:%s]" % top.audio # set audio field content to the respective sound self.log.emit("Placed sound string in field") card.note().flush() # flush the toilet self.log.emit("Saved note") except Exception as e: # Save all raised exceptions in a list to retrieve them later in the FailedDownloadsDialog self.failed.append(FailedDownload(reason=e, card=card)) self.log.emit( "[Error] Card with 1. Field %s failed due to Exception: %s" % (card.note().fields[0], str(e))) with open(os.path.join( log_dir, "bulk_error_log-" + datetime.now().strftime('%Y-%m-%dT%H') + ".log"), "a", encoding="utf8") as f: f.write("\n".join( traceback.format_exception(None, e, e.__traceback__)) + "\n------------------\n") self.done_cards.append(card) self.cnt += 1 # Increase count for progress bar self.change_value.emit( self.cnt) # emit signal to update progress bar self.msleep(1000) # sleep to give progress bar time to update # self.mutex.unlock() Forvo.cleanup( ) # cleanup files in temp directory (None is passed as the self parameter here) def toggle_status(self): # toggle pause state self._status = not self._status if self._status: self.cond.wakeAll() @property def status(self): return self._status
class CollectToMySQLThread(QThread): def __init__(self, config, market='SH'): super(self.__class__, self).__init__() self.working = True self._config = config self.market = market.lower() self.marketid = None assert config.getboolean("mysql", "enable", fallback=False) self._db_config = { 'user': config['mysql']['usr'], 'password': config['mysql']['pwd'], 'host': config['mysql']['host'], 'port': config['mysql']['port'] } self._connect = None self.quotations = [ 'stock', ] # sina 不支持基金,qq支持,此处屏蔽基金 #if config['quotation']['stock']: # self.quotations.append('stock') #if config['quotation']['fund']: # self.quotations.append('fund') #self.logger.info(self.quotations) self._interval = TimeDelta( seconds=config.getint('collect', 'interval', fallback=60 * 60)) self._phase1_start_time = Datetime( datetime.datetime.combine( datetime.date.today(), datetime.time.fromisoformat((config.get('collect', 'phase1_start', fallback='09:05'))))) self._phase1_end_time = Datetime( datetime.datetime.combine( datetime.date.today(), datetime.time.fromisoformat((config.get('collect', 'phase1_end', fallback='09:05'))))) self._use_zhima_proxy = config.getboolean('collect', 'use_zhima_proxy', fallback=False) self.cond = QWaitCondition() self.mutex = QMutex() def stop(self): if self.working: self.working = False self.cond.wakeAll() self.wait() if self._connect is not None: hku_trace('关闭数据库连接', logger=self.logger) self._connect.close() def __del__(self): self.stop() @hku_catch() def run(self): self.logger.info("{} 数据采集同步线程启动".format(self.market)) stk_list = self.get_stock_list() hku_warn_if(not stk_list, "从数据库中获取的股票列表为空!", logger=self.logger) self.mutex.tryLock() end_delta = self._phase1_end_time - self._phase1_end_time.start_of_day( ) start_delta = self._phase1_start_time - self._phase1_start_time.start_of_day( ) start = Datetime.now() if self._phase1_start_time >= self._phase1_end_time: delta = TimeDelta(0) elif start >= self._phase1_end_time: delta = (self._phase1_start_time + TimeDelta(1) - start) elif start < self._phase1_start_time: delta = (self._phase1_start_time - start) else: delta = self._interval * ceil( (start - self._phase1_start_time) / self._interval) - ( start - self._phase1_start_time) hku_info('{} 下次采集时间:{}', self.market, start + delta, logger=self.logger) delta = int(delta.total_milliseconds()) while self.working and not self.cond.wait(self.mutex, int(delta)): last_time = Datetime.today() + end_delta start = Datetime.now() if start >= last_time: next_time = Datetime.today() + TimeDelta(1) + start_delta hku_info('{} 明日采集时间:{}', self.market, next_time, logger=self.logger) delta = next_time - start delta = int(delta.total_milliseconds()) continue hku_trace("start:{}".format(start)) self.collect(stk_list) end = Datetime.now() x = end - start if x + TimeDelta(seconds=1) < self._interval: delta = self._interval - x - TimeDelta(seconds=1) delta = int(delta.total_milliseconds()) self.logger.info("{} {:<.2f} 秒后重新采集".format( self.market, delta / 1000)) #self.sleep(delta) self.logger.info("{} 数据采集同步线程终止!".format(self.market)) def record_is_valid(self, record): return record['amount'] > 0.0 and record['volumn'] > 0.0 \ and record['high'] >= record['open'] >= record['low'] > 0.0 \ and record['high'] >= record['close'] >= record['low'] @hku_catch(ret=False) def process_one_record(self, record): if not self.record_is_valid(record): return (0, 0) connect = self.get_connect() current_date = Datetime(record['datetime'].date()).number table = get_table(connect, self.market, record['code'], 'day') sql = 'replace into {} (date, open, high, low, close, amount, count) \ values ({}, {}, {}, {}, {}, {}, {})'.format( table, current_date, record['open'], record['high'], record['low'], record['close'], record['amount'], record['volumn']) cur = connect.cursor() cur.execute(sql) cur.close() return @hku_catch() def collect(self, stk_list): record_list = get_spot_parallel(stk_list, source='sina', use_proxy=self._use_zhima_proxy) hku_info("{} 网络获取数量:{}".format(self.market, len(record_list))) connect = self.get_connect() if self.marketid == None: self.marketid = get_marketid(connect, self.market) update_count = 0 for record in record_list: if not self.working: break if self.process_one_record(record): update_count += 1 connect.commit() hku_info("{} 数据库更新记录数:{}".format(self.market, update_count)) def get_connect(self): if self._connect: return self._connect try: self._connect = mysql.connector.connect(**self._db_config) except mysql.connector.Error as err: if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: self.logger.error("MYSQL密码或用户名错误!") elif err.errno == errorcode.ER_BAD_DB_ERROR: self.logger.error("MySQL数据库不存在!") else: self.logger.error("连接数据库失败,{}".format(err.msg)) except: self.logger.error("未知原因导致无法连接数据库!") return self._connect @hku_catch(retry=2, ret=[]) def get_stock_list(self): connect = self.get_connect() stk_list = get_stock_list(connect, self.market, self.quotations) return [ "{}{}".format(self.market.lower(), item[2]) for item in stk_list if item[3] == 1 ]
class FileConverter(QThread): progress_signal = pyqtSignal(int, int) conversion_status_signal = pyqtSignal(str, int, int) file_converted_signal = pyqtSignal() conversion_complete = pyqtSignal() ask_overwrite_signal = pyqtSignal(str) def __init__(self, data_file_container, parameters): # parameters is a dict of parameters required by FileConverter super().__init__() self.mutex = QMutex() self.wait_condition = QWaitCondition() self.data_file_container = data_file_container self.parameters = parameters self.current_file_ind = 0 self.file_sizes = [file.size if file.status == 'unconverted' else 0 for file in data_file_container] self.unconverted_files = self.data_file_container.unconverted() self.total_mb = sum(self.file_sizes) self._is_running = False self.converter = None self.overwrite = None def run(self): self._is_running = True count = 0 for i, file in enumerate(self.data_file_container): if not self._is_running: break if file.status != 'unconverted': continue count += 1 self.current_file_ind = i self.conversion_status_signal.emit( file.filename, count, self.unconverted_files) # if not os.path.isfile(file.path): # file.status = 'not found' # continue self._convert_file(file) self.file_converted_signal.emit() self.conversion_complete.emit() def _convert_file(self, file): self.current_file = file try: conversion_parameters = default_parameters() conversion_parameters.update(self.parameters) conversion_parameters['overwrite'] = self._process_overwrite() self.converter = DataConverter(file.path, conversion_parameters) self.converter.register_observer(self.update_progress) self.converter.convert() self.data_file_container.change_status(file, 'converted') except FileExistsError as message: self.ask_overwrite(file.filename) if self.overwrite in ['once', 'yes_to_all']: self._convert_file(file) except (TypeError, ValueError, IndexError) as m: if str(m) == 'Not all required sensors present': self.data_file_container.change_status( file, 'error_sensor_missing') else: self.data_file_container.change_status(file, 'error_failed') except FileNotFoundError: self.data_file_container.change_status(file, 'error_missing') except NoDataError: self.data_file_container.change_status(file, 'error_no_data') finally: self.converter.close_source() # check for the case that the conversion was canceled if not self.converter._is_running: self.data_file_container.change_status(file, 'unconverted') def update_progress(self, percent_done): # This is an observer function that gets notified when a data # page is parsed if not self._is_running: self.converter.cancel_conversion() cumulative_mb = sum([size for size in self.file_sizes[:self.current_file_ind]]) cumulative_mb += (self.data_file_container[self.current_file_ind].size * (percent_done/100)) overall_percent = cumulative_mb / self.total_mb overall_percent *= 100 self.progress_signal.emit(percent_done, overall_percent) def _process_overwrite(self): # TODO why is there a tuple used below when index 0 isn't used? action_map = { 'once': (None, True), 'yes_to_all': ('yes_to_all', True), 'no': (None, False), 'no_to_all': ('no_to_all', False) } _, overwrite_status = action_map.get(self.overwrite, (None, False)) return overwrite_status def ask_overwrite(self, filename): if self.overwrite is None: self.ask_overwrite_signal.emit(str(filename)) self.mutex.lock() self.wait_condition.wait(self.mutex) self.mutex.unlock() def set_overwrite(self, state): self.overwrite = state self.wait_condition.wakeAll() def cancel(self): self._is_running = False
class LogThread(QThread): exeCnt = 0 logTreeFinished = pyqtSignal(dict, int, str) logViewFinished = pyqtSignal(dict, int) def __init__(self, ip, tp): QThread.__init__(self) self.cond = None self.mutex = None self._status = True self.ip = ip self.tp = tp self.guid = '' self.icnt = 0 self.tot_cnt = 0 self.max_line = 8000 def __del__(self): self.wait() def run(self): log_tree = {} tot_line_cnt = 0 guid = '' self.cond = QWaitCondition() self.mutex = QMutex() self.mutex.lock() # self.msleep(100) if not self._status: self.cond.wait(self.mutex) try: swgs_url = 'http://172.31.196.21:8060/websquare/Service/SVC?commonsvc=0&rtcode=0&Trx_code=ZORDSCOM06020_TR01&ScreenName=ZORDSCOM06020&fCloseAccount=0&LogLvlGbn=&G_BizCd=null&G_Biz_Start_Time=null&__smReqSeq=5&_useLayout=true' payload = {"input1": [{"fcnt": "0", "flag": "T", "guid": self.guid, "icnt": self.icnt, "ip_addr": self.ip, "rowStatus": "C", "tp_id": self.tp, "prod_skip": "N"}], "HEAD": {"Trx_Code": "ZORDSCOM06020_TR01", "Ngms_UserId": "1000852323", "Ngms_LogInId": "ENJOYHAN", "Ngms_EmpNum": "", "Ngms_OrgId": "A000700000", "Ngms_HrOrgCd": "", "Ngms_PostOrgCd": "A000700000", "Ngms_PostSaleOrgCd": "A000700000", "Ngms_SupSaleOrgCd": "A010890000", "Ngms_IpAddr": "150.28.65.76", "Ngms_BrTypCd": "450", "Ngms_AuthId": "", "Ngms_ConnOrgId": "A000700000", "Ngms_ConnOrgCd": "A000700000", "Ngms_ConnSaleOrgId": "A000700000", "Ngms_ConnSaleOrgCd": "A000700000", "Ngms_AuthTypPermCd": "EQ", "Ngms_PostSaleOrgId": "A000700000", "Ngms_SupSaleOrgId": "A010890000", "Term_Type": "0", "User_Term_Type": "", "St_Stop": "0", "St_Trace": "", "Stx_Dt": "", "Stx_Tm": "", "Etx_Dt": "", "Etx_Tm": "", "Rt_Cd": "", "Screen_Name": "ZORDSCOM06020", "Msg_Cnt": "0", "Handle_Id": "863017520 ", "Ngms_Filler1": "", "Ngms_CoClCd": "T", "Screen_Call_Trace": "Top-ZORDSCOM06020-ZORDSCOM06020_TR01", "rowStatus": "C"}} ''' 1. icnt 값이 0 인 경우 log tree 에 보여줄 값을 조회 2. log view에 보여줄 상세 값을 조회 2-1) tot_cnt 가 0 보다 크고 icnt 가 0인 경우 (최초 조회) 2-2) rem_cnt 가 0 보다 큰 경우 (Append 하기 조회) ''' if self.icnt == 0: log_tree_result = requests.get(swgs_url, json=payload) log_tree = log_tree_result.json() if log_tree: if log_tree['output2']: self.tot_line_cnt =int(log_tree['output2'][0]['total_cnt']) self.guid = log_tree['output2'][0]['guid'] cnt = divmod(int(self.tot_line_cnt), int(self.max_line)) self.tot_cnt = cnt[0] + 1 self.logTreeFinished.emit(log_tree, self.tot_cnt, self.guid) rem_cnt = self.tot_cnt - self.icnt if self.tot_cnt > 0 and self.icnt == 0: payload['input1'][0]['flag'] = 'L' payload['input1'][0]['guid'] = guid payload['input1'][0]['icnt'] = self.icnt log_view_result = requests.get(swgs_url, json=payload) log_view = log_view_result.json() self.icnt += 1 self.logViewFinished.emit(log_view, self.icnt) print('{}번 조회완료'.format(self.icnt)) elif rem_cnt > 0: log_view = {} for ix in range(0, rem_cnt): payload['input1'][0]['flag'] = 'L' payload['input1'][0]['guid'] = guid payload['input1'][0]['icnt'] = self.icnt log_view_result = requests.get(swgs_url, json=payload) if ix == 0: log_view = log_view_result.json() else: log_view_temp = log_view_result.json() log_view['output1'].append(log_view_temp['output1']) self.icnt += 1 print('{}번 조회완료'.format(self.icnt)) self.logViewFinished.emit(log_view, self.icnt) except Exception as e: print(e) finally: self.mutex.unlock() def toggle_status(self): self._status = not self._status if self._status: self.cond.wakeAll() @property def status(self): return self._status def stop(self): self.terminate()
class MainWindow(QMainWindow): inputReceived = pyqtSignal(str) def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) # Left Browser tabs self.ui.tabWidgetBrowser.removeTab(1) self.ui.tabWidgetBrowser.removeTab(1) self.ui.tabWidgetBrowser.setTabsClosable(True) self.ui.tabWidgetBrowser.tabCloseRequested.connect(self.closeBrowserTab) self.ui.tabWidgetBrowser.tabBarDoubleClicked.connect(lambda: self.maximizeTabs(self.ui.tabWidgetBrowser)) # Left tree views self.fileTreeModel = QFileSystemModel(self) self.fileTreeModel.setRootPath(QDir.currentPath() + QDir.separator() + 'test') self.ui.treeViewFile.setModel(self.fileTreeModel) self.ui.treeViewFile.setRootIndex(self.fileTreeModel.index(QDir.currentPath() + QDir.separator() + 'test')) self.ui.treeViewFile.hideColumn(1) self.ui.treeViewFile.hideColumn(2) self.ui.treeViewFile.hideColumn(3) self.ui.treeViewFile.doubleClicked.connect(self.openFileFromTree) self.ui.treeViewFile.setAnimated(True) self.ui.treeViewSyntax.setAnimated(True) self.ui.treeViewToken.setAnimated(True) self.ui.treeViewFile.setHeaderHidden(True) self.ui.treeViewSyntax.setHeaderHidden(True) self.ui.treeViewToken.setHeaderHidden(True) # Editor tabs self.currentEditor = self.ui.codeEditor self.currentEditor.file = None self.currentEditorTab = self.ui.tabEditor self.openedEditors = [self.currentEditor] self.openedEditorTabs = [self.currentEditorTab] self.currentEditor.setFocus() # set focus self.ui.tabWidgetEditor.tabCloseRequested.connect(self.closeEditorTab) self.ui.tabWidgetEditor.tabBarClicked.connect(self.switchEditorTab) self.ui.tabWidgetEditor.tabBarDoubleClicked.connect(lambda: self.maximizeTabs(self.ui.tabWidgetEditor)) # Bottom console font = QFont() font.setFamily("Courier") font.setStyleHint(QFont.Monospace) font.setFixedPitch(True) font.setPointSize(10) self.ui.console.setFont(font) self.ui.console.setReadOnly(True) self.waitInputCond = QWaitCondition() self.oldConsoleText = None # Bottom output tabs self.ui.tabWidgetOutput.hide() self.ui.tabWidgetOutput.tabCloseRequested.connect(self.closeOutputTab) self.ui.tabWidgetOutput.tabBarDoubleClicked.connect(lambda: self.maximizeTabs(self.ui.tabWidgetOutput)) self.ui.tabWidgetOutput.setTabText(0, 'Console') # Previous opened tabs,for maximizing self.preOpenedTabs = None # Initial size of inner splitter self.ui.splitterInner.setSizes([180, 459 * 2 - 180]) # Menu "File" self.ui.actionOpen.triggered.connect(self.openFile) self.ui.actionNew.triggered.connect(self.newFile) self.ui.actionSave.triggered.connect(self.saveFile) self.ui.actionSaveAs.triggered.connect(self.saveFileAs) self.ui.actionQuit.triggered.connect(self.close) # Menu "Edit" self.connectMenuEditSlots() # Menu "View" self.ui.menuView.triggered.connect(self.manageMenuView) self.ui.actionAboutQt.triggered.connect(QApplication.aboutQt) # Menu "Run" self.ui.actionRun.triggered.connect(self.run) self.ui.actionBuild.triggered.connect(self.runCompile) self.ui.actionShowStable.triggered.connect(self.runSemantic) self.ui.actionRunParser.triggered.connect(self.runParser) self.ui.actionRunLexer.triggered.connect(self.runLexer) @pyqtSlot(bool) def runLexer(self, checked): """ Run lexer and present result on self.ui.tabToken Tree :return: """ p = self.genParser(Parser.mode_lexer) tokenNode = p.lexse() if p else None if not tokenNode: self.endEcho(False) return self.showBrowserTree(self.ui.tabToken, tokenNode) self.endEcho(True) @pyqtSlot(bool) def runParser(self, checked): """ Run parser and present result on self.ui.tabSyntax Tree :return: """ # Begin parse p = self.genParser(Parser.mode_parser) result = p.parse() if p else None if not result: self.endEcho(False) return syntaxNode, tokenNode = result # self.showBrowserTree(self.ui.tabToken, tokenNode) self.ui.treeViewToken.setModel(TreeModel(tokenNode)) self.showBrowserTree(self.ui.tabSyntax, syntaxNode) self.endEcho(True) @pyqtSlot(bool) def runSemantic(self, checked): """ run semantics analysing and print symbol table :return: """ p = self.genParser(Parser.mode_stable) result = p.semantic() if p else None if not result: self.endEcho(False) return stable, syntaxNode, tokenNode = result self.ui.treeViewToken.setModel(TreeModel(tokenNode)) self.ui.treeViewSyntax.setModel(TreeModel(syntaxNode)) self.endEcho(True) @pyqtSlot(bool) def runCompile(self, checked): """ Run compiler and print Intermediate code :return: """ p = self.genParser(Parser.mode_compile) result = p.compile() if p else None if not result: self.endEcho(False) return codes, stable, syntaxNode, tokenNode = result self.ui.treeViewToken.setModel(TreeModel(tokenNode)) self.ui.treeViewSyntax.setModel(TreeModel(syntaxNode)) self.endEcho(True) @pyqtSlot(bool) def run(self, checked): """ compile and run the source code compile in main thread and run in a worker thread """ p = self.genParser(Parser.mode_execute) result = p.compile() if p else None if not result: self.endEcho(False) return codes, stable, syntaxNode, tokenNode = result self.ui.treeViewToken.setModel(TreeModel(tokenNode)) self.ui.treeViewSyntax.setModel(TreeModel(syntaxNode)) console = Console(self.ui.console, parent=self, waitCond=self.waitInputCond) console.update.connect(self.updateOutput) self.inputReceived.connect(console.receivedInput) self.ui.console.blockCountChanged.connect(self.waitInput) self.ui.console.textChanged.connect(self.disableBack) interp = Interpreter(codes, stdin=console, stdout=console, stderr=console) thread = ExecuteThread(interp.inter, self) thread.start() def genParser(self, mode=Parser.mode_execute): """ Generate a parser instance :param mode: :return: """ if not self.saveFile(): return self.showOutputPanel() self.ui.actionViewConsole.setChecked(True) self.beginEcho() stdin = open(self.currentEditor.file, 'r') console = Console(self.ui.console, parent=self) console.update.connect(self.updateOutput) return Parser(stdin, stdout=console, stderr=console, mode=mode) def beginEcho(self): self.updateOutput('%s\n' % self.currentEditor.file) def endEcho(self, success=True): msg = 'successfully' if success else 'unsuccessfully' self.updateOutput('Process finished %s\n' % msg) @pyqtSlot(str) def updateOutput(self, content): """ Update bottom text browser when content is writen to it. :param content: :return: """ self.ui.console.moveCursor(QTextCursor.End) self.ui.console.insertPlainText('%s' % content) self.oldConsoleText = self.ui.console.toPlainText() @pyqtSlot(int) def waitInput(self, newBlockCount): """ :param newBlockCount: line count :return: """ if not self.ui.console.isReadOnly(): self.inputReceived.emit(self.ui.console.toPlainText() .replace(self.oldConsoleText, '')) self.waitInputCond.wakeAll() self.ui.console.setReadOnly(True) @pyqtSlot() def disableBack(self): """ disable backspace when waiting for input :return: """ if not self.ui.console.isReadOnly(): if len(self.oldConsoleText) > len(self.ui.console.toPlainText()): self.ui.console.setPlainText(self.oldConsoleText) self.ui.console.moveCursor(QTextCursor.End) def closeEvent(self, event): """ Override. When Close Event Triggered. Ask user for saving modified files :param event: :return: """ for i in range(len(self.openedEditors)): editor = self.openedEditors[i] editorTab = self.openedEditorTabs[i] if editor.document().isModified(): name = ntpath.basename(editor.file) if editor.file else 'New File' ret = QMessageBox.warning( self, name, 'The document has been modified.\nDo you want to save your changes?', QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if ret == QMessageBox.Save: event.accept() if self.saveFile() else event.ignore() elif ret == QMessageBox.Discard: index = self.ui.tabWidgetEditor.indexOf(editorTab) self.ui.tabWidgetEditor.removeTab(index) event.accept() else: event.ignore() def showOutputPanel(self): """ Clear previous output and show the ouput panel :return: """ self.ui.console.clear() self.ui.tabWidgetOutput.show() def showBrowserTree(self, tab, rootNode): """ Show treeView on tabWidgetBrowser :param tab: :param rootNode: """ model = TreeModel(rootNode) if tab == self.ui.tabSyntax: treeView = self.ui.treeViewSyntax name = 'Syntax' self.ui.actionViewSystaxTree.setChecked(True) else: treeView = self.ui.treeViewToken name = 'Token' self.ui.actionViewTokenTree.setChecked(True) treeView.setModel(model) # show the tab index = self.ui.tabWidgetBrowser.indexOf(tab) if index == -1: self.ui.tabWidgetBrowser.addTab(tab, name) index = self.ui.tabWidgetBrowser.indexOf(tab) self.ui.tabWidgetBrowser.setCurrentIndex(index) self.addjustBrowserWidth() def connectMenuEditSlots(self): """ set menu "Edit" signals connect to current editor slots :return: """ self.ui.actionCopy.triggered.connect(self.currentEditor.copy) self.ui.actionCut.triggered.connect(self.currentEditor.cut) self.ui.actionPaste.triggered.connect(self.currentEditor.paste) self.ui.actionUndo.triggered.connect(self.currentEditor.undo) self.ui.actionRedo.triggered.connect(self.currentEditor.redo) self.ui.actionSelectAll.triggered.connect(self.currentEditor.selectAll) def disconnectMenuEditSlots(self): """ disconnect menu "Edit" signals :return: """ self.ui.actionCopy.triggered.disconnect(self.currentEditor.copy) self.ui.actionCut.triggered.disconnect(self.currentEditor.cut) self.ui.actionPaste.triggered.disconnect(self.currentEditor.paste) self.ui.actionUndo.triggered.disconnect(self.currentEditor.undo) self.ui.actionRedo.triggered.disconnect(self.currentEditor.redo) self.ui.actionSelectAll.triggered.disconnect(self.currentEditor.selectAll) def createEditorTab(self): """ Create a new Editor tab and set as current editor Should reconnect the signal on menu 'Edit' actions :return: """ # add a new editor self.currentEditorTab = QtWidgets.QWidget() horizontalLayout = QtWidgets.QHBoxLayout(self.currentEditorTab) horizontalLayout.setContentsMargins(0, 0, 0, 0) horizontalLayout.setSpacing(6) codeEditor = CodeEditor(self.currentEditorTab) horizontalLayout.addWidget(codeEditor) self.ui.tabWidgetEditor.addTab(self.currentEditorTab, "") # disconnect signals self.disconnectMenuEditSlots() # change current tab and editors self.currentEditor = codeEditor self.currentEditor.file = None self.openedEditors.append(self.currentEditor) self.openedEditorTabs.append(self.currentEditorTab) # connect signals self.connectMenuEditSlots() # set tab closeable if len(self.openedEditorTabs) > 1: self.ui.tabWidgetEditor.setTabsClosable(True) @pyqtSlot(int) def switchEditorTab(self, index): """ Switch current active editor tab to index Should reconnect the signal on menu 'Edit' actions :param index: :return: """ self.disconnectMenuEditSlots() self.currentEditorTab = self.openedEditorTabs[index] self.currentEditor = self.openedEditors[index] self.connectMenuEditSlots() @pyqtSlot(int) def closeEditorTab(self, index): """ Triggered when closing the editor tab at index requested :param index: :return: """ self.ui.tabWidgetEditor.removeTab(index) self.openedEditorTabs.pop(index) self.openedEditors.pop(index) self.switchEditorTab(0) # choose the beginning tab as current active if len(self.openedEditorTabs) == 1: self.ui.tabWidgetEditor.setTabsClosable(False) @pyqtSlot(int) def closeBrowserTab(self, index): """ Close Left Browser Tab at index :param index: :return: """ # make menu "View" corresponding w = self.ui.tabWidgetBrowser.widget(index) if w == self.ui.tabFile: self.ui.actionViewFiles.setChecked(False) elif w == self.ui.tabToken: self.ui.actionViewTokenTree.setChecked(False) else: self.ui.actionViewSystaxTree.setChecked(False) # remove tab self.ui.tabWidgetBrowser.removeTab(index) if self.ui.tabWidgetBrowser.count() == 0: self.ui.tabWidgetBrowser.hide() @pyqtSlot(int) def closeOutputTab(self, index): """ Close(hide) the output tab widget :param index: """ # make menu "View" corresponding self.ui.actionViewConsole.setChecked(False) self.ui.tabWidgetOutput.hide() def recoverTabWidgets(self): """ recover tabs when cancel maximizing :return: """ for tab in self.preOpenedTabs: tab.show() self.preOpenedTabs = None def storeOpenedTabs(self): """ store tabs opened before maximize :return: """ self.preOpenedTabs = [] if not self.ui.tabWidgetOutput.isHidden(): self.preOpenedTabs.append(self.ui.tabWidgetOutput) if not self.ui.tabWidgetEditor.isHidden(): self.preOpenedTabs.append(self.ui.tabWidgetEditor) if not self.ui.tabWidgetBrowser.isHidden(): self.preOpenedTabs.append(self.ui.tabWidgetBrowser) def maximizeTabs(self, widget): if self.preOpenedTabs: self.recoverTabWidgets() else: self.storeOpenedTabs() for w in [self.ui.tabWidgetBrowser, self.ui.tabWidgetOutput, self.ui.tabWidgetEditor]: if w != widget: w.hide() @pyqtSlot(QAction) def manageMenuView(self, action): """ Handle the action on menu "View" :param action: :return: """ if action == self.ui.actionViewToolbar: self.ui.toolBar.show() if action.isChecked() else self.ui.toolBar.hide() return pair = { self.ui.actionViewFiles: (self.ui.tabWidgetBrowser, self.ui.tabFile, 'File'), self.ui.actionViewTokenTree: (self.ui.tabWidgetBrowser, self.ui.tabToken, 'Token'), self.ui.actionViewSystaxTree: (self.ui.tabWidgetBrowser, self.ui.tabSyntax, 'Syntax'), self.ui.actionViewConsole: (self.ui.tabWidgetOutput, self.ui.tabConsole, 'Console'), } p = pair[action] widget = p[0] tab = p[1] name = p[2] if action.isChecked(): widget.addTab(tab, name) widget.setCurrentWidget(tab) if widget == self.ui.tabWidgetBrowser: # reset tab inner splitter size self.addjustBrowserWidth() if widget.isHidden(): widget.show() else: widget.removeTab( widget.indexOf(tab)) if widget.count() == 0: widget.hide() def addjustBrowserWidth(self): w = self.ui.tabWidgetBrowser.count() * 80 self.ui.splitterInner.setSizes([w, self.ui.splitterInner.width() - w]) @pyqtSlot(bool) def openFile(self, checked=True, path=None): """ Open a new file. If current editor is associated with a file or its content is not null, Then create a new editor tab :return: """ path = QFileDialog.getOpenFileName()[0] if not path else path if len(path) != 0: qfile = QFile(path) if not qfile.open(QFile.ReadOnly or QFile.Text): QMessageBox.warning(self, 'Application', 'Cannot read file %s:\n%s.' % (path, qfile.errorString())) return with open(path, 'r') as _file: content = _file.read() if self.currentEditor.file or len(self.currentEditor.document().toPlainText()) > 0: self.createEditorTab() # associate file on disk with editor self.currentEditor.file = path # update tab name index = self.ui.tabWidgetEditor.indexOf(self.currentEditorTab) _translate = QCoreApplication.translate self.ui.tabWidgetEditor.setTabText( index, _translate("MainWindow", ntpath.basename(path))) self.ui.tabWidgetEditor.setCurrentIndex(index) self.currentEditor.setPlainText(content) @pyqtSlot(int) def openFileFromTree(self, index): f = self.fileTreeModel.fileInfo(index) if f.isFile(): self.openFile(path=f.filePath()) @pyqtSlot(bool) def newFile(self, checked): """ create a new editor tab :param action: :return: """ self.createEditorTab() index = self.ui.tabWidgetEditor.indexOf(self.currentEditorTab) _translate = QCoreApplication.translate self.ui.tabWidgetEditor.setTabText( index, _translate("MainWindow", 'New File')) self.ui.tabWidgetEditor.setCurrentIndex(index) @pyqtSlot(bool) def saveFile(self, checked=None): """ Save file. If current editor is associated with a file on the disk, then save it. Or save file as... :param checked: :return: Saved or canceled """ if self.currentEditor.file: if self.currentEditor.document().isModified(): with open(self.currentEditor.file, 'w') as f: f.write(self.currentEditor.document().toPlainText()) self.currentEditor.document().setModified(False) return True else: return self.saveFileAs() @pyqtSlot(bool) def saveFileAs(self, checked=None): """ Save File As... :param checked: :return: If saved or canceled """ dialog = QFileDialog() dialog.setWindowModality(Qt.WindowModal) dialog.setAcceptMode(QFileDialog.AcceptSave) if dialog.exec_(): filepath = dialog.selectedFiles()[0] with open(filepath, 'w') as f: f.write(self.currentEditor.document().toPlainText()) self.currentEditor.document().setModified(False) self.currentEditor.file = filepath return True else: return False