def quit(self): if self.hasQuit: return self.hasQuit = True dprint("schedule to kill all python instances in a few seconds") skevents.runlater(lambda: os.system("tskill pythonw & tskill python"), config.QT_QUIT_TIMEOUT + config.QT_THREAD_TIMEOUT) # wait for for done or kill all threads from PySide.QtCore import QThreadPool if QThreadPool.globalInstance().activeThreadCount(): dwarn("warning: wait for active threads") QThreadPool.globalInstance().waitForDone(config.QT_THREAD_TIMEOUT) dprint("leave qthread pool") dprint("send quit signal to qApp") qApp = QCoreApplication.instance() # Make sure settings.sync is the last signal conneced with aboutToQuit #qApp.aboutToQuit.connect(self.settings.sync) skevents.runlater(qApp.quit)
def testSlowJobs(self): for i in range(3): task = Task() QThreadPool.globalInstance().start(task) time.sleep(1) # Sleep 1 second QThreadPool.globalInstance().waitForDone()
def quit(self): if self.hasQuit: return self.hasQuit = True import curtheme curtheme.unload() for w in self.widgets: if w.isVisible(): w.hide() # wait for for done or kill all threads from PySide.QtCore import QThreadPool if QThreadPool.globalInstance().activeThreadCount(): dwarn("warning: wait for active threads") QThreadPool.globalInstance().waitForDone(config.QT_THREAD_TIMEOUT) dprint("leave qthread pool") dprint("send quit signal to qApp") qApp = QCoreApplication.instance() # Make sure settings.sync is the last signal conneced with aboutToQuit #qApp.aboutToQuit.connect(self.settings.sync) skevents.runlater(qApp.quit)
def __loadInitialFieldValues(self): runnable = ProgressRunnable2(self.gui.getInfiniteProgressDialog()) runnable.setDialogMessage("Loading...") runnable.setRunMethod(self.manager.getObsServerList, reachable=True) runnable.finished[object].connect(self.__loadServerList) if not self.__isNewProject(): runnable.finished.connect(self.__loadKnownProjectValues) QThreadPool.globalInstance().start(runnable)
def execute(self, id_, data=None): """Generate the relation graph.""" if not data: data = self.read(id_) self.executed.emit('dependency', id_, data) worker = GraphWorker(id_, data, lambda: self._execute(id_, data)) worker.result_ready.connect(self._process_result) worker.exception_raised.connect(self._handle_exception) QThreadPool.globalInstance().start(worker)
def runOnGlobalInstance(self, wait=False): """ Run this ProgressRunnable on the global QThreadPool instance. If `wait` is True, process the UI events while waiting for the ProgressRunnable to finish. """ QThreadPool.globalInstance().start(self) if wait: # self.__finishedCalled is made True by the setHasFinished() # method, which is called from try/finally blocks so guaranteed # to be called even if there are exceptions. while not self.__finishedCalled: sleep(0.01) QApplication.processEvents()
def run(self): L.d("running") self.stopvar = False rex = re.compile(".*\[(\d{7})\]$") imdb_db = imdb.IMDb() db = get_user_db() tp = QThreadPool.globalInstance() writer = IndexWriter() count = 0 it = QDirIterator(self.media_path, QDirIterator.Subdirectories) while it.hasNext(): dir = it.next() try: directory = unicode(dir) match = rex.match(directory) if match: count += 1 imdb_id = match.group(1) movie = db.get_doc(imdb_id) if movie: L.d("%s already in db - skipping" % imdb_id) else: j = Job(imdb_db, imdb_id, self) j.obj.finished.connect(writer.index_movie, Qt.QueuedConnection) tp.start(j) except: pass print count self.exec_()
def __init__(self): super(PythonCalltipMode, self).__init__( self.IDENTIFIER, self.DESCRIPTION) self.__request_queue = deque() self.__is_running = False self.__threadPool = QThreadPool() self.__threadPool.setMaxThreadCount(1) self.__thread_counter = 0
def on_configDialog_accepted(self): progress = self.gui.getInfiniteProgressDialog() runnable = ProgressRunnable2() runnable.setProgressDialog(progress) if self.__oldRepoAlias is None: runnable.setDialogMessage( "Importing repository in project file system...") runnable.setRunMethod(self.manager.addRepo, self.__projectAlias, repoUrl=self.getRepoUrl(), alias=self.getRepoAlias()) else: runnable.setDialogMessage("Modifying repository...") runnable.setRunMethod(self.manager.modifyRepo, self.__projectAlias, self.__oldRepoAlias, newUrl=self.getRepoUrl(), newAlias=self.getRepoAlias()) runnable.caughtException.connect(self.gui.popupErrorCallback) QThreadPool.globalInstance().start(runnable)
def __init__(self): """ ClimateControlModel constructor Initializes Flow library, thread pool """ super(ClimateControlModel, self).__init__() self.__thread_pool = QThreadPool() self.__thread_pool.setMaxThreadCount(THREAD_POOL_MAX_THREADS) self.__flow_user = None self.__controller_device = None self.__checking_connection_status = False self.__last_measurement_event = None self.__last_relay_status_event = None self.__last_device_status_event = None self.__controller_heartbeat = None self.latency = Latency() self.__latency_timer = QTimer(self) self.__latency_timer.timeout.connect(self.__latency_timer_expired) ClimateControlModel.__message_received_signal = MessageReceived() ClimateControlModel.__message_received_signal.signal.connect( self.__message_received)
def importFromProject(self): """ Run this method in order to add the repository of another OBS project. """ projects = self.manager.getLocalProjectList() selectedProject, accepted = QInputDialog.getItem( self.mainWindow, "Select project", "Project to import repository from:", projects, editable=False) if not accepted: return progress = self.gui.getInfiniteProgressDialog() runnable = ProgressRunnable2() runnable.setProgressDialog(progress) runnable.setDialogMessage("Importing repository...") runnable.setRunMethod(self.manager.addRepo, self.__projectAlias, fromProject=selectedProject) runnable.caughtException.connect(self.gui.popupErrorCallback) QThreadPool.globalInstance().start(runnable)
def on_configDialog_accepted(self): if self.__isNewProject(): runnable = ProgressRunnable2(self.gui.getInfiniteProgressDialog()) runnable.setDialogMessage("Importing project...") runnable.caughtException.connect(self.gui.popupErrorCallback) runnable.setRunMethod( self.manager.addProject, self.getCurrentServerAlias(), self.getCurrentProjectObsName(), self.getCurrentTarget(), self.getCurrentArch(), projectLocalName=self.getCurrentProjectLocalName()) def emitFinished(): self.finished.emit(True) runnable.finished.connect(emitFinished) QThreadPool.globalInstance().start(runnable) else: # Currently we can't relocate a project. # self.manager.setProjectParameter(self.getCurrentProjectLocalName(), # "projectObsName", # self.getCurrentProjectObsName()) # self.manager.setProjectParameter(self.getCurrentProjectLocalName(), # "obsServer", # self.getCurrentServerAlias()) # self.manager.setProjectParameter(self.getCurrentProjectLocalName(), # u"projectTarget", # self.getCurrentTarget()) # self.manager.setProjectParameter(self.getCurrentProjectLocalName(), # u"projectArchitecture", # self.getCurrentArch()) self.manager.setProjectParameter(self.getCurrentProjectLocalName(), u"title", self.getCurrentTitle()) self.manager.setProjectParameter(self.getCurrentProjectLocalName(), u"description", self.getCurrentDescription()) self.finished.emit(True)
def deleteRepo(self): """ Run this method to remove a repository from the project file system. """ repos = self.manager.getChRootRepositories(self.__projectAlias) if repos is None or len(repos) < 1: return selectedAlias, accepted = QInputDialog.getItem( self.mainWindow, "Select repository", "Project repository to delete:", repos.keys(), editable=False) if not accepted: return progress = self.gui.getInfiniteProgressDialog() runnable = ProgressRunnable2() runnable.setProgressDialog(progress) runnable.setDialogMessage("Deleting repository...") runnable.setRunMethod(self.manager.deleteRepo, self.__projectAlias, selectedAlias) runnable.caughtException.connect(self.gui.popupErrorCallback) QThreadPool.globalInstance().start(runnable)
def __init__(self, name, description, base_cmd): super(CheckerMode, self).__init__(name, description) self.__thread_pool = QThreadPool() self.__thread_pool.setMaxThreadCount(1) self.__thread_counter = 0 self.__timer = QTimer() self.__timer.timeout.connect(self._runCmd) self.__timer.setInterval(500) self.__decorations = [] self.__markers = [] self.__canceled = False self.base_cmd = base_cmd self.checkers_panel = None self.colors = {ERROR_TYPE_WARNING: "#FF0000", ERROR_TYPE_SYNTAX: "#FFFF00"}
def startSimu(self): self.log("=== SIMULATIONS START ===") self.logText.clear() self.startTime = datetime.now() self.simulations = [] #self.nextPrate = 0 self.gapPrate = self.gapPrateOption.getValue() self.sameSimuTimes = self.sameSimuTimesOption.getValue() #self.nextSimu = 0 self.blockUi() self.simulationsDone = 0 #output = self.pathOption.getValue() + dateToFilename(d) + '_results.txt' pRate = 0 self.simulationsTotal = 0 # print 'sameSimuTimes: %d'%self.sameSimuTimes # print 'gapPrate: %d'%self.gapPrate while pRate <= 100: simu = 0 self.options['prate'] = pRate while simu<self.sameSimuTimes: waf = WafThread(self.options, self.pathOption.getValue(), self.scenarioOption.getName()) waf.setAutoDelete(True) waf.simuDone.connect(self.wafDone) self.simulations.append(waf) QThreadPool.globalInstance().start(waf) self.simulationsTotal += 1 simu += 1 pRate += self.gapPrate runningSimulations = 'Running %d Simulations...' % self.simulationsTotal self.startButton.setText(runningSimulations) self.log(runningSimulations) self.progressBar.setRange(0,self.simulationsTotal) self.progressBar.setValue(0) # 300 seconds per task average roughTime = self.simulationsTotal*self.resultsWidget.averageSimulationTime/QThreadPool.globalInstance().maxThreadCount() self.infoLabel.setText('Rough time estimation: %s' % formatTimeLeft(roughTime))
def __init__(self): super(CodeCompletionMode, self).__init__( self.IDENTIFIER, self.DESCRIPTION) self.thread_pool = QThreadPool() self.thread_pool.setMaxThreadCount(2) self.__cached_request = None self.__active_thread_count = 0 self.__updating_models = False self.__timer = QTimer() #: Defines the min number of suggestions. This is used to know we should # avoid using lower priority models. # If there is at least minSuggestions in the suggestions list, we won't # use other completion model. self.minSuggestions = 50 #: Trigger key (automatically associated with the control modifier) self.triggerKey = Qt.Key_Space #: Number of chars needed to trigger the code completion self.nbTriggerChars = 1 #: Tells if the completion should be triggered automatically (when # len(wordUnderCursor) > nbTriggerChars ) # Default is True. Turning this option off might enhance performances # and usability self.autoTrigger = True self.periodIsTrigger = True #: Show/Hide current suggestion tooltip self.displayTooltips = True self.__caseSensitivity = Qt.CaseSensitive #: The internal QCompleter self.__completer = QCompleter() # self.__completer.activated.connect(self._insertCompletion) self.__completer.highlighted.connect(self._onHighlighted) self.__completer.activated.connect(self._insertCompletion) self.__prev_txt_len = 0 #: List of completion models self._models = [] self.__tooltips = {}
def __init__(self): """ ClimateControlModel constructor Initializes Flow library, thread pool """ super(ClimateControlModel, self).__init__() self.__thread_pool = QThreadPool() self.__thread_pool.setMaxThreadCount(THREAD_POOL_MAX_THREADS) self.__flow_user = None self.__controller_device = None self.__checking_connection_status = False self.__last_measurement_event = None self.__last_relay_status_event = None self.__last_device_status_event = None self.__controller_heartbeat = None self.latency = Latency() self.__latency_timer = QTimer(self) self.__latency_timer.timeout.connect(self.__latency_timer_expired) ClimateControlModel.__message_received_signal = MessageReceived() ClimateControlModel.__message_received_signal.signal.connect(self.__message_received)
caughtException.traceback = traceback_ results.append((arg, 1)) finally: if caughtException is not None: self.setHasCaughtException(caughtException) self.setHasProgressed() except: print sys.exc_info() finally: self.setHasFinished(results) self.deleteLater() self.run = run QThreadPool.globalInstance().setExpiryTimeout(0) def firstArgLast(func): """ Return a function which will call 'func' with first argument as last argument. """ def swappedArgsFunc(*args, **kwargs): newArgs = list(args[1:]) newArgs.append(args[0]) return func(*newArgs, **kwargs) return swappedArgsFunc
class PythonCalltipMode(Mode): IDENTIFIER = "Python calltips mode" DESCRIPTION = "Provides call tips in python function/methods calls" def _onStateChanged(self, state): if state is True: self.editor.codeEdit.keyReleased.connect(self.__onKeyReleased) else: self.editor.codeEdit.keyReleased.disconnect(self.__onKeyReleased) def __onKeyReleased(self, event): if event.key() == Qt.Key_ParenLeft or \ event.key() == Qt.Key_Comma or \ event.key() == Qt.Key_Space: if self.__thread_counter >= 1: return self.__thread_counter += 1 tc = self.editor.codeEdit.textCursor() line = tc.blockNumber() + 1 col = tc.columnNumber() fn = self.editor.codeEdit.tagFilename encoding = self.editor.codeEdit.tagEncoding source = self.editor.codeEdit.toPlainText() runnable = RunnableCalltip( CalltipRequest(source_code=source, line=line, col=col, filename=fn, encoding=encoding)) runnable.failedEvent.signal.connect(self.__apply_results) runnable.resultsAvailable.signal.connect(self.__apply_results) self.__threadPool.start(runnable) else: QToolTip.hideText() def __apply_results(self, call=None, request=None): # QToolTip.hideText() self.__thread_counter -= 1 if call: # create a formatted calltip (current index appear in bold) calltip = "<nobr>{0}.{1}(".format( call.module.name, call.call_name) for i, param in enumerate(call.params): if i != 0: calltip += ", " if i == call.index: calltip += "<b>" calltip += unicode(param.token_list[0]) if i == call.index: calltip += "</b>" calltip += ')</nobr>' # set tool tip position at the start of the bracket charWidth = self.editor.codeEdit.fm.width('A') w_offset = (request.col - call.bracket_start[1]) * charWidth position = QPoint( self.editor.codeEdit.cursorRect().x() - w_offset, self.editor.codeEdit.cursorRect().y()) position = self.editor.codeEdit.mapToGlobal(position) # show tooltip QToolTip.showText(position, calltip, self.editor.codeEdit) else: QToolTip.hideText() def __init__(self): super(PythonCalltipMode, self).__init__( self.IDENTIFIER, self.DESCRIPTION) self.__request_queue = deque() self.__is_running = False self.__threadPool = QThreadPool() self.__threadPool.setMaxThreadCount(1) self.__thread_counter = 0
class ClimateControlModel(QObject): """ Model class representing the climate control system Talks with flow, fetches required data from flow, caches some of the data """ __message_received_signal = None setting_received = Signal(dict) save_setting_result = Signal(dict) measurement_changed = Signal(MeasurementEvent) relay_status_changed = Signal(RelayStatusEvent) device_status_changed = Signal(DeviceStatusEvent) controller_status = Signal(str) command_response_received = Signal(dict) command_sending_result = Signal(dict) connection_status = Signal(dict) latency_changed = Signal(float) def __init__(self): """ ClimateControlModel constructor Initializes Flow library, thread pool """ super(ClimateControlModel, self).__init__() self.__thread_pool = QThreadPool() self.__thread_pool.setMaxThreadCount(THREAD_POOL_MAX_THREADS) self.__flow_user = None self.__controller_device = None self.__checking_connection_status = False self.__last_measurement_event = None self.__last_relay_status_event = None self.__last_device_status_event = None self.__controller_heartbeat = None self.latency = Latency() self.__latency_timer = QTimer(self) self.__latency_timer.timeout.connect(self.__latency_timer_expired) ClimateControlModel.__message_received_signal = MessageReceived() ClimateControlModel.__message_received_signal.signal.connect( self.__message_received) def initialize(self, user_name, password): """ Initializes the system Initializes flow libraries and connects to server Logs in as user and tries to find the controller device, caches if found :param str user_name: flow user name :param str password: flow user password :raises ControllerNotFound, LoginFailed, FlowLibraryError """ flow_url, flow_key, flow_secret = get_server_details() try: flow_initialize(flow_url, flow_key, flow_secret) except FlowException as flow_error: if flow_error.connection_error: self.check_connection_status() LOGGER.exception(flow_error) raise FlowLibraryError("Failed to initialize flow library") try: self.__flow_user = FlowUser(user_name, password) except FlowException as flow_error: if flow_error.connection_error: self.check_connection_status() LOGGER.exception(flow_error) raise LoginFailed() except ValueError as value_error: LOGGER.exception(value_error) raise LoginFailed() try: self.__controller_device = self.__flow_user.find_device( CONTROLLER_DEVICE_TYPE) except FlowException as flow_error: if flow_error.connection_error: self.check_connection_status() LOGGER.exception(flow_error) raise ControllerNotFound() # enable message reception self.__flow_user.enable_message_reception( ClimateControlModel.message_received_callback) def close(self): """ De-initialize the model This function won't return till all the worker thread finish their job """ LOGGER.debug("waiting for threads in thread pool") self.__thread_pool.waitForDone() LOGGER.debug("thread pool exit done") if self.__flow_user: self.__flow_user.logout() def get_settings(self): """ Get setting for the controller device Schedules a worker thread for getting setting """ runnable = WorkerThread(get_setting_work, self.__settings_received, device=self.__controller_device, key=ControllerSetting.controller_config_key) self.__thread_pool.start(runnable) def save_settings(self, setting): """ Save setting of controller device :param ControllerSetting setting: setting object to be saved in KVS """ setting_xml = setting.to_xml() LOGGER.debug("Trying to save setting xml = {}".format(setting_xml)) runnable = WorkerThread(save_setting_work, self.__save_settings_result, device=self.__controller_device, key=ControllerSetting.controller_config_key, value=setting_xml) self.__thread_pool.start(runnable) def send_command(self, command): """ Send command to the controller device :param ControllerCommandEnum command: command to be sent """ if command not in ControllerCommandEnum: raise InvalidCommand("Command not supported") LOGGER.info("sending command {}".format(command.value)) command_xml = ControllerCommand(command).xml LOGGER.debug("command xml {}".format(command_xml)) runnable = WorkerThread(send_command_work, self.__command_sent_result, user=self.__flow_user, device=self.__controller_device, message=command_xml) self.__thread_pool.start(runnable) def check_connection_status(self): """ Starts worker thread for checking connection status """ if not self.__checking_connection_status: self.__checking_connection_status = True runnable = WorkerThread(check_connection_status_work, self.__connection_status_result) self.__thread_pool.start(runnable) @Slot(str, str) def __settings_received(self, setting, error): """ Slot function called when get setting worker thread finishes the task :param str setting: received setting from flow :param str error: error string if any """ parsed_setting = None if not error: LOGGER.debug("Received setting xml = {}".format(setting)) try: parsed_setting = ControllerSetting(setting_xml=setting) if not self.__controller_heartbeat: # start heartbeat timer with twice the heartbeat period so that even if some # heartbeat message failed to receive, it should wait for another # heartbeat message self.__controller_heartbeat = \ HeartBeatTimer(parsed_setting.controller_heartbeat*2*1000, self.__heartbeat_timer_status_changed) else: # if heartbeat already exist then restart with new time self.__controller_heartbeat.change_timeout_period( parsed_setting.controller_heartbeat * 2 * 1000) except ValueError as value_error: LOGGER.exception(value_error) error = "Invalid setting XML received" else: if error["connection_error"]: self.check_connection_status() self.setting_received.emit({"setting": parsed_setting, "error": error}) @Slot(str) def __save_settings_result(self, error=None): """ Slot function for the save setting worker function result :param str error: error string if any """ self.save_setting_result.emit({"error": error}) if error: LOGGER.debug("Save setting failed: {}".format(error)) if error["connection_error"]: self.check_connection_status() else: # if KVS updated then send message to device to update the settings self.send_command(ControllerCommandEnum.retrieve_settings) LOGGER.debug("Setting saved to KVS") @Slot(bool, bool) def __connection_status_result(self, network, internet): """ Slot function for connection status result :param bool network: False if network is down :param bool internet: False if internet is down """ self.__checking_connection_status = False connection_status = {"network": network, "internet": internet} self.connection_status.emit(connection_status) @Slot(str) def __command_sent_result(self, error=None): """ Slot function called at the end of sending command :param str error: error string if any """ if error: self.command_sending_result.emit({"error": error}) LOGGER.debug("Message sending failed: {}".format(error)) if error["connection_error"]: self.check_connection_status() else: LOGGER.debug("Message sending success") # pylint: disable=invalid-name @Slot(str) def __heartbeat_timer_status_changed(self, status): """ Slot function called when heartbeat timer changes its status(start, expire etc) It receives controller status. on timer expire-controller status = "OFFLINE" on timer refresh(start)- controller status = "ONLINE" :param str status: "ONLINE" or "OFFLINE" status """ self.controller_status.emit(status) if status == "OFFLINE": # timer expired so there might be something wrong with the # network or internet so check connection status self.check_connection_status() LOGGER.debug("Latency timer stopped") self.__latency_timer.stop() if self.__last_device_status_event: # if controller is OFFLINE, make sensor and actuator also OFFLINE self.__last_device_status_event.sensor_alive = False self.__last_device_status_event.actuator_alive = False self.device_status_changed.emit( self.__last_device_status_event) else: self.__latency_timer.start(LATENCY_PERIOD * 1000) LOGGER.debug("Latency timer started") # pylint: enable=invalid-name @Slot() def __latency_timer_expired(self): """ Slot called on the expiry of latency timer """ # send ping message to controller and calculate latency based on when it is received self.send_command(ControllerCommandEnum.ping) def __handle_command_response(self, response_dict): """ Parse the received response and emit signal if valid response found :param dict response_dict: response xml dictionary """ try: response = ControllerResponse(response_dict) LOGGER.info("received response {}".format(response.response.value)) if response.response == ControllerResponseEnum.ping: # round_trip_time is the difference between current local time and timestamp # when message was sent, this includes any processing delay on controller side round_trip_time = (datetime.datetime.utcnow() - response.sent_time).total_seconds() LOGGER.debug("round_trip_time: {}".format(round_trip_time)) # Ignore value where round_trip_time > MAX_LATENCY_TIME if round_trip_time <= MAX_LATENCY_VALUE: latency = self.latency.calculate_exponential_moving_average( round_trip_time) else: latency = round_trip_time self.latency_changed.emit(latency) LOGGER.debug("Latency: {}".format(latency)) else: self.command_response_received.emit( {"response": response.response}) # if retrieve_settings_success is received, get the settings again as it might # be update by some other app # for e.g. admin app updating threshold and display app updating its values accordingly if response.response == ControllerResponseEnum.retrieve_settings_success: self.get_settings() except ValueError as error: LOGGER.exception(error) def __process_heartbeat_event(self, event): """ Processes HeartBeat event data :param HeartBeatEvent event: HeartBeat event object """ if self.__last_measurement_event: if not event.measurement_data == self.__last_measurement_event: self.measurement_changed.emit(event.measurement_data) self.__last_measurement_event = event.measurement_data else: LOGGER.debug("Ignoring measurement data") else: self.measurement_changed.emit(event.measurement_data) self.__last_measurement_event = event.measurement_data LOGGER.debug("Heartbeat Temp: {} Humidity: {} ".format( event.measurement_data.temperature, event.measurement_data.humidity)) if self.__last_relay_status_event: if not event.relay_status == self.__last_relay_status_event: self.relay_status_changed.emit(event.relay_status) self.__last_relay_status_event = event.relay_status else: LOGGER.debug("Ignoring relay status data") else: self.relay_status_changed.emit(event.relay_status) self.__last_relay_status_event = event.relay_status if self.__last_device_status_event: if not event.device_status == self.__last_device_status_event: self.device_status_changed.emit(event.device_status) self.__last_device_status_event = event.device_status else: LOGGER.debug("Ignoring device status data") else: self.device_status_changed.emit(event.device_status) self.__last_device_status_event = event.device_status LOGGER.debug("Heartbeat Temp: {} Humidity: {} " "Relay 1 ON: {} Relay 2 ON: {} " "Sensor: {} Actuator: {}".format( event.measurement_data.temperature, event.measurement_data.humidity, event.relay_status.relay_1_on, event.relay_status.relay_2_on, event.device_status.sensor_alive, event.device_status.actuator_alive)) def __handle_event(self, message_dict): """ Create event object according to event type and handle the event :param dict message_dict: message content in the dictionary format """ try: event = ControllerEventFactory.create_event(message_dict) if self.__controller_heartbeat: self.__controller_heartbeat.refresh_timer() if isinstance(event, MeasurementEvent): self.measurement_changed.emit(event) self.__last_measurement_event = event LOGGER.debug("Measurement Temp: {} Humidity: {}".format( event.temperature, event.humidity)) elif isinstance(event, RelayStatusEvent): self.relay_status_changed.emit(event) self.__last_relay_status_event = event LOGGER.debug( "RelayStatus Relay 1 ON: {} Relay 2 ON: {}".format( event.relay_1_on, event.relay_2_on)) elif isinstance(event, DeviceStatusEvent): self.device_status_changed.emit(event) self.__last_device_status_event = event LOGGER.debug("DeviceStatus Sensor: {} Actuator: {}".format( event.sensor_alive, event.actuator_alive)) elif isinstance(event, HeartBeatEvent): self.__process_heartbeat_event(event) except ValueError as value_error: LOGGER.exception(value_error) @Slot(str) def __message_received(self, message_content): """ Slot function called when message is received by callback function This function parses message_content(xml_string) into dictionary :param str message_content: message content which is xml string """ LOGGER.debug("Received message {}".format(message_content)) # We have received a message from controller means network and internet are up status = {"network": True, "internet": True} self.connection_status.emit(status) try: message_dict = xmltodict.parse(message_content) root_tag = message_dict.keys()[0] if root_tag == "response": self.__handle_command_response(message_dict) elif root_tag == "event": self.__handle_event(message_dict) else: LOGGER.error( "Unsupported message received {}".format(message_content)) except (ExpatError, KeyError) as error: LOGGER.exception("Error in parsing xml {} xml={}".format( error.message, message_content)) @staticmethod def message_received_callback(flow_message): """ Callback called by library, libflow expects this to be a static class method :param flow_message: message object from library """ message = FlowMessage(flow_message) message_content = message.get_message_content() ClimateControlModel.__message_received_signal.signal.emit( message_content)
def stop_thread_func(self, ui): runnable = Ui_Form.StopRunnable(ui) QThreadPool.globalInstance().start(runnable)
def handleTargetIndexChanged(self): task = ProgressRunnable2() task.setRunMethod(self.__loadArchPossibilities) QThreadPool.globalInstance().start(task)
try: result = "%3.3d\t%f" % (int(r['settings']['prate']),float(r['results']['timeToReachDest'])) except TypeError, e: result = 'PYTHON ERROR: %s | File: %s' % (e, outputPath) print result print r else: result = 'ERROR: No timeToReachDest (%s)' % outputPath self.startButton.setText('%d simulations left...' % simulationsLeft) self.log(result) # with open(self.resultFile, 'a') as summary: # summary.write('%s | %s\n' % (datetime.now(), result)) # summary.close() self.progressBar.setValue(self.simulationsDone) if self.simulationsDone==self.simulationsTotal: QThreadPool.globalInstance().waitForDone() del self.simulations[:] self.releaseUi() if self.actionWhenDone.currentIndex()==1: self.saveSettings() from time import sleep print 'shutdown in 20 seconds...' sleep(20) os.system('sudo halt') elif self.actionWhenDone.currentIndex()==2: self.startSimu() else: # calculate estimated time left # percentage_done = 1.0*self.simulationsDone/self.simulationsTotal # done_in = (datetime.now()-self.startTime).seconds # timeLeft = done_in*((1.0/percentage_done)-1.0)
def main(): """ @return int """ import os, sys from PySide.QtCore import QTextCodec # Use UTF-8 encoding for Qt #sys_codec = QTextCodec.codecForLocale() u8codec = QTextCodec.codecForName("UTF-8") QTextCodec.setCodecForCStrings(u8codec) QTextCodec.setCodecForTr(u8codec) debug = '--debug' in sys.argv # bool print >> sys.stderr, "reader: debug = %s" % debug from sakurakit import skdebug #skdebug.DEBUG = config.APP_DEBUG or '--debug' in sys.argv skdebug.DEBUG = debug import config config.APP_DEBUG = debug from sakurakit.skdebug import dprint, dwarn dprint("enter") if '--help' in sys.argv: print_help() dprint("exit: help") #sys.exit(os.EX_USAGE) return 0 # Singleton # - Through mutex # See: http://code.activestate.com/recipes/474070-creating-a-single-instance-application/ # See: http://code.google.com/p/python-windows-tiler/source/browse/singleinstance.py # - Through file # See: http://stackoverflow.com/questions/380870/python-single-instance-of-program dprint("check single instance") from lockfile import lockfile app_mutex = lockfile.SingleProcessMutex() single_app = app_mutex.tryLock() if not single_app: dprint("multiple instances are running") dprint("python = %s" % sys.executable) #dprint("rootdir = %s" % rootdir) #dprint("mecabrc = %s" % mecabrc_path) from sakurakit import skos # Must be set before any GUI is showing up # http://stackoverflow.com/questions/1551605/how-to-set-applications-taskbar-icon-in-windows-7 if skos.WIN: dprint("set app id") from sakurakit import skwin skwin.set_app_id("org.sakurakit.reader") # Detect user language import settings ss = settings.global_() uilang = ss.uiLanguage() if not uilang: uilang = guess_language() ss.setValue('Language', uilang) lang = ss.userLanguage() if not lang: lang = guess_language() ss.setValue('UserLanguage', lang) dprint("user language = %s" % lang) # Warm-up shiboken dlls #if os.name == 'nt': # dprint("load shiboken plugins") # import pytexscript # import pytexthook #Switch to OpenGL engine #from Qt5.QtWidgets import QApplication #QApplication.setGraphicsSystem("opengl") #dprint("elevate process priviledges") #from sakurakit import skos #if skos.WIN: # from sakurakit import skwin # skwin.enable_drop_event() dprint("init dic locations") from opencc import opencc opencc.setdicpaths(config.OPENCC_DICS) from hanviet import hanviet hanviet.setdicpaths(config.HANVIET_DICS) from hanjaconv import hanjaconv hanjaconv.setdicdir(config.HANJA_DIC_PATH) from pinyinconv import pinyinconv pinyinconv.setdicpath(config.PINYIN_DIC_PATH) dprint("create app") import app a = app.Application(sys.argv) #dprint("os default font:", a.font()) #a.setFont(config.FONT_DEFAULT) #dprint("current default font:", a.font()) # Fix the encoding issue for the current directory #from PySide.QtCore import QDir #QDir.setCurrent(a.applicationDirPath()) if not single_app: from rpcman import RpcClient dprint("send metacall") r = RpcClient() r.start() if r.waitForConnected(): r.activate() a.processEvents() else: dprint("warning: cannot connect to the server") dwarn("leave: multiple instance") #sys.exit(os.EX_UNAVAILABLE) return 0 # Must come after QApplication is created dprint("load fonts") from PySide.QtGui import QFontDatabase for path in config.FONT_LOCATIONS.itervalues(): if os.path.exists(path): for root, dirs, files in os.walk(path): FONT_EXTS = frozenset(('.otf', '.ttf', '.ttc')) for f in files: if os.path.splitext(f.lower())[1] in FONT_EXTS: p = os.path.join(root, f) index = QFontDatabase.addApplicationFont(p) if index >= 0: dprint( QFontDatabase.applicationFontFamilies(index)) else: dwarn("failed to load font %s" % f) ff = config.ui_font(ss.uiLanguage()) if ff: a.setFontFamily(ff) #ff = ss.applicationFontFamily() #if ff: # dprint("font family = %s" % ff) # a.setFontFamily(ff) #ss.applicationFontFamilyChanged.connect(a.setFontFamily) dprint("load translation") a.loadTranslations() dprint("autosync settings") ss.autoSync() # Load before qapplication is created opt_splash = '--nosplash' not in sys.argv if opt_splash: dprint("show splash") from splashscreen import StartupSplashScreen splash = StartupSplashScreen() splash.show() a.processEvents() # process event to make it show #dprint("cache fonts") #import fonts #fonts.test() # Take the ownership of sakurakit translation dprint("take the ownership of translations") from sakurakit import sktr sktr.manager().setParent(a) import mytr mytr.manager().setParent(a) mytr.my.setParent(a) # There should be at least one existing window (rootWindow), or sth is wrong #a.setQuitOnLastWindowClosed(False) #dprint("check unicode codec") #from sakurakit.skunicode import qunicode #ustr = qunicode("あのね", 'utf8') #assert ustr, "failed to load text code plugin from qt.conf" #dprint('init directories') #from PySide.QtCore import QDir import rc from sakurakit import skfileio dprint("remove broken caches") for it in rc.DIR_APP_TMP, : if os.path.exists(it): skfileio.removetree(it) map( skfileio.makedirs, ( rc.DIR_YAML_SUB, rc.DIR_XML_COMMENT, rc.DIR_XML_VOICE, rc.DIR_XML_REF, #rc.DIR_DICT_MECAB, # not used rc.DIR_CACHE_AVATAR, rc.DIR_CACHE_AWS, rc.DIR_CACHE_DATA, rc.DIR_CACHE_IMAGE, rc.DIR_CACHE_DMM, rc.DIR_CACHE_TOKUTEN, rc.DIR_CACHE_FREEM, rc.DIR_CACHE_STEAM, rc.DIR_CACHE_MELON, rc.DIR_CACHE_GETCHU, rc.DIR_CACHE_GYUTTO, rc.DIR_CACHE_DIGIKET, rc.DIR_CACHE_DLSITE, rc.DIR_CACHE_HOLYSEAL, rc.DIR_CACHE_SCAPE, rc.DIR_CACHE_TRAILERS, rc.DIR_CACHE_WEB, rc.DIR_CACHE_SYNC, rc.DIR_TMP_OCR, rc.DIR_TMP_TERM, # not needed, though rc.DIR_TMP_TTS, )) if skos.WIN: from sakurakit import skwin for it in rc.DIR_APP_LIBRARY, rc.DIR_APP_CACHE: if os.path.exists(it): skwin.set_file_readonly(it) dprint("load settings") ss.setParent(a) dprint("append library path") from sakurakit import skpaths skpaths.append_paths(( # TransCAT must be initialized BEFORE JBeijing, or the translation will fail ss.transcatLocation(), ss.jbeijingLocation(), ss.ezTransLocation(), ss.atlasLocation(), ss.zunkoLocation(), ss.localeEmulatorLocation(), ss.ntleasLocation(), os.path.join(ss.dreyeLocation(), r"DreyeMT\SDK\bin") if ss.dreyeLocation() else "", )) path = ss.lecLocation() if path: skpaths.append_paths(( os.path.join(path, r"Nova\JaEn"), os.path.join(path, r"PARS\EnRU"), )) path = ss.fastaitLocation() if path: path = os.path.join(path, 'GTS') if os.path.exists(path): dllpaths = skfileio.listdirs(path) if dllpaths: skpaths.append_paths(dllpaths) if sys.getrecursionlimit() < config.PY_RECURSION_LIMIT: dprint("increase recursion limit") sys.setrecursionlimit(config.PY_RECURSION_LIMIT) dprint("reduce socket timeout") import socket socket.setdefaulttimeout(config.PY_SOCKET_TIMEOUT) #import threading #if threading.stack_size() < config.PY_STACK_SIZE: # dprint("increase stack size") # threading.stack_size(config.PY_STACK_SIZE) # On unix: # stackoverflow.com/questions/5061582/setting-stacksize-in-a-python-script #import resource #resource.setrlimit(resource.RLIMIT_STACK, (2**29,-1)) dprint("config python site-packages") # Disable requests SSL certificate warning # https://github.com/kennethreitz/requests/issues/2214 import requests requests.packages.urllib3.disable_warnings() # Disable HTTP request session # See: http://docs.python-requests.org/en/latest/user/advanced/#keep-alive # See: http://stackoverflow.com/questions/10115126/python-requests-close-http-connection #import requests #s = requests.session() #s.config['keep_alive'] = False import numpy numpy.seterr(all='ignore') # ignore overflow warning dprint("update settings") ss_version = ss.version() if ss_version != config.VERSION_TIMESTAMP: dprint("app update detected, migrate settings") if ss_version: migrate(ss_version) from sakurakit import skdatetime ss.setUpdateTime(skdatetime.current_unixtime()) ss.setVersion(config.VERSION_TIMESTAMP) ss.sync() if not ss.userName() or not ss.userId(): dprint("set user credential to guest") # Must be consistent with dataman.GUEST ss.setValue('UserId', 4) ss.setValue('UserName', 'guest') ss.setValue('UserPassword', 'guest') ss.setValue('UserGender', '') ss.setValue('UserAvatar', '') ss.setValue('UserColor', '') if ss.isCursorThemeEnabled(): dprint("load cursor theme") import curtheme curtheme.load() # Disable RBMT if CaboCha or UniDic is disabled #if ss.isTranslationSyntaxEnabled() and not ( # ss.isCaboChaEnabled() and ss.meCabDictionary() == 'unidic'): # ss.setTranslationSyntaxEnabled(False) #dprint("set max thread count") from PySide.QtCore import QThreadPool currentThreadCount = QThreadPool.globalInstance().maxThreadCount() if currentThreadCount < config.QT_THREAD_COUNT: dprint("increase thread pool capacity: %s -> %s" % (currentThreadCount, config.QT_THREAD_COUNT)) QThreadPool.globalInstance().setMaxThreadCount(config.QT_THREAD_COUNT) dprint("register qml plugins") import qmlplugin dprint("query system metrics") import sysinfo dprint("create main object") import main m = main.MainObject(a) m.init() if opt_splash: dprint("schedule to finish splash") splash.finishLater(1500) # hide after 1.5 seconds from functools import partial from sakurakit import skevents skevents.runlater(partial(m.run, a.arguments()), 50) #m.run(a.arguments()) #import netman #netman.manager().queryComments(gameId=183) #import hashutil #print hashutil.md5sum('/Users/jichi/tmp/t.cpp') dprint("exec") returnCode = a.exec_() # FIXME: Cannot normally exit # Shiboken 1.2 hang on exit! # All destructors are Invoked! dprint("unlock the mutex") app_mutex.unlock() import defs if returnCode == defs.EXIT_RESTART: skos.restart_my_process(['-B']) # -B: force disabling *.pyc and *.pyo else: #sys.exit(returnCode) #if skos.WIN: # prevent hanging on windows/mac skos.kill_my_process()
def stop_thread_func(): runnable = StopRunnable() QThreadPool.globalInstance().start(runnable)
else: j = Job(imdb_db, imdb_id, self) j.obj.finished.connect(writer.index_movie, Qt.QueuedConnection) tp.start(j) except: pass print count self.exec_() def set_stopped(self): L.d("setting stopvar") self.stopvar = True QTimer.singleShot(10, self._shutdown) def _shutdown(self): tp = QThreadPool.globalInstance() L.d("waiting for threadpool to be done...") tp.waitForDone() self.quit() if __name__ == "__main__": app = QApplication(sys.argv) tp = QThreadPool.globalInstance() tp.setMaxThreadCount(8) t = IndexThread("/tmp/mv/") t.start() sys.exit(app.exec_())
def main(): # Use UTF-8 encoding for Qt from PySide.QtCore import QTextCodec #sys_codec = QTextCodec.codecForLocale() u8codec = QTextCodec.codecForName("UTF-8") QTextCodec.setCodecForCStrings(u8codec) QTextCodec.setCodecForTr(u8codec) import config from sakurakit import skdebug #skdebug.DEBUG = config.APP_DEBUG or '--debug' in sys.argv skdebug.DEBUG = '--debug' in sys.argv print "browser: debug = %s" % skdebug.DEBUG from sakurakit.skdebug import dprint, dwarn dprint("enter") if '--help' in sys.argv: print_help() dprint("leave: help") return dprint("python = %s" % sys.executable) #dprint("rootdir = %s" % rootdir) #dprint("mecabrc = %s" % mecabrc_path) from sakurakit import skos if skos.WIN: dprint("set app id") from sakurakit import skwin skwin.set_app_id("org.sakurakit.browser") import rc for it in ( rc.DIR_CACHE_DATA, rc.DIR_CACHE_HISTORY, rc.DIR_CACHE_NETMAN, rc.DIR_CACHE_WEBKIT, ): if not os.path.exists(it): try: os.makedirs(it) except OSError: dwarn("warning: failed to create directory: %s" % it) dprint("init opencc") from opencc import opencc opencc.setdicpaths(config.OPENCC_DICS) dprint("create app") import app a = app.Application(sys.argv) dprint("load translations") a.loadTranslations() # Take the ownership of sakurakit translation from sakurakit import sktr sktr.manager().setParent(a) dprint("load settings") import settings ss = settings.global_() ss.setParent(a) reader = settings.reader() #reader.setParent(a) # reader does NOT have a app parent dprint("update settings") ss_version = ss.version() if ss_version != config.VERSION_TIMESTAMP: dprint("app update detected, migrate settings") if ss_version: from sakurakit import skfileio if ss_version <= 1417339268: for it in ( #rc.DIR_CACHE_DATA, rc.DIR_CACHE_HISTORY, rc.DIR_CACHE_NETMAN, rc.DIR_CACHE_WEBKIT, ): if os.path.exists(it): skfileio.removetree(it) try: os.makedirs(it) except OSError: dwarn("warning: failed to create directory: %s" % it) if ss_version <= 1396371158: skfileio.removefile(rc.COOKIES_LOCATION) ss.setVersion(config.VERSION_TIMESTAMP) ss.sync() if reader.isCursorThemeEnabled(): dprint("load cursor theme") import curtheme curtheme.load() from sakurakit import skpaths skpaths.append_paths(( #reader.localeEmulatorLocation(), reader.jbeijingLocation(), reader.ezTransLocation(), reader.atlasLocation(), os.path.join(reader.lecLocation(), r"Nova\JaEn") if reader.lecLocation() else "", os.path.join(reader.dreyeLocation(), r"DreyeMT\SDK\bin") if reader.dreyeLocation() else "", )) path = reader.fastaitLocation() if path: path = os.path.join(path, "GTS") if os.path.exists(path): from sakurakit import skfileio dllpaths = skfileio.listdirs(path) if dllpaths: skpaths.append_paths(dllpaths) dprint("set max thread count") from PySide.QtCore import QThreadPool if QThreadPool.globalInstance().maxThreadCount() < config.QT_THREAD_COUNT: QThreadPool.globalInstance().setMaxThreadCount(config.QT_THREAD_COUNT) dprint("load web settings") import webrc webrc.update_web_settings() if reader.isMainlandChina(): dprint("set up proxy") from google import googletts googletts.setapi(config.PROXY_GOOGLE_TTS) import googleman googleman.setapi(config.PROXY_GOOGLE_TRANS) dprint("create main object") import main m = main.MainObject() m.run(a.arguments()) dprint("exec") sys.exit(a.exec_())
def _shutdown(self): tp = QThreadPool.globalInstance() L.d("waiting for threadpool to be done...") tp.waitForDone() self.quit()
class CheckerMode(Mode): def __init__(self, name, description, base_cmd): super(CheckerMode, self).__init__(name, description) self.__thread_pool = QThreadPool() self.__thread_pool.setMaxThreadCount(1) self.__thread_counter = 0 self.__timer = QTimer() self.__timer.timeout.connect(self._runCmd) self.__timer.setInterval(500) self.__decorations = [] self.__markers = [] self.__canceled = False self.base_cmd = base_cmd self.checkers_panel = None self.colors = {ERROR_TYPE_WARNING: "#FF0000", ERROR_TYPE_SYNTAX: "#FFFF00"} def _onStateChanged(self, state): if state: self.editor.codeEdit.textSaved.connect(self.__onTextChanged) self.editor.codeEdit.newTextSet.connect(self.__onTextChanged) if hasattr(self.editor, "checkers_panel"): self.checkers_panel = self.editor.checkers_panel else: self.editor.codeEdit.textSaved.disconnect(self.__onTextChanged) self.editor.codeEdit.newTextSet.disconnect(self.__onTextChanged) self.checkers_panel = None def __clear_decorations(self): for deco in self.__decorations: self.editor.codeEdit.removeDecoration(deco) self.__decorations[:] = [] def __clear_markers(self): for marker in self.__markers: if self.checkers_panel: try: self.checkers_panel.removeMarker(marker) except ValueError: pass self.__markers[:] = [] def addError(self, error_type, line, column=1, message=None, selectLine=True): assert error_type in self.colors and self.colors[error_type] is not None selectLine = selectLine or not column c = cursorForPosition(self.editor.codeEdit, line, column, selectEndOfLine=selectLine) deco = TextDecoration(c, draw_order=error_type + 1, tooltip=message) deco.setSpellchecking(color=QColor(self.colors[error_type])) self.__decorations.append(deco) self.editor.codeEdit.addDecoration(deco) if self.checkers_panel: self.__markers.append( self.checkers_panel.addCheckerMarker(error_type, line, message)) def __apply_results(self, raw_results): """ Apply squiggle on all lines :param raw_results: raw results from pep8.py :type raw_results: str """ # prepare context self.__clear_decorations() self.__clear_markers() current_cursor = self.editor.codeEdit.textCursor() hbar_pos = self.editor.codeEdit.horizontalScrollBar().sliderPosition() vbar_pos = self.editor.codeEdit.verticalScrollBar().sliderPosition() # let specific checkers do the main job self.onResultsAvailable(raw_results) # restore context self.editor.codeEdit.setTextCursor(current_cursor) self.editor.codeEdit.horizontalScrollBar().setSliderPosition(hbar_pos) self.editor.codeEdit.verticalScrollBar().setSliderPosition(vbar_pos) self.__thread_counter -= 1 def onResultsAvailable(self, raw_results): raise NotImplementedError("The checker mode %s does not implement " "onResultsAvailable" % self.name) def _start_runnable(self, runner): self.__thread_counter += 1 self.__thread_pool.start(runner) def _runCmd(self): self.__timer.stop() cmd = "{0} {1}".format( self.base_cmd, self.editor.codeEdit.tagFilename) runner = RunnableChecker() runner.connect(self.__apply_results) runner.cmd = cmd self._start_runnable(runner) def __onTextChanged(self): filename = self.editor.codeEdit.tagFilename if filename and self.__thread_counter == 0: self.__timer.stop() self.__timer.start() def _onStyleChanged(self): self.colors[ERROR_TYPE_WARNING] = QColor( self.editor.currentStyle.warningColor) self.colors[ERROR_TYPE_SYNTAX] = QColor( self.editor.currentStyle.errorColor) self.__onTextChanged()
class ClimateControlModel(QObject): """ Model class representing the climate control system Talks with flow, fetches required data from flow, caches some of the data """ __message_received_signal = None setting_received = Signal(dict) save_setting_result = Signal(dict) measurement_changed = Signal(MeasurementEvent) relay_status_changed = Signal(RelayStatusEvent) device_status_changed = Signal(DeviceStatusEvent) controller_status = Signal(str) command_response_received = Signal(dict) command_sending_result = Signal(dict) connection_status = Signal(dict) latency_changed = Signal(float) def __init__(self): """ ClimateControlModel constructor Initializes Flow library, thread pool """ super(ClimateControlModel, self).__init__() self.__thread_pool = QThreadPool() self.__thread_pool.setMaxThreadCount(THREAD_POOL_MAX_THREADS) self.__flow_user = None self.__controller_device = None self.__checking_connection_status = False self.__last_measurement_event = None self.__last_relay_status_event = None self.__last_device_status_event = None self.__controller_heartbeat = None self.latency = Latency() self.__latency_timer = QTimer(self) self.__latency_timer.timeout.connect(self.__latency_timer_expired) ClimateControlModel.__message_received_signal = MessageReceived() ClimateControlModel.__message_received_signal.signal.connect(self.__message_received) def initialize(self, user_name, password): """ Initializes the system Initializes flow libraries and connects to server Logs in as user and tries to find the controller device, caches if found :param str user_name: flow user name :param str password: flow user password :raises ControllerNotFound, LoginFailed, FlowLibraryError """ flow_url, flow_key, flow_secret = get_server_details() try: flow_initialize(flow_url, flow_key, flow_secret) except FlowException as flow_error: if flow_error.connection_error: self.check_connection_status() LOGGER.exception(flow_error) raise FlowLibraryError("Failed to initialize flow library") try: self.__flow_user = FlowUser(user_name, password) except FlowException as flow_error: if flow_error.connection_error: self.check_connection_status() LOGGER.exception(flow_error) raise LoginFailed() except ValueError as value_error: LOGGER.exception(value_error) raise LoginFailed() try: self.__controller_device = self.__flow_user.find_device(CONTROLLER_DEVICE_TYPE) except FlowException as flow_error: if flow_error.connection_error: self.check_connection_status() LOGGER.exception(flow_error) raise ControllerNotFound() # enable message reception self.__flow_user.enable_message_reception(ClimateControlModel.message_received_callback) def close(self): """ De-initialize the model This function won't return till all the worker thread finish their job """ LOGGER.debug("waiting for threads in thread pool") self.__thread_pool.waitForDone() LOGGER.debug("thread pool exit done") if self.__flow_user: self.__flow_user.logout() def get_settings(self): """ Get setting for the controller device Schedules a worker thread for getting setting """ runnable = WorkerThread(get_setting_work, self.__settings_received, device=self.__controller_device, key=ControllerSetting.controller_config_key) self.__thread_pool.start(runnable) def save_settings(self, setting): """ Save setting of controller device :param ControllerSetting setting: setting object to be saved in KVS """ setting_xml = setting.to_xml() LOGGER.debug("Trying to save setting xml = {}".format(setting_xml)) runnable = WorkerThread(save_setting_work, self.__save_settings_result, device=self.__controller_device, key=ControllerSetting.controller_config_key, value=setting_xml) self.__thread_pool.start(runnable) def send_command(self, command): """ Send command to the controller device :param ControllerCommandEnum command: command to be sent """ if command not in ControllerCommandEnum: raise InvalidCommand("Command not supported") LOGGER.info("sending command {}".format(command.value)) command_xml = ControllerCommand(command).xml LOGGER.debug("command xml {}".format(command_xml)) runnable = WorkerThread(send_command_work, self.__command_sent_result, user=self.__flow_user, device=self.__controller_device, message=command_xml) self.__thread_pool.start(runnable) def check_connection_status(self): """ Starts worker thread for checking connection status """ if not self.__checking_connection_status: self.__checking_connection_status = True runnable = WorkerThread(check_connection_status_work, self.__connection_status_result) self.__thread_pool.start(runnable) @Slot(str, str) def __settings_received(self, setting, error): """ Slot function called when get setting worker thread finishes the task :param str setting: received setting from flow :param str error: error string if any """ parsed_setting = None if not error: LOGGER.debug("Received setting xml = {}".format(setting)) try: parsed_setting = ControllerSetting(setting_xml=setting) if not self.__controller_heartbeat: # start heartbeat timer with twice the heartbeat period so that even if some # heartbeat message failed to receive, it should wait for another # heartbeat message self.__controller_heartbeat = \ HeartBeatTimer(parsed_setting.controller_heartbeat*2*1000, self.__heartbeat_timer_status_changed) else: # if heartbeat already exist then restart with new time self.__controller_heartbeat.change_timeout_period( parsed_setting.controller_heartbeat*2*1000) except ValueError as value_error: LOGGER.exception(value_error) error = "Invalid setting XML received" else: if error["connection_error"]: self.check_connection_status() self.setting_received.emit({"setting": parsed_setting, "error": error}) @Slot(str) def __save_settings_result(self, error=None): """ Slot function for the save setting worker function result :param str error: error string if any """ self.save_setting_result.emit({"error": error}) if error: LOGGER.debug("Save setting failed: {}".format(error)) if error["connection_error"]: self.check_connection_status() else: # if KVS updated then send message to device to update the settings self.send_command(ControllerCommandEnum.retrieve_settings) LOGGER.debug("Setting saved to KVS") @Slot(bool, bool) def __connection_status_result(self, network, internet): """ Slot function for connection status result :param bool network: False if network is down :param bool internet: False if internet is down """ self.__checking_connection_status = False connection_status = {"network": network, "internet": internet} self.connection_status.emit(connection_status) @Slot(str) def __command_sent_result(self, error=None): """ Slot function called at the end of sending command :param str error: error string if any """ if error: self.command_sending_result.emit({"error": error}) LOGGER.debug("Message sending failed: {}".format(error)) if error["connection_error"]: self.check_connection_status() else: LOGGER.debug("Message sending success") # pylint: disable=invalid-name @Slot(str) def __heartbeat_timer_status_changed(self, status): """ Slot function called when heartbeat timer changes its status(start, expire etc) It receives controller status. on timer expire-controller status = "OFFLINE" on timer refresh(start)- controller status = "ONLINE" :param str status: "ONLINE" or "OFFLINE" status """ self.controller_status.emit(status) if status == "OFFLINE": # timer expired so there might be something wrong with the # network or internet so check connection status self.check_connection_status() LOGGER.debug("Latency timer stopped") self.__latency_timer.stop() if self.__last_device_status_event: # if controller is OFFLINE, make sensor and actuator also OFFLINE self.__last_device_status_event.sensor_alive = False self.__last_device_status_event.actuator_alive = False self.device_status_changed.emit(self.__last_device_status_event) else: self.__latency_timer.start(LATENCY_PERIOD*1000) LOGGER.debug("Latency timer started") # pylint: enable=invalid-name @Slot() def __latency_timer_expired(self): """ Slot called on the expiry of latency timer """ # send ping message to controller and calculate latency based on when it is received self.send_command(ControllerCommandEnum.ping) def __handle_command_response(self, response_dict): """ Parse the received response and emit signal if valid response found :param dict response_dict: response xml dictionary """ try: response = ControllerResponse(response_dict) LOGGER.info("received response {}".format(response.response.value)) if response.response == ControllerResponseEnum.ping: # round_trip_time is the difference between current local time and timestamp # when message was sent, this includes any processing delay on controller side round_trip_time = (datetime.datetime.utcnow() - response.sent_time).total_seconds() LOGGER.debug("round_trip_time: {}".format(round_trip_time)) # Ignore value where round_trip_time > MAX_LATENCY_TIME if round_trip_time <= MAX_LATENCY_VALUE: latency = self.latency.calculate_exponential_moving_average(round_trip_time) else: latency = round_trip_time self.latency_changed.emit(latency) LOGGER.debug("Latency: {}".format(latency)) else: self.command_response_received.emit({"response": response.response}) # if retrieve_settings_success is received, get the settings again as it might # be update by some other app # for e.g. admin app updating threshold and display app updating its values accordingly if response.response == ControllerResponseEnum.retrieve_settings_success: self.get_settings() except ValueError as error: LOGGER.exception(error) def __process_heartbeat_event(self, event): """ Processes HeartBeat event data :param HeartBeatEvent event: HeartBeat event object """ if self.__last_measurement_event: if not event.measurement_data == self.__last_measurement_event: self.measurement_changed.emit(event.measurement_data) self.__last_measurement_event = event.measurement_data else: LOGGER.debug("Ignoring measurement data") else: self.measurement_changed.emit(event.measurement_data) self.__last_measurement_event = event.measurement_data LOGGER.debug("Heartbeat Temp: {} Humidity: {} ".format(event.measurement_data.temperature, event.measurement_data.humidity)) if self.__last_relay_status_event: if not event.relay_status == self.__last_relay_status_event: self.relay_status_changed.emit(event.relay_status) self.__last_relay_status_event = event.relay_status else: LOGGER.debug("Ignoring relay status data") else: self.relay_status_changed.emit(event.relay_status) self.__last_relay_status_event = event.relay_status if self.__last_device_status_event: if not event.device_status == self.__last_device_status_event: self.device_status_changed.emit(event.device_status) self.__last_device_status_event = event.device_status else: LOGGER.debug("Ignoring device status data") else: self.device_status_changed.emit(event.device_status) self.__last_device_status_event = event.device_status LOGGER.debug("Heartbeat Temp: {} Humidity: {} " "Relay 1 ON: {} Relay 2 ON: {} " "Sensor: {} Actuator: {}".format(event.measurement_data.temperature, event.measurement_data.humidity, event.relay_status.relay_1_on, event.relay_status.relay_2_on, event.device_status.sensor_alive, event.device_status.actuator_alive)) def __handle_event(self, message_dict): """ Create event object according to event type and handle the event :param dict message_dict: message content in the dictionary format """ try: event = ControllerEventFactory.create_event(message_dict) if self.__controller_heartbeat: self.__controller_heartbeat.refresh_timer() if isinstance(event, MeasurementEvent): self.measurement_changed.emit(event) self.__last_measurement_event = event LOGGER.debug("Measurement Temp: {} Humidity: {}".format(event.temperature, event.humidity)) elif isinstance(event, RelayStatusEvent): self.relay_status_changed.emit(event) self.__last_relay_status_event = event LOGGER.debug("RelayStatus Relay 1 ON: {} Relay 2 ON: {}".format(event.relay_1_on, event.relay_2_on)) elif isinstance(event, DeviceStatusEvent): self.device_status_changed.emit(event) self.__last_device_status_event = event LOGGER.debug("DeviceStatus Sensor: {} Actuator: {}".format(event.sensor_alive, event.actuator_alive)) elif isinstance(event, HeartBeatEvent): self.__process_heartbeat_event(event) except ValueError as value_error: LOGGER.exception(value_error) @Slot(str) def __message_received(self, message_content): """ Slot function called when message is received by callback function This function parses message_content(xml_string) into dictionary :param str message_content: message content which is xml string """ LOGGER.debug("Received message {}".format(message_content)) # We have received a message from controller means network and internet are up status = {"network": True, "internet": True} self.connection_status.emit(status) try: message_dict = xmltodict.parse(message_content) root_tag = message_dict.keys()[0] if root_tag == "response": self.__handle_command_response(message_dict) elif root_tag == "event": self.__handle_event(message_dict) else: LOGGER.error("Unsupported message received {}".format(message_content)) except (ExpatError, KeyError) as error: LOGGER.exception("Error in parsing xml {} xml={}". format(error.message, message_content)) @staticmethod def message_received_callback(flow_message): """ Callback called by library, libflow expects this to be a static class method :param flow_message: message object from library """ message = FlowMessage(flow_message) message_content = message.get_message_content() ClimateControlModel.__message_received_signal.signal.emit(message_content)
def handleObsNameEditingFinished(self): if self.__projectObsNameEdited: self.__projectObsNameEdited = False task = ProgressRunnable2() task.setRunMethod(self.__loadTargetPossibilities) QThreadPool.globalInstance().start(task)
class CodeCompletionMode(Mode): """ This mode provides code completion to the CodeEdit widget. The list of suggestion is supplied by a CodeCompletionModel. Code completion may use more than one completion model. The suggestions list is then filled model per model by beginning by the highest priority as long as the number of suggestions is lower than :attr:`pcef.modes.code_completion.CodeCompletion.minSuggestions`. For example, a python editor will use a smart completion model with a high priority and use the DocumentWordsCompletion model as a fallback system when the smart model fails to provide enough suggestions. The mode uses a QCompleter to provides display the list of suggestions. Code completion is triggered using ctrl+space or when there is at least three characters in the word being typed. """ #: Mode identifier IDENTIFIER = "Code completion" #: Mode description DESCRIPTION = "Provides code completion though completion models" def __init__(self): super(CodeCompletionMode, self).__init__( self.IDENTIFIER, self.DESCRIPTION) self.thread_pool = QThreadPool() self.thread_pool.setMaxThreadCount(2) self.__cached_request = None self.__active_thread_count = 0 self.__updating_models = False self.__timer = QTimer() #: Defines the min number of suggestions. This is used to know we should # avoid using lower priority models. # If there is at least minSuggestions in the suggestions list, we won't # use other completion model. self.minSuggestions = 50 #: Trigger key (automatically associated with the control modifier) self.triggerKey = Qt.Key_Space #: Number of chars needed to trigger the code completion self.nbTriggerChars = 1 #: Tells if the completion should be triggered automatically (when # len(wordUnderCursor) > nbTriggerChars ) # Default is True. Turning this option off might enhance performances # and usability self.autoTrigger = True self.periodIsTrigger = True #: Show/Hide current suggestion tooltip self.displayTooltips = True self.__caseSensitivity = Qt.CaseSensitive #: The internal QCompleter self.__completer = QCompleter() # self.__completer.activated.connect(self._insertCompletion) self.__completer.highlighted.connect(self._onHighlighted) self.__completer.activated.connect(self._insertCompletion) self.__prev_txt_len = 0 #: List of completion models self._models = [] self.__tooltips = {} def __del__(self): self.__completer.setWidget(None) self.__completer = None def addModel(self, model): """ Adds a completion model to the completion models list. :param model: CompletionModel to add """ self._models.append(model) self._models = sorted(self._models, key=lambda mdl: mdl.priority, reverse=True) def install(self, editor): """ Setup the completer with the CodeEdit. :param editor: CodeEditorWidget instance """ super(CodeCompletionMode, self).install(editor) self.__completer.setWidget(editor.codeEdit) self.__completer.setCaseSensitivity(self.__caseSensitivity) self.__completer.setCompletionMode(QCompleter.PopupCompletion) def __set_case(self, case): if case != self.__caseSensitivity: self.__caseSensitivity = case self.__completer.setCaseSensitivity(case) def __get_case(self): return self.__caseSensitivity #: The completion case sensitivity caseSensitivity = property(__get_case, __set_case) def _onStateChanged(self, state): """ Enables/Disables code completion. :param state: True to enable, False to disable """ if state: self.editor.codeEdit.keyPressed.connect(self._onKeyPressed) self.editor.codeEdit.postKeyPressed.connect(self._onKeyReleased) self.editor.codeEdit.focusedIn.connect(self._onFocusIn) self.__completer.highlighted.connect( self._displayHighlightedTooltip) else: self.editor.codeEdit.keyPressed.disconnect(self._onKeyPressed) self.editor.codeEdit.postKeyPressed.disconnect(self._onKeyReleased) self.editor.codeEdit.focusedIn.disconnect(self._onFocusIn) self.__completer.highlighted.disconnect( self._displayHighlightedTooltip) def _onFocusIn(self, event): """ Resets completer widget :param event: QFocusEvent """ self.__completer.setWidget(self.editor.codeEdit) def _onHighlighted(self, completion): """ Remembers the current completion when the hilighted signal is emitted. :param completion: Current completion """ self.currentCompletion = completion def _onKeyReleased(self, event): """ Handles the key released event to adapt completer prefix, run the cc library if necessary or prevent completer popup when removing text. :param event: :return: """ word = self._textUnderCursor() isShortcut = self._isShortcut(event) or event.key() == Qt.Key_Period tooShort = len(word) < self.nbTriggerChars # closes popup if completion prefix is empty and we are not removing # some text if (not self.__completer.popup().isVisible() and event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete) or\ (not isShortcut and event.modifiers() == 0 and ( word.isspace() or word == "")): self._hideCompletions() return # . is an auto-trigger if self.periodIsTrigger and \ (event.key() == Qt.Key_Period and self.autoTrigger): self._requestCompletion(completionPrefix=word, onlyAdapt=False) return # adapt completion prefix if self.__completer.popup().isVisible(): self._requestCompletion(completionPrefix=word, onlyAdapt=True) # run cc if word is long enough and auto trigger is on elif not tooShort and self.autoTrigger and event.text() != "" \ and (event.modifiers() == 0 or event.modifiers() & Qt.ShiftModifier): self._requestCompletion(completionPrefix=word, onlyAdapt=False) def _isShortcut(self, event): """ Checks if the event's key and modifiers make the completion shortcut. :param event: QKeyEvent :return: bool """ return ((event.modifiers() & Qt.ControlModifier > 0) and event.key() == self.triggerKey) def _onKeyPressed(self, event): """ Trigger the completion with ctrl+triggerKey and handle completion events ourselves (insert completion and hide completer) :param event: QKeyEvent """ isShortcut = self._isShortcut(event) completionPrefix = self._textUnderCursor() # handle completer popup events ourselves if self.__completer.popup().isVisible(): # complete if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return: self._insertCompletion(self.currentCompletion) self.__completer.popup().hide() event.stop = True return # hide elif event.key() == Qt.Key_Escape or event.key() == Qt.Key_Backtab: self.__completer.popup().hide() event.stop = True return # user completion request: update models and show completions if isShortcut: self._requestCompletion(completionPrefix, onlyAdapt=False) if event.key() == self.triggerKey: event.stop = True def selectWordUnderCursor(self): tc = self.editor.codeEdit.textCursor() original_pos = pos = tc.position() space_found = False how_many = 0 while not space_found and pos != 0: tc.movePosition(QTextCursor.Left, QTextCursor.MoveAnchor, 1) tc.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, 1) ch = tc.selectedText()[0] if tc.selectedText() in WORD_SEPARATORS or ch.isspace(): space_found = True how_many += 1 pos = tc.position() tc.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor, 1) tc.setPosition(original_pos) tc.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, how_many) return tc def _textUnderCursor(self): """ Returns the word under the cursor """ tc = self.selectWordUnderCursor() selectedText = tc.selectedText() tokens = selectedText.split('.') wuc = tokens[len(tokens) - 1] if selectedText == ".": wuc = '.' return wuc def _lastCharOfLine(self): """ Returns the last char of the active line. :return: unicode """ tc = self.editor.codeEdit.textCursor() tc.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, 1) return tc.selectedText() def _getCCRequest(self, completionPrefix): """ Creates a CompletionRequest from context (line nbr, ...) :param completionPrefix: the completion request prefix """ tc = self.editor.codeEdit.textCursor() line = tc.blockNumber() + 1 col = tc.columnNumber() fn = self.editor.codeEdit.tagFilename encoding = self.editor.codeEdit.tagEncoding source = self.editor.codeEdit.toPlainText() return CompletionRequest( col=col, encoding=encoding, filename=fn, line=line, source_code=source, completionPrefix=completionPrefix) def _execRequest(self, request): """ Executes a cc request and emit __completionResultsAvailable when the execution is done. :param request: The CodeCompletionRequest to execute. """ pass def _createCompleterModel(self, completionPrefix): """ Creates a QStandardModel that holds the suggestion from the completion models for the QCompleter :param completionPrefix: """ # build the completion model cc_model = QStandardItemModel() cptSuggestion = 0 displayedTexts = [] self.__tooltips.clear() for model in self._models: for s in model.suggestions: # skip redundant completion if s.display != completionPrefix and \ not s.display in displayedTexts: displayedTexts.append(s.display) items = [] item = QStandardItem() items.append(item) item.setData(s.display, Qt.DisplayRole) if s.description is not None: self.__tooltips[s.display] = s.description if s.decoration is not None: item.setData(QIcon(s.decoration), Qt.DecorationRole) cc_model.appendRow(items) cptSuggestion += 1 # do we need to use more completion model? if cptSuggestion >= self.minSuggestions: break # enough suggestions return cc_model, cptSuggestion def _showCompletions(self, completionPrefix): """ Shows the completion popup :param completionPrefix: completion prefix use to set the popup pos """ c = self.__completer c.setCompletionPrefix(completionPrefix) c.popup().setCurrentIndex( self.__completer.completionModel().index(0, 0)) cr = self.editor.codeEdit.cursorRect() charWidth = self.editor.codeEdit.fm.width('A') cr.setX(cr.x() - len(completionPrefix) * charWidth) cr.setWidth(400) c.complete(cr) # popup it up! self._displayHighlightedTooltip(c.currentCompletion()) def _hideCompletions(self): """ Hides the completion popup """ self.__completer.popup().hide() QToolTip.hideText() def _requestCompletion(self, completionPrefix, onlyAdapt=False): """ Requests a code completion. The request will be transmitted to the background thread and treated by the __applyRequestResults slot when __completionResultsAvailable is emitted. :param completionPrefix: :param onlyAdapt: :return: """ # cancel prev running request if not onlyAdapt: request = self._getCCRequest(completionPrefix) else: request = CompletionRequest(completionPrefix=completionPrefix, onlyAdapt=True) # only one at a time if self.__active_thread_count == 0: if self.__cached_request: self.__cached_request, request = request, self.__cached_request self.__active_thread_count += 1 runnable = RunnableCompleter(self._models, request) runnable.connect(self._applyRequestResults) self.thread_pool.start(runnable) # cache last request else: self.__cached_request = request def _applyRequestResults(self, request): """ Updates the completer model and show the popup """ self.__active_thread_count -= 1 # is the request still up to date ? if request.completionPrefix == self._textUnderCursor(): if not request.onlyAdapt: # update completion model and show completer cc_model, cptSuggestion = self._createCompleterModel( request.completionPrefix) if cptSuggestion > 1: self.__completer.setModel(cc_model) self.__cc_model = cc_model self._showCompletions(request.completionPrefix) else: self._hideCompletions() else: # only adapt completion prefix, the completer is already visible self.__completer.setCompletionPrefix(request.completionPrefix) idx = self.__completer.completionModel().index(0, 0) self.__completer.popup().setCurrentIndex(idx) if self.__completer.currentCompletion() == "" or \ self.__completer.currentCompletion() == \ request.completionPrefix: self._hideCompletions() # do we have any cached requests? if self.__cached_request and self.__active_thread_count == 0: self.__active_thread_count += 1 # prevent normal start immediately self.__timer.singleShot(10, self.__start_cached_request) def __start_cached_request(self): request = self.__cached_request self.__cached_request = None runnable = RunnableCompleter(self._models, request) runnable.connect(self._applyRequestResults) self.thread_pool.start(runnable) @Slot(unicode) def _displayHighlightedTooltip(self, txt): """ Shows/hides current suggestion tooltip next to the completer popup :param txt: :return: """ if not self.displayTooltips or not txt in self.__tooltips: QToolTip.hideText() return tooltip = self.__tooltips[txt] charWidth = self.editor.codeEdit.fm.width('A') # show tooltip pos = self.__completer.popup().pos() pos.setX(pos.x() + 400) pos.setY(pos.y() - 15) QToolTip.showText(pos, tooltip, self.editor.codeEdit) def _insertCompletion(self, completion): """ Inserts the completion (replace the word under cursor) :param completion: the completion text to insert """ offset = 0 if len(self._textUnderCursor()) > 1: offset = 1 tc = self.selectWordUnderCursor() tc.insertText(completion) self.editor.codeEdit.setTextCursor(tc)
def refresh(self): value = QThreadPool.globalInstance().activeThreadCount() if self.activeThreadCount != value: self.activeThreadCount = value self.q.threadCountChanged.emit(value)
def main(): # Use UTF-8 encoding for Qt from PySide.QtCore import QTextCodec #sys_codec = QTextCodec.codecForLocale() u8codec = QTextCodec.codecForName("UTF-8") QTextCodec.setCodecForCStrings(u8codec) QTextCodec.setCodecForTr(u8codec) import config from sakurakit import skdebug #skdebug.DEBUG = config.APP_DEBUG or '--debug' in sys.argv skdebug.DEBUG = '--debug' in sys.argv print "installer: debug = %s" % skdebug.DEBUG from sakurakit.skdebug import dprint, dwarn dprint("enter") if '--help' in sys.argv: print_help() dprint("leave: help") return # Singleton #dprint("check single instance") #from sakurakit import skipc #inst = skipc.SingleInstance() #single_app = inst.passed #if not single_app: # dprint("multiple instances are running") # sys.exit(-1) dprint("python = %s" % sys.executable) #dprint("rootdir = %s" % rootdir) #dprint("mecabrc = %s" % mecabrc_path) dprint("create app") import app a = app.Application(sys.argv) dprint("load translations") a.loadTranslations() # Take the ownership of sakurakit translation from sakurakit import sktr sktr.manager().setParent(a) dprint("load settings") import settings ss = settings.global_() ss.setParent(a) dprint("update settings") if ss.version() != config.VERSION_TIMESTAMP: dprint("app update detected, migrate settings") ss.setVersion(config.VERSION_TIMESTAMP) ss.sync() dprint("set max thread count") from PySide.QtCore import QThreadPool if QThreadPool.globalInstance().maxThreadCount() < config.QT_THREAD_COUNT: QThreadPool.globalInstance().setMaxThreadCount(config.QT_THREAD_COUNT) dprint("create main object") import main m = main.MainObject() m.run(a.arguments()) #import netman #netman.manager().queryComments(gameId=183) #import hashman #print hashman.md5sum('/Users/jichi/tmp/t.cpp') dprint("exec") sys.exit(a.exec_())
def start_thread_func(ui): runnable = StartRunnable(ui) QThreadPool.globalInstance().start(runnable)