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 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 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): 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 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 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 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 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 Worker(QThread): result = pyqtSignal(np.ndarray) leftImage = pyqtSignal(np.ndarray) rightImage = pyqtSignal(np.ndarray) def __init__(self, parent=None): super().__init__(parent) self._mutex = QMutex() self._condition = QWaitCondition() self.frame = None self.parameters = None self.abort = False def processFrame(self, frame, parameters): self._mutex.lock() self.frame = frame self.parameters = parameters self._mutex.unlock() if not self.isRunning(): self.start() else: self._condition.wakeOne() def run(self): while not self.abort: # copy new frame and parameters: self._mutex.lock() frame = self.frame parameters = self.parameters self.frame = None self.parameters = None self._mutex.unlock() # convert frame to grayscale and rotate to give the correction orientation data = frame.sum(axis=2).astype(np.float64) data = np.rot90(data, axes=(1, 0)) # split data in half and subtract the two halves: center = data.shape[0] // 2 left = data[0:center, :] right = data[center:, :] res = left - right # update the user interface: self.result.emit(res) self.leftImage.emit(left) self.rightImage.emit(right) # see if new data is available, go to sleep if not self._mutex.lock() data_available = self.frame is not None and self.parameters is not None if not data_available: self._condition.wait(self._mutex) self._mutex.unlock()
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 Worker(QThread): result = pyqtSignal(np.ndarray) def __init__(self, parent=None): super().__init__(parent) self._mutex = QMutex() self._condition = QWaitCondition() self.frame = None self.parameters = None self.abort = False def processFrame(self, frame, parameters): self._mutex.lock() self.frame = frame self.parameters = parameters self._mutex.unlock() if not self.isRunning(): self.start() else: self._condition.wakeOne() def run(self): while not self.abort: # copy new frame and parameters: self._mutex.lock() frame = self.frame parameters = self.parameters self.frame = None self.parameters = None self._mutex.unlock() homogenize = parameters["homogenize"] sigma = parameters["sigma"] blur = parameters["blur"] if homogenize: frame = vtc.highpass(frame, sigma, blur) #frame = np.uint16(np.float32(frame) / np.float32(frame.max()) * 255) # update the user interface: self.result.emit(frame) # see if new data is available, go to sleep if not self._mutex.lock() data_available = self.frame is not None and self.parameters is not None if not data_available: self._condition.wait(self._mutex) 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 FetchPage(QThread): fetchSignal = pyqtSignal(str, name='fetchComplete') def __init__(self, parent=None): super(FetchPage, self).__init__(parent) print('thread initialized') self.mutex = QMutex() self.condition = QWaitCondition() self.restart = False self.abort = False def __del__(self): self.mutex.lock() self.abort = True self.condition.wakeOne() self.mutex.unlock() self.wait() def fetch(self, page): locker = QMutexLocker(self.mutex) self.page = page if page.content is not None: print('Returning old content') self.fetchSignal.emit(page.content) else: if not self.isRunning(): self.start(QThread.LowPriority) else: self.restart = True self.condition.wakeOne() def run(self): print("running page fetch for " + self.page.title) rest_api = RestAPI() self.page.content = (rest_api.get_page_content(self.page.content_url)) # print(self.page.content) self.fetchSignal.emit(self.page.content) # self.fetchSignal.emit() print('signal emitted') self.mutex.lock() if not self.restart: self.condition.wait(self.mutex) self.restart = False self.mutex.unlock()
class ProgressBar(QThread): countChanged = pyqtSignal(int) stopSignal = pyqtSignal(str) musicLengthSignal = pyqtSignal(int) setCountPosition = pyqtSignal(int) moveToTheNextMusic = pyqtSignal( int ) #Let's say, when we signal integer 1337 signal, that would mean that the current song is finished playing. def __init__(self, parent=None): super().__init__(parent) self.musicLengthSignal.connect(self.progressBarMusicLength) def run(self): self.count = 0 self.mtx = QMutex() self.wCndt = QWaitCondition() self.continueToSend = True while self.count < self.musicLength: self.stopSignal.connect(self.stopProgressBar) self.setCountPosition.connect(self.settingUpCount) if not self.continueToSend: self.mtx.lock() try: self.wCndt.wait(self.mtx) finally: self.mtx.unlock() else: self.count += 1 time.sleep(1) self.countChanged.emit(self.count) self.moveToTheNextMusic.emit( 1337) #It means that the current song has finished playing. def stop(self): self.terminate() def settingUpCount(self, countVal): self.count = countVal def stopProgressBar(self, cSignal): if cSignal == "stop": self.continueToSend = False def progressBarMusicLength(self, musicLength): self.musicLength = musicLength
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 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 STT(QThread): signal_stt_done = pyqtSignal(list) def __init__(self, max_alternatives=1): super().__init__() self.max_alter = max_alternatives self._mutex = QMutex() self._abort = False self._condition = QWaitCondition() self.client = speech.Client() self.file_path = None def __del__(self): self._abort = True self.wait() def activate(self, audio_file_path): self.file_path = audio_file_path self._condition.wakeOne() def run(self): while True: if self._abort: return self._mutex.lock() self._condition.wait(self._mutex) ### DOING THING trans = [] with open(self.file_path, 'rb') as audio_file: sample = self.client.sample(content=audio_file.read(), sample_rate=16000, encoding=speech.Encoding.FLAC) try: alternatives = sample.sync_recognize( language_code='en-US', max_alternatives=self.max_alter) for a in alternatives: trans.append(a.transcript) except ValueError as e: print("error: ", e) self.signal_stt_done.emit(trans) ### DONE DOING THING self._mutex.unlock()
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 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 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 SyncAllThread(QThread): syncCompleteSignal = pyqtSignal(Dbm, name="syncComplete") def __init__(self, parent=None): super(SyncAllThread, self).__init__(parent) print("thread initialized") self.mutex = QMutex() self.condition = QWaitCondition() self.restart = False self.abort = False def __del__(self): self.mutex.lock() self.abort = True self.condition.wakeOne() self.mutex.unlock() self.wait() def sync(self): locker = QMutexLocker(self.mutex) self.dbm = Dbm() print("in sync thread") if not self.isRunning(): self.start(QThread.LowPriority) else: self.restart = True self.condition.wakeOne() def run(self): print("running sync thread") self.dbm.fetch() # print(self.page.content) self.syncCompleteSignal.emit(self.dbm) # self.fetchSignal.emit() print("signal emitted") self.mutex.lock() if not self.restart: self.condition.wait(self.mutex) self.restart = False self.mutex.unlock()
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 AAThread(QThread): # 시그널 선언 change_value = pyqtSignal(int) def __init__(self, multi=10): QThread.__init__(self) self.cond = QWaitCondition() self.mutex = QMutex() self.count = 0 self._status = True self.multi = multi print(multi) def set_multi(self, multi): self.multi = multi def set_count(self, value): self.count = value 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.count: self.count = 0 self.count += 1 self.change_value.emit(self.count) self.msleep(10000 // self.multi) self.mutex.unlock() @property def status(self): return self._status
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 UpdaterTask(QThread): update = QtCore.pyqtSignal() def __init__(self, refresh_rate): super(UpdaterTask, self).__init__(None) self.refresh_rate = refresh_rate self.mutex = QMutex() self.cond = QWaitCondition() def run(self): while True: self.mutex.lock() while not self.cond.wait(self.mutex, self.refresh_rate * 1000): self.update.emit() self.mutex.unlock()
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 SwitchRefreshThread(QThread): # Initialize class signals. data_signal = pyqtSignal(bool) """ This function is responsible for initializing any related objects for refresh thread. """ def __init__(self, plugin_id, address, socket): QThread.__init__(self) self.plugin_id = plugin_id self.address = address self.udp_socket = socket self.finished.connect(self.quit) self.wait = QWaitCondition() self.mutex = QMutex() """ This is the entry point for refresh thread. """ def run(self): # Run indefinately. while True: # Wait for trigger. self.mutex.lock() self.wait.wait(self.mutex) self.mutex.unlock() # Receive and discard any datagrams from this socket. self.udp_socket.setblocking(0) try: while True: _ = self.udp_socket.recv(65535) except: pass self.udp_socket.setblocking(1) self.udp_socket.settimeout(WV_REQ_TIMEOUT) try: rx_data = None if DEBUG: print("Sending an update request for", self.plugin_id, "to", self.address) # Send a request update for this plugin. self.udp_socket.sendto(bytes.fromhex(WV_UPDATE) + bytes([((self.plugin_id & 0xFF00) >> 8), (self.plugin_id & 0x00FF)]), self.address) # Receive data form the UDP port. rx_data = self.udp_socket.recv(65535) # If we did receive a vaild reply. if (rx_data[ : 4] == bytes.fromhex(WV_UPDATE_REPLY)): # Remove packet descriptor. rx_data = rx_data[4 : ] # If we did receive some data. if len(rx_data) == 1: if DEBUG: print("Got an update for", self.plugin_id, "from", self.address) # Check if we are now turned on. if (rx_data[0] == WV_PLUGIN_SWITCH_ON): # Signal the data to update the plugin display. self.data_signal.emit(True) # Check if we are now turned off. elif (rx_data[0] == WV_PLUGIN_SWITCH_OFF): # Signal the data to append the plugin display. self.data_signal.emit(False) else: if DEBUG: print("Invalid header for", self.plugin_id, "from", self.address) else: if DEBUG: print("No data received for", self.plugin_id, "from", self.address, "or invalid data was received") else: if DEBUG: print("Invalid header for", self.plugin_id, "from", self.address) except: # Nothing to do here. pass
class RenderThread(QThread): ColormapSize = 512 renderedImage = pyqtSignal(QImage, float) def __init__(self, parent=None): super(RenderThread, self).__init__(parent) self.mutex = QMutex() self.condition = QWaitCondition() self.centerX = 0.0 self.centerY = 0.0 self.scaleFactor = 0.0 self.resultSize = QSize() self.colormap = [] self.restart = False self.abort = False for i in range(RenderThread.ColormapSize): self.colormap.append(self.rgbFromWaveLength(380.0 + (i * 400.0 / RenderThread.ColormapSize))) def __del__(self): self.mutex.lock() self.abort = True self.condition.wakeOne() self.mutex.unlock() self.wait() def render(self, centerX, centerY, scaleFactor, resultSize): locker = QMutexLocker(self.mutex) self.centerX = centerX self.centerY = centerY self.scaleFactor = scaleFactor self.resultSize = resultSize if not self.isRunning(): self.start(QThread.LowPriority) else: self.restart = True self.condition.wakeOne() def run(self): while True: self.mutex.lock() resultSize = self.resultSize scaleFactor = self.scaleFactor centerX = self.centerX centerY = self.centerY self.mutex.unlock() halfWidth = resultSize.width() // 2 halfHeight = resultSize.height() // 2 image = QImage(resultSize, QImage.Format_RGB32) NumPasses = 8 curpass = 0 while curpass < NumPasses: MaxIterations = (1 << (2 * curpass + 6)) + 32 Limit = 4 allBlack = True for y in range(-halfHeight, halfHeight): if self.restart: break if self.abort: return ay = 1j * (centerY + (y * scaleFactor)) for x in range(-halfWidth, halfWidth): c0 = centerX + (x * scaleFactor) + ay c = c0 numIterations = 0 while numIterations < MaxIterations: numIterations += 1 c = c*c + c0 if abs(c) >= Limit: break numIterations += 1 c = c*c + c0 if abs(c) >= Limit: break numIterations += 1 c = c*c + c0 if abs(c) >= Limit: break numIterations += 1 c = c*c + c0 if abs(c) >= Limit: break if numIterations < MaxIterations: image.setPixel(x + halfWidth, y + halfHeight, self.colormap[numIterations % RenderThread.ColormapSize]) allBlack = False else: image.setPixel(x + halfWidth, y + halfHeight, qRgb(0, 0, 0)) if allBlack and curpass == 0: curpass = 4 else: if not self.restart: self.renderedImage.emit(image, scaleFactor) curpass += 1 self.mutex.lock() if not self.restart: self.condition.wait(self.mutex) self.restart = False self.mutex.unlock() def rgbFromWaveLength(self, wave): r = 0.0 g = 0.0 b = 0.0 if wave >= 380.0 and wave <= 440.0: r = -1.0 * (wave - 440.0) / (440.0 - 380.0) b = 1.0 elif wave >= 440.0 and wave <= 490.0: g = (wave - 440.0) / (490.0 - 440.0) b = 1.0 elif wave >= 490.0 and wave <= 510.0: g = 1.0 b = -1.0 * (wave - 510.0) / (510.0 - 490.0) elif wave >= 510.0 and wave <= 580.0: r = (wave - 510.0) / (580.0 - 510.0) g = 1.0 elif wave >= 580.0 and wave <= 645.0: r = 1.0 g = -1.0 * (wave - 645.0) / (645.0 - 580.0) elif wave >= 645.0 and wave <= 780.0: r = 1.0 s = 1.0 if wave > 700.0: s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0) elif wave < 420.0: s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0) r = pow(r * s, 0.8) g = pow(g * s, 0.8) b = pow(b * s, 0.8) return qRgb(r*255, g*255, b*255)
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 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 FortuneThread(QThread): newFortune = pyqtSignal(str) error = pyqtSignal(int, str) def __init__(self, parent=None): super(FortuneThread, self).__init__(parent) self.quit = False self.hostName = '' self.cond = QWaitCondition() self.mutex = QMutex() self.port = 0 def __del__(self): self.mutex.lock() self.quit = True self.cond.wakeOne() self.mutex.unlock() self.wait() def requestNewFortune(self, hostname, port): locker = QMutexLocker(self.mutex) self.hostName = hostname self.port = port if not self.isRunning(): self.start() else: self.cond.wakeOne() def run(self): self.mutex.lock() serverName = self.hostName serverPort = self.port self.mutex.unlock() while not self.quit: Timeout = 5 * 1000 socket = QTcpSocket() socket.connectToHost(serverName, serverPort) if not socket.waitForConnected(Timeout): self.error.emit(socket.error(), socket.errorString()) return while socket.bytesAvailable() < 2: if not socket.waitForReadyRead(Timeout): self.error.emit(socket.error(), socket.errorString()) return instr = QDataStream(socket) instr.setVersion(QDataStream.Qt_4_0) blockSize = instr.readUInt16() while socket.bytesAvailable() < blockSize: if not socket.waitForReadyRead(Timeout): self.error.emit(socket.error(), socket.errorString()) return self.mutex.lock() fortune = instr.readQString() self.newFortune.emit(fortune) self.cond.wait(self.mutex) serverName = self.hostName serverPort = self.port self.mutex.unlock()
class RequestHandler(QObject): """ Worker object for handling requests. """ waitingRequest = pyqtSignal() requestAccepted = pyqtSignal() error = pyqtSignal(Exception) terminated = pyqtSignal() def __init__(self, parent): super(RequestHandler, self).__init__() self.parent = parent self.__terminated = False self.mutex = QMutex() self.waitForClick = QWaitCondition() def run(self): """ Uses parent's server to listen for request. When a valid request is handled, emits requestAccepted singal and waits on Mutex condition. The parent should wake the worker when a click is made via wakeOnClick() method. When woken respond to the request with the click that was made. Can be terminated from the parent. Listening ignores bad requests. If OSError occurres, terminates itself and emits error signal. On termination emits the terminate signal. """ # print('run') self.__terminated = False while not self.__terminated: # print('Waiting for request') self.waitingRequest.emit() try: self.parent.server.listen(self.onMoveRequest) except OSError as e: print('error ', e) self.error.emit(e) self.__terminated = True except BadRequestError as e: print(e) continue print('Worker terminated') self.terminated.emit() def onMoveRequest(self, name, macroboard): if self.__terminated: return None self.opponentName = name self.macroboard = macroboard self.requestAccepted.emit() self.__sleepUntilClick() if self.__terminated: return None move = self.parent.last_click return move def __sleepUntilClick(self): self.mutex.lock() self.waitForClick.wait(self.mutex) self.mutex.unlock() def wakeOnClick(self): self.mutex.lock() self.waitForClick.wakeOne() self.mutex.unlock() def terminate(self): """ Terminates the worker. """ if self.__terminated: return self.__terminated = True self.wakeOnClick() self.parent.server.stop()
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 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