class SortedListByThread(QObject):
    def __init__(self):
        super(SortedListByThread, self).__init__()
        self.thread = self.worker = None

    def run(self, lst, key, reverse):
        def finished(l_sorted):
            self.sortedList = l_sorted
            loop.exit()

        self.worker = WorkerSorted(lst, key, reverse)
        self.thread = QThread(self)
        loop = QEventLoop()
        self.sortedList = None

        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.run)
        self.worker.finished.connect(finished)
        self.thread.start()
        loop.exec_()
        self._finishThread()

        return self.sortedList

    def kill(self):
        if not self.thread is None:
            self._finishThread()

    def _finishThread(self):
        self.thread.quit()
        self.thread.wait()
        self.thread.deleteLater()
        self.thread = self.worker = None
예제 #2
0
파일: soundmanager.py 프로젝트: 3vi1/vintel
 def quit(self):
     self.active = False
     self.queue.put((None, None, None))
     if self.player:
         self.player.pause()
         self.player.delete()
     QThread.quit(self)
예제 #3
0
    def quit(self):
        loop = QEventLoop()
        reply = self._make_request('quit')
        reply.finished.connect(loop.quit)
        loop.exec_()

        QThread.quit(self)
예제 #4
0
 def quit(self):
     self.active = False
     self.queue.put((None, None, None))
     if self.player:
         self.player.pause()
         self.player.delete()
     QThread.quit(self)
예제 #5
0
class AsyncThreadController(AsyncAbstractController):
    def __init__(self,
      # |parent|
      parent=None):

        super(AsyncThreadController, self).__init__(parent)
        # Create a worker and a thread it runs in. This approach was
        # inspired by  example given in the `QThread docs
        # <http://qt-project.org/doc/qt-4.8/qthread.html>`_.
        self._worker = _AsyncWorker()
        self._workerThread = QThread(parent)
        # Attach the worker to the thread's event queue.
        self._worker.moveToThread(self._workerThread)
        # Hook up signals.
        self._worker.startSignal.connect(self._worker.onStart)
        # Everything is ready. Start the worker thread, so it will
        # be ready for functions to run.
        self._workerThread.start()

    # |_start|
    def _start(self, future):
        self._worker.startSignal.emit(future)

    # |terminate|
    def _terminate(self):
        # Shut down the thread the Worker runs in.
        self._workerThread.quit()
        self._workerThread.wait()
        # Finally, detach (and probably garbage collect) the objects
        # used by this class.
        del self._worker
        del self._workerThread
예제 #6
0
class Task(QObject):
    started = pyqtSignal()
    finished = pyqtSignal(object)

    def __init__(self, callback, *args, **kwargs):
        super(Task, self).__init__()

        self._callback = callback
        self._args = args
        self._kwargs = kwargs
        self.result = None
        self.error = None

        self.thread = QThread(iface.mainWindow())
        self.thread.run = self.run
        self.thread.finished.connect(self.exit_loop)

        self.loop = QEventLoop()

    def run(self):
        try:
            self.result = self._callback(*self._args, **self._kwargs)

        except Exception, e:
            self.error = (e, traceback.format_exc())
            self.exit_loop()
            self.thread.quit()
예제 #7
0
파일: workers.py 프로젝트: KelSolaar/Umbra
	def quit(self):
		"""
		Reimplements the :meth:`QThread.quit` method.
		"""

		self.__interrupt = True

		QThread.quit(self)
예제 #8
0
	def quit(self):
		"""
		Reimplements the :meth:`QThread.quit` method.
		"""

		self.__interrupt = True
		self.__requests.put(None)

		QThread.quit(self)
class SignalStream(QObject):
    '''SignalStream is a file-like object that emits a text signal on writing

    This class is used to provide threadsafe communication of data to the GUI.
    A SignalStream can be used in place of sys.stdout and the instance's 
    write_signal can be connected to a slot that processes the text to where it
    ought to go.  Since signals and slots are threadsafe, this lets you pass
    text from anywhere to anywhere reasonably safely

    SignalStream uses some intelligent buffering to prevent the signalstorm that
    happened the first time I used it.  Signal emit only happens when flush()
    is called - so an application can force a flush - but in order to make sure
    that happens reasonable often SignalStream can be initialized with a QTimer
    on an interval (default: 100ms) and the QTimer will make sure to call flush()
    every 100ms.
    '''

    write_signal = pyqtSignal(str)

    def __init__(self, interval_ms=100):
        '''Create a SignalStream that emits text at least every interval_ms'''

        super(SignalStream, self).__init__()
        self.mutex = QMutex()

        self.data = []
        self.thread = QThread()

        self.pbar_timer = QTimer()
        self.pbar_timer.moveToThread(self.thread)
        self.pbar_timer.setInterval(interval_ms)
        self.pbar_timer.timeout.connect(self.flush)
        self.thread.started.connect(self.pbar_timer.start)
        self.thread.start()

    def __del__(self):
        self.thread.quit()
        self.thread.wait()

    def write(self, m):
        '''Add the message in m to this stream's cache'''
        locker = QMutexLocker(self.mutex)

        self.data.append(m)

    @pyqtSlot()
    def flush(self):
        '''Write all data in the stream and clear the stream's cache'''
        locker = QMutexLocker(self.mutex)

        if self.data:
            self.write_signal.emit(''.join(self.data))
            self.data = []

    def set_interval(self, interval_ms):
        '''Alter the pbar_timer period'''
        self.pbar_timer.setInteval(interval_ms)
예제 #10
0
    def quit(self):
        """
		Reimplements the :meth:`QThread.quit` method.
		"""

        self.__interrupt = True
        self.__requests.put(None)

        QThread.quit(self)
예제 #11
0
파일: traces.py 프로젝트: OpBox/OpBoxPhys
    def start(self):
        """Start acquisition by starting a new thread.
        """
        thread = QThread()
        self.thread = thread
        obj = Worker(self.args)
        self.obj = obj
        obj.dataReady.connect(self.plot_data)
        obj.moveToThread(thread)

        thread.started.connect(obj.start_task)
        thread.start()
        thread.quit()  # why does it go here?
예제 #12
0
class SlicerEngineManager(QObject):
    '''
    SlicerEngineManager is class designed for managing slicers engine and prepare parameters
    '''
    cancel_signal = pyqtSignal()

    def __init__(self, controller):
        super(SlicerEngineManager, self).__init__()
        self.controller = controller
        self.slice_thread = None
        self.slice_engine = Slic3rEngineRunner(self.controller)

    def slice(self):
        self.slice_thread = QThread()
        #TODO:Make it universal(for other slice engines)
        self.slice_engine = Slic3rEngineRunner(self.controller)
        self.slice_engine.moveToThread(self.slice_thread)
        self.slice_thread.started.connect(self.slice_engine.slice)
        self.slice_engine.finished.connect(self.thread_ended)
        self.slice_engine.filament_info.connect(
            self.controller.set_print_info_text)
        self.slice_engine.step_increased.connect(
            self.controller.set_progress_bar)
        self.slice_engine.send_message.connect(self.controller.slicing_message)
        self.slice_engine.send_gcodedata.connect(
            self.controller.set_gcode_instance)

        self.cancel_signal.connect(
            self.slice_engine.gcode.gcode_parser.cancel_parsing)

        self.slice_thread.start()

    def cancel(self):
        logging.debug("Thread canceling")
        if self.slice_engine and self.slice_thread:
            self.slice_engine.is_running = False
            self.cancel_signal.emit()
            self.slice_engine.kill()
            self.slice_thread.quit()
            self.slice_thread.wait()
            self.controller.status = 'canceled'
            self.controller.set_generate_button()
            self.controller.set_progress_bar(0.0)

    def thread_ended(self):
        self.slice_thread.quit()
        #TODO: add function to read gcode
        self.controller.scene_was_sliced()

    def get_version(self):
        return self.slice_engine.get_version()
예제 #13
0
class Analyzer(object):
    def __init__(self, controller):
        self.controller = controller
        self.analyzer_runner = AnalyzerRunner(controller)
        self.analyzer_runner_thread = QThread()
        self.finish_function = None
        self.send_result_function = None

    def make_analyze(self, finish_function, result_function):
        self.finish_function = finish_function
        self.send_result_function = result_function
        if self.analyzer_runner.is_running:
            print("cancel old analyze")
            self.cancel_analyz()

        print("start new analyze")
        #self.analyzer_runner.whole_scene = whole_scene
        self.analyzer_runner.moveToThread(self.analyzer_runner_thread)
        self.analyzer_runner_thread.started.connect(self.analyzer_runner.start_analyze)

        self.analyzer_runner.finished.connect(self.set_finished_read)
        self.analyzer_runner.send_result.connect(self.set_result)

        self.analyzer_runner.is_running = True
        self.analyzer_runner_thread.start()


    def cancel_analyz(self):
        self.analyzer_runner.is_running = False
        self.analyzer_runner_thread.quit()
        self.analyzer_runner_thread.wait()

        self.analyzer_runner_thread = QThread()
        self.analyzer_runner = AnalyzerRunner(self.controller)


    def set_finished_read(self):
        print("analyze done")
        if self.finish_function:
            self.finish_function()

    def set_result(self, result):
        print(result)
        if self.send_result_function:
            self.send_result_function(result)



    '''
class NativePocketSphinx(AsrBackend):
    recognizedToFile = QtCore.pyqtSignal(str)

    def __init__(self):
        super().__init__()

        logger.info("Initializing PocketSphinx backend")
        self.ps = PocketSphinx()

        self.enablePocketSphinx()

        self.contWorker = ContinuousAsrWorker()
        self.workerThread = QThread(self)
        self.workerThread.started.connect(self.contWorker.start)
        self.workerThread.finished.connect(self.contWorker.stop)
        self.contWorker.moveToThread(self.workerThread)

    def enablePocketSphinx(self):
        logger.debug("Initializing PocketSphinx decoder")
        self.ps.initializeDecoder()
        logger.debug("Initializing audio recording")
        self.ps.initializeAudio()

    def disablePocketSphinx(self):
        logger.debug("Shutting down audio recording")
        self.ps.shutdownAudio()
        logger.debug("Shutting down PocketSphinx decoder")
        self.ps.shutdownDecoder()

    def recognizeFromMicrophone(self, sinkFileName):
        logger.debug("[NativePocketSphinx] Recognizing from microphone to " + sinkFileName)
        self.ps.recognizeFromMicrophone(sinkFileName)
        self.recognizedToFile.emit(sinkFileName)
        logger.debug("[NativePocketSphinx] Recognition done")

    def startContinuousRecognition(self):
        logger.info("Starting continuous speech recognition")
        self.disablePocketSphinx()
        self.workerThread.start()

    def stopContinuousRecognition(self):
        logger.info("Stopping continuous speech recognition")
        self.workerThread.quit()
        self.enablePocketSphinx()

    #TODO: Implement actual checking of availability of the backend
    @classmethod
    def supported(self):
        return True
예제 #15
0
class NativePocketSphinx(QObject):
    recognizedToFile = QtCore.pyqtSignal(str)

    def __init__(self):
        super().__init__()

        logger.info("Initializing PocketSphinx backend")
        self.ps = PocketSphinx()
        logger.debug("Initializing PocketSphinx decoder")
        self.ps.initializeDecoder()
        logger.debug("Initializing audio recording")
        self.ps.initializeAudio()

        self.contWorker = ContinuousAsrWorker()
        self.workerThread = QThread(self)
        self.workerThread.started.connect(self.contWorker.start)
        self.workerThread.finished.connect(self.contWorker.deleteLater)
        self.contWorker.moveToThread(self.workerThread)

    def recognizeFromMicrophone(self, sinkFileName):
        self.ps.recognizeFromMicrophone(sinkFileName)
        self.recognizedToFile.emit(sinkFileName)

    # This returns an iterator for n file names following some naming schema
    def fileNamesRange(self, n, stem="hyp"):
        for i in range(1, n+1):
            yield stem + str(i)

    #TODO: Write a solution for continuous recognition
    # Location of written files (and naming schema) should be governed by
    # a configuration manager
    # This will probably need a separate thread (QThread to be used)
    # FIXME: We should probably shut down the main PS instance to avoid conflicts
    # between it and the worker
    def startContinuousRecognition(self):
        logger.info("Starting continuous speech recognition")
        self.workerThread.start()

    def stopContinuousRecognition(self):
        logger.info("Stopping continuous speech recognition")
        self.workerThread.quit()

    @classmethod
    def supported():
        return True
예제 #16
0
class SlicerEngineManager(object):
    '''
    SlicerEngineManager is class designed for managing slicers engine and prepare parameters
    '''
    def __init__(self, controller):
        self.controller = controller
        self.slice_thread = None
        self.slice_engine = Slic3rEngineRunner(self.controller)


    def slice(self):
        self.slice_thread = QThread()
        #TODO:Make it universal(for other slice engines)
        self.slice_engine = Slic3rEngineRunner(self.controller)
        self.slice_engine.moveToThread(self.slice_thread)
        self.slice_thread.started.connect(self.slice_engine.slice)
        self.slice_engine.finished.connect(self.thread_ended)
        self.slice_engine.filament_info.connect(self.controller.set_print_info_text)
        self.slice_engine.step_increased.connect(self.controller.set_progress_bar)
        self.slice_engine.send_message.connect(self.controller.slicing_message)
        self.slice_engine.send_gcodedata.connect(self.controller.set_gcode_instance)

        self.slice_thread.start()

    def cancel(self):
        logging.debug("Thread canceling")
        if self.slice_engine and self.slice_thread:
            self.slice_engine.is_running = False
            self.slice_engine.kill()
            self.slice_thread.quit()
            self.slice_thread.wait()
            self.controller.status = 'canceled'
            self.controller.set_generate_button()
            self.controller.set_progress_bar(0.0)

    def thread_ended(self):
        self.slice_thread.quit()
        #TODO: add function to read gcode
        self.controller.scene_was_sliced()


    def get_version(self):
        return self.slice_engine.get_version()
예제 #17
0
    def quit(self):
        if not self.exiting:
            self.exiting = True

            if self.connection.isRunning():
                self.log.debug("Closing connection...")
                self.connection.quit()
                self.connection.wait()

            if self.parser.isRunning():
                self.log.debug("Closing parser...")
                self.parser.quit()
                self.parser.wait()

            self.log.debug("Ending InstrumentController thread")
            QThread.quit(self)

        else:
            self.log.error("quit() called twice!")
예제 #18
0
파일: threads.py 프로젝트: knkp/FLspyglass
 def quit(self):
     self.active = False
     self.queue.put(None)
     QThread.quit(self)
예제 #19
0
class MQTTClient(QtCore.QObject):
    """
    Wrapper class for Mosquitto MQTT client
    Provides inherited helper classes for SingleShot and Test requests
    Initial approach was to sub class QThread, but reading revealed that
    running the timers within a thread was the preferred approach.
    
    
    """

    kMaxAttempts = 3
    kMinKeepAlive = 5
    kResetTimer = 60

    mqttOnConnect = pyqtSignal(QObject, QObject, int)
    mqttOnDisConnect = pyqtSignal(QObject, QObject, int)
    mqttOnMessage = pyqtSignal(QObject, QObject, QObject)
    mqttOnPublish = pyqtSignal(QObject, QObject, int)
    mqttOnSubscribe = pyqtSignal(QObject, QObject, int, int)
    mqttOnLog = pyqtSignal(str, int)
    mqttOnTimeout = pyqtSignal(QObject)
    mqttConnectionError = pyqtSignal(QObject, str)

    # Hmmm new style signals cause problems with multiple parameters
    #    mqttConnectionError =  QtCore.pyqtSignal([str])

    # Add username/password
    def __init__(self, creator, clientId, broker, cleanSession=True):

        super(MQTTClient, self).__init__()
        # Load settings
        self._creator = creator

        # create client id
        self._cleanSession = cleanSession
        self._resetTimer = QTimer()
        self._resetTimer.setSingleShot(True)
        self._resetTimer.timeout.connect(self._reset)

        self._killTimer = QTimer()
        self._killTimer.setSingleShot(True)
        self._killTimer.timeout.connect(self._kill)
        self._killing = False

        self._loopTimer = QTimer()
        self._loopTimer.setSingleShot(False)
        self._loopTimer.timeout.connect(self._loop)
        self._clientId = clientId
        self._host = broker.host()
        self._port = int(broker.port())
        self._poll = int(broker.poll())
        self.setKeepAlive(broker.keepAlive())
        self._attempts = 0
        self._attempted = 0
        self._connected = False
        self._thread = QThread(self)
        self._thread.started.connect(lambda: self._loopTimer.start(self._poll))
        self._thread.finished.connect(self._loopTimer.stop)

        self._thread.started.connect(lambda: Log.debug("Thread started"))
        self._thread.finished.connect(lambda: Log.debug("Thread stopped"))
        self._thread.terminated.connect(lambda: Log.debug("Thread terminated"))
        self._restarting = False
        self._subscribed = []

        #        self.mqttc = mqtt.Client(self._clientId, self._cleanSession)
        self.mqttc = mqtt.Mosquitto(self._clientId, self._cleanSession)

        if broker.username():  # Basic Auth!
            self.mqttc.username_pw_set(broker.username(), broker.password())

        self.mqttc.on_connect = self.on_connect
        self.mqttc.on_disconnect = self.on_disconnect
        self.mqttc.on_message = self.onMessage
        self.mqttc.on_publish = self.onPublish
        self.mqttc.on_subscribe = self.onSubscribe
        #        self.mqttc.on_unsubscribe = self.onSubscribe - not implemented - remove element from self._subscribed
        self.mqttc.on_log = self.onLog

    def _canRun(self):
        return True

    def run(self):
        Log.debug("MQTT client run")

        if self.isRunning() or self._killing:
            self.restart()
            return

        if self._restarting:
            self._thread.finished.disconnect(self.run)
            self._restarting = False

        self._thread.start(QThread.LowestPriority)

    def stop(self):
        self._thread.quit()  # emits finished
        Log.debug("Thread quit")

    def isRunning(self):
        return self._thread.isRunning()

    def _loop(self):
        if self._canRun():
            self.loop()

    def setHost(self, host):
        self._host = host

    def host(self):
        return self._host

    def setPort(self, port):
        self._port = int(port)

    def port(self):
        return self._port

    def setPoll(self, poll):
        self._poll = int(poll)

    def setKeepAlive(self, keepAlive):
        self._keepAlive = max(
            int(keepAlive) + int(self._poll), self.kMinKeepAlive)

    def getClientId(self):
        return self._clientId

    def on_connect(self, client, obj, flags, rc):  # paho
        #    def on_connect(self, client, obj, rc): # mosquitto
        Log.debug("Connected " + str(rc))
        if rc != mqtt.MQTT_ERR_SUCCESS:  # paho
            #        if rc != mqtt.MOSQ_ERR_SUCCESS: # mosquitto
            return
        self._connected = True
        self._attempts = 0
        self._subscribed = []

        self.onConnect(client, obj, rc)

    def restart(self):

        Log.debug("Restarting")
        if self.isRunning():
            self._restarting = True
            self._thread.finished.connect(self.run)
            if not self._killing:
                self.kill()
        else:
            self.run()

    def on_disconnect(self, client, obj, rc):
        Log.debug("disconnecting rc: " + str(rc) + " " + str(self._connected))
        if self._killing:
            Log.debug("killing")
            self._kill()
        self.onDisConnect(client, obj, rc)
        self._connected = False

    def onConnect(self, client, obj, rc):
        self.mqttOnConnect.emit(self, obj, rc)
        #        QObject.emit(self, SIGNAL('mqttOnConnect'), self, obj, rc)
        pass

    def onDisConnect(self, client, obj, rc):
        self.mqttOnDisConnect.emit(self, obj, rc)
        #        QObject.emit(self, SIGNAL('mqttOnDisConnect'), self, obj, rc)
        pass

    def onMessage(self, client, obj, msg):
        self.mqttOnMessage.emit(self, obj, msg)
#        QObject.emit(self, SIGNAL('mqttOnMessage'), self, obj, msg)
# Log.debug('super ' + msg.topic+" "+str(msg.qos)+" "+str(msg.payload))

    def onPublish(self, client, obj, mid):
        self.mqttOnPublish.emit(self, obj, mid)
        # QObject.emit(self._creator, SIGNAL('mqttOnPublish'), self, obj, mid)
        Log.debug("onPublish - Message ID: " + str(mid))

    def onSubscribe(self, client, obj, mid, granted_qos):
        self.mqttOnSubscribe.emit(self, obj, mid, granted_qos)
        Log.info("Subscribed: " + str(mid) + " " + str(granted_qos))

    def onLog(self, client, obj, level, msg):
        self.mqttOnLog.emit(msg, level)
        #Log.debug(string,level)

    def isConnected(self):
        return self.mqttc.socket() is not None and self._connected

    def publish(self, topic, payload, qos=0, retain=True):
        self.mqttc.publish(str(topic), payload, int(qos), retain)

    def subscribe(self, topic, qos=0):
        if self.isConnected() and not str(topic) in self._subscribed:
            try:
                self.mqttc.subscribe(str(topic), int(qos))
                self._subscribed.append(str(topic))
                Log.debug('Subscribed to ' + topic + " " + str(qos))
            except Exception as e:
                Log.debug("Error on subscribe " + str(e))
                raise e

    def unsubscribe(self, topic):
        if self.isConnected():
            self.mqttc.unsubscribe(topic)
            Log.debug('Un_subscribed to ' + topic)

    def loop(self, timeout=0.1):
        if not self.isConnected():
            if not self._killing:
                self._connect()
            return
        try:
            connResult = self.mqttc.loop(timeout)
            if connResult == mqtt.MQTT_ERR_SUCCESS:  # paho
                #            if connResult == mqtt.MOSQ_ERR_SUCCESS: # mosquitto
                return

            self._connected = False
            self._attempts += 1

            Log.warn("MQTT: An error occurred while looping")
            self.mqttConnectionError.emit(self, mqtt.error_string(connResult))
        except ValueError as e:
            if e == 'Invalid timeout.':
                self.mqttOnTimeout.emit(self, "Connection Timeout")
            else:
                Log.debug("Paho Client ValueError" + str(e))
        except Exception as e:
            self.mqttConnectionError.emit(self, str(e))
            Log.debug("MQTT Connect: Unknown exception raised " + str(e))
            exc_type, exc_value, exc_traceback = sys.exc_info()
            Log.debug(
                repr(
                    traceback.format_exception(exc_type, exc_value,
                                               exc_traceback)))

    def _kill(self):
        self._loopTimer.stop(
        )  # Stopped in self.stop but lets preempt this to avoid self.loop being called by running thread
        self._killTimer.stop()
        self._killing = False
        self._reset()  # reset timer
        self.stop()

    def kill(self):
        try:
            if self.isConnected():
                self._disconnect()
            self._killing = True
            self._killTimer.start(self._keepAlive)
        except Exception as e:
            Log.warn("Error cleaning up " + str(e))
        pass

    def _connect(self):
        try:
            if not self._connected:
                if not self._attempts < self.kMaxAttempts:
                    if not self._resetTimer.isActive():
                        Log.progress(
                            Settings.getMeta("name") +
                            ": Max connection attempts reached - waiting " +
                            str(self.kResetTimer) + " seconds before retrying")
                        self._resetTimer.start(self.kResetTimer *
                                               1000)  # 1 minute parameterise
                    return
                if self._attempts > 0 and (time.time() - pow(
                        2, self._attempts + 1)) < self._attemped:
                    return
                Log.debug("Trying to connect")
                self._attemped = time.time()
                result = self.mqttc.connect(str(self._host), int(self._port),
                                            int(self._keepAlive), 1)
                self._connected = result == mqtt.MQTT_ERR_SUCCESS  # paho
                #                self._connected = result == mqtt.MOSQ_ERR_SUCCESS # mosquitto
                if not self._connected:
                    self._attempts += 1
                    Log.progress(mqtt.connack_string(connResult))
                    self.mqttConnectionError.emit(
                        self, mqtt.connack_string(connResult))

        except Exception as e:
            msg = 'MQTT: ' + str(e)

            self.mqttConnectionError.emit(self, msg)
            #Log.progress(msg)
            Log.debug(msg)
            #exc_type, exc_value, exc_traceback = sys.exc_info()
            #Log.debug(repr(traceback.format_exception(exc_type, exc_value,
            #                                         exc_traceback)))
            self._attempts += 1
            self._connected = False

    def _disconnect(self):
        try:
            self.mqttc.disconnect()
        except Exception as e:
            Log.warn('MQTT Disconnection Error' + str(e))

    def _reset(self):
        Log.warn("Timer reset ")
        self._attempts = 0
        self._resetTimer.stop()  # not required
예제 #20
0
class InferenceViewer(QtGui.QMainWindow):
    def __init__(self, model_name, model_format, image_dir, model_location,
                 label, hierarchy, image_val, input_dims, output_dims,
                 batch_size, output_dir, add, multiply, verbose, fp16, replace,
                 loop, rali_mode, gui, container_logo, fps_file, cpu_name,
                 gpu_name, parent):
        super(InferenceViewer, self).__init__(parent)
        self.parent = parent

        self.model_name = model_name
        self.model_format = model_format
        self.image_dir = image_dir
        self.model_location = model_location
        self.label = label
        self.hierarchy = hierarchy
        self.image_val = image_val
        self.input_dims = input_dims
        self.output_dims = output_dims
        self.batch_size = batch_size
        self.batch_size_int = (int)(batch_size)
        self.output_dir = output_dir
        self.add = add
        self.multiply = multiply
        self.gui = True if gui == 'yes' else False
        self.fp16 = fp16
        self.replace = replace
        self.verbose = verbose
        self.loop = loop
        self.rali_mode = rali_mode
        inputImageDir = os.path.expanduser(image_dir)
        self.total_images = len(os.listdir(inputImageDir))
        self.origImageQueue = Queue.Queue()
        self.augImageQueue = Queue.Queue()
        self.fps_file = fps_file
        self.inferenceEngine = None
        self.receiver_thread = None

        self.initEngines()

        if self.gui:
            self.container_index = (int)(container_logo)
            self.cpu_name = cpu_name
            self.gpu_name = gpu_name
            self.pauseState = False
            self.showAug = False
            self.elapsedTime = QTime.currentTime()
            self.lastTime = 0
            self.totalElapsedTime = 0.0
            self.totalAccuracy = 0
            self.progIndex = 0
            self.augIntensity = 0.0
            self.imgCount = 0
            self.frameCount = 9
            self.lastIndex = self.frameCount - 1
            self.x = [0]
            self.y = [0]
            self.augAccuracy = []
            self.totalCurve = None
            self.augCurve = None
            self.graph = None
            self.legend = None
            self.lastAugName = None
            self.pen = pg.mkPen('w', width=4)
            self.AMD_Radeon_pixmap = QPixmap("./data/images/AMD_Radeon.png")
            self.AMD_Radeon_white_pixmap = QPixmap(
                "./data/images/AMD_Radeon-white.png")
            self.MIVisionX_pixmap = QPixmap("./data/images/MIVisionX-logo.png")
            self.MIVisionX_white_pixmap = QPixmap(
                "./data/images/MIVisionX-logo-white.png")
            self.EPYC_pixmap = QPixmap("./data/images/EPYC-blue.png")
            self.EPYC_white_pixmap = QPixmap(
                "./data/images/EPYC-blue-white.png")
            self.docker_pixmap = QPixmap("./data/images/Docker.png")
            self.singularity_pixmap = QPixmap("./data/images/Singularity.png")
            self.rali_pixmap = QPixmap("./data/images/RALI.png")
            self.rali_white_pixmap = QPixmap("./data/images/RALI-white.png")
            self.graph_image_pixmap = QPixmap("./data/images/Graph-image.png")
            self.graph_image_white_pixmap = QPixmap(
                "./data/images/Graph-image-white.png")

            self.initUI()
            self.updateTimer = QTimer()
            self.updateTimer.timeout.connect(self.update)
            self.updateTimer.timeout.connect(self.plotGraph)
            self.updateTimer.timeout.connect(self.setProgressBar)
            self.updateTimer.start(40)

    def initUI(self):
        uic.loadUi("inference_viewer.ui", self)
        self.setStyleSheet("background-color: white")
        self.name_label.setText("Model: %s" % (self.model_name))
        self.cpuName_label.setText(self.cpu_name)
        self.gpuName_label.setText(self.gpu_name)
        self.dataset_label.setText("Augmentation set - %d" % (self.rali_mode))
        self.imagesFrame.setStyleSheet(
            ".QFrame {border-width: 20px; border-image: url(./data/images/filmStrip.png);}"
        )
        self.total_progressBar.setStyleSheet(
            "QProgressBar::chunk { background: lightblue; }")
        self.top1_progressBar.setStyleSheet(
            "QProgressBar::chunk { background: green; }")
        self.top5_progressBar.setStyleSheet(
            "QProgressBar::chunk { background: lightgreen; }")
        self.mis_progressBar.setStyleSheet(
            "QProgressBar::chunk { background: red; }")
        self.total_progressBar.setMaximum(self.total_images *
                                          self.batch_size_int)
        self.graph = pg.PlotWidget(title="Accuracy vs Time")
        self.graph.setLabel('left', 'Accuracy', '%')
        self.graph.setLabel('bottom', 'Time', 's')
        self.graph.setYRange(0, 100, padding=0)
        pg.setConfigOptions(antialias=True)
        self.totalCurve = self.graph.plot(pen=self.pen)
        self.augCurve = self.graph.plot(pen=pg.mkPen('b', width=4))
        self.legend = pg.LegendItem(offset=(370, 1))
        self.legend.setParentItem(self.graph.plotItem)
        self.legend.addItem(self.totalCurve, 'Cumulative')
        self.graph.setBackground(None)
        self.graph.setMaximumWidth(550)
        self.graph.setMaximumHeight(300)
        self.verticalLayout_2.addWidget(self.graph)
        self.level_slider.setMaximum(100)
        self.level_slider.valueChanged.connect(self.setIntensity)
        self.pause_pushButton.setStyleSheet(
            "color: white; background-color: darkBlue")
        self.stop_pushButton.setStyleSheet(
            "color: white; background-color: darkRed")
        self.pause_pushButton.clicked.connect(self.pauseView)
        self.stop_pushButton.clicked.connect(self.terminate)
        self.dark_checkBox.stateChanged.connect(self.setBackground)
        self.verbose_checkBox.stateChanged.connect(self.showVerbose)
        self.rali_checkBox.stateChanged.connect(self.showRALI)
        self.dark_checkBox.setChecked(True)
        self.graph_imageLabel.setPixmap(self.graph_image_pixmap)
        if self.container_index == 1:
            self.container_logo.setPixmap(self.docker_pixmap)
        elif self.container_index == 2:
            self.container_logo.setPixmap(self.singularity_pixmap)
        else:
            self.container_logo.hide()
        for augmentation in range(self.batch_size_int):
            self.augAccuracy.append([0])

        self.showVerbose()
        self.showRALI()

    def initEngines(self):
        self.receiver_thread = QThread()
        # Creating an object for inference.
        self.inferenceEngine = modelInference(
            self.model_name, self.model_format, self.image_dir,
            self.model_location, self.label, self.hierarchy, self.image_val,
            self.input_dims, self.output_dims, self.batch_size,
            self.output_dir, self.add, self.multiply, self.verbose, self.fp16,
            self.replace, self.loop, self.rali_mode, self.origImageQueue,
            self.augImageQueue, self.gui, self.total_images, self.fps_file)

        self.inferenceEngine.moveToThread(self.receiver_thread)
        self.receiver_thread.started.connect(self.inferenceEngine.runInference)
        self.receiver_thread.finished.connect(self.inferenceEngine.deleteLater)
        self.receiver_thread.start()
        self.receiver_thread.terminate()

    def paintEvent(self, event):
        self.showAugImage()
        self.showImage()
        self.displayFPS()
        if self.imgCount == self.total_images:
            if self.loop == 'yes':
                self.resetViewer()
            else:
                self.terminate()

    def resetViewer(self):
        self.imgCount = 0
        del self.x[:]
        self.x.append(0)
        del self.y[:]
        self.y.append(0)
        del self.augAccuracy[:]
        for augmentation in range(self.batch_size_int):
            self.augAccuracy.append([0])

        self.lastTime = 0
        self.elapsedTime = QTime.currentTime()
        self.totalElapsedTime = 0.0
        self.progIndex = 0
        self.showAug = False
        self.lastIndex = self.frameCount - 1
        self.totalCurve.clear()
        self.augCurve.clear()
        self.name_label.setText("Model: %s" % (self.model_name))
        self.legend.removeItem(self.lastAugName)

    def setProgressBar(self):
        if self.showAug:
            self.setAugProgress(self.progIndex)
        else:
            self.setTotalProgress()

    def setTotalProgress(self):
        totalStats = self.inferenceEngine.getTotalStats()
        top1 = totalStats[0]
        top5 = totalStats[1]
        mis = totalStats[2]
        totalCount = top5 + mis
        self.totalAccuracy = (float)(top5) / (totalCount + 1) * 100
        self.total_progressBar.setValue(totalCount)
        self.total_progressBar.setMaximum(self.total_images *
                                          self.batch_size_int)
        self.imgProg_label.setText(
            "Processed: %d of %d" %
            (totalCount, self.total_images * self.batch_size_int))
        self.top1_progressBar.setValue(top1)
        self.top1_progressBar.setMaximum(totalCount)
        self.top5_progressBar.setValue(top5)
        self.top5_progressBar.setMaximum(totalCount)
        self.mis_progressBar.setValue(mis)
        self.mis_progressBar.setMaximum(totalCount)

    def setAugProgress(self, augmentation):
        augStats = self.inferenceEngine.getAugStats(augmentation)
        top1 = augStats[0]
        top5 = augStats[1]
        mis = augStats[2]
        totalCount = top5 + mis
        self.total_progressBar.setValue(totalCount)
        self.total_progressBar.setMaximum(self.total_images)
        self.imgProg_label.setText("Processed: %d of %d" %
                                   (totalCount, self.total_images))
        self.top1_progressBar.setValue(top1)
        self.top1_progressBar.setMaximum(totalCount)
        self.top5_progressBar.setValue(top5)
        self.top5_progressBar.setMaximum(totalCount)
        self.mis_progressBar.setValue(mis)
        self.mis_progressBar.setMaximum(totalCount)

    def plotGraph(self):
        if not self.pauseState:
            curTime = self.elapsedTime.elapsed() / 1000.0
            if (curTime - self.lastTime > 0.01):
                self.x.append(curTime + self.totalElapsedTime)
                self.y.append(self.totalAccuracy)
                self.totalCurve.setData(x=self.x, y=self.y, pen=self.pen)
                for augmentation in range(self.batch_size_int):
                    augStats = self.inferenceEngine.getAugStats(augmentation)
                    top5 = augStats[1]
                    mis = augStats[2]
                    totalCount = top5 + mis
                    totalAccuracy = (float)(top5) / (totalCount + 1) * 100
                    self.augAccuracy[augmentation].append(totalAccuracy)

                if self.showAug:
                    self.augCurve.setData(x=self.x,
                                          y=self.augAccuracy[self.progIndex],
                                          pen=pg.mkPen('b', width=4))

            self.lastTime = curTime

    def showImage(self):
        if not self.origImageQueue.empty():
            origImage = self.origImageQueue.get()
            origWidth = origImage.shape[1]
            origHeight = origImage.shape[0]
            qOrigImage = QtGui.QImage(origImage, origWidth, origHeight,
                                      origWidth * 3,
                                      QtGui.QImage.Format_RGB888)
            qOrigImageResized = qOrigImage.scaled(self.image_label.width(),
                                                  self.image_label.height(),
                                                  QtCore.Qt.IgnoreAspectRatio)
            index = self.imgCount % self.frameCount
            self.origImage_layout.itemAt(index).widget().setPixmap(
                QtGui.QPixmap.fromImage(qOrigImageResized))
            self.origImage_layout.itemAt(index).widget().setStyleSheet(
                "border: 5px solid yellow;")
            self.origImage_layout.itemAt(
                self.lastIndex).widget().setStyleSheet("border: 0")
            self.imgCount += 1
            self.lastIndex = index

    def showAugImage(self):
        if not self.augImageQueue.empty():
            augImage = self.augImageQueue.get()
            augWidth = augImage.shape[1]
            augHeight = augImage.shape[0]
            qAugImage = QtGui.QImage(augImage, augWidth, augHeight,
                                     augWidth * 3, QtGui.QImage.Format_RGB888)
            if self.batch_size_int == 64:
                qAugImageResized = qAugImage.scaled(
                    self.aug_label.width(), self.aug_label.height(),
                    QtCore.Qt.IgnoreAspectRatio)
            else:
                qAugImageResized = qAugImage.scaled(self.aug_label.width(),
                                                    self.aug_label.height(),
                                                    QtCore.Qt.KeepAspectRatio)
            self.aug_label.setPixmap(QtGui.QPixmap.fromImage(qAugImageResized))

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            self.terminate()

        if event.key() == QtCore.Qt.Key_Space:
            self.pauseView()

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            mousePos = event.pos()
            if self.aug_label.geometry().contains(mousePos):
                index = self.calculateIndex(mousePos.x(), mousePos.y())
                self.progIndex = index
                self.showAug = True
                augName = self.inferenceEngine.getAugName(index)
                self.name_label.setText(augName)
                self.augCurve.setData(x=self.x,
                                      y=self.augAccuracy[self.progIndex],
                                      pen=pg.mkPen('b', width=4))
                self.legend.removeItem(self.lastAugName)
                self.legend.addItem(self.augCurve, augName)
                self.lastAugName = augName
            else:
                self.showAug = False
                self.name_label.setText("Model: %s" % (self.model_name))
                self.augCurve.clear()
                self.legend.removeItem(self.lastAugName)
                self.legend.removeItem('Cumulative')
                self.legend.addItem(self.totalCurve, 'Cumulative')
            if not self.pauseState:
                self.totalCurve.clear()
                self.augCurve.clear()

    def setBackground(self):
        if self.dark_checkBox.isChecked():
            self.setStyleSheet("background-color: #25232F;")
            self.pen = pg.mkPen('w', width=4)
            self.graph.setBackground(None)
            self.origTitle_label.setStyleSheet("color: #C82327;")
            self.controlTitle_label.setStyleSheet("color: #C82327;")
            self.progTitle_label.setStyleSheet("color: #C82327;")
            self.graphTitle_label.setStyleSheet("color: #C82327;")
            self.augTitle_label.setStyleSheet("color: #C82327;")
            self.name_label.setStyleSheet("color: white;")
            self.dataset_label.setStyleSheet("color: white;")
            self.imgProg_label.setStyleSheet("color: white;")
            self.fps_label.setStyleSheet("color: #C82327;")
            self.dark_checkBox.setStyleSheet("color: white;")
            self.verbose_checkBox.setStyleSheet("color: white;")
            self.rali_checkBox.setStyleSheet("color: white;")
            self.level_label.setStyleSheet("color: white;")
            self.low_label.setStyleSheet("color: white;")
            self.high_label.setStyleSheet("color: white;")
            self.cpu_label.setStyleSheet("color: #C82327;")
            self.gpu_label.setStyleSheet("color: #C82327;")
            self.cpuName_label.setStyleSheet("color: white;")
            self.gpuName_label.setStyleSheet("color: white;")
            self.AMD_logo.setPixmap(self.AMD_Radeon_white_pixmap)
            if self.rali_checkBox.isChecked():
                self.MIVisionX_logo.setPixmap(self.rali_white_pixmap)
                self.graph_imageLabel.setPixmap(self.graph_image_white_pixmap)
            else:
                self.MIVisionX_logo.setPixmap(self.MIVisionX_white_pixmap)
            self.EPYC_logo.setPixmap(self.EPYC_white_pixmap)
            self.totalCurve.setData(x=self.x, y=self.y, pen=self.pen)
        else:
            self.setStyleSheet("background-color: white;")
            self.pen = pg.mkPen('k', width=4)
            self.graph.setBackground(None)
            self.origTitle_label.setStyleSheet("color: 0;")
            self.controlTitle_label.setStyleSheet("color: 0;")
            self.progTitle_label.setStyleSheet("color: 0;")
            self.graphTitle_label.setStyleSheet("color: 0;")
            self.augTitle_label.setStyleSheet("color: 0;")
            self.name_label.setStyleSheet("color: 0;")
            self.dataset_label.setStyleSheet("color: 0;")
            self.imgProg_label.setStyleSheet("color: 0;")
            self.fps_label.setStyleSheet("color: 0;")
            self.dark_checkBox.setStyleSheet("color: 0;")
            self.verbose_checkBox.setStyleSheet("color: 0;")
            self.rali_checkBox.setStyleSheet("color: 0;")
            self.level_label.setStyleSheet("color: 0;")
            self.low_label.setStyleSheet("color: 0;")
            self.high_label.setStyleSheet("color: 0;")
            self.cpu_label.setStyleSheet("color: 0;")
            self.gpu_label.setStyleSheet("color: 0;")
            self.cpuName_label.setStyleSheet("color: 0;")
            self.gpuName_label.setStyleSheet("color: 0;")
            self.AMD_logo.setPixmap(self.AMD_Radeon_pixmap)
            if self.rali_checkBox.isChecked():
                self.MIVisionX_logo.setPixmap(self.rali_pixmap)
                self.graph_imageLabel.setPixmap(self.graph_image_pixmap)
            else:
                self.MIVisionX_logo.setPixmap(self.MIVisionX_pixmap)
            self.EPYC_logo.setPixmap(self.EPYC_pixmap)
            self.totalCurve.setData(x=self.x, y=self.y, pen=self.pen)

    def showVerbose(self):
        if self.verbose_checkBox.isChecked():
            self.dataset_label.show()
            self.fps_label.show()
            self.fps_lcdNumber.show()
            self.legend.show()
            self.cpu_label.show()
            self.gpu_label.show()
            self.cpuName_label.show()
            self.gpuName_label.show()
        else:
            self.dataset_label.hide()
            self.fps_label.hide()
            self.fps_lcdNumber.hide()
            self.legend.hide()
            self.cpu_label.hide()
            self.gpu_label.hide()
            self.gpuName_label.hide()
            self.cpuName_label.hide()

    def showRALI(self):
        if self.rali_checkBox.isChecked():
            if self.dark_checkBox.isChecked():
                self.MIVisionX_logo.setPixmap(self.rali_white_pixmap)
                self.graph_imageLabel.setPixmap(self.graph_image_white_pixmap)
            else:
                self.MIVisionX_logo.setPixmap(self.rali_pixmap)
                self.graph_imageLabel.setPixmap(self.graph_image_pixmap)
            self.graph_imageLabel.show()
        else:
            if self.dark_checkBox.isChecked():
                self.MIVisionX_logo.setPixmap(self.MIVisionX_white_pixmap)
            else:
                self.MIVisionX_logo.setPixmap(self.MIVisionX_pixmap)
            self.graph_imageLabel.hide()

    def displayFPS(self):
        self.fps_lcdNumber.display(self.inferenceEngine.getFPS())

    def pauseView(self):
        self.pauseState = not self.pauseState
        if self.pauseState:
            self.totalElapsedTime += self.elapsedTime.elapsed() / 1000.0
            self.pause_pushButton.setText('Resume')
        else:
            self.elapsedTime.restart()
            self.pause_pushButton.setText('Pause')

        self.inferenceEngine.pauseInference()

    def terminate(self):
        self.inferenceEngine.terminate()
        self.receiver_thread.quit()
        for count in range(10):
            QThread.msleep(50)

        self.close()

    def closeEvent(self, event):
        self.terminate()
        exit(0)

    def setIntensity(self):
        augIntensity = (float)(self.level_slider.value()) / 100.0
        self.inferenceEngine.setIntensity(augIntensity)

    def calculateIndex(self, x, y):
        if self.batch_size_int == 64:
            imgWidth = self.aug_label.width() / 16.0
        else:
            imgWidth = self.aug_label.width() / 4.0
        imgHeight = self.aug_label.height() / 4.0
        x -= self.aug_label.x()
        y -= self.aug_label.y()
        column = (int)(x / imgWidth)
        row = (int)(y / imgHeight)
        index = 4 * column + row
        return index
예제 #21
0
 def quit(self):
     if self.h5file:
         self.h5file.close()
     QThread.quit(self)
예제 #22
0
class BisectRunner(QObject):
    bisector_created = Signal(object)
    running_state_changed = Signal(bool)

    def __init__(self, mainwindow):
        QObject.__init__(self)
        self.mainwindow = mainwindow
        self.bisector = None
        self.thread = None
        self.pending_threads = []

    def bisect(self, fetch_config, options):
        self.stop()

        # global preferences
        global_prefs = get_prefs()
        # apply the global prefs now
        apply_prefs(global_prefs)

        self.bisector = GuiBisector(fetch_config,
                                    persist=global_prefs['persist'])
        # create a QThread, and move self.bisector in it. This will
        # allow to the self.bisector slots (connected after the move)
        # to be automatically called in the thread.
        self.thread = QThread()
        self.bisector.moveToThread(self.thread)
        self.bisector.download_manager.download_progress.connect(
            self.show_dl_progress)
        self.bisector.test_runner.evaluate_started.connect(
            self.evaluate)
        self.bisector.finished.connect(self.bisection_finished)
        self.bisector_created.emit(self.bisector)
        if options['bisect_type'] == 'nightlies':
            handler = NightlyHandler(find_fix=options['find_fix'])
            start = options['start_date']
            end = options['end_date']
        else:
            handler = InboundHandler(find_fix=options['find_fix'])
            start = options['start_changeset']
            end = options['end_changeset']

        # options for the app launcher
        launcher_kwargs = {}
        for name in ('profile', 'preferences'):
            if name in options:
                value = options[name]
                if value:
                    launcher_kwargs[name] = value
        self.bisector.test_runner.launcher_kwargs = launcher_kwargs

        self.thread.start()
        self.bisector._bisect_args = (handler, start, end)
        # this will be called in the worker thread.
        QTimer.singleShot(0, self.bisector.bisect)

        self.running_state_changed.emit(True)

    @Slot()
    def stop(self, wait=True):
        if self.bisector:
            self.bisector.finished.disconnect(self.bisection_finished)
            self.bisector.download_manager.cancel()
            self.bisector = None
        if self.thread:
            self.thread.quit()
            if wait:
                # wait for thread(s) completion - this is the case when
                # user close the application
                self.thread.wait()
                for thread in self.pending_threads:
                    thread.wait()
            else:
                # do not block, just keep track of the thread - we got here
                # when user cancel the bisection with the button.
                self.pending_threads.append(self.thread)
                self.thread.finished.connect(self._remove_pending_thread)
            self.thread = None
        self.running_state_changed.emit(False)

    @Slot()
    def _remove_pending_thread(self):
        for thread in self.pending_threads[:]:
            if thread.isFinished():
                self.pending_threads.remove(thread)

    @Slot(object, int, int)
    def show_dl_progress(self, dl, current, total):
        message = "downloading %s: %d/%d" % (dl.get_dest(), current, total)
        self.mainwindow.ui.statusbar.showMessage(message, 2000)

    @Slot()
    def evaluate(self):
        verdict = get_verdict(self.mainwindow)
        self.bisector.test_runner.finish(verdict)

    @Slot(object, int)
    def bisection_finished(self, bisection, resultcode):
        if resultcode == Bisection.USER_EXIT:
            msg = "Bisection stopped."
            dialog = QMessageBox.information
        elif resultcode == Bisection.NO_DATA:
            msg = "Unable to find enough data to bisect."
            dialog = QMessageBox.warning
        elif resultcode == Bisection.EXCEPTION:
            msg = "Error: %s" % self.bisector.error[1]
            dialog = QMessageBox.critical
        else:
            if bisection.fetch_config.can_go_inbound() and \
                    isinstance(bisection.handler, NightlyHandler):
                # we can go on inbound, let's ask the user
                if QMessageBox.question(
                    self.mainwindow,
                    "End of the bisection",
                    "Nightly bisection is done, but you can continue the"
                    " bisection on inbound builds. Contibue with inbounds ?",
                    QMessageBox.Yes | QMessageBox.No,
                    QMessageBox.Yes
                ) == QMessageBox.Yes:
                    # let's go on inbound
                    QTimer.singleShot(0, self.bisector.nightlies_to_inbound)
                else:
                    # no inbound, bisection is done.
                    self.stop()
                return
            msg = "The bisection is done."
            dialog = QMessageBox.information
        dialog(self.mainwindow, "End of the bisection", msg)
        self.stop()
예제 #23
0
class BisectRunner(QObject):
    bisector_created = Signal(object)
    running_state_changed = Signal(bool)

    def __init__(self, mainwindow):
        QObject.__init__(self)
        self.mainwindow = mainwindow
        self.bisector = None
        self.thread = None
        self.pending_threads = []

    def bisect(self, fetch_config, options):
        self.stop()

        # global preferences
        global_prefs = get_prefs()
        # apply the global prefs now
        apply_prefs(global_prefs)

        download_dir = global_prefs['persist']
        persist_limit = int(abs(global_prefs['persist_size_limit'])
                            * 1073741824)
        if not download_dir:
            download_dir = self.mainwindow.persist

        self.bisector = GuiBisector(fetch_config,
                                    download_dir, persist_limit)
        # create a QThread, and move self.bisector in it. This will
        # allow to the self.bisector slots (connected after the move)
        # to be automatically called in the thread.
        self.thread = QThread()
        self.bisector.moveToThread(self.thread)
        self.bisector.test_runner.evaluate_started.connect(
            self.evaluate)
        self.bisector.finished.connect(self.bisection_finished)
        self.bisector.choose_next_build.connect(self.choose_next_build)
        self.bisector_created.emit(self.bisector)
        if options['bisect_type'] == 'nightlies':
            handler = NightlyHandler(find_fix=options['find_fix'])
            good = options['good_date']
            bad = options['bad_date']
        else:
            handler = InboundHandler(find_fix=options['find_fix'])
            good = options['good_changeset']
            bad = options['bad_changeset']

        # options for the app launcher
        launcher_kwargs = {}
        for name in ('profile', 'preferences'):
            if name in options:
                value = options[name]
                if value:
                    launcher_kwargs[name] = value

        # add add-ons paths to the app launcher
        launcher_kwargs['addons'] = options['addons']
        self.bisector.test_runner.launcher_kwargs = launcher_kwargs

        self.thread.start()
        self.bisector._bisect_args = (handler, good, bad)
        # this will be called in the worker thread.
        QTimer.singleShot(0, self.bisector.bisect)

        self.running_state_changed.emit(True)

    @Slot()
    def stop(self, wait=True):
        if self.bisector:
            self.bisector.finished.disconnect(self.bisection_finished)
            self.bisector.download_manager.cancel()
            self.bisector = None
        if self.thread:
            self.thread.quit()
            if wait:
                # wait for thread(s) completion - this is the case when
                # user close the application
                self.thread.wait()
                for thread in self.pending_threads:
                    thread.wait()
            else:
                # do not block, just keep track of the thread - we got here
                # when user cancel the bisection with the button.
                self.pending_threads.append(self.thread)
                self.thread.finished.connect(self._remove_pending_thread)
            self.thread = None
        self.running_state_changed.emit(False)

    @Slot()
    def _remove_pending_thread(self):
        for thread in self.pending_threads[:]:
            if thread.isFinished():
                self.pending_threads.remove(thread)

    @Slot(str)
    def evaluate(self, err_message):
        if not err_message:
            verdict = get_verdict(self.mainwindow)
        else:
            QMessageBox.warning(
                self.mainwindow,
                "Launcher Error",
                ("An error occured while starting the process, so the build"
                 " will be skipped. Error message:<br><strong>%s</strong>"
                 % err_message)
            )
            verdict = 's'
        self.bisector.test_runner.finish(verdict)

    @Slot()
    def choose_next_build(self):
        dlg = SkipDialog(self.bisector.bisection.build_range)
        self.bisector._next_build_index = dlg.choose_next_build()
        QTimer.singleShot(0, self.bisector._bisect_next)

    @Slot(object, int)
    def bisection_finished(self, bisection, resultcode):
        if resultcode == Bisection.USER_EXIT:
            msg = "Bisection stopped."
            dialog = QMessageBox.information
        elif resultcode == Bisection.NO_DATA:
            msg = "Unable to find enough data to bisect."
            dialog = QMessageBox.warning
        elif resultcode == Bisection.EXCEPTION:
            msg = "Error: %s" % self.bisector.error[1]
            dialog = QMessageBox.critical
        else:
            if self.bisector.fetch_config.can_go_inbound() and \
                    isinstance(bisection.handler, NightlyHandler):
                # we can go on inbound, let's ask the user
                if QMessageBox.question(
                    self.mainwindow,
                    "End of the bisection",
                    "Nightly bisection is done, but you can continue the"
                    " bisection on inbound builds. Continue with inbounds ?",
                    QMessageBox.Yes | QMessageBox.No,
                    QMessageBox.Yes
                ) == QMessageBox.Yes:
                    # let's go on inbound
                    QTimer.singleShot(0, self.bisector.nightlies_to_inbound)
                else:
                    # no inbound, bisection is done.
                    self.stop()
                return
            msg = "The bisection is done."
            dialog = QMessageBox.information
        dialog(self.mainwindow, "End of the bisection", msg)
        self.stop()
예제 #24
0
class file_transfer(iface_gui_plugin):
    VERSION_INITIAL = 0
    VERSION_CURRENT = VERSION_INITIAL
    
    def __init__(self):
        super(file_transfer, self).__init__()
        self.options = [((u"download_dir", u"Save received files in directory", self._downloadDirChanged), os.path.join(os.path.expanduser("~"), "Downloads")),
                        ((u"overwrite", u"Overwrite existing files", self._overwriteChanged), False),
                        ((u"compression", u"Use compression when sending", self._compressionChanged, (u"No", u"GZip", u"BZip2")), u"No")]
    
    def get_displayed_name(self):
        return u"File Transfer"
        
    def activate(self):
        iface_gui_plugin.activate(self)
        self._sendFileAction = _TransferFileAction()
        
    def deactivate(self):
        iface_gui_plugin.deactivate(self)
    
    def create_widget(self, parent):
        from file_transfer.file_transfer_widget import FileTransferWidget
        from file_transfer.file_transfer_handler import FileTransferHandler
        
        if canUseBackgroundQThreads():
            from PyQt4.QtCore import QThread
            self._handlerThread = QThread()
        else:
            self._handlerThread = None
            
        self._handler = FileTransferHandler(self.logger,
                                            self.get_option(u"download_dir"),
                                            self.get_option(u"overwrite"),
                                            self.get_option(u"compression"))
        if self._handlerThread is not None:
            self._handlerThread.moveToThread(self._handlerThread)
            self._handlerThread.start()
        
        self._gui = FileTransferWidget(parent, self.logger, self)
        self._toolWindow = FileTransferWidget(parent, self.logger, self, asWindow=True)
        self._toolWindow.setWindowTitle("File Transfers")

        for gui in (self._gui, self._toolWindow):        
            gui.retry.connect(self._handler.retrySendFileToPeer)
            gui.cancel.connect(self._handler.cancelOutgoingTransfer)
            self._handler.startOutgoingTransfer.connect(gui.startOutgoingTransfer)
            self._handler.outgoingTransferStarted.connect(gui.outgoingTransferStarted)
            self._handler.outgoingTransferCanceled.connect(gui.outgoingTransferCanceled)
            self._handler.incomingTransferStarted.connect(gui.incomingTransferStarted)
        
        return self._gui
    
    def destroy_widget(self):
        for gui in (self._gui, self._toolWindow):        
            gui.retry.disconnect(self._handler.retrySendFileToPeer)
            gui.cancel.disconnect(self._handler.cancelOutgoingTransfer)
            self._handler.startOutgoingTransfer.disconnect(gui.startOutgoingTransfer)
            self._handler.outgoingTransferStarted.disconnect(gui.outgoingTransferStarted)
            self._handler.outgoingTransferCanceled.disconnect(gui.outgoingTransferCanceled)
            self._handler.incomingTransferStarted.disconnect(gui.incomingTransferStarted)
        
        self._handler.deactivate()
        if self._handlerThread is not None:
            self._handlerThread.quit()
            self._handlerThread.wait()
            self._handlerThread.deleteLater()
            self._handlerThread = None
        self._handler = None
        
        iface_gui_plugin.destroy_widget(self)
    
    def extendsInfoDict(self):
        # do not except file transfers without GUI
        return lunchinator_has_gui()
        
    def extendInfoDict(self, infoDict):
        infoDict[u"FT_v"] = self.VERSION_CURRENT
        
    def get_peer_actions(self):
        return [self._sendFileAction]
        
    def process_event(self, cmd, value, peerIP, peerInfo, preprocessedData=None):
        if not cmd.startswith(u"HELO_FT"):
            return
        
        peerID = peerInfo[u"ID"]
        
        subcmd = cmd[7:]
        if subcmd == u"":
            self._handler.processSendRequest(peerID, peerIP, value, preprocessedData)
        elif subcmd == u"_ACK":
            self._handler.processAck(peerID, peerIP, value)
        elif subcmd == u"_CANCEL":
            self._handler.processCancel(peerID, value)
            
    def getSendFileAction(self):
        return self._sendFileAction
            
    def chooseAndSendFilesToPeer(self, peerID, parent):
        from PyQt4.QtGui import QFileDialog
        selectedFiles = QFileDialog.getOpenFileNames(parent, u"Chooses files to upload")
        if len(selectedFiles) > 0:
            self._handler.sendFilesToPeer([convert_string(f) for f in selectedFiles], peerID)
        
    def sendFilesToPeer(self, toSend, peerID):
        self._handler.sendFilesToPeer([convert_string(f) for f in toSend], peerID)
        
    def _downloadDirChanged(self, _setting, newVal):
        self._handler.downloadDirChanged(newVal)
        return newVal
    
    def _overwriteChanged(self, _setting, newVal):
        self._handler.overwriteChanged(newVal)
        return newVal
    
    def _compressionChanged(self, _setting, newVal):
        self._handler.compressionChanged(newVal)
        return newVal
예제 #25
0
class NGWResourcesModelJob(QObject):
    started = pyqtSignal()
    statusChanged = pyqtSignal(unicode)
    warningOccurred = pyqtSignal(object)
    errorOccurred = pyqtSignal(object)
    finished = pyqtSignal()

    def __init__(self, parent, worker, model_response=None):
        """Create job.

            Arguments:
                job_id -- Job identification
                worker -- The class object inherits from NGWResourceModelJob
        """
        QObject.__init__(self, parent)
        self.__result = None
        self.__worker = worker
        self.__job_id = self.__worker.id
        self.__error = None
        self.__warnings = []
        # self.__job_id = "%s_%s" % (self.__worker.id, str(uuid.uuid1()))

        self.__worker.started.connect(self.started.emit)
        self.__worker.dataReceived.connect(self.__rememberResult)
        self.__worker.statusChanged.connect(self.statusChanged.emit)
        self.__worker.errorOccurred.connect(self.processJobError)
        self.__worker.warningOccurred.connect(self.processJobWarnings)

        self.model_response = model_response

    def setResponseObject(self, resp):
        self.model_response = resp
        self.model_response.job_id = self.__job_id

    def __rememberResult(self, result):
        self.__result = result

    def getJobId(self):
        return self.__job_id

    def getResult(self):
        return self.__result

    def error(self):
        return self.__error

    def processJobError(self, job_error):
        self.__error = job_error
        self.errorOccurred.emit(job_error)

    def processJobWarnings(self, job_error):
        if self.model_response:
            self.model_response._warnings.append(job_error)
        # self.warningOccurred.emit(job_error)

    def start(self):
        self.__thread = QThread(self)
        self.__worker.moveToThread(self.__thread)
        self.__worker.finished.connect(self.finishProcess)
        self.__thread.started.connect(self.__worker.run)

        self.__thread.start()

    def finishProcess(self):
        self.__worker.started.disconnect()
        self.__worker.dataReceived.disconnect()
        self.__worker.statusChanged.disconnect()
        self.__worker.errorOccurred.disconnect()
        self.__worker.warningOccurred.disconnect()
        self.__worker.finished.disconnect()

        self.__thread.quit()
        self.__thread.wait()

        self.finished.emit()
예제 #26
0
class MQTTClient(QtCore.QObject):
    """
    Wrapper class for Mosquitto MQTT client
    Provides inherited helper classes for SingleShot and Test requests
    Initial approach was to sub class QThread, but reading revealed that
    running the timers within a thread was the preferred approach.
    
    
    """

    kMaxAttempts    = 3
    kMinKeepAlive   = 5
    kResetTimer     = 60

    mqttOnConnect       = pyqtSignal(QObject,QObject,int)
    mqttOnDisConnect    = pyqtSignal(QObject,QObject,int)
    mqttOnMessage       = pyqtSignal(QObject,QObject,QObject)
    mqttOnPublish       = pyqtSignal(QObject,QObject,int)
    mqttOnSubscribe     = pyqtSignal(QObject,QObject,int,int)
    mqttOnLog           = pyqtSignal(str,int)
    mqttOnTimeout       = pyqtSignal(QObject)
    mqttConnectionError = pyqtSignal(QObject,str)

    # Hmmm new style signals cause problems with multiple parameters
    #    mqttConnectionError =  QtCore.pyqtSignal([str])

    # Add username/password
    def __init__(self,
                 creator,
                 clientId,
                 broker,
                 cleanSession=True):

        super(MQTTClient, self).__init__()
        # Load settings
        self._creator = creator

        # create client id
        self._cleanSession = cleanSession
        self._resetTimer = QTimer()
        self._resetTimer.setSingleShot(True)
        self._resetTimer.timeout.connect(self._reset)

        self._killTimer = QTimer()
        self._killTimer.setSingleShot(True)
        self._killTimer.timeout.connect(self._kill)
        self._killing = False

        self._loopTimer = QTimer()
        self._loopTimer.setSingleShot(False)
        self._loopTimer.timeout.connect(self._loop)
        self._clientId = clientId
        self._host = broker.host()
        self._port = int(broker.port())
        self._poll = int(broker.poll())
        self.setKeepAlive(broker.keepAlive())
        self._attempts = 0
        self._attempted = 0
        self._connected = False
        self._thread = QThread(self)
        self._thread.started.connect(lambda: self._loopTimer.start(self._poll))
        self._thread.finished.connect(self._loopTimer.stop)

        self._thread.started.connect(lambda:Log.debug("Thread started"))
        self._thread.finished.connect(lambda:Log.debug("Thread stopped"))
        self._thread.terminated.connect(lambda:Log.debug("Thread terminated"))
        self._restarting = False
        self._subscribed =[]
        
#        self.mqttc = mqtt.Client(self._clientId, self._cleanSession)
        self.mqttc = mqtt.Mosquitto(self._clientId, self._cleanSession)
        
        if broker.username(): # Basic Auth!
                self.mqttc.username_pw_set(broker.username(), broker.password())

        self.mqttc.on_connect = self.on_connect
        self.mqttc.on_disconnect = self.on_disconnect
        self.mqttc.on_message = self.onMessage
        self.mqttc.on_publish = self.onPublish
        self.mqttc.on_subscribe = self.onSubscribe
#        self.mqttc.on_unsubscribe = self.onSubscribe - not implemented - remove element from self._subscribed
        self.mqttc.on_log = self.onLog

    def _canRun(self):
           return True

    def run(self):
        Log.debug("MQTT client run")

        if self.isRunning() or self._killing:
            self.restart()
            return

        if self._restarting:
            self._thread.finished.disconnect(self.run)
            self._restarting = False

        self._thread.start(QThread.LowestPriority)

    def stop(self):
        self._thread.quit()  # emits finished
        Log.debug("Thread quit")

    def isRunning(self):
        return self._thread.isRunning()

    def _loop(self):
        if self._canRun():
            self.loop()

    def setHost(self, host):
        self._host = host

    def host(self):
        return self._host

    def setPort(self, port):
        self._port = int(port)

    def port(self):
        return self._port

    def setPoll(self, poll):
        self._poll = int(poll)

    def setKeepAlive(self, keepAlive):
        self._keepAlive = max(int(keepAlive) + int(self._poll), self.kMinKeepAlive)

    def getClientId(self):
        return self._clientId

    def on_connect(self, client, obj,flags, rc):   # paho
#    def on_connect(self, client, obj, rc): # mosquitto
        Log.debug("Connected " + str(rc))
        if rc != mqtt.MQTT_ERR_SUCCESS: # paho
#        if rc != mqtt.MOSQ_ERR_SUCCESS: # mosquitto
            return
        self._connected = True
        self._attempts = 0
        self._subscribed =[]

        self.onConnect(client, obj, rc)

    def restart(self):
     
        Log.debug("Restarting")
        if self.isRunning():
            self._restarting = True
            self._thread.finished.connect(self.run)
            if not self._killing:
                self.kill()
        else:
            self.run()


    def on_disconnect(self, client, obj, rc):
        Log.debug("disconnecting rc: " + str(rc) + " " + str(self._connected))
        if self._killing:
            Log.debug("killing")
            self._kill()
        self.onDisConnect(client, obj, rc)
        self._connected = False

    def onConnect(self, client, obj, rc):
        self.mqttOnConnect.emit(self, obj, rc)
#        QObject.emit(self, SIGNAL('mqttOnConnect'), self, obj, rc)
        pass

    def onDisConnect(self, client, obj, rc):
        self.mqttOnDisConnect.emit(self,obj,rc)
#        QObject.emit(self, SIGNAL('mqttOnDisConnect'), self, obj, rc)
        pass


    def onMessage(self, client, obj, msg):
        self.mqttOnMessage.emit(self,obj,msg)
#        QObject.emit(self, SIGNAL('mqttOnMessage'), self, obj, msg)
        # Log.debug('super ' + msg.topic+" "+str(msg.qos)+" "+str(msg.payload))

    def onPublish(self, client, obj, mid):
        self.mqttOnPublish.emit(self,obj,mid)
        # QObject.emit(self._creator, SIGNAL('mqttOnPublish'), self, obj, mid)
        Log.debug("onPublish - Message ID: " + str(mid))

    def onSubscribe(self, client, obj, mid, granted_qos):
        self.mqttOnSubscribe.emit(self, obj, mid, granted_qos)
        Log.info("Subscribed: " + str(mid) + " " + str(granted_qos))

    def onLog(self, client, obj, level, msg):
        self.mqttOnLog.emit(msg, level)
        #Log.debug(string,level)

    def isConnected(self):
        return self.mqttc.socket() is not None and self._connected

    def publish(self, topic, payload, qos=0, retain=True):
        self.mqttc.publish(str(topic), payload, int(qos), retain)   

    def subscribe(self, topic, qos =0):
        if self.isConnected() and not str(topic) in self._subscribed:
            try:
                self.mqttc.subscribe(str(topic), int(qos))
                self._subscribed.append(str(topic))
                Log.debug('Subscribed to ' + topic + " " + str(qos))
            except Exception as e:
                Log.debug("Error on subscribe " + str(e))
                raise e

    def unsubscribe(self, topic):
        if self.isConnected():
            self.mqttc.unsubscribe(topic)
            Log.debug('Un_subscribed to ' + topic)

    def loop(self, timeout=0.1):
        if not self.isConnected():
            if not self._killing:
                self._connect()
            return
        try:
            connResult = self.mqttc.loop(timeout)
            if connResult == mqtt.MQTT_ERR_SUCCESS: # paho
#            if connResult == mqtt.MOSQ_ERR_SUCCESS: # mosquitto
                return
            
            self._connected = False
            self._attempts += 1
            
            Log.warn("MQTT: An error occurred while looping")
            self.mqttConnectionError.emit(self, mqtt.error_string(connResult))
        except ValueError as e:
            if e == 'Invalid timeout.':
                self.mqttOnTimeout.emit(self, "Connection Timeout")
            else:
                Log.debug("Paho Client ValueError" + str(e))
        except Exception as e:
            self.mqttConnectionError.emit(self, str(e))
            Log.debug("MQTT Connect: Unknown exception raised "  + str(e))
            exc_type, exc_value, exc_traceback = sys.exc_info()
            Log.debug(repr(traceback.format_exception(exc_type, exc_value,
                                                     exc_traceback)))


    def _kill(self):
        self._loopTimer.stop()  # Stopped in self.stop but lets preempt this to avoid self.loop being called by running thread
        self._killTimer.stop()
        self._killing = False
        self._reset() # reset timer
        self.stop()

    def kill(self):
        try:
            if self.isConnected():
                self._disconnect()
            self._killing = True
            self._killTimer.start(self._keepAlive)
        except Exception as e:
            Log.warn("Error cleaning up " + str(e))
        pass

    def _connect(self):
        try:
            if not self._connected:
                if not self._attempts < self.kMaxAttempts:
                    if not self._resetTimer.isActive():
                        Log.progress(Settings.getMeta("name") + ": Max connection attempts reached - waiting " + str(self.kResetTimer) + " seconds before retrying" )
                        self._resetTimer.start(self.kResetTimer*1000)  # 1 minute parameterise
                    return
                if self._attempts > 0 and (time.time() - pow(2,self._attempts +1)) < self._attemped:
                        return
                Log.debug("Trying to connect")
                self._attemped = time.time()
                result = self.mqttc.connect(str(self._host), int(self._port),int( self._keepAlive), 1)
                self._connected = result == mqtt.MQTT_ERR_SUCCESS # paho
#                self._connected = result == mqtt.MOSQ_ERR_SUCCESS # mosquitto
                if not self._connected:
                    self._attempts += 1
                    Log.progress(mqtt.connack_string(connResult))
                    self.mqttConnectionError.emit(self, mqtt.connack_string(connResult))
 
        except Exception as e:
            msg = 'MQTT: ' + str(e)

            self.mqttConnectionError.emit(self, msg)
            #Log.progress(msg)
            Log.debug(msg)
            #exc_type, exc_value, exc_traceback = sys.exc_info()
            #Log.debug(repr(traceback.format_exception(exc_type, exc_value,
             #                                         exc_traceback)))
            self._attempts += 1
            self._connected = False


    def _disconnect(self):
        try:
            self.mqttc.disconnect()
        except Exception as e:
            Log.warn('MQTT Disconnection Error' + str(e))

    def _reset(self):
        Log.warn("Timer reset ")
        self._attempts = 0
        self._resetTimer.stop() # not required
class v_calculator_main(QObject):
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgisInterface
        """
        super(v_calculator_main, self).__init__()
        self.calculation_thread = QThread(self)
        self.calculation_worker = None

        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'vegetation_calculator_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.getTranslation(u'&Vegetation calculator')
        # We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'vegetation_calculator')
        self.toolbar.setObjectName(u'vegetation_calculator')

        self.LOGGER = logging.getLogger("calculator_logger")
        if len(self.LOGGER.handlers) == 0:
            format_log = \
                "%(asctime)s - [%(levelname)s] -  %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s"
            fh = RotatingFileHandler(filename=os.path.join(self.plugin_dir, "calculator.log"),
                                     maxBytes=5 * 1024 * 1024,
                                     backupCount=5)
            fh.setFormatter(logging.Formatter(format_log))
            self.LOGGER.addHandler(fh)
            self.LOGGER.setLevel(logging.DEBUG)

    # noinspection PyMethodMayBeStatic
    def getTranslation(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('v_calculator_main', message)

    def add_action(
            self,
            icon_path,
            text,
            callback,
            enabled_flag=True,
            add_to_menu=True,
            add_to_toolbar=True,
            status_tip=None,
            whats_this=None,
            parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        # Create the dialog (after translation) and keep reference
        self.dlg = vegetation_calculatorDialog()
        self.initHandlers()

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToRasterMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = os.path.join(self.plugin_dir, 'icon.png')
        self.add_action(
            icon_path,
            text=self.getTranslation(u'Open calculator'),
            callback=self.run,
            parent=self.iface.mainWindow())

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginRasterMenu(
                self.getTranslation(u'&Vegetation calculator'),
                action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        del self.toolbar

    def initHandlers(self):
        """
        Initializes handlers for UI element events.
        """

        self.LOGGER.debug("init handlers")

        self.dlg.accepted.connect(self.startCalculation)

        self.dlg.cbx_ndvi_redLayer.currentIndexChanged.connect(self.showLayerBandsForNdviRed)
        self.dlg.cbx_ndvi_infraredLayer.currentIndexChanged.connect(self.showLayerBandsForNdviInfrared)
        self.dlg.cbx_agr_swirLayer.currentIndexChanged.connect(self.showLayerBandsForAgroSwir)
        self.dlg.cbx_agr_nnirLayer.currentIndexChanged.connect(self.showLayerBandsForAgroIr)
        self.dlg.cbx_agr_blueLayer.currentIndexChanged.connect(self.showLayerBandsForAgroBlue)

    def run(self):
        """Run method that performs all the real work"""
        logging.info("start")

        layers = QgsMapLayerRegistry.instance().mapLayers()

        self.showLayersLists(layers)
        self.showColorSchemes()

        # show the dialog
        self.LOGGER.debug("show the dialog")
        self.dlg.show()
        self.LOGGER.debug("run the dialog event loop")
        # Run the dialog event loop
        result = self.dlg.exec_()
        self.LOGGER.info("end")

    def showLayersLists(self, layers):
        """
        Display a list of raster layers on the UI.

        :param layers: layers to displaying.
        :type: [QgsMapLayer, ...]
        """

        self.LOGGER.debug("showing layers lists")

        self.dlg.cbx_ndvi_redLayer.clear()
        self.dlg.cbx_ndvi_infraredLayer.clear()
        self.dlg.cbx_agr_swirLayer.clear()
        self.dlg.cbx_agr_nnirLayer.clear()
        self.dlg.cbx_agr_blueLayer.clear()

        layer_names = []
        for name, layer in layers.iteritems():
            if layer.type() == 1:  # 1 = raster layer
                layer_names.append(layer.name())

        layer_names.sort(cmp=locale.strcoll)

        self.dlg.cbx_ndvi_redLayer.addItems(layer_names)
        self.dlg.cbx_ndvi_infraredLayer.addItems(layer_names)
        self.dlg.cbx_agr_swirLayer.addItems(layer_names)
        self.dlg.cbx_agr_nnirLayer.addItems(layer_names)
        self.dlg.cbx_agr_blueLayer.addItems(layer_names)

    def showLayerBandsForNdviRed(self, index):
        """
        Display bands of selected layer with red band for NDVI.

        :param index: index of an item in the QCombobox.
        :type: int
        """

        self.LOGGER.debug("showing bands of the red layer (NDVI)")

        layer_name = self.dlg.cbx_ndvi_redLayer.itemText(index)
        self.showLayerBands(self.dlg.lstw_ndvi_redBands, layer_name, 3)  # 3 = red

    def showLayerBandsForNdviInfrared(self, index):
        """
        Display bands of selected layer with infrared band for NDVI.

        :param index: index of an item in the QCombobox.
        :type: int
        """

        self.LOGGER.debug("showing bands of the infrared layer (NDVI)")

        layer_name = self.dlg.cbx_ndvi_infraredLayer.itemText(index)
        self.showLayerBands(self.dlg.lstw_ndvi_infraredBands, layer_name, 0)  # 0 = undefined color

    def showLayerBandsForAgroSwir(self, index):
        """
        Display bands of selected layer with SWIR (short wave infrared) band for agriculture or healthy vegetation.

        :param index: index of an item in the QCombobox.
        :type: int
        """

        self.LOGGER.debug("showing bands of the SWIR layer (agriculture and HV)")

        layer_name = self.dlg.cbx_agr_swirLayer.itemText(index)
        self.showLayerBands(self.dlg.lstw_agr_swirBands, layer_name, 0)  # 0 = undefined color

    def showLayerBandsForAgroIr(self, index):
        """
        Display bands of selected layer with infrared band for agriculture or healthy vegetation.

        :param index: index of an item in the QCombobox.
        :type: int
        """

        self.LOGGER.debug("showing bands of the IR layer (agriculture and HV)")

        layer_name = self.dlg.cbx_agr_nnirLayer.itemText(index)
        self.showLayerBands(self.dlg.lstw_agr_nnirBands, layer_name, 0)  # 0 = undefined color

    def showLayerBandsForAgroBlue(self, index):
        """
        Display bands of selected layer with blue band for agriculture or healthy vegetation.

        :param index: index of an item in the QCombobox.
        :type: int
        """

        self.LOGGER.debug("showing bands of the blue layer (agriculture and HV)")

        layer_name = self.dlg.cbx_agr_blueLayer.itemText(index)
        self.showLayerBands(self.dlg.lstw_agr_blueBands, layer_name, 5)  # 5 = blue

    def showLayerBands(self, qListWidget, layer_name, color_interpretation=None):
        """
        Display bands of the layer into the QListWidget.

        :param qListWidget: A QListWidget on the UI.
        :type QListWidget

        :param layer_name: A name of layer with bands to display
        :type: unicode

        :param color_interpretation: Color interpretation for automatic band selection.
        :type: int
        """

        self.LOGGER.debug("showing bands of %s", layer_name)

        try:
            raster_layer = QgsMapLayerRegistry.instance().mapLayersByName(layer_name)[0]
        except IndexError:
            return
        bands_dictionary = self.getBandsFromLayer(raster_layer)
        sorted(bands_dictionary)

        qListWidget.clear()

        index = 0
        band_number = None
        for band_information in bands_dictionary.values():
            qListWidget.addItem(band_information.full_name)
            if band_number is None and band_information.color_interpretation == color_interpretation:
                band_number = index
            index += 1

        if band_number is not None:
            qListWidget.setCurrentRow(band_number)
        else:
            qListWidget.setCurrentRow(0)

    def getBandsFromLayer(self, raster_layer):
        """
        Get bands of the raster layer.

        :param raster_layer: A layer to get channels from.
        :type: QgsRasterLayer

        :return: dictionary of BandInformation.
        :type: {unicode: BandInformation}
        """

        self.LOGGER.debug("getting bands of %s", raster_layer.name())

        layer_data_provider = raster_layer.dataProvider()

        bands = {}
        for band_number in range(1, raster_layer.bandCount() + 1):
            band = BandInformation(layer_data_provider.colorInterpretationName(band_number),
                                   band_number,
                                   layer_data_provider.colorInterpretation(band_number))
            bands[band.full_name] = band

        return OrderedDict(sorted(bands.items()))

    def showColorSchemes(self):
        """
        Display color schemes.
        """
        self.LOGGER.debug("showing color schemes")

        self.dlg.cbx_color_schemes.clear()
        color_schemes = OrderedDict(sorted(ColorsForNdviMap().colorSchemes.items()))

        for color_scheme_name in color_schemes:
            color_scheme = color_schemes[color_scheme_name]
            icon_pixmap = QPixmap(50, 20)
            painter = QPainter(icon_pixmap)

            painter.fillRect(0, 0, 10, 20, color_scheme["ndvi_0"])
            painter.fillRect(10, 0, 20, 20, color_scheme["ndvi_0.25"])
            painter.fillRect(20, 0, 30, 20, color_scheme["ndvi_0.5"])
            painter.fillRect(30, 0, 40, 20, color_scheme["ndvi_0.75"])
            painter.fillRect(40, 0, 50, 20, color_scheme["ndvi_1"])
            painter.end()

            icon = QIcon(icon_pixmap)
            self.dlg.cbx_color_schemes.addItem(icon, color_scheme_name)

    def startCalculation(self):
        """
        Start calculating NDVI, agriculture or healthy vegetation
        """

        self.LOGGER.debug("start calculation")

        if self.calculation_thread.isRunning() is True:
            return

        if self.dlg.tabw_content.currentIndex() == 0:  # NDVI
            if self.dlg.rbtn_calculateNdvi.isChecked():
                self.calculateNdvi()
            elif self.dlg.rbtn_openNdviFile.isChecked():
                try:
                    input_file_name = self.dlg.led_ndvi_inputFile.text()
                    self.validateInputFilePath(input_file_name)
                except CalculatorException as exp:
                    self.LOGGER.info(exp.message)
                    self.dlg.show_error_message(self.getTranslation(exp.title), self.getTranslation(exp.message))
                    return
                self.openNdviFile(input_file_name)
        elif self.dlg.tabw_content.currentIndex() == 1:  # Agriculture and HV
            self.calculateAgricultureOrHv()

    def calculateAgricultureOrHv(self):
        """
        Start calculating agriculture or healthy vegetation
        """

        self.LOGGER.info("start agriculture or hv calculation")
        self.LOGGER.info("Agriculture: %s", self.dlg.rbtn_agr_agriculture.isChecked())
        self.LOGGER.info("HV: %s", self.dlg.rbtn_agr_hv.isChecked())

        if self.dlg.cbx_agr_swirLayer.count() == 0 or \
                self.dlg.cbx_agr_nnirLayer.count() == 0 or \
                self.dlg.cbx_agr_blueLayer.count() == 0:
            self.LOGGER.info("Layers not found")
            self.dlg.show_error_message(self.getTranslation("Error"), self.getTranslation("Layers not found"))
            return

        self.LOGGER.info("SWIR: %s", self.dlg.cbx_agr_swirLayer.currentText())
        self.LOGGER.info("NNIR: %s", self.dlg.cbx_agr_nnirLayer.currentText())
        self.LOGGER.info("blue: %s", self.dlg.cbx_agr_blueLayer.currentText())

        output_file_name = self.dlg.led_agr_outputFile.text()

        try:
            self.validateOutputFilePath(output_file_name)
            swir_layer = self.getLayerByName(self.dlg.cbx_agr_swirLayer.currentText())
            nnir_layer = self.getLayerByName(self.dlg.cbx_agr_nnirLayer.currentText())
            blue_layer = self.getLayerByName(self.dlg.cbx_agr_blueLayer.currentText())

            swir_band = self.getBandsFromLayer(swir_layer)[self.getCurrentBandName(self.dlg.lstw_agr_swirBands)]
            nnir_band = self.getBandsFromLayer(nnir_layer)[self.getCurrentBandName(self.dlg.lstw_agr_nnirBands)]
            blue_band = self.getBandsFromLayer(blue_layer)[self.getCurrentBandName(self.dlg.lstw_agr_blueBands)]
        except CalculatorException as exp:
            self.LOGGER.info(exp.message)
            self.dlg.show_error_message(self.getTranslation(exp.title), self.getTranslation(exp.message))
            return

        if self.dlg.rbtn_agr_agriculture.isChecked():
            layer_list = [(swir_layer, swir_band.serial_number),
                          (nnir_layer, nnir_band.serial_number),
                          (blue_layer, blue_band.serial_number)]
        elif self.dlg.rbtn_agr_hv.isChecked():
            layer_list = [(nnir_layer, nnir_band.serial_number),
                          (swir_layer, swir_band.serial_number),
                          (blue_layer, blue_band.serial_number)]
        else:
            return

        self.dlg.enable_load_mode()

        self.calculation_worker = RasterLayerHandler(output_file_name, layer_list)
        self.calculation_worker.moveToThread(self.calculation_thread)
        self.calculation_thread.started.connect(self.calculation_worker.combine_bands)
        self.calculation_worker.warning.connect(self.showWarning)
        self.calculation_worker.finished.connect(self.finishAgricultureOrHvCalculation)
        self.calculation_thread.start()

    def calculateNdvi(self):
        """
        Start calculating NDVI
        """

        self.LOGGER.info("start NDVI calculation")

        if self.dlg.cbx_ndvi_redLayer.count() == 0 or \
                self.dlg.cbx_ndvi_infraredLayer.count() == 0:
            self.LOGGER.info("Layers not found")
            self.dlg.show_error_message(self.getTranslation("Error"), self.getTranslation("Layers not found"))
            return

        self.LOGGER.info("red: %s", self.dlg.cbx_ndvi_redLayer.currentText())
        self.LOGGER.info("red band number: %s", self.dlg.lstw_ndvi_redBands.currentItem().text())
        self.LOGGER.info("IR: %s", self.dlg.cbx_ndvi_infraredLayer.currentText())
        self.LOGGER.info("IR band number: %s", self.dlg.lstw_ndvi_infraredBands.currentItem().text)

        output_file_name = self.dlg.led_ndvi_outputFile.text()

        try:
            self.validateOutputFilePath(output_file_name)
            red_layer_for_calculation = self.getCurrentLayerWithRedBand()
            infrared_layer_for_calculation = self.getCurrentLayerWithInfraredBand()

            bands = self.getBandsFromLayer(red_layer_for_calculation)
            red_band = bands[self.getCurrentBandName(self.dlg.lstw_ndvi_redBands)]

            bands = self.getBandsFromLayer(infrared_layer_for_calculation)
            infrared_band = bands[self.getCurrentBandName(self.dlg.lstw_ndvi_infraredBands)]
        except CalculatorException as exp:
            self.LOGGER.info(exp.message)
            self.dlg.show_error_message(self.getTranslation(exp.title), self.getTranslation(exp.message))
            return

        self.dlg.enable_load_mode()

        self.calculation_worker = NdviCalculator(red_layer_for_calculation, infrared_layer_for_calculation,
                                                 red_band.serial_number, infrared_band.serial_number, output_file_name)
        self.calculation_worker.moveToThread(self.calculation_thread)
        self.calculation_thread.started.connect(self.calculation_worker.run)
        self.calculation_worker.finished.connect(self.finishCalculationNdvi)
        self.calculation_thread.start()

    def getCurrentLayerWithRedBand(self):
        """
        Get user selected layer with red band.

        :raise CalculatorException: layer with this name not found
        """

        self.LOGGER.debug("getting current a layer with red band")

        layer_name = self.dlg.cbx_ndvi_redLayer.currentText()
        return self.getLayerByName(layer_name)

    def getCurrentLayerWithInfraredBand(self):
        """
        Get user selected layer with infrared band.

        :raise CalculatorException: layer with this name not found
        """

        self.LOGGER.debug("getting current a layer with IR band")

        layer_name = self.dlg.cbx_ndvi_infraredLayer.currentText()
        return self.getLayerByName(layer_name)

    def getLayerByName(self, layer_name):
        """
        Get layer by name.

        :param layer_name: layer name
        :type: unicode

        :return: QGis layer
        :type: QgsMapLayer

        :raise CalculatorException: layer with this name not found
        """

        self.LOGGER.debug("getting a layer by name: %s", layer_name)

        try:
            return QgsMapLayerRegistry.instance().mapLayersByName(layer_name)[0]
        except IndexError:
            raise CalculatorException("Layer not found", "One of the specified layers was not found")

    def getCurrentBandName(self, lstw_ndv):
        """
        Get text from QListView with band name

        :param lstw_ndv: QListView with band name
        :type: QListView

        :return: band name
        :type: unicode
        """

        self.LOGGER.debug("getting current band name from the UI. Band name: %s", lstw_ndv.currentItem().text())

        return lstw_ndv.currentItem().text()

    def validateInputFilePath(self, file_path):
        """
        Checking for the correctness of the path to the file to be opened.

        :param file_path: file path
        :type: unicode

        :raise CalculatorException: the file is not exist
        """

        self.LOGGER.debug("validating input file path: %s", file_path)

        if not os.path.exists(file_path):
            self.LOGGER.info("input file - file do not exist")
            raise CalculatorException("File error", "File does not exist")

    def validateOutputFilePath(self, file_path):
        """
        Checking for the correctness of the path to the file to be created.

        :param file_path: file path
        :type: unicode

        :raise CalculatorException: the path is not correct
        """

        self.LOGGER.debug("validating output file path: %s", file_path)

        if not file_path:
            self.LOGGER.info("output file - file path is None")
            raise CalculatorException("File error", "File path is empty")

        file_path_copy = copy.copy(file_path)
        pattern = re.compile(ur"/(?u)\w+.tif$")

        try:
            file_name = pattern.search(file_path_copy).group(0)
        except AttributeError:
            self.LOGGER.info("output file - incorrect file name")
            raise CalculatorException("File error", "Incorrect file name")

        directory_name = pattern.sub(u"", file_path_copy)
        if not os.path.isdir(directory_name):
            self.LOGGER.info("output file - incorrect directory name")
            raise CalculatorException("File error", "Incorrect directory name")

    def finishCalculationNdvi(self, output_file_name):
        """
        Completion of NDVI calculation.

        Unlocking UI and opening file with NDVI.
        Callback for calculation thread.

        :param output_file_name: path to file with NDVI
        :type: unicode
        """

        self.LOGGER.debug("end of NDVI calculation")

        self.calculation_thread.quit()
        self.dlg.disable_load_mode()
        self.openNdviFile(output_file_name)

    def openNdviFile(self, file_name):
        """
        Open file with NDVI

        :param file_name: path to file with NDVI
        :type: unicode
        """

        self.LOGGER.info("opening NDVI file: %s", file_name)

        try:
            self.validateInputFilePath(file_name)
        except CalculatorException as e:
            self.LOGGER.info(e.message)
            self.dlg.show_error_message(self.getTranslation(e.title), self.getTranslation(e.message))
            return

        ndvi0_raster_layer = QgsRasterLayer(file_name, "NDVI - <0")

        layer_data_type = ndvi0_raster_layer.dataProvider().dataType(1)
        ndvi_thresholds = NdviThreshold().dataTypes.get(layer_data_type)
        if ndvi_thresholds is None:
            self.LOGGER.info("NDVI file - unknown data type")
            self.dlg.show_error_message(self.getTranslation("NDVI file open error"),
                                        self.getTranslation("Unknown data type"))
            ndvi_raster_layer = QgsRasterLayer(file_name, "NDVI")
            map_layer_registry = QgsMapLayerRegistry.instance()
            map_layer_registry.addMapLayer(ndvi_raster_layer)
            return

        ndvi025_raster_layer = QgsRasterLayer(file_name, "NDVI - 0-0.25")
        ndvi05_raster_layer = QgsRasterLayer(file_name, "NDVI - 0.25-0.5")
        ndvi075_raster_layer = QgsRasterLayer(file_name, "NDVI - 0.5-0.75")
        ndvi1_raster_layer = QgsRasterLayer(file_name, "NDVI - 0.75-1")

        algorithm = QgsContrastEnhancement.StretchToMinimumMaximum
        limits = QgsRaster.ContrastEnhancementMinMax
        ndvi0_raster_layer.setContrastEnhancement(algorithm, limits)
        ndvi025_raster_layer.setContrastEnhancement(algorithm, limits)
        ndvi05_raster_layer.setContrastEnhancement(algorithm, limits)
        ndvi075_raster_layer.setContrastEnhancement(algorithm, limits)
        ndvi1_raster_layer.setContrastEnhancement(algorithm, limits)

        colors_scheme = ColorsForNdviMap().getColorScheme(self.dlg.cbx_color_schemes.currentText())
        ndvi0_raster_layer.setRenderer(
            self.getRenderer(ndvi0_raster_layer.dataProvider(),
                             self.getColorMapForNdvi0(colors_scheme, ndvi_thresholds)))
        ndvi025_raster_layer.setRenderer(
            self.getRenderer(ndvi025_raster_layer.dataProvider(),
                             self.getColorMapForNdvi025(colors_scheme, ndvi_thresholds)))
        ndvi05_raster_layer.setRenderer(
            self.getRenderer(ndvi05_raster_layer.dataProvider(),
                             self.getColorMapForNdvi05(colors_scheme, ndvi_thresholds)))
        ndvi075_raster_layer.setRenderer(
            self.getRenderer(ndvi075_raster_layer.dataProvider(),
                             self.getColorMapForNdvi075(colors_scheme, ndvi_thresholds)))
        ndvi1_raster_layer.setRenderer(
            self.getRenderer(ndvi1_raster_layer.dataProvider(),
                             self.getColorMapForNdvi1(colors_scheme, ndvi_thresholds)))

        map_layer_registry = QgsMapLayerRegistry.instance()
        map_layer_registry.addMapLayer(ndvi0_raster_layer)
        map_layer_registry.addMapLayer(ndvi025_raster_layer)
        map_layer_registry.addMapLayer(ndvi05_raster_layer)
        map_layer_registry.addMapLayer(ndvi075_raster_layer)
        map_layer_registry.addMapLayer(ndvi1_raster_layer)

    def getRenderer(self, layer_data_provider, color_map):
        """
        Get QgsSingleBandPseudoColorRenderer for NDVI display.

        :param layer_data_provider: layer data provider
        :type: QgsDataProvider

        :param color_map: color list
        :type: [ColorRampItem...]

        :return: QgsSingleBandPseudoColorRenderer
        """

        self.LOGGER.debug("getting renderer")

        raster_shader = QgsRasterShader()
        color_ramp_shader = QgsColorRampShader()
        color_ramp_shader.setColorRampType(QgsColorRampShader.DISCRETE)

        color_ramp_shader.setColorRampItemList(color_map)
        raster_shader.setRasterShaderFunction(color_ramp_shader)
        return QgsSingleBandPseudoColorRenderer(layer_data_provider, 1, raster_shader)

    def getColorMapForNdvi0(self, color_scheme, ndvi_thresholds):
        """
        Get list of colors for layer with NDVI less than 0

        :param color_scheme: color scheme (described in colors_for_ndvi_map.py)
        :type: {str: QColor}

        :param ndvi_thresholds: NDVI thresholds for the current data type
        :type: NdviThreshold.DataType

        :return: color list
        :type: [ColorRampItem...]
        """

        self.LOGGER.debug("getting color map for NDVI 0")

        color_list = []
        qri = QgsColorRampShader.ColorRampItem
        color_list.append(qri(ndvi_thresholds.ndvi0, color_scheme["ndvi_0"], "<0"))
        color_list.append(qri(ndvi_thresholds.ndvi1, QColor(0, 0, 0, 0), ">0"))
        return color_list

    def getColorMapForNdvi025(self, color_scheme, ndvi_thresholds):
        """
        Get a list of colors for a layer with NDVI from 0 to 0.25.

        :param color_scheme: color scheme (described in colors_for_ndvi_map.py)
        :type: {str: QColor}

        :param ndvi_thresholds: NDVI thresholds for the current data type
        :type: NdviThreshold.DataType

        :return: color list
        :type: [ColorRampItem...]
        """

        self.LOGGER.debug("getting color map for NDVI 0.25")

        color_list = []
        qri = QgsColorRampShader.ColorRampItem
        color_list.append(qri(ndvi_thresholds.ndvi0, QColor(0, 0, 0, 0), "<0"))
        color_list.append(qri(ndvi_thresholds.ndvi025, color_scheme["ndvi_0.25"], "0-0.25"))
        color_list.append(qri(ndvi_thresholds.ndvi1, QColor(0, 0, 0, 0), ">0.25"))
        return color_list

    def getColorMapForNdvi05(self, color_scheme, ndvi_thresholds):
        """
        Get a list of colors for a layer with NDVI from 0.25 to 0.5.

        :param color_scheme: color scheme (described in colors_for_ndvi_map.py)
        :type: {str: QColor}

        :param ndvi_thresholds: NDVI thresholds for the current data type
        :type: NdviThreshold.DataType

        :return: color list
        :type: [ColorRampItem...]
        """

        self.LOGGER.debug("getting color map for NDVI 0.5")

        color_list = []
        qri = QgsColorRampShader.ColorRampItem
        color_list.append(qri(ndvi_thresholds.ndvi025, QColor(0, 0, 0, 0), "<0.25"))
        color_list.append(qri(ndvi_thresholds.ndvi05, color_scheme["ndvi_0.5"], "0.25-0.5"))
        color_list.append(qri(ndvi_thresholds.ndvi1, QColor(0, 0, 0, 0), ">0.5"))
        return color_list

    def getColorMapForNdvi075(self, color_scheme, ndvi_thresholds):
        """
        Get a list of colors for a layer with NDVI from 0.5 to 0.75.

        :param color_scheme: color scheme (described in colors_for_ndvi_map.py)
        :type: {str: QColor}

        :param ndvi_thresholds: NDVI thresholds for the current data type
        :type: NdviThreshold.DataType

        :return: color list
        :type: [ColorRampItem...]
        """

        self.LOGGER.debug("getting color map for NDVI 0.75")

        color_list = []
        qri = QgsColorRampShader.ColorRampItem
        color_list.append(qri(ndvi_thresholds.ndvi05, QColor(0, 0, 0, 0), "<0.5"))
        color_list.append(qri(ndvi_thresholds.ndvi075, color_scheme["ndvi_0.75"], "0.5-0.75"))
        color_list.append(qri(ndvi_thresholds.ndvi1, QColor(0, 0, 0, 0), ">0.75"))
        return color_list

    def getColorMapForNdvi1(self, color_scheme, ndvi_thresholds):
        """
        Get a list of colors for a layer with NDVI from 0.75 to 1.

        :param color_scheme: color scheme (described in colors_for_ndvi_map.py)
        :type: {str: QColor}

        :param ndvi_thresholds: NDVI thresholds for the current data type
        :type: NdviThreshold.DataType

        :return: color list
        :type: [ColorRampItem...]
        """

        self.LOGGER.debug("getting color map for NDVI 1")

        color_list = []
        qri = QgsColorRampShader.ColorRampItem
        color_list.append(qri(ndvi_thresholds.ndvi075, QColor(0, 0, 0, 0), "<0.75"))
        color_list.append(qri(ndvi_thresholds.ndvi1, color_scheme["ndvi_1"], ">0.75"))
        return color_list

    def showWarning(self, message):
        """
        Display warning window.

        :param message: warning text
        :type: unicode
        """

        self.LOGGER.debug("showing warning dialog. message: %s", message)

        self.dlg.show_error_message(self.getTranslation("Warning"), self.getTranslation(message))

    def finishAgricultureOrHvCalculation(self, status, message, output_file_name):
        """
        Completion of agriculture or healthy vegetation calculation.

        Unlocking UI and opening file with result.
        Callback for calculation thread.

        :param output_file_name: path to file with agriculture or HV
        :type: unicode
        """

        self.LOGGER.debug("end of agriculture or HV calculation")

        self.calculation_thread.quit()
        self.dlg.disable_load_mode()

        if status is False:
            self.dlg.show_error_message(self.getTranslation("Calculation error"), self.getTranslation(message))
        else:
            self.openAgricultureOrHvFile(output_file_name)

    def openAgricultureOrHvFile(self, input_file_name):
        """
        Open file with agriculture or healthy vegetation.

        :param input_file_name: path to file with agriculture or healthy vegetation
        :type: unicode
        """

        self.LOGGER.info("opening agriculture or HV file %s", input_file_name)

        if self.dlg.rbtn_agr_agriculture.isChecked():
            layer_name = "Agriculture"
        elif self.dlg.rbtn_agr_hv.isChecked():
            layer_name = "Healthy_Vegetation"
        else:
            return

        raster_layer = QgsRasterLayer(input_file_name, layer_name)
        map_layer_registry = QgsMapLayerRegistry.instance()
        map_layer_registry.addMapLayer(raster_layer)
예제 #28
0
 def quit(self):
     self._shouldStop = True
     QThread.quit(self)
예제 #29
0
class RasterLegendSensitive(QObject):
    def __init__(self, iface, treeView, ckEnabled):
        super(RasterLegendSensitive, self).__init__()
        self.tree = TreeLegend(treeView)
        self.ckEnabled = ckEnabled
        #
        self.layer = self.worker = self.thread = self.transparencyLayer = None
        self.isExtentLayer = self.valuesFullExtent = None
        self.hasConnect = self.hasConnectTree = None
        self.iface = iface
        self.legend = iface.legendInterface()
        self.canvas = iface.mapCanvas()
        self.msgBar = iface.messageBar()
        self.nameModulus = "RasterLegendSensitive"
        #
        self.initThread()
        self._connect()
        self._connectTree()

    def __del__(self):
        del self.tree
        self.finishThread()
        if not self.hasConnect:
            self._connect(False)
        if not self.layer is None:
            self.setTransparenceLayer([])

    def initThread(self):
        self.thread = QThread(self)
        self.thread.setObjectName(self.nameModulus)
        self.worker = WorkerRasterLegendSensitive()
        self.worker.moveToThread(self.thread)
        self._connectWorker()

    def finishThread(self):
        self._connectWorker(False)
        self.worker.deleteLater()
        self.thread.wait()
        self.thread.deleteLater()
        self.thread = self.worker = None

    def _connectWorker(self, isConnect=True):
        ss = [{
            'signal': self.thread.started,
            'slot': self.worker.run
        }, {
            'signal': self.worker.finished,
            'slot': self.finishedWorker
        }, {
            'signal': self.worker.messageStatus,
            'slot': self.messageStatusWorker
        }]
        if isConnect:
            for item in ss:
                item['signal'].connect(item['slot'])
        else:
            for item in ss:
                item['signal'].disconnect(item['slot'])

    def _connect(self, isConnect=True):
        ss = [{
            'signal': self.legend.currentLayerChanged,
            'slot': self.selectLayer
        }, {
            'signal': QgsMapLayerRegistry.instance().layerWillBeRemoved,
            'slot': self.removeLayer
        }, {
            'signal': self.canvas.extentsChanged,
            'slot': self.changeSensitiveLegend
        }]
        if isConnect:
            self.hasConnect = True
            for item in ss:
                item['signal'].connect(item['slot'])
        else:
            self.hasConnect = False
            for item in ss:
                item['signal'].disconnect(item['slot'])

    def _connectTree(self, isConnect=True):
        ss = [{
            'signal': self.tree.toggledLegend,
            'slot': self.setTransparenceLayer
        }, {
            'signal': self.tree.descriptionLegend,
            'slot': self.sendClipboard
        }]
        if isConnect:
            self.hasConnectTree = True
            for item in ss:
                item['signal'].connect(item['slot'])
        else:
            self.hasConnectTree = False
            for item in ss:
                item['signal'].disconnect(item['slot'])

    def _resetLayer(self):
        if self.thread.isRunning():
            self.worker.isKilled = True
        self.layer = None
        self.tree.setHeader()
        self.tree.layer = None

    def setEnabled(self, isEnabled=True):
        if not isEnabled and self.thread.isRunning():
            self.worker.isKilled = True
        #
        self._connect(isEnabled)
        self._connectTree(isEnabled)
        self.tree.setEnabled(isEnabled)
        #
        if isEnabled:
            activeLayer = self.iface.activeLayer()
            if activeLayer == self.layer:
                if activeLayer is None:
                    return
                self.changeSensitiveLegend()
            else:
                self.selectLayer(activeLayer)

    @pyqtSlot(list)
    def finishedWorker(self, values):
        self.thread.quit()
        self.msgBar.popWidget()
        if not self.worker.isKilled:
            if len(values) > 0:  # Never Happing otherwise...
                self.tree.setLegend(values)
                if self.isExtentLayer:
                    self.valuesFullExtent = values
        else:  # When PAN/ZOOM/...
            self.thread.wait()
            if self.ckEnabled.checkState() == Qt.Checked:
                self.changeSensitiveLegend()

    @pyqtSlot(str)
    def messageStatusWorker(self, msg):
        self.msgBar.popWidget()
        self.msgBar.pushMessage(self.nameModulus, msg, QgsMessageBar.INFO)

    @pyqtSlot(list)
    def setTransparenceLayer(self, visibleItems):
        def refreshLayer():
            if hasattr(self.layer, "setCacheImage"):
                self.layer.setCacheImage(None)  # Refresh
            else:
                self.layer.triggerRepaint()

        def setTransparence(value, visible):
            t = QgsRasterTransparency.TransparentSingleValuePixel()
            t.min = t.max = value
            percent = 100.0 if not visible else 0.0
            t.percentTransparent = percent

            return t

        valuesTransparent = []
        item = 0
        for visible in visibleItems:
            valuesTransparent.append(setTransparence(item, visible))
            item += 1
        self.transparencyLayer.setTransparentSingleValuePixelList(
            valuesTransparent)
        refreshLayer()
        del valuesTransparent[:]

    @pyqtSlot(str)
    def sendClipboard(self, description):

        mapSettings = self.canvas.mapSettings()
        crsCanvas = mapSettings.destinationCrs()
        extentCanvas = self.canvas.extent()
        extentLayer = self.layer.extent()

        if self.layer.crs() != crsCanvas:
            extentCanvas = mapSettings.mapToLayerCoordinates(
                self.layer, extentCanvas)

        if extentCanvas == extentLayer or extentCanvas.contains(extentLayer):
            msg = "Calculate for all extent of layer '%s'\n\n%s" % (
                self.layer.name(), description)
        else:
            msg = "Calculate for subset of layer '%s' (extend: %s)\n\n%s" % (
                self.layer.name(), extentCanvas.toString(), description)
        clip = QApplication.clipboard()
        clip.setText(msg)
        self.msgBar.pushMessage(self.nameModulus, "Copy to Clipboard",
                                QgsMessageBar.INFO, 5)

    @pyqtSlot('QgsMapLayer')
    def selectLayer(self, layer):
        def processLegend():
            self.tree.setLayer(layer)
            if not self.valuesFullExtent is None:  # Save legend with all extent layer
                del self.valuesFullExtent[:]
                self.valuesFullExtent = None
            (self.layer,
             self.transparencyLayer) = (layer,
                                        layer.renderer().rasterTransparency())
            self.worker.setLegendReadBlock(layer)
            self.changeSensitiveLegend()

        if not self.layer is None:
            if not self.layer in self.legend.layers():
                self.removeLayer(self.layer.id())
            else:
                self.setTransparenceLayer([])
                self._resetLayer()

        if not layer is None and layer.type() == QgsMapLayer.RasterLayer:
            legendItems = layer.legendSymbologyItems()
            total = len(legendItems)
            if total > 0:  # Had a classification
                processLegend()

    @pyqtSlot(str)
    def removeLayer(self, idLayer):
        if not self.layer is None and self.layer.id() == idLayer:
            msg = "Layer '%s' was removed" % self.tree.getLayerName()
            self.msgBar.pushMessage(self.nameModulus, msg,
                                    QgsMessageBar.WARNING, 5)
            self._resetLayer()

    @pyqtSlot()
    def changeSensitiveLegend(self):
        if self.layer is None:
            return

        if self.thread.isRunning():
            self.worker.isKilled = True
            return

        mapSettings = self.canvas.mapSettings()
        crsCanvas = mapSettings.destinationCrs()
        extentCanvas = self.canvas.extent()

        extentLayer = self.layer.extent()
        resX = self.layer.rasterUnitsPerPixelX()
        resY = self.layer.rasterUnitsPerPixelY()

        if self.layer.crs() != crsCanvas:
            extentCanvas = mapSettings.mapToLayerCoordinates(
                self.layer, extentCanvas)

        if not extentCanvas.intersects(extentLayer):
            self.msgBar.popWidget()
            self.msgBar.pushMessage(
                self.nameModulus,
                "View not intersects Raster '%s'" % self.layer.name(),
                QgsMessageBar.WARNING, 5)
            self.tree.setLegend([])
            return

        if extentCanvas == extentLayer or extentCanvas.contains(extentLayer):
            self.isExtentLayer = True
            if not self.valuesFullExtent is None:
                self.tree.setLegend(self.valuesFullExtent)
                return
            extent = extentLayer
            delta = 0
        else:
            self.isExtentLayer = False
            extent = extentCanvas.intersect(extentLayer)
            delta = 1

        widthRead = int(extent.width() / resX) + delta
        heightRead = int(extent.height() / resY) + delta

        self.worker.setProcessImage(extent, widthRead, heightRead)
        self.thread.start()
예제 #30
0
파일: mav_gui.py 프로젝트: cstefanovic/mav
class MavDialog(QDialog):
    # .. _updateMavState:
    #
    # This signal, sent by a MAV, informs the GUI of the MAV's current state. It simply invokes _on_updateMavState.
    updateMavState = pyqtSignal(
      # See mavIndex_.
      int,
      # See MAV_STATES_.
      object)

    def __init__(self,
      # .. _numMavs:
      #
      # The number of MAVs in the simulation.
      numMavs,
      # See _flyTimeSec.
      flyTimeSec,
      # See _chargeTimeSec.
      chargeTimeSec):

        # First, let the QDialog initialize itself.
        super(MavDialog, self).__init__()

        # Create a ChargingStation to manage the MAVs.
        self._chargingStation = ChargingStation(self, numMavs, flyTimeSec,
                                                chargeTimeSec)

        # `Load <http://pyqt.sourceforge.net/Docs/PyQt4/designer.html#PyQt4.uic.loadUi>`_
        # in our UI. The secord parameter lods the resulting UI directly into
        # this class.
        uic.loadUi(join(dirname(__file__), 'mav_gui.ui'), self)

        # Only allow numbers between 0 and 99 for the line edits.
        flyTimeValidator = QDoubleValidator(0.0, 9.9, 1, self)
        flyTimeValidator.setNotation(QDoubleValidator.StandardNotation)
        self.leFlyTime.setValidator(flyTimeValidator)
        chargeTimeValidator = QDoubleValidator(0.0, 9.9, 1, self)
        chargeTimeValidator.setNotation(QDoubleValidator.StandardNotation)
        self.leChargeTime.setValidator(chargeTimeValidator)

        # Example: create a separate thread
        self._thread = QThread(self)
        #self._thread.start()
        # Create a worker.
        self._worker = DummyWorker(self)

        # Timer examples
        # ^^^^^^^^^^^^^^
        # A single-shot timer. It can't be canceled.
        QTimer.singleShot(1500, self._onTimeout)
        # Another single-shot timer. Because it has a name, it can be canceled.
        self._timer = QTimer(self)
        self._timer.timeout.connect(self._onTimeout)
        self._timer.setSingleShot(True)
        self._timer.start(3000)

        # Add in status info GUI for numMavs MAVs.
        hl = QHBoxLayout()
        self.wMavStatus.setLayout(hl)
        assert numMavs > 0
        self.numMavs = numMavs
        self.mavStatus = []
        self.electrodeStatus = []
        self._chargeTimeSec = [chargeTimeSec]*self.numMavs
        self._flyTimeSec = [flyTimeSec]*self.numMavs
        for index in range(self.numMavs):
            e = UncheckableRadioButton(self)
            self.electrodeStatus.append(e)
            hl.addWidget(e)

            # Add in a group box.
            smw = SingleMavWidget()
            mavName = 'MAV {}'.format(index + 1)
            smw.gb = QGroupBox(mavName, self.wMavStatus)
            vl = QVBoxLayout()
            smw.gb.setLayout(vl)
            smw.rbFlying = UncheckableRadioButton('Flying', smw.gb)
            smw.rbWaiting = UncheckableRadioButton('Waiting', smw.gb)
            smw.rbCharging = UncheckableRadioButton('Charging', smw.gb)
            vl.addWidget(smw.rbFlying)
            vl.addWidget(smw.rbWaiting)
            vl.addWidget(smw.rbCharging)
            self.mavStatus.append(smw)
            hl.addWidget(smw.gb)

            # Update the combo box.
            self.cbSelectedMav.insertItem(index, mavName)

        # Update GUI with parameters.
        self.on_cbSelectedMav_currentIndexChanged(0)

        self.updateMavState.connect(self._on_updateMavState)

    # .. _on_updateMavState:
    #
    # A standardized way for MAVs to update their status. Should be invoked
    @pyqtSlot(int, object)
    def _on_updateMavState(self,
      # See mavIndex_.
      mavIndex,
      # See MAV_STATES_.
      mavState):

        # Make only one of the radio buttons checkable, so that the user can't check a different one.
        ms = self.mavStatus[mavIndex]
        if mavState == _MAV_STATES.Waiting:
            ms.rbWaiting.setCheckable(True)
            ms.rbFlying.setCheckable(False)
            ms.rbCharging.setCheckable(False)
            ms.rbWaiting.setChecked(True)
        elif mavState == _MAV_STATES.Flying:
            ms.rbWaiting.setCheckable(False)
            ms.rbFlying.setCheckable(True)
            ms.rbCharging.setCheckable(False)
            self.mavStatus[mavIndex].rbFlying.setChecked(True)
        elif mavState == _MAV_STATES.Charging:
            ms.rbWaiting.setCheckable(False)
            ms.rbFlying.setCheckable(False)
            ms.rbCharging.setCheckable(True)
            self.mavStatus[mavIndex].rbCharging.setChecked(True)
        else:
            assert False

    @pyqtSlot()
    def _onTimeout(self):
        self.hsFlyTime.setValue(50)

    @pyqtSlot(int)
    def on_hsFlyTime_valueChanged(self, value):
        flyTimeSec = value/10.0
        self._chargingStation._mav[self.cbSelectedMav.currentIndex()].updateFlyTimeSec.emit(flyTimeSec)
        self.leFlyTime.setText(str(flyTimeSec))
        self._flyTimeSec[self.cbSelectedMav.currentIndex()] = flyTimeSec
        self._worker.run.emit(1.5)

    @pyqtSlot()
    def on_leFlyTime_editingFinished(self):
        self.hsFlyTime.setValue(float(self.leFlyTime.text())*10.0)

    @pyqtSlot(int)
    def on_hsChargeTime_valueChanged(self, value):
        chargeTimeSec = value/10.0
        self._chargingStation._mav[self.cbSelectedMav.currentIndex()].updateChargeTimeSec.emit(chargeTimeSec)
        self.leChargeTime.setText(str(chargeTimeSec))
        self._chargeTimeSec[self.cbSelectedMav.currentIndex()] = chargeTimeSec
        self._worker.run.emit(1.5)

    @pyqtSlot()
    def on_leChargeTime_editingFinished(self):
        self.hsChargeTime.setValue(float(self.leChargeTime.text())*10.0)

    @pyqtSlot(int)
    def on_cbSelectedMav_currentIndexChanged(self, index):
        self.hsChargeTime.setValue(self._chargeTimeSec[index]*10)
        self.hsFlyTime.setValue(self._flyTimeSec[index]*10)

    # Free all resources used by this class.
    def terminate(self):
        self._thread.quit()
        self._thread.wait()
        self._timer.stop()
예제 #31
0
class BAONQtApplication(QApplication):
    BACKUP_DIALOG_CAPTION = 'Rename Plan Backup Detected'
    BACKUP_DIALOG_ERROR_CAPTION = 'Error'
    BACKUP_INTRO_TEXT = 'BAON has detected a backed up rename plan from a previous run of the '\
        'application. This suggests that the application crashed partway through executing a rename operation. The '\
        'files may have been left in an inconsistent state.'
    BACKUP_PROMPT_TEXT = 'What do you want to do?'

    REVERT_BACKUP_PROGRESS_TEXT = 'Reverting the rename operation'

    SUCCESS_DIALOG_CAPTION = 'Success'
    WARNING_DIALOG_CAPTION = 'Warning'

    BACKUP_DELETED_DIALOG_TEXT =\
        'The backed up plan has been deleted. Further runs of the application will proceed normally.'
    BACKUP_REVERTED_SUCCESS_DIALOG_TEXT = 'The rename operation has been reverted successfully. The directory state '\
        'should now have been completely restored.'
    BACKUP_REVERTED_WARNING_DIALOG_TEXT = 'There were inconsistencies while trying to revert the previous rename '\
        'operation. The directory state may not have been fully restored.'

    REVERT_BACKUP_BUTTON_TEXT = 'Revert the rename (recommended)'
    DELETE_BACKUP_BUTTON_TEXT = 'Delete the backup file'
    EXAMINE_BACKUP_BUTTON_TEXT = 'Examine the plan in a text editor'
    QUIT_BUTTON_TEXT = 'Quit BAON'

    request_revert_backup = pyqtSignal()
    request_delete_backup = pyqtSignal()

    _main_window = None
    _core = None
    _progress_dialog = None

    _core_thread = None

    def __init__(self, args):
        super().__init__(sys.argv)

        # Actually we do quit when the last window is closed, but we need to do this in a more controlled way
        self.setQuitOnLastWindowClosed(False)

        self._init_threads()
        self._init_main_objects(args)
        self._connect_main_objects()
        self._start_core()

    def event(self, evt):
        if isinstance(evt, QFileOpenEvent):
            path = evt.file()
            if not os.path.isdir(path):
                path, _ = os.path.split(path)

            self._main_window.set_base_path(path)
            return True

        return super().event(evt)

    def _init_threads(self):
        self._core_thread = QThread()
        self._core_thread.start()

    def _init_main_objects(self, args):
        self._main_window = MainWindow(args)

        self._core = BAONQtCore(args)
        self._core.moveToThread(self._core_thread)

    def _connect_main_objects(self):
        self.aboutToQuit.connect(self._on_quit)

        # Core vs. application

        self._core.request_backup_decision.connect(self.backup_decision_requested)
        self._core.reverted_backup.connect(self.notify_backup_reverted)
        self._core.revert_backup_error.connect(self.handle_backup_op_error)
        self._core.deleted_backup.connect(self.notify_backup_deleted)
        self._core.delete_backup_error.connect(self.handle_backup_op_error)

        self.request_revert_backup.connect(self._core.revert_backup)
        self.request_delete_backup.connect(self._core.delete_backup)

        # Core vs. main window

        self._core.prologue_finished.connect(self._main_window.show_first_time)

        self._core.status_changed.connect(self._main_window.report_status)
        self._core.scanned_files_updated.connect(self._main_window.update_scanned_files)
        self._core.renamed_files_updated.connect(self._main_window.update_renamed_files)

        self._core.has_shutdown.connect(self.quit)

        self._main_window.base_path_edited.connect(self._core.update_base_path)
        self._main_window.scan_recursive_changed.connect(self._core.update_scan_recursive)

        self._main_window.rules_text_changed.connect(self._core.update_rules_text)
        self._main_window.use_path_changed.connect(self._core.update_use_path)
        self._main_window.use_extension_changed.connect(self._core.update_use_extension)

        self._main_window.request_add_override.connect(self._core.add_override)
        self._main_window.request_remove_override.connect(self._core.remove_override)

        self._main_window.request_do_rename.connect(self._core.do_rename)
        self._main_window.request_rescan.connect(self._core.rescan)

        self._main_window.rejected.connect(self._core.shutdown)

    def _start_core(self):
        QMetaObject.invokeMethod(self._core, 'start', Qt.QueuedConnection)

    def _on_quit(self):
        self._core_thread.quit()
        self._core_thread.wait()

    @pyqtSlot()
    def backup_decision_requested(self):
        self._show_backup_decision()

    @pyqtSlot(Exception)
    def handle_backup_op_error(self, error):
        self._close_progress_dialog()
        self._show_backup_decision(error=error)

    @pyqtSlot()
    def notify_backup_deleted(self):
        QMessageBox.information(
            None,
            self.SUCCESS_DIALOG_CAPTION,
            self.BACKUP_DELETED_DIALOG_TEXT,
        )

    @pyqtSlot(bool)
    def notify_backup_reverted(self, complete_success):
        self._close_progress_dialog()
        if complete_success:
            QMessageBox.information(
                None,
                self.SUCCESS_DIALOG_CAPTION,
                self.BACKUP_REVERTED_SUCCESS_DIALOG_TEXT,
            )
        else:
            QMessageBox.warning(
                None,
                self.WARNING_DIALOG_CAPTION,
                self.BACKUP_REVERTED_WARNING_DIALOG_TEXT,
            )

    def _show_backup_decision(self, error=None):
        text = '<p>{0}</p><p>{1}</p>'.format(
            self.BACKUP_INTRO_TEXT if error is None else error,
            self.BACKUP_PROMPT_TEXT,
        )

        dialog = QMessageBox(
            QMessageBox.Question if error is None else QMessageBox.Critical,
            self.BACKUP_DIALOG_CAPTION if error is None else self.BACKUP_DIALOG_ERROR_CAPTION,
            text,
        )

        revert_button = dialog.addButton(self.REVERT_BACKUP_BUTTON_TEXT, QMessageBox.AcceptRole)
        delete_button = dialog.addButton(self.DELETE_BACKUP_BUTTON_TEXT, QMessageBox.DestructiveRole)
        examine_button = dialog.addButton(self.EXAMINE_BACKUP_BUTTON_TEXT, QMessageBox.ActionRole)
        dialog.addButton(self.QUIT_BUTTON_TEXT, QMessageBox.RejectRole)

        dialog.exec()
        clicked_button = dialog.clickedButton()

        if clicked_button == examine_button:
            QMetaObject.invokeMethod(self, '_examine_backup', Qt.QueuedConnection)
        elif clicked_button == revert_button:
            self._progress_dialog = QProgressDialog(None)
            self._progress_dialog.setLabelText(self.REVERT_BACKUP_PROGRESS_TEXT)
            self._progress_dialog.setCancelButton(None)
            self._progress_dialog.setRange(0, 0)
            self._progress_dialog.forceShow()

            self.request_revert_backup.emit()
        elif clicked_button == delete_button:
            self.request_delete_backup.emit()
        else:
            self.quit()

    @pyqtSlot()
    def _examine_backup(self):
        error = None
        try:
            filename = get_rename_plan_backup_filename()
            QDesktopServices.openUrl(QUrl.fromLocalFile(filename))
        except Exception as err:
            error = err
        finally:
            self._show_backup_decision(error)

    def _close_progress_dialog(self):
        if self._progress_dialog is not None:
            self._progress_dialog.close()

        self._progress_dialog = None
예제 #32
0
class SentinelDownloader:
    '''
    QGIS Plugin Implementation.
    '''
    def __init__(self, iface):
        '''
        Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        '''
        #
        # Save reference to the QGIS interface.
        #
        self.iface = iface

        #
        # Initialize class variables.
        #
        self.dlg = None
        self.downloader = None
        self.worker = None
        self.workerD = None
        self.thread = None
        self.threadD = None

        #
        # Initialize plugin directory.
        #
        self.plugin_dir = os.path.dirname(__file__)

        #
        # Initialize locale.
        #
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n',
                                   'SentinelDownloader_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        #
        # Declare instance attributes.
        #
        self.actions = []

        #
        # Set plugin label under 'Web' tab in QGIS toolbar.
        #
        self.menu = self.tr(u'&Sentinel Downloader')

        # TODO: We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'SentinelDownloader')
        self.toolbar.setObjectName(u'SentinelDownloader')

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        '''
        Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        '''
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('SentinelDownloader', message)

    def add_action(self,
                   icon_path,
                   text,
                   callback,
                   enabled_flag=True,
                   add_to_menu=True,
                   add_to_toolbar=True,
                   status_tip=None,
                   whats_this=None,
                   parent=None):
        '''
        Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        '''

        #
        # Create the dialog (after translation) and keep reference.
        #
        self.dlg = SentinelDownloaderDialog()

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToWebMenu(self.menu, action)

        self.actions.append(action)
        '''
        TODO: Need to add threading for button actions.
        '''

        self.downloader = SentinelSearch(self.dlg)

        #
        # Button actions.
        #
        self.dlg.writeDir_toolButton.clicked.connect(self.downloader.open)
        self.dlg.btnExtent.clicked.connect(self.get_extent)
        self.dlg.btnSearch.clicked.connect(self.search_thread)
        self.dlg.btnSearchCancel.clicked.connect(self.kill)
        self.dlg.btnReset.clicked.connect(self.reset_parameters)
        self.dlg.btnTileSearch.clicked.connect(self.downloader.get_tile_coords)
        self.dlg.btnClearSelected.clicked.connect(
            self.downloader.remove_selected)
        self.dlg.btnDownload.clicked.connect(self.download_thread)
        # self.dlg.btnDownload.clicked.connect(self.download_S1thread)
        self.dlg.btnDownloadCancel.clicked.connect(self.kill)
        self.dlg.btnClear.clicked.connect(self.downloader.clearTable)

        return action

    def initGui(self):
        '''
        Create the menu entries and toolbar icons inside the QGIS GUI.
        '''

        icon_path = ':/plugins/SentinelDownloader/icon.png'
        self.add_action(icon_path,
                        text=self.tr(u'Sentinel Downloader'),
                        callback=self.run,
                        parent=self.iface.mainWindow())

    def unload(self):
        '''
        Removes the plugin menu item and icon from QGIS GUI.
        '''

        for action in self.actions:
            self.iface.removePluginWebMenu(self.tr(u'&Sentinel Downloader'),
                                           action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        del self.toolbar

    def run(self):
        '''
        Run method that performs all the real work.
        '''

        #
        # Show the dialog.
        #
        self.dlg.show()

        # # Run the dialog event loop
        # result = self.dlg.exec_()
        # # See if OK was pressed
        # if result:
        #     # Do something useful here - delete the line containing pass and
        #     # substitute with your code.
        #     pass

    def get_extent(self):
        '''
        Returns current extent shown in QGIS as upper and lower limits for both
        X and Y axis in the current projection.
        '''

        #
        # Get current extent coordinates.
        #
        e = self.iface.mapCanvas().extent()

        ULX = e.xMaximum()
        ULY = e.yMaximum()
        LLX = e.xMinimum()
        LLY = e.yMinimum()

        #
        # Determine origin CRS and define destination CRS (EPSG:4326).
        #
        canvas = self.iface.mapCanvas()
        epsg_code = canvas.mapRenderer().destinationCrs().authid()
        inProj = pyproj.Proj(init=epsg_code)
        outProj = pyproj.Proj(init='epsg:4326')

        #
        # Transform coordinates
        #
        ULX_new, ULY_new = pyproj.transform(inProj, outProj, ULX, ULY)
        LLX_new, LLY_new = pyproj.transform(inProj, outProj, LLX, LLY)

        #
        # Set values.
        #
        self.dlg.LLX_lineEdit.setText(str('{0:.2f}'.format(LLX_new)))
        self.dlg.ULX_lineEdit.setText(str('{0:.2f}'.format(ULX_new)))
        self.dlg.LLY_lineEdit.setText(str('{0:.2f}'.format(LLY_new)))
        self.dlg.ULY_lineEdit.setText(str('{0:.2f}'.format(ULY_new)))

    def search_thread(self):
        '''
        Creates Qt thread for searching so that the GUI does not freeze and
        QGIS does not crash.
        '''

        #
        # Disable search button while searching.
        #
        self.dlg.btnSearch.setEnabled(False)
        self.dlg.btnSearchCancel.setEnabled(True)

        self.worker = SentinelSearch(self.dlg)
        self.thread = QThread()
        self.worker.moveToThread(self.thread)

        self.thread.start()
        self.thread.started.connect(self.worker.get_query_xml)

        #
        # Signal handelling from thread.
        #
        self.worker.query_check.connect(self.query_search_check)
        self.worker.connecting_message.connect(self.set_search_label)
        self.worker.searching_message.connect(self.set_search_label)
        self.worker.enable_btnSearch.connect(self.enable_btnSearch)
        self.worker.search_progress_max.connect(self.set_progress_max)
        self.worker.search_progress_set.connect(self.set_progress)
        self.worker.set_message.connect(self.set_messageBar)
        self.worker.finished.connect(self.search_finished)

    def query_search_check(self, header):

        if header == 'Inconsistent geometries.':
            self.text_to_messagebox(header,
                                    'Pick one polygon, point or no geometry.')

        elif header == 'Incomplete point.':

            self.text_to_messagebox(header,
                                    'Point is missing one coordinate value.')

        elif header == 'Incomplete polygon.':

            self.text_to_messagebox(
                header, 'Polygon is missing at least one coordinate value.')

        elif header == 'No parameters.':

            self.text_to_messagebox(header,
                                    'Please enter at least one parameter.')

        elif header == 'Missing authorization credentials.':

            self.text_to_messagebox(
                header, 'Please enter both a username and password.')

        elif header == 'Tile extraction error':

            self.text_to_messagebox(
                header,
                'Tile extraction option can only be used for Sentinel-2')

        elif header == 'Error with connection.':

            message = (
                'Error with connection.\n'
                'Please check credentials, try another hub or try again '
                'later.')

            self.text_to_messagebox(header, message)

        elif header == 'Error with hub.':

            message = ('Error with connection.\n'
                       'Please try another hub or try again later.')

            self.text_to_messagebox(header, message)

        elif header == 'No write directory.':

            self.text_to_messagebox(
                header, 'Please enter a directory to download the data to!')

        else:
            self.text_to_messagebox('Error.', header)

    def set_search_label(self, text):

        self.dlg.search_label.setText(text)

        if text == 'Connecting . . .':
            #
            # This makes progressBar move until real max is set.
            #
            self.dlg.search_progressBar.setMinimum(0)
            self.dlg.search_progressBar.setMaximum(0)

    def set_progress_max(self, max_value):

        if max_value == 0:
            #
            # If there are no entries, reset bar to avoid problems.
            #
            self.dlg.search_progressBar.setMinimum(0)
            self.dlg.search_progressBar.reset()

        else:
            self.dlg.search_progressBar.setMinimum(0)
            self.dlg.search_progressBar.setMaximum(100)

    def set_progress(self, percent):

        if percent > 100:
            percent = 100

        self.dlg.search_progressBar.setValue(percent)

    def enable_btnSearch(self):

        self.dlg.btnSearch.setEnabled(True)
        self.dlg.btnSearchCancel.setEnabled(False)

    def search_finished(self, killed=False):

        if killed is False:

            self.text_to_messagebox('Done!', 'Done fetching search results!')

        #
        # Clean up Thread.
        #
        self.worker.deleteLater()
        self.thread.quit()
        self.thread.deleteLater()

        #
        # Enable search button after searching.
        #
        self.dlg.btnSearch.setEnabled(True)
        self.dlg.btnSearchCancel.setEnabled(False)

        #
        # Clear progress bar widget and label.
        #
        self.dlg.search_progressBar.setMinimum(0)
        self.dlg.search_progressBar.setMaximum(100)
        self.dlg.search_progressBar.reset()
        self.set_search_label('')

    def kill(self):
        '''
        Starts to kill either the search or download processes, which are
        both initiated by Cancel buttons. It also disables the Cancel
        buttons such that the user does not crash QGIS.
        '''

        if self.worker:

            self.worker.killed = True
            self.dlg.btnSearchCancel.setEnabled(False)
            self.dlg.search_label.setText('Cancelling . . .')

        if self.workerD:

            self.workerD.killed = True
            self.dlg.btnDownloadCancel.setEnabled(False)
            self.dlg.download_label.setText('Cancelling . . .')

    def reset_parameters(self):
        '''
        Sets all user input back to default values. Initaited by the user
        clicking the reset button.
        '''

        self.dlg.sensor_comboBox.setCurrentIndex(0)

        self.dlg.maxRecords_spinBox.setValue(100)
        self.dlg.orderBy_comboBox.setCurrentIndex(0)
        self.dlg.LLX_lineEdit.clear()
        self.dlg.ULX_lineEdit.clear()
        self.dlg.LLY_lineEdit.clear()
        self.dlg.ULY_lineEdit.clear()
        self.dlg.lat_lineEdit.clear()
        self.dlg.lon_lineEdit.clear()
        self.dlg.s2Tile_lineEdit.clear()
        self.dlg.s2Extract_checkBox.setChecked(False)

        today = QDate.currentDate()
        self.dlg.ingestFrom_dateEdit.setEnabled(False)
        self.dlg.ingestFrom_dateEdit.setDate(QDate(2013, 04, 13))
        self.dlg.ingestTo_dateEdit.setEnabled(False)
        self.dlg.ingestTo_dateEdit.setDate(today)
        self.dlg.ingest_enable.setChecked(False)
        self.dlg.dateFrom_dateEdit.setEnabled(False)
        self.dlg.dateFrom_dateEdit.setDate(QDate(2013, 04, 13))
        self.dlg.dateTo_dateEdit.setEnabled(False)
        self.dlg.dateTo_dateEdit.setDate(today)
        self.dlg.date_enable.setChecked(False)

        self.dlg.orbit_lineEdit.clear()
        self.dlg.relOrbit_radioButton.setChecked(True)
        self.dlg.orbitDir_comboBox.setCurrentIndex(0)

        self.dlg.s1Mode_comboBox.setCurrentIndex(0)
        self.dlg.s1Polar_comboBox.setCurrentIndex(0)
        self.dlg.s1Product_comboBox.setCurrentIndex(0)

        self.dlg.s2Product_comboBox.setCurrentIndex(0)
        self.dlg.cloudCover_spinBox.setValue(10)
        self.dlg.cloudCover_enable.setChecked(False)

    def download_thread(self):
        '''
        Starts a download thread. Initiated by the user clicking the download
        button.
        '''

        self.dlg.btnDownload.setEnabled(False)
        self.dlg.btnDownloadCancel.setEnabled(True)

        self.workerD = SentinelSearch(self.dlg)
        self.threadD = QThread()
        self.workerD.moveToThread(self.threadD)

        self.threadD.start()
        self.threadD.started.connect(self.workerD.download_results)
        self.workerD.query_check.connect(self.query_search_check)
        self.workerD.download_progress_set.connect(self.set_download_progress)
        self.workerD.download_message.connect(self.set_download_label)
        self.workerD.connecting_message.connect(self.set_download_label)
        self.workerD.download_progress_max.connect(self.set_download_max)

        self.workerD.finished_download.connect(self.download_finished)

    def set_download_progress(self, percent):
        '''
        Sets the download progress bar for the overall download progress in
        percent, based on the total bits to download according to the products
        sizes in the GUI tables.
        '''

        if percent > 100:
            percent = 100

        self.dlg.download_progressBar.setValue(percent)

    def set_download_max(self, max_value):

        if max_value == 0:
            #
            # If there are no entries, reset bar to avoid problems.
            #
            self.dlg.download_progressBar.setMinimum(0)
            self.dlg.download_progressBar.reset()

        else:
            self.dlg.download_progressBar.setMinimum(0)
            self.dlg.download_progressBar.setMaximum(100)

    def set_download_label(self, text):

        self.dlg.download_label.setText(text)

        if text == 'Connecting . . .':
            #
            # This makes progressBar move until real max is set.
            #
            self.dlg.download_progressBar.setMinimum(0)
            self.dlg.download_progressBar.setMaximum(0)

    def download_finished(self, killed=False):
        '''
        Cleans up the download thread once downloading is complete, or if the
        process was killed by the user.
        '''

        if killed is False:

            self.text_to_messagebox('Done!',
                                    'Done downloading Sentinel products!')

        #
        # Clean up Thread.
        #
        self.workerD.deleteLater()
        self.threadD.quit()
        self.threadD.deleteLater()

        #
        # Enable search button after searching.
        #
        self.dlg.btnDownload.setEnabled(True)
        self.dlg.btnDownloadCancel.setEnabled(False)

        #
        # Clear progress bar widget and label.
        #
        self.dlg.download_progressBar.setMinimum(0)
        self.dlg.download_progressBar.setMaximum(100)
        self.dlg.download_progressBar.reset()
        self.dlg.download_label.setText('')

    @staticmethod
    def text_to_messagebox(header, message, long_text=None):
        '''
        Prints a given message to a pop-up message box.
        '''

        msg_txt = QMessageBox()
        msg_txt.setIcon(QMessageBox.Information)
        msg_txt.setText(message)
        # msg_txt.setInformativeText("This is additional information")
        msg_txt.setWindowTitle(header)
        if long_text is not None:
            msg_txt.setDetailedText(long_text)
        msg_txt.exec_()

    def set_messageBar(self, message):
        '''
        Prints the total size of all products in the GUI tables to the QGIS
        message bar.
        '''

        self.iface.messageBar().pushMessage('Results', message, duration=30)
예제 #33
0
 def quit(self):
     self.jobs={}
     QThread.quit(self)
예제 #34
0
class Measurement(QObject):
    throwMessage = pyqtSignal(str, int, name='throwMessage')
    sigSaveMeasurement = pyqtSignal(bool, name='save')
    updateWindows=pyqtSignal(str,name="updateView")
    sigUpdateCountrate=pyqtSignal(int,str)

    sigTest=pyqtSignal()

    def __init__(self,openFile=None,themisApp=None):
        QObject.__init__(self)
        self.themisApp=themisApp
        self.configWidget=configurationWidget.configurationWidget(self)
        self.config=self.configWidget.p
        self.DataThread=QThread(self)
        self.dataHandler=DataHandler(self.configWidget.toDict())
        self.dataHandler.moveToThread(self.DataThread)
        self.dataHandler.updateTimer.timeout.connect(self.dataHandler.updateGui)
        self.dataHandler.sigUpdateGui.connect(self.updateView,QtCore.Qt.QueuedConnection)
        self.configWidget.sigConfigChanged.connect(self.dataHandler.configChanged,QtCore.Qt.QueuedConnection)
        self.DataThread.start()


        self.viewer=DataViewer(name="Measurement")
        self.timeFilter=[None,None]
        self.acquisitionTime=-1



        #SetWindows
        self.viewer.addWidget("Control",self.configWidget,position="left",Size=(2,2),minSize=(250,250),sizePolicy=(QtGui.QSizePolicy.Fixed,QtGui.QSizePolicy.Fixed))
        self.timeImage=self.viewer.addWidget("Time Image",PlotBase.TimeImageWidget(self),position="right",relativeTo="Control",Size=(10,10),minSize=(300,250))
        self.energyImage=self.viewer.addWidget("Energy Image",PlotBase.EnergyImageWidget(self),position="below",relativeTo="Time Image",Size=(10,10),minSize=(300,250))
        self.countrate=self.viewer.addWidget("Countrate",PlotBase.CountrateWidget(),position="bottom",relativeTo="Time Image",Size=(10,10),minSize=(300,250))
        self.keithley=self.viewer.addWidget("Keithley",PlotBase.KeithleyWidget(),position="below",relativeTo="Countrate",Size=(10,10),minSize=(300,250))
        self.timeHistogram=self.viewer.addWidget("Time Histogram",PlotBase.TimeHistogramWidget(),position="right",relativeTo="Time Image",Size=(10,10),minSize=(300,250))
        self.energyHistogram=self.viewer.addWidget("Energy Histogram",PlotBase.EnergyHistogramWidget(self),position="below",relativeTo="Time Histogram",Size=(10,10),minSize=(300,250))

        if themisApp!=None:
            self.liveView=self.viewer.addWidget("MCP",PlotBase.LiveView(self),position="above",relativeTo="Time Image",Size=(10,10),minSize=(400,250))
            self.viewer.addWidget("Themis",self.themisApp,position="above",relativeTo="Control",Size=(10,10),minSize=(250,250))
            # Buttons=QtGui.QHBoxLayout()
            # self.start=QtGui.QPushButton("Start")
            # self.start.setIcon(QtGui.QIcon('Bilder/accept.png'))
            # #self.start.clicked.connect(self.startMeasurement)
            # Buttons.addWidget(self.start)
            # self.pause=QtGui.QPushButton("Pause")
            # self.pause.setIcon(QtGui.QIcon('Bilder/pause.png'))
            # #self.pause.clicked.connect(self.pauseMeasurement)
            # Buttons.addWidget(self.pause)
            # self.stop=QtGui.QPushButton("Stop")
            # self.stop.setIcon(QtGui.QIcon('Bilder/stop.png'))
            # #self.stop.clicked.connect(self.on_stop_clicked)
            # Buttons.addWidget(self.stop)
            # #self.configWidget.layout().insertWidget(0,Buttons)
        else:
            self.liveView=None #None#self.viewer.addWidget("MCP",PlotBase.LiveView(),position="above",relativeTo="Time Image",Size=(10,10),minSize=(400,250))

        if not openFile==None:
            self.loadMeasurement(openFile)
        self.initializeSignals()


    def finalize(self):
        self.dataHandler.finalize()
        self.dataHandler.deleteLater()
        del self.dataHandler
        self.DataThread.quit()
        self.DataThread.wait()
        #self.dataHandler.updateTimer.timeout.disconnect(self.dataHandler.updateGui)
        #self.dataHandler.sigUpdateGui.disconnect(self.updateView)
        #self.configWidget.sigConfigChanged.disconnect(self.dataHandler.configChanged,)
        #self.dataHandler.deleteLater()

    def initializeSignals(self):
        self.configWidget.connectSignal(self.config.param("Spectra","Time Histogram","Time min").sigValueChanged,self.timeConfigChanged)
        self.configWidget.connectSignal(self.config.param("Spectra","Time Histogram","Time max").sigValueChanged,self.timeConfigChanged)
        self.configWidget.connectSignal(self.config.param("Spectra","Time Histogram","Time resolution").sigValueChanged,self.timeConfigChanged)
        self.configWidget.connectSignal(self.config.param("Spectra","Time Image","Xbins").sigValueChanged,self.timeConfigChanged)
        self.configWidget.connectSignal(self.config.param("Spectra","Time Image","Ybins").sigValueChanged,self.timeConfigChanged)
        self.configWidget.connectSignal(self.config.param("Spectra","Rotate MCP").sigValueChanged,self.dataHandler.rotationChanged)
        self.configWidget.connectSignal(self.config.param("DLLParams","X Min").sigValueChanged,self.timeConfigChanged)
        self.configWidget.connectSignal(self.config.param("DLLParams","X Max").sigValueChanged,self.timeConfigChanged)
        self.configWidget.connectSignal(self.config.param("DLLParams","Y Min").sigValueChanged,self.timeConfigChanged)
        self.configWidget.connectSignal(self.config.param("DLLParams","Y Max").sigValueChanged,self.timeConfigChanged)


        self.configWidget.connectSignal(self.config.param('File Configuration', 'Save Measurement').sigActivated,self.saveMeasurement)
        self.configWidget.connectSignal(self.config.param('Spectra', 'Create new Conversion').sigActivated,self.createStandardConversion)


        self.sigSaveMeasurement.connect(self.saveMeasurement)
        self.timeHistogram.selectionChanged.connect(self.selectionChanged)




    def selectionChanged(self,min,max):
        with self.dataHandler:
            self.dataHandler.dataSet.timeImage.fill(0)
            electrons=self.dataHandler.dataSet.getElectronsFromRawData()
            if min==-999999999:
                timeFilter=(None,None)
            else:
                timeFilter=(self.dataHandler.dataSet.unitsToRawData(min,"T"),self.dataHandler.dataSet.unitsToRawData(max,"T"))
            if not timeFilter[0]==None and not timeFilter[1]==None:
                electrons = electrons[np.logical_and(electrons["time"] > timeFilter[0], electrons["time"] < timeFilter[1])]
            elif not timeFilter[0]==None:
                electrons = electrons[electrons["time"] > timeFilter[0]]
            elif not timeFilter[1]==None:
                electrons = electrons[electrons["time"] < timeFilter[1]]

            self.dataHandler.dataSet.setElectrons(electrons=electrons,spectrum="timeImage")
            self.updateView({"timeImage":np.copy(self.dataHandler.dataSet.timeImage)})


    def timeConfigChanged(self):
        with self.dataHandler:
            if not self.dataHandler.dataSet.rawData==None:
                self.dataHandler.dataSet.setTimeRange()
                self.dataHandler.dataSet.setTimeImageRange()
                electrons=self.dataHandler.dataSet.getElectronsFromRawData()
                self.dataHandler.dataSet.setElectrons(electrons=electrons,spectrum=["timeHistogram","timeImage"])
                self.dataHandler.dataTransfer(["timeHistogram","timeImage"])

            else:
                self.dataHandler.dataSet.initialize()
                self.dataHandler.sigUpdateRequest.emit(["all"])


    def updateView(self, data=None):
            if data==None:
                self.dataHandler.sigUpdateRequest.emit("all")
                return
            if "timeHistogram" in data:
                self.timeHistogram.updateData(data["timeHistogram"][0],data["timeHistogram"][1])
            if "energyHistogram" in data:
                self.energyHistogram.updateData(data["energyHistogram"][0],data["energyHistogram"][1])
            if "timeImage" in data:
                self.timeImage.updateData(data["timeImage"])
            if "energyImage" in data:
                self.energyImage.updateData(data["energyImage"])
            if "countrate" in data:
                self.countrate.updateData(data["countrate"][0],data["countrate"][1])
            if "keithley" in data:
                self.keithley.updateData(data["keithley"][0],data["keithley"][1])
            if "liveView" in data:
                if self.liveView!=None:

                    self.liveView.updateData(data["liveView"][0])
                    self.liveView.countrate.setValue(data["liveView"][1])
                    self.liveView.selection.setValue(data["liveView"][2])

    def setDLDParameter(self,factors,offsets,pxLimits): #set from dld
        self.configWidget.setDLLParams(factors=factors,offsets=offsets,pxLimits=pxLimits)

    def createConversion(self,dialog=False,recommended=False):
        conversion=EnergyConversion.ConversionItem(self.dataHandler.dataSet,self.configWidget)
        with self.dataHandler:
            if not self.dataHandler.dataSet.rawData==None: conversion.control.state.getEventData()._data=self.dataHandler.dataSet.getElectronsFromRawData()
        if dialog:
            newconversion=conversion.startConversionDialog()
        else:
            self.throwMessage.emit("Create ConversionSplines",2)
            newconversion=conversion.createStandardConversion(recommended=recommended)
            self.throwMessage.emit("--> Finished",4)
        if newconversion==None: return
        self.configWidget.setEnergyParams(newconversion.factors,newconversion.offsets)
        with self.dataHandler:
            self.dataHandler.dataSet.conversion=conversion
            self.dataHandler.dataSet.energyHistogram=np.sum(np.sum(newconversion.getDataContent(),0),0)
            self.dataHandler.dataSet.energyImage=np.sum(newconversion.getDataContent(),2)
            self.dataHandler.dataSet.setEnergyRange()

        self.energyImage.setExtent()
        self.dataHandler.sigUpdateRequest.emit(["energyHistogram","energyImage"])



    def startConversionDialog(self):
        self.createConversion(dialog=True)

    def createStandardConversion(self):
        self.createConversion()


    def clearSpectra(self,rawData=True):
        QtCore.QMetaObject.invokeMethod(self.dataHandler,"clearSpectra",QtCore.Qt.QueuedConnection,QtCore.Q_ARG(bool,True))
        # with self.dataHandler:
        #
        #     self.dataHandler.dataSet.clearSpectra()
        #     self.dataHandler.electrons=np.empty(0, [("x", 'i2'), ("y", 'i2'), ("time", 'i4')])
        # if rawData:
        #     self.dataHandler.closeRawData()
        # self.dataHandler.sigUpdateRequest.emit(["all"])

    def saveMeasurement(self,confirm=True,autoOverride=False):
        path=self.config["File Configuration","Folder"]
        if path=="Default": path=fileaccess.createDefaultPath(self.config["File Configuration","Folder","Beamtime"],self.config["File Configuration","Folder","Groupname"])
        else: path=self.config["File Configuration","Folder","Custom Folder"]
        if not fileaccess.checkIfPathExist(path):
            self.throwMessage.emit("--> Could not create the desired Path",0)
            self.throwMessage.emit("--> Measurement was not Saved",2)
            return False
        filename=self.config["File Configuration","Filename"]
        if self.themisApp!=None:
            filename=filename.replace("%n",("%03d"% self.themisApp.parent.joblist.measurementNumber.value()))
            self.themisApp.parent.joblist.measurementNumber.setValue(self.themisApp.parent.joblist.measurementNumber.value()+1)
        file=path+"/"+filename+".lv"
        if not autoOverride:
            if fileaccess.checkIfFileExists(file):
                file=fileaccess.fileOverwriteDialog(file,path)
                if file==None:
                    self.throwMessage.emit("--> Measurement was not Saved",2)
                    return False
        self.throwMessage.emit("Save Measurement as: "+file,2)
        file=file.replace("/","\\")
        with self.dataHandler:
            if not self.dataHandler.dataSet.rawData==None and self.dataHandler.dataSet.rawData.filename.replace("/","\\")==file.replace("/","\\"):
                file=file+"_temporay_while_edited"
            h5file = fileaccess.openFile(file, mode = "w", title = "Measurement")

            ##! Adjust and Save Config
            config=self.config.saveState()
            config["children"]["File Configuration"]["children"]["Folder"]["children"]["Custom Folder"]["value"]=path
            config["children"]["File Configuration"]["children"]["Folder"]["value"]="Custom"
            config["children"]["File Configuration"]["children"]["Filename"]["value"]=filename
            if config["children"]["Measurement Info"]["children"]["End of Acquisition"]["value"]=="not yet finished":
                config["children"]["Measurement Info"]["children"]["End of Acquisition"]["value"]=datetime.datetime.now().strftime("%Y-%m-%d, %H:%M:%S")
            h5file.root._v_attrs.config=str(config)
            self.dataHandler.dataSet.saveDataSet(h5file)
            h5file.flush()
            if "_temporay_while_edited" in file:
                self.dataHandler.dataSet.rawData.close()
                _cwd=os.getcwd()
                os.chdir(path)
                name=file.split("\\")[-1]
                os.remove(file[0:-22])
                h5file.close()
                os.rename(name,name[0:-22])
                self.dataHandler.dataSet.rawData=fileaccess.openFile(file[0:-22], mode = "a")
                self.dataHandler.dataSet.events=self.dataHandler.dataSet.rawData.getNode("/rawData/", "events")
            else:
                h5file.close()

            if self.config["File Configuration","Copy to Grouphome"]:
                grouphome=path.replace("C:/","Z:/")
                if grouphome==path: return
                try:
                    fileaccess.checkIfPathExist(grouphome,create=True)
                    shutil.copy(file,grouphome)
                except(WindowsError):
                    self.throwMessage.emit("Error: Could not connect to Grouphome",2)
            if confirm:
                msgBox=QtGui.QMessageBox(self.viewer)
                msgBox.setWindowTitle("Measurement Saved")
                msgBox.setText("Measurement has been saved to:")
                msgBox.setInformativeText(file)
                msgBox.exec_()

    @staticmethod
    def loadMeasurement(file,mode="r"):
        measurement=Measurement()
        measurement.load(file,mode=mode)
        return(measurement)

    def load(self,file,mode="r"):
        self.viewer.setWindowTitle("Data Viewer - "+ file)

        if not fileaccess.checkIfFileExists(file):
            self.throwMessage.emit("Load Error: File "+file+" not found",0)
            return
        h5file = fileaccess.openFile(file, mode = mode)
        h5file =self.configWidget.restoreState(h5file,file=file)

        with self.dataHandler:
            self.dataHandler.dataSet.config=self.configWidget.toDict()
            self.dataHandler.dataSet.loadDataSet(h5file)
        self.timeImage.setExtent()
        self.energyImage.setExtent()
        self.dataHandler.sigUpdateRequest.emit(["all"])



    def show(self):
        self.viewer.show()
예제 #35
0
class GCode(object):
    def __init__(self, filename, controller, done_loading_callback,
                 done_writing_callback):
        self.controller = controller
        self.done_loading_callback = done_loading_callback
        self.writing_done_callback = done_writing_callback
        self.data = defaultdict(list)
        self.all_data = []
        self.data_keys = set()
        self.color_change_data = []
        self.actual_z = '0.0'
        self.speed = 0.0
        self.z_hop = False
        self.last_point = np.array([0.0, 0.0, 0.0])
        self.actual_point = [0.0, 0.0, 0.0]

        self.printing_time = 0.0
        self.filament_length = 0.0
        #print("Filename type: " + str(type(filename)))
        #print("Filename: " + filename)
        #if type(filename)==:
        #self.filename = u'c:\\models\\super mega testovací Jindřich šložka čěýáéůú\\anubis_PLA_OPTIMAL.gcode'
        self.filename = filename

        self.is_loaded = False

        self.gcode_parser = GcodeParserRunner(controller, self.filename)
        self.gcode_parser_thread = QThread()

        self.gcode_copy = GcodeCopyRunner(
            self.filename, "", color_change_lst=self.color_change_data)
        self.gcode_copy_thread = QThread()

    def cancel_parsing_gcode(self):
        print("Cancel presset")
        if self.gcode_parser and self.gcode_parser_thread and self.gcode_parser_thread.isRunning(
        ):
            self.gcode_parser.is_running = False
            self.gcode_parser_thread.quit()
            self.gcode_parser_thread.wait()
            self.is_loaded = False
            self.data = {}
            self.all_data = []
            self.data_keys = []
        self.controller.set_progress_bar(0)

    def cancel_writing_gcode(self):
        print("Cancel writing gcode")
        if self.gcode_copy and self.gcode_copy_thread and self.gcode_copy_thread.isRunning(
        ):
            self.gcode_copy.quit()
            self.gcode_copy_thread.wait()

    def get_first_extruding_line_number_of_gcode_for_layers(
            self, layers_keys_lst):
        lines_number = []
        for i in layers_keys_lst:
            line = self.data[i]
            for o in line:
                _a, _b, type, _speed, _extr, _extruder, line_n = o
                if 'E' in type:
                    lines_number.append(line_n)
                    break

        return lines_number

    def read_in_thread(self, update_progressbar_function, after_done_function):
        print("reading in thread")
        self.gcode_parser.moveToThread(self.gcode_parser_thread)
        self.done_loading_callback = after_done_function

        # connect all signals to thread class
        self.gcode_parser_thread.started.connect(
            self.gcode_parser.load_gcode_file)
        # connect all signals to parser class
        self.gcode_parser.finished.connect(self.set_finished_read)
        self.gcode_parser.update_progressbar = True
        self.gcode_parser.set_update_progress.connect(
            update_progressbar_function)
        self.gcode_parser.set_data_keys.connect(self.set_data_keys)
        self.gcode_parser.set_data.connect(self.set_data)
        self.gcode_parser.set_all_data.connect(self.set_all_data)
        self.gcode_parser.set_printing_time.connect(self.set_printig_time)

        self.gcode_parser_thread.start()

    def read_in_realtime(self):
        print("Read in realtime")
        self.gcode_parser.set_data_keys.connect(self.set_data_keys)
        self.gcode_parser.set_data.connect(self.set_data)
        self.gcode_parser.set_all_data.connect(self.set_all_data)
        self.gcode_parser.set_printing_time.connect(self.set_printig_time)
        self.gcode_parser.update_progressbar = False

        print("start read procedure")
        self.gcode_parser.load_gcode_file()

        self.is_loaded = True

    def set_printig_time(self, time):
        self.printing_time = time

    def set_data_keys(self, data_keys):
        self.data_keys = data_keys

    def set_all_data(self, all_data):
        self.all_data = all_data

    def set_data(self, data):
        self.data = data

    def set_finished_read(self):
        self.gcode_parser_thread.quit()
        self.is_loaded = True
        self.done_loading_callback()
        #self.controller.set_gcode()

    def set_finished_copy(self):
        self.gcode_copy_thread.quit()
        #print(str(self.writing_done_callback))
        self.writing_done_callback()

    def set_color_change_data(self, data):
        self.color_change_data = data

    def write_with_changes_in_thread(self, filename_in, filename_out,
                                     update_function):
        self.gcode_copy.filename_in = filename_in
        self.gcode_copy.filename_out = filename_out
        self.gcode_copy.color_change_lst = self.color_change_data
        self.gcode_copy.moveToThread(self.gcode_copy_thread)

        self.gcode_copy_thread.started.connect(self.gcode_copy.write_file)

        self.gcode_copy.finished.connect(self.set_finished_copy)
        self.gcode_copy.set_update_progress.connect(update_function)

        self.gcode_copy_thread.start()
예제 #36
0
class VNCClient(QObject):
    started = pyqtSignal()
    finished = pyqtSignal()
    imageSizeChanged = pyqtSignal(QSize)
    imageChanged = pyqtSignal(int, int, int, int)
    passwordRequested = pyqtSignal(bool)
    textCut = pyqtSignal(unicode)

    def __init__(self, host, port, settings, parent=None):
        super(VNCClient, self).__init__(parent)
        self.thread = QThread()
        self.moveToThread(self.thread)
        self.host = host
        self.port = port
        self.settings = settings
        self.username = None
        self.password = None
        self.rfb_client = None
        self.socket_notifier = None
        self.thread.started.connect(self._SH_ThreadStarted)
        self.thread.finished.connect(self._SH_ThreadFinished)

    def _get_settings(self):
        return self.__dict__['settings']
    def _set_settings(self, settings):
        old_settings = self.__dict__.get('settings', None)
        if settings == old_settings:
            return
        self.__dict__['settings'] = settings
        if self.thread.isRunning():
            QApplication.postEvent(self, RFBConfigureClientEvent())
    settings = property(_get_settings, _set_settings)
    del _get_settings, _set_settings

    @property
    def image(self):
        return self.rfb_client.image if self.rfb_client is not None else None

    def start(self):
        self.thread.start()

    def stop(self):
        self.thread.quit()

    def key_event(self, key, down):
        if self.thread.isRunning():
            QApplication.postEvent(self, RFBKeyEvent(key, down))

    def mouse_event(self, x, y, button_mask):
        if self.thread.isRunning():
            QApplication.postEvent(self, RFBMouseEvent(x, y, button_mask))

    def cut_text_event(self, text):
        if text and self.thread.isRunning():
            QApplication.postEvent(self, RFBCutTextEvent(text))

    def _SH_ThreadStarted(self):
        self.started.emit()
        notification_center = NotificationCenter()
        notification_center.post_notification('VNCClientWillStart', sender=self)
        self.rfb_client = RFBClient(parent=self)
        try:
            self.rfb_client.connect()
        except RFBClientError:
            self.thread.quit()
        else:
            self.socket_notifier = QSocketNotifier(self.rfb_client.socket, QSocketNotifier.Read, self)
            self.socket_notifier.activated.connect(self._SH_SocketNotifierActivated)
            notification_center.post_notification('VNCClientDidStart', sender=self)

    def _SH_ThreadFinished(self):
        self.finished.emit()
        notification_center = NotificationCenter()
        notification_center.post_notification('VNCClientWillEnd', sender=self)
        if self.socket_notifier is not None:
            self.socket_notifier.activated.disconnect(self._SH_SocketNotifierActivated)
            self.socket_notifier = None
        self.rfb_client = None
        notification_center.post_notification('VNCClientDidEnd', sender=self)

    def _SH_SocketNotifierActivated(self, sock):
        self.socket_notifier.setEnabled(False)
        try:
            self.rfb_client.handle_server_message()
        except RFBClientError:
            self.thread.quit()
        else:
            self.socket_notifier.setEnabled(True)

    def _SH_ConfigureRFBClient(self):
        if self.rfb_client is not None:
            self.rfb_client.configure()

    def customEvent(self, event):
        handler = getattr(self, '_EH_%s' % event.name, Null)
        handler(event)

    def _EH_RFBConfigureClientEvent(self, event):
        if self.rfb_client is not None:
            self.rfb_client.configure()

    def _EH_RFBKeyEvent(self, event):
        if self.rfb_client is not None:
            self.rfb_client.send_key_event(event.key, event.down)

    def _EH_RFBMouseEvent(self, event):
        if self.rfb_client is not None:
            self.rfb_client.send_pointer_event(event.x, event.y, event.button_mask)

    def _EH_RFBCutTextEvent(self, event):
        if self.rfb_client is not None:
            self.rfb_client.send_client_cut_text(event.text)
예제 #37
0
 def quit(self):
     try:
         self.listener.close()
     except Exception:
         pass
     QThread.quit(self)
예제 #38
0
class BisectRunner(QObject):
    bisector_created = Signal(object)
    running_state_changed = Signal(bool)

    def __init__(self, mainwindow):
        QObject.__init__(self)
        self.mainwindow = mainwindow
        self.bisector = None
        self.thread = None
        self.pending_threads = []

    def bisect(self, fetch_config, options):
        self.stop()

        # global preferences
        global_prefs = get_prefs()
        # apply the global prefs now
        apply_prefs(global_prefs)

        self.bisector = GuiBisector(fetch_config,
                                    persist=global_prefs['persist'])
        # create a QThread, and move self.bisector in it. This will
        # allow to the self.bisector slots (connected after the move)
        # to be automatically called in the thread.
        self.thread = QThread()
        self.bisector.moveToThread(self.thread)
        self.bisector.download_manager.download_progress.connect(
            self.show_dl_progress)
        self.bisector.test_runner.evaluate_started.connect(self.evaluate)
        self.bisector.finished.connect(self.bisection_finished)
        self.bisector_created.emit(self.bisector)
        if options['bisect_type'] == 'nightlies':
            handler = NightlyHandler(find_fix=options['find_fix'])
            good = options['good_date']
            bad = options['bad_date']
        else:
            handler = InboundHandler(find_fix=options['find_fix'])
            good = options['good_changeset']
            bad = options['bad_changeset']

        # options for the app launcher
        launcher_kwargs = {}
        for name in ('profile', 'preferences'):
            if name in options:
                value = options[name]
                if value:
                    launcher_kwargs[name] = value
        self.bisector.test_runner.launcher_kwargs = launcher_kwargs

        self.thread.start()
        self.bisector._bisect_args = (handler, good, bad)
        # this will be called in the worker thread.
        QTimer.singleShot(0, self.bisector.bisect)

        self.running_state_changed.emit(True)

    @Slot()
    def stop(self, wait=True):
        if self.bisector:
            self.bisector.finished.disconnect(self.bisection_finished)
            self.bisector.download_manager.cancel()
            self.bisector = None
        if self.thread:
            self.thread.quit()
            if wait:
                # wait for thread(s) completion - this is the case when
                # user close the application
                self.thread.wait()
                for thread in self.pending_threads:
                    thread.wait()
            else:
                # do not block, just keep track of the thread - we got here
                # when user cancel the bisection with the button.
                self.pending_threads.append(self.thread)
                self.thread.finished.connect(self._remove_pending_thread)
            self.thread = None
        self.running_state_changed.emit(False)

    @Slot()
    def _remove_pending_thread(self):
        for thread in self.pending_threads[:]:
            if thread.isFinished():
                self.pending_threads.remove(thread)

    @Slot(object, int, int)
    def show_dl_progress(self, dl, current, total):
        message = "downloading %s: %d/%d" % (dl.get_dest(), current, total)
        self.mainwindow.ui.statusbar.showMessage(message, 2000)

    @Slot()
    def evaluate(self):
        verdict = get_verdict(self.mainwindow)
        self.bisector.test_runner.finish(verdict)

    @Slot(object, int)
    def bisection_finished(self, bisection, resultcode):
        if resultcode == Bisection.USER_EXIT:
            msg = "Bisection stopped."
            dialog = QMessageBox.information
        elif resultcode == Bisection.NO_DATA:
            msg = "Unable to find enough data to bisect."
            dialog = QMessageBox.warning
        elif resultcode == Bisection.EXCEPTION:
            msg = "Error: %s" % self.bisector.error[1]
            dialog = QMessageBox.critical
        else:
            if bisection.fetch_config.can_go_inbound() and \
                    isinstance(bisection.handler, NightlyHandler):
                # we can go on inbound, let's ask the user
                if QMessageBox.question(
                        self.mainwindow, "End of the bisection",
                        "Nightly bisection is done, but you can continue the"
                        " bisection on inbound builds. Contibue with inbounds ?",
                        QMessageBox.Yes | QMessageBox.No,
                        QMessageBox.Yes) == QMessageBox.Yes:
                    # let's go on inbound
                    QTimer.singleShot(0, self.bisector.nightlies_to_inbound)
                else:
                    # no inbound, bisection is done.
                    self.stop()
                return
            msg = "The bisection is done."
            dialog = QMessageBox.information
        dialog(self.mainwindow, "End of the bisection", msg)
        self.stop()
예제 #39
0
class VNCClient(QObject):
    started = pyqtSignal()
    finished = pyqtSignal()
    imageSizeChanged = pyqtSignal(QSize)
    imageChanged = pyqtSignal(int, int, int, int)
    passwordRequested = pyqtSignal(bool)
    textCut = pyqtSignal(unicode)

    def __init__(self, host, port, settings, parent=None):
        super(VNCClient, self).__init__(parent)
        self.thread = QThread()
        self.moveToThread(self.thread)
        self.host = host
        self.port = port
        self.settings = settings
        self.username = None
        self.password = None
        self.rfb_client = None
        self.socket_notifier = None
        self.thread.started.connect(self._SH_ThreadStarted)
        self.thread.finished.connect(self._SH_ThreadFinished)

    def _get_settings(self):
        return self.__dict__['settings']

    def _set_settings(self, settings):
        old_settings = self.__dict__.get('settings', None)
        if settings == old_settings:
            return
        self.__dict__['settings'] = settings
        if self.thread.isRunning():
            QApplication.postEvent(self, RFBConfigureClientEvent())

    settings = property(_get_settings, _set_settings)
    del _get_settings, _set_settings

    @property
    def image(self):
        return self.rfb_client.image if self.rfb_client is not None else None

    def start(self):
        self.thread.start()

    def stop(self):
        self.thread.quit()

    def key_event(self, key, down):
        if self.thread.isRunning():
            QApplication.postEvent(self, RFBKeyEvent(key, down))

    def mouse_event(self, x, y, button_mask):
        if self.thread.isRunning():
            QApplication.postEvent(self, RFBMouseEvent(x, y, button_mask))

    def cut_text_event(self, text):
        if text and self.thread.isRunning():
            QApplication.postEvent(self, RFBCutTextEvent(text))

    def _SH_ThreadStarted(self):
        self.started.emit()
        notification_center = NotificationCenter()
        notification_center.post_notification('VNCClientWillStart', sender=self)
        self.rfb_client = RFBClient(parent=self)
        try:
            self.rfb_client.connect()
        except RFBClientError:
            self.thread.quit()
        else:
            self.socket_notifier = QSocketNotifier(self.rfb_client.socket, QSocketNotifier.Read, self)
            self.socket_notifier.activated.connect(self._SH_SocketNotifierActivated)
            notification_center.post_notification('VNCClientDidStart', sender=self)

    def _SH_ThreadFinished(self):
        self.finished.emit()
        notification_center = NotificationCenter()
        notification_center.post_notification('VNCClientWillEnd', sender=self)
        if self.socket_notifier is not None:
            self.socket_notifier.activated.disconnect(self._SH_SocketNotifierActivated)
            self.socket_notifier = None
        self.rfb_client = None
        notification_center.post_notification('VNCClientDidEnd', sender=self)

    def _SH_SocketNotifierActivated(self, sock):
        self.socket_notifier.setEnabled(False)
        try:
            self.rfb_client.handle_server_message()
        except RFBClientError:
            self.thread.quit()
        else:
            self.socket_notifier.setEnabled(True)

    def _SH_ConfigureRFBClient(self):
        if self.rfb_client is not None:
            self.rfb_client.configure()

    def customEvent(self, event):
        handler = getattr(self, '_EH_%s' % event.name, Null)
        handler(event)

    def _EH_RFBConfigureClientEvent(self, event):
        if self.rfb_client is not None:
            self.rfb_client.configure()

    def _EH_RFBKeyEvent(self, event):
        if self.rfb_client is not None:
            self.rfb_client.send_key_event(event.key, event.down)

    def _EH_RFBMouseEvent(self, event):
        if self.rfb_client is not None:
            self.rfb_client.send_pointer_event(event.x, event.y, event.button_mask)

    def _EH_RFBCutTextEvent(self, event):
        if self.rfb_client is not None:
            self.rfb_client.send_client_cut_text(event.text)
예제 #40
0
 def quit(self):
     QThread.quit(self)
예제 #41
0
class remote_pictures(iface_gui_plugin):
    VERSION_DB = 0
    VERSION_CURRENT = VERSION_DB
    
    def __init__(self):
        super(remote_pictures, self).__init__()
        self.options = [((u"min_opacity", u"Minimum opacity of controls:", self._minOpacityChanged), 20),
                        ((u"max_opacity", u"Maximum opacity of controls:", self._maxOpacityChanged), 80),
                        ((u"thumbnail_size", u"Thumbnail Size:", self._thumbnailSizeChanged), 150),
                        ((u"smooth_scaling", u"Smooth scaling", self._smoothScalingChanged), False),
                        ((u"store_locally", u"Store pictures locally", self._storeLocallyChanged), True)]
        self._gui = None
        self._handler = None
        self._rpAction = None
        
    def _handleOpacity(self, newValue, signal):
        if newValue < 0:
            newValue = 0
        elif newValue > 100:
            newValue = 100
            
        if signal is not None:
            signal.emit(float(newValue) / 100.)
        return newValue
        
    def _minOpacityChanged(self, _setting, newValue):
        return self._handleOpacity(newValue, None if self._gui is None else self._gui.minOpacityChanged)
    
    def _maxOpacityChanged(self, _setting, newValue):
        return self._handleOpacity(newValue, None if self._gui is None else self._gui.maxOpacityChanged)
    
    def _thumbnailSizeChanged(self, _setting, newValue):
        from remote_pictures.remote_pictures_category_model import CategoriesModel
        if newValue < CategoriesModel.MIN_THUMBNAIL_SIZE:
            newValue = CategoriesModel.MIN_THUMBNAIL_SIZE
        elif newValue > CategoriesModel.MAX_THUMBNAIL_SIZE:
            newValue = CategoriesModel.MAX_THUMBNAIL_SIZE
        
        if self._gui is not None:
            self._gui.thumbnailSizeChanged(newValue)
        if self._handler is not None:
            self._handler.thumbnailSizeChanged(newValue)
        return newValue
    
    def _storeLocallyChanged(self, _setting, newValue):
        self._handler.storeLocallyChanged(newValue)
        return newValue
        
    def _smoothScalingChanged(self, _setting, newValue):
        if self._gui is not None:
            self._gui.setSmoothScaling(newValue)
        
    def create_widget(self, parent):
        from PyQt4.QtCore import QThread
        from remote_pictures.remote_pictures_gui import RemotePicturesGui
        from remote_pictures.remote_pictures_handler import RemotePicturesHandler
        super(remote_pictures, self).create_widget(parent)
        self._gui = RemotePicturesGui(parent,
                                      self.logger,
                                      self.get_option(u"smooth_scaling"),
                                      self.get_option(u"min_opacity"),
                                      self.get_option(u"max_opacity"))
        
        if canUseBackgroundQThreads():
            self._messagesThread = QThread()
        else:
            self._messagesThread = None
        self._handler = RemotePicturesHandler(self.logger,
                                              self.get_option(u"thumbnail_size"),
                                              self.get_option(u"store_locally"),
                                              self._gui)
        if self._messagesThread is not None:
            self._handler.moveToThread(self._messagesThread)
            self._messagesThread.start()
        
        self._gui.openCategory.connect(self._handler.openCategory)
        self._gui.displayPrev.connect(self._handler.displayPrev)
        self._gui.displayNext.connect(self._handler.displayNext)
        self._gui.pictureDownloaded.connect(self._handler.pictureDownloaded)
        self._gui.setCategoryThumbnail.connect(self._handler.setCategoryThumbnail)
        
        self._handler.addCategory.connect(self._gui.categoryModel.addCategory)
        self._handler.categoryThumbnailChanged.connect(self._gui.categoryModel.categoryThumbnailChanged) 
        self._handler.displayImageInGui.connect(self._gui.displayImage)
        
        self._gui.categoryModel.categoriesChanged.connect(self._privacySettingsChanged)
        self._handler.categoriesChanged.connect(self._privacySettingsChanged)
        
        self._handler.loadPictures()
        
        return self._gui
    
    def destroy_widget(self):
        if self._gui is not None and self._handler is not None:
            self._gui.openCategory.disconnect(self._handler.openCategory)
            self._gui.displayPrev.disconnect(self._handler.displayPrev)
            self._gui.displayNext.disconnect(self._handler.displayNext)
            self._gui.pictureDownloaded.disconnect(self._handler.pictureDownloaded)
            self._gui.setCategoryThumbnail.disconnect(self._handler.setCategoryThumbnail)
            
            self._handler.addCategory.disconnect(self._gui.categoryModel.addCategory)
            self._handler.categoryThumbnailChanged.disconnect(self._gui.categoryModel.categoryThumbnailChanged)
            self._handler.displayImageInGui.disconnect(self._gui.displayImage)
            
        if self._gui is not None:
            self._gui.categoryModel.categoriesChanged.disconnect(self._privacySettingsChanged)
            self._gui.destroyWidget()
        
        if self._handler is not None:
            self._handler.categoriesChanged.disconnect(self._privacySettingsChanged)
            self._handler.finish()
            
        if self._messagesThread is not None:
            self._messagesThread.quit()
            self._messagesThread.wait()
            self._messagesThread.deleteLater()
        
        iface_gui_plugin.destroy_widget(self)

    def extendsInfoDict(self):
        return lunchinator_has_gui()
        
    def extendInfoDict(self, infoDict):
        infoDict[u"RP_v"] = self.VERSION_CURRENT
        
    def get_peer_actions(self):
        if lunchinator_has_gui():
            self._rpAction = _RemotePictureAction()
            return [self._rpAction]
        else:
            return None
            
    def checkCategory(self, cat):
        if self._handler is not None:
            self._handler.checkCategory(cat)
            
    def process_event(self, cmd, value, ip, _info, _prep):
        if cmd=="HELO_REMOTE_PIC":
            if self._handler is not None:
                self._handler.processRemotePicture(value, ip)
                
    def getCategories(self):
        if self._handler is None:
            self.logger.error("Remote Pictures not initialized")
            return []
    
        return self._handler.getCategoryNames(alsoEmpty=True)
    
    def getCategoryIcon(self, category):
        if self._gui is None:
            self.logger.error("Remote Pictures not initialized")
            return None
        return self._gui.getCategoryIcon(category)
    
    def willIgnorePeerAction(self, category, url):
        return self._handler.willIgnorePeerAction(category, url)
    
    def sendRemotePicture(self, peerID, peerInfo, parent):
        from remote_pictures.remote_pictures_dialog import RemotePicturesDialog
        dialog = RemotePicturesDialog(parent, peerID, peerInfo)
        result = dialog.exec_()
        if result == RemotePicturesDialog.Accepted:
            data = [dialog.getURL().encode('utf-8')]
            if dialog.getDescription():
                data.append(dialog.getDescription().encode('utf-8'))
                if dialog.getCategory():
                    data.append(dialog.getCategory().encode('utf-8'))
            with contextlib.closing(StringIO()) as strOut:
                writer = csv.writer(strOut, delimiter = ' ', quotechar = '"')
                writer.writerow(data)
                get_server().call("HELO_REMOTE_PIC " + strOut.getvalue(), peerIDs=[peerID])
    
    @loggingFunc
    def _privacySettingsChanged(self):
        get_notification_center().emitPrivacySettingsChanged(self._rpAction.getPluginName(), self._rpAction.getName())
예제 #42
0
class ImageStream(QtGui.QLabel):
    def __init__(self, cal_wizard, device):
        super(ImageStream, self).__init__()
        self.cal_wizard = cal_wizard
        self.signal_snap = QtCore.SIGNAL("snapshot_taken")
        self.signal_reload = QtCore.SIGNAL("reload")
        self.device = device

        tree = ET.parse(device.local_config_path)
        self.group = tree.find('communicator').find('group').text

        self.receiver_thread = QThread()
        self.receiver_thread.start()

        self.image_receiver = ImageReceiver(self.device, self.group)
        self.image_receiver.moveToThread(self.receiver_thread)
        self.connect(self.image_receiver, self.image_receiver.signal, self.update_image)

        self.transmitter_thread = QThread()
        self.transmitter_thread.start()

        self.image_transmitter = ImageTransmitter(self.device)
        self.image_transmitter.moveToThread(self.transmitter_thread)
        self.connect(self.image_transmitter, self.image_transmitter.signal, self.reload)

    def finish(self):
        self.stop()
        self.receiver_thread.quit()
        self.receiver_thread.wait()
        self.transmitter_thread.quit()
        self.transmitter_thread.wait()

    def start(self):
        QtCore.QTimer.singleShot(0, self.image_transmitter.task)
        QtCore.QTimer.singleShot(0, self.image_receiver.task)

    def update_image(self):
        self.setPixmap(QtGui.QPixmap.fromImage(self.image_receiver.img))
        return

    def stop(self):
        # note: The image receiver has to be stopped first
        #       otherwise zyre will keep waiting for a message from the
        #       transmitter indefinitely
        self.image_receiver.stop()
        self.image_transmitter.stop()

    def snap(self):
        # give command to take snapshot
        self.image_receiver.snap()
        # download snapshot
        ssh = self.device.ssh_manager.get_ssh()
        sftp = ssh.open_sftp()
        sftp.get(os.path.join(paths.get_remote_config_dir(self.device), 'snapshot.png'), self.cal_wizard.get_next_snap_path(self.device))
        sftp.remove(os.path.join(paths.get_remote_config_dir(self.device), 'snapshot.png'))
        ssh.close()
        self.emit(self.signal_snap, 'snapshot taken')

    def reload(self):
        # Stop ImageTransmitter/Receiver
        self.stop()
        # Start ImageTransmitter again
        self.start()
        self.emit(self.signal_reload, 'reload')
예제 #43
0
class Measurement(QObject):
    throwMessage = pyqtSignal(str, int, name='throwMessage')
    sigSaveMeasurement = pyqtSignal(bool, name='save')
    updateWindows = pyqtSignal(str, name="updateView")
    sigUpdateCountrate = pyqtSignal(int, str)

    sigTest = pyqtSignal()

    def __init__(self, openFile=None, themisApp=None):
        QObject.__init__(self)
        self.themisApp = themisApp
        self.configWidget = configurationWidget.configurationWidget(self)
        self.config = self.configWidget.p
        self.DataThread = QThread(self)
        self.dataHandler = DataHandler(self.configWidget.toDict())
        self.dataHandler.moveToThread(self.DataThread)
        self.dataHandler.updateTimer.timeout.connect(
            self.dataHandler.updateGui)
        self.dataHandler.sigUpdateGui.connect(self.updateView,
                                              QtCore.Qt.QueuedConnection)
        self.configWidget.sigConfigChanged.connect(
            self.dataHandler.configChanged, QtCore.Qt.QueuedConnection)
        self.DataThread.start()

        self.viewer = DataViewer(name="Measurement")
        self.timeFilter = [None, None]
        self.acquisitionTime = -1

        #SetWindows
        self.viewer.addWidget("Control",
                              self.configWidget,
                              position="left",
                              Size=(2, 2),
                              minSize=(250, 250),
                              sizePolicy=(QtGui.QSizePolicy.Fixed,
                                          QtGui.QSizePolicy.Fixed))
        self.timeImage = self.viewer.addWidget("Time Image",
                                               PlotBase.TimeImageWidget(self),
                                               position="right",
                                               relativeTo="Control",
                                               Size=(10, 10),
                                               minSize=(300, 250))
        self.energyImage = self.viewer.addWidget(
            "Energy Image",
            PlotBase.EnergyImageWidget(self),
            position="below",
            relativeTo="Time Image",
            Size=(10, 10),
            minSize=(300, 250))
        self.countrate = self.viewer.addWidget("Countrate",
                                               PlotBase.CountrateWidget(),
                                               position="bottom",
                                               relativeTo="Time Image",
                                               Size=(10, 10),
                                               minSize=(300, 250))
        self.keithley = self.viewer.addWidget("Keithley",
                                              PlotBase.KeithleyWidget(),
                                              position="below",
                                              relativeTo="Countrate",
                                              Size=(10, 10),
                                              minSize=(300, 250))
        self.timeHistogram = self.viewer.addWidget(
            "Time Histogram",
            PlotBase.TimeHistogramWidget(),
            position="right",
            relativeTo="Time Image",
            Size=(10, 10),
            minSize=(300, 250))
        self.energyHistogram = self.viewer.addWidget(
            "Energy Histogram",
            PlotBase.EnergyHistogramWidget(self),
            position="below",
            relativeTo="Time Histogram",
            Size=(10, 10),
            minSize=(300, 250))

        if themisApp != None:
            self.liveView = self.viewer.addWidget("MCP",
                                                  PlotBase.LiveView(self),
                                                  position="above",
                                                  relativeTo="Time Image",
                                                  Size=(10, 10),
                                                  minSize=(400, 250))
            self.viewer.addWidget("Themis",
                                  self.themisApp,
                                  position="above",
                                  relativeTo="Control",
                                  Size=(10, 10),
                                  minSize=(250, 250))
            # Buttons=QtGui.QHBoxLayout()
            # self.start=QtGui.QPushButton("Start")
            # self.start.setIcon(QtGui.QIcon('Bilder/accept.png'))
            # #self.start.clicked.connect(self.startMeasurement)
            # Buttons.addWidget(self.start)
            # self.pause=QtGui.QPushButton("Pause")
            # self.pause.setIcon(QtGui.QIcon('Bilder/pause.png'))
            # #self.pause.clicked.connect(self.pauseMeasurement)
            # Buttons.addWidget(self.pause)
            # self.stop=QtGui.QPushButton("Stop")
            # self.stop.setIcon(QtGui.QIcon('Bilder/stop.png'))
            # #self.stop.clicked.connect(self.on_stop_clicked)
            # Buttons.addWidget(self.stop)
            # #self.configWidget.layout().insertWidget(0,Buttons)
        else:
            self.liveView = None  #None#self.viewer.addWidget("MCP",PlotBase.LiveView(),position="above",relativeTo="Time Image",Size=(10,10),minSize=(400,250))

        if not openFile == None:
            self.loadMeasurement(openFile)
        self.initializeSignals()

    def finalize(self):
        self.dataHandler.finalize()
        self.dataHandler.deleteLater()
        del self.dataHandler
        self.DataThread.quit()
        self.DataThread.wait()
        #self.dataHandler.updateTimer.timeout.disconnect(self.dataHandler.updateGui)
        #self.dataHandler.sigUpdateGui.disconnect(self.updateView)
        #self.configWidget.sigConfigChanged.disconnect(self.dataHandler.configChanged,)
        #self.dataHandler.deleteLater()

    def initializeSignals(self):
        self.configWidget.connectSignal(
            self.config.param("Spectra", "Time Histogram",
                              "Time min").sigValueChanged,
            self.timeConfigChanged)
        self.configWidget.connectSignal(
            self.config.param("Spectra", "Time Histogram",
                              "Time max").sigValueChanged,
            self.timeConfigChanged)
        self.configWidget.connectSignal(
            self.config.param("Spectra", "Time Histogram",
                              "Time resolution").sigValueChanged,
            self.timeConfigChanged)
        self.configWidget.connectSignal(
            self.config.param("Spectra", "Time Image",
                              "Xbins").sigValueChanged, self.timeConfigChanged)
        self.configWidget.connectSignal(
            self.config.param("Spectra", "Time Image",
                              "Ybins").sigValueChanged, self.timeConfigChanged)
        self.configWidget.connectSignal(
            self.config.param("Spectra", "Rotate MCP").sigValueChanged,
            self.dataHandler.rotationChanged)
        self.configWidget.connectSignal(
            self.config.param("DLLParams", "X Min").sigValueChanged,
            self.timeConfigChanged)
        self.configWidget.connectSignal(
            self.config.param("DLLParams", "X Max").sigValueChanged,
            self.timeConfigChanged)
        self.configWidget.connectSignal(
            self.config.param("DLLParams", "Y Min").sigValueChanged,
            self.timeConfigChanged)
        self.configWidget.connectSignal(
            self.config.param("DLLParams", "Y Max").sigValueChanged,
            self.timeConfigChanged)

        self.configWidget.connectSignal(
            self.config.param('File Configuration',
                              'Save Measurement').sigActivated,
            self.saveMeasurement)
        self.configWidget.connectSignal(
            self.config.param('Spectra', 'Create new Conversion').sigActivated,
            self.createStandardConversion)

        self.sigSaveMeasurement.connect(self.saveMeasurement)
        self.timeHistogram.selectionChanged.connect(self.selectionChanged)

    def selectionChanged(self, min, max):
        with self.dataHandler:
            self.dataHandler.dataSet.timeImage.fill(0)
            electrons = self.dataHandler.dataSet.getElectronsFromRawData()
            if min == -999999999:
                timeFilter = (None, None)
            else:
                timeFilter = (self.dataHandler.dataSet.unitsToRawData(
                    min,
                    "T"), self.dataHandler.dataSet.unitsToRawData(max, "T"))
            if not timeFilter[0] == None and not timeFilter[1] == None:
                electrons = electrons[np.logical_and(
                    electrons["time"] > timeFilter[0],
                    electrons["time"] < timeFilter[1])]
            elif not timeFilter[0] == None:
                electrons = electrons[electrons["time"] > timeFilter[0]]
            elif not timeFilter[1] == None:
                electrons = electrons[electrons["time"] < timeFilter[1]]

            self.dataHandler.dataSet.setElectrons(electrons=electrons,
                                                  spectrum="timeImage")
            self.updateView(
                {"timeImage": np.copy(self.dataHandler.dataSet.timeImage)})

    def timeConfigChanged(self):
        with self.dataHandler:
            if not self.dataHandler.dataSet.rawData == None:
                self.dataHandler.dataSet.setTimeRange()
                self.dataHandler.dataSet.setTimeImageRange()
                electrons = self.dataHandler.dataSet.getElectronsFromRawData()
                self.dataHandler.dataSet.setElectrons(
                    electrons=electrons,
                    spectrum=["timeHistogram", "timeImage"])
                self.dataHandler.dataTransfer(["timeHistogram", "timeImage"])

            else:
                self.dataHandler.dataSet.initialize()
                self.dataHandler.sigUpdateRequest.emit(["all"])

    def updateView(self, data=None):
        if data == None:
            self.dataHandler.sigUpdateRequest.emit("all")
            return
        if "timeHistogram" in data:
            self.timeHistogram.updateData(data["timeHistogram"][0],
                                          data["timeHistogram"][1])
        if "energyHistogram" in data:
            self.energyHistogram.updateData(data["energyHistogram"][0],
                                            data["energyHistogram"][1])
        if "timeImage" in data:
            self.timeImage.updateData(data["timeImage"])
        if "energyImage" in data:
            self.energyImage.updateData(data["energyImage"])
        if "countrate" in data:
            self.countrate.updateData(data["countrate"][0],
                                      data["countrate"][1])
        if "keithley" in data:
            self.keithley.updateData(data["keithley"][0], data["keithley"][1])
        if "liveView" in data:
            if self.liveView != None:

                self.liveView.updateData(data["liveView"][0])
                self.liveView.countrate.setValue(data["liveView"][1])
                self.liveView.selection.setValue(data["liveView"][2])

    def setDLDParameter(self, factors, offsets, pxLimits):  #set from dld
        self.configWidget.setDLLParams(factors=factors,
                                       offsets=offsets,
                                       pxLimits=pxLimits)

    def createConversion(self, dialog=False, recommended=False):
        conversion = EnergyConversion.ConversionItem(self.dataHandler.dataSet,
                                                     self.configWidget)
        with self.dataHandler:
            if not self.dataHandler.dataSet.rawData == None:
                conversion.control.state.getEventData(
                )._data = self.dataHandler.dataSet.getElectronsFromRawData()
        if dialog:
            newconversion = conversion.startConversionDialog()
        else:
            self.throwMessage.emit("Create ConversionSplines", 2)
            newconversion = conversion.createStandardConversion(
                recommended=recommended)
            self.throwMessage.emit("--> Finished", 4)
        if newconversion == None: return
        self.configWidget.setEnergyParams(newconversion.factors,
                                          newconversion.offsets)
        with self.dataHandler:
            self.dataHandler.dataSet.conversion = conversion
            self.dataHandler.dataSet.energyHistogram = np.sum(
                np.sum(newconversion.getDataContent(), 0), 0)
            self.dataHandler.dataSet.energyImage = np.sum(
                newconversion.getDataContent(), 2)
            self.dataHandler.dataSet.setEnergyRange()

        self.energyImage.setExtent()
        self.dataHandler.sigUpdateRequest.emit(
            ["energyHistogram", "energyImage"])

    def startConversionDialog(self):
        self.createConversion(dialog=True)

    def createStandardConversion(self):
        self.createConversion()

    def clearSpectra(self, rawData=True):
        QtCore.QMetaObject.invokeMethod(self.dataHandler, "clearSpectra",
                                        QtCore.Qt.QueuedConnection,
                                        QtCore.Q_ARG(bool, True))
        # with self.dataHandler:
        #
        #     self.dataHandler.dataSet.clearSpectra()
        #     self.dataHandler.electrons=np.empty(0, [("x", 'i2'), ("y", 'i2'), ("time", 'i4')])
        # if rawData:
        #     self.dataHandler.closeRawData()
        # self.dataHandler.sigUpdateRequest.emit(["all"])

    def saveMeasurement(self, confirm=True, autoOverride=False):
        path = self.config["File Configuration", "Folder"]
        if path == "Default":
            path = fileaccess.createDefaultPath(
                self.config["File Configuration", "Folder", "Beamtime"],
                self.config["File Configuration", "Folder", "Groupname"])
        else:
            path = self.config["File Configuration", "Folder", "Custom Folder"]
        if not fileaccess.checkIfPathExist(path):
            self.throwMessage.emit("--> Could not create the desired Path", 0)
            self.throwMessage.emit("--> Measurement was not Saved", 2)
            return False
        filename = self.config["File Configuration", "Filename"]
        if self.themisApp != None:
            filename = filename.replace(
                "%n",
                ("%03d" %
                 self.themisApp.parent.joblist.measurementNumber.value()))
            self.themisApp.parent.joblist.measurementNumber.setValue(
                self.themisApp.parent.joblist.measurementNumber.value() + 1)
        file = path + "/" + filename + ".lv"
        if not autoOverride:
            if fileaccess.checkIfFileExists(file):
                file = fileaccess.fileOverwriteDialog(file, path)
                if file == None:
                    self.throwMessage.emit("--> Measurement was not Saved", 2)
                    return False
        self.throwMessage.emit("Save Measurement as: " + file, 2)
        file = file.replace("/", "\\")
        with self.dataHandler:
            if not self.dataHandler.dataSet.rawData == None and self.dataHandler.dataSet.rawData.filename.replace(
                    "/", "\\") == file.replace("/", "\\"):
                file = file + "_temporay_while_edited"
            h5file = fileaccess.openFile(file, mode="w", title="Measurement")

            ##! Adjust and Save Config
            config = self.config.saveState()
            config["children"]["File Configuration"]["children"]["Folder"][
                "children"]["Custom Folder"]["value"] = path
            config["children"]["File Configuration"]["children"]["Folder"][
                "value"] = "Custom"
            config["children"]["File Configuration"]["children"]["Filename"][
                "value"] = filename
            if config["children"]["Measurement Info"]["children"][
                    "End of Acquisition"]["value"] == "not yet finished":
                config["children"]["Measurement Info"]["children"][
                    "End of Acquisition"]["value"] = datetime.datetime.now(
                    ).strftime("%Y-%m-%d, %H:%M:%S")
            h5file.root._v_attrs.config = str(config)
            self.dataHandler.dataSet.saveDataSet(h5file)
            h5file.flush()
            if "_temporay_while_edited" in file:
                self.dataHandler.dataSet.rawData.close()
                _cwd = os.getcwd()
                os.chdir(path)
                name = file.split("\\")[-1]
                os.remove(file[0:-22])
                h5file.close()
                os.rename(name, name[0:-22])
                self.dataHandler.dataSet.rawData = fileaccess.openFile(
                    file[0:-22], mode="a")
                self.dataHandler.dataSet.events = self.dataHandler.dataSet.rawData.getNode(
                    "/rawData/", "events")
            else:
                h5file.close()

            if self.config["File Configuration", "Copy to Grouphome"]:
                grouphome = path.replace("C:/", "Z:/")
                if grouphome == path: return
                try:
                    fileaccess.checkIfPathExist(grouphome, create=True)
                    shutil.copy(file, grouphome)
                except (WindowsError):
                    self.throwMessage.emit(
                        "Error: Could not connect to Grouphome", 2)
            if confirm:
                msgBox = QtGui.QMessageBox(self.viewer)
                msgBox.setWindowTitle("Measurement Saved")
                msgBox.setText("Measurement has been saved to:")
                msgBox.setInformativeText(file)
                msgBox.exec_()

    @staticmethod
    def loadMeasurement(file, mode="r"):
        measurement = Measurement()
        measurement.load(file, mode=mode)
        return (measurement)

    def load(self, file, mode="r"):
        self.viewer.setWindowTitle("Data Viewer - " + file)

        if not fileaccess.checkIfFileExists(file):
            self.throwMessage.emit("Load Error: File " + file + " not found",
                                   0)
            return
        h5file = fileaccess.openFile(file, mode=mode)
        h5file = self.configWidget.restoreState(h5file, file=file)

        with self.dataHandler:
            self.dataHandler.dataSet.config = self.configWidget.toDict()
            self.dataHandler.dataSet.loadDataSet(h5file)
        self.timeImage.setExtent()
        self.energyImage.setExtent()
        self.dataHandler.sigUpdateRequest.emit(["all"])

    def show(self):
        self.viewer.show()
예제 #44
0
파일: parser.py 프로젝트: xbosch/gdais
 def quit(self):
     self.exiting = True
     QThread.quit(self)
class SensitiveLegendRaster(QObject):
    def __init__(self):
        super(SensitiveLegendRaster, self).__init__()  # QThread
        self.layer = self.worker = self.thread = None
        self.canvas = iface.mapCanvas()
        self.msgBar = iface.messageBar()
        self.legend = iface.legendInterface()
        self.nameModulus = "Script_Sensitive_Legend"
        #
        self.initThread()
        self._connect()
        #
        self.selectLayer(iface.activeLayer())

    def __del__(self):
        self.finishThread()
        self._connect(False)

    def printMsgBar(self, msg, typeMsg=QgsMessageBar.INFO):
        self.msgBar.popWidget()
        if typeMsg == QgsMessageBar.INFO:
            self.msgBar.pushMessage("SensitiveLegendRaster Script", msg, typeMsg)
        else:
            self.msgBar.pushMessage("SensitiveLegendRaster Script", msg, typeMsg, 5)

    def initThread(self):
        self.thread = QThread(self)
        self.thread.setObjectName(self.nameModulus)
        self.worker = WorkerSensitiveLegendRaster()
        self.worker.moveToThread(self.thread)
        self._connectWorker()

    def finishThread(self):
        self._connectWorker(False)
        self.worker.deleteLater()
        self.thread.wait()
        self.thread.deleteLater()
        self.thread = self.worker = None

    def _connectWorker(self, isConnect=True):
        ss = [
            {"signal": self.thread.started, "slot": self.worker.run},
            {"signal": self.worker.finished, "slot": self.finishedWorker},
            {"signal": self.worker.messageResult, "slot": self.messageResultWorker},
            {"signal": self.worker.messageStatus, "slot": self.messageStatusWorker},
        ]
        if isConnect:
            for item in ss:
                item["signal"].connect(item["slot"])
        else:
            for item in ss:
                item["signal"].disconnect(item["slot"])

    def _connect(self, isConnect=True):
        ss = [
            {"signal": self.legend.currentLayerChanged, "slot": self.selectLayer},
            {"signal": QgsMapLayerRegistry.instance().layerWillBeRemoved, "slot": self.unselectLayer},
            {"signal": self.canvas.extentsChanged, "slot": self.changeSensitiveLegend},
        ]
        if isConnect:
            for item in ss:
                item["signal"].connect(item["slot"])
        else:
            for item in ss:
                item["signal"].disconnect(item["slot"])

    @pyqtSlot()
    def finishedWorker(self):
        self.thread.quit()
        if self.worker.isKilled:  # When PAN/ZOOM/...
            self.thread.wait()
            self.changeSensitiveLegend()

    @pyqtSlot(str)
    def messageResultWorker(self, msg):
        self.printMsgBar(msg)

    @pyqtSlot(str)
    def messageStatusWorker(self, msg):
        self.printMsgBar(msg)

    @pyqtSlot("QgsMapLayer")
    def selectLayer(self, layer):

        if self.thread.isRunning():
            return

        isOk = True
        msg = ""
        typeMsg = QgsMessageBar.WARNING
        if not layer is None and layer.type() == QgsMapLayer.RasterLayer:
            legendColorAll = layer.legendSymbologyItems()
            if len(legendColorAll) > 0:  # Had a classification
                self.layer = layer
                self.worker.setLegendReadBlock(layer)
                msg = "Raster Layer '%s' actived" % layer.name()
                typeMsg = QgsMessageBar.INFO
            else:
                msg = "Raster Layer '%s' need be a classification" % layer.name()
                isOk = False
        else:
            if layer is None:
                msg = "Active a Raster layer"
            else:
                msg = "Layer '%s' need be a Raster" % layer.name()
            isOk = False

        self.printMsgBar(msg, typeMsg)

        return isOk

    @pyqtSlot(str)
    def unselectLayer(self, idLayer):
        if idLayer == self.layer.id():
            if self.thread.isRunning():
                self.worker.isKilled = True
            msg = "Raster Layer '%s' was removed" % self.layer.name()
            self.printMsgBar(msg, QgsMessageBar.WARNING)
            self.layer = None

    @pyqtSlot()
    def changeSensitiveLegend(self):

        if self.layer is None:
            return

        if self.thread.isRunning():
            self.worker.isKilled = True
            return

        mapSettings = self.canvas.mapSettings()
        crsCanvas = mapSettings.destinationCrs()
        extentCanvas = self.canvas.extent()

        extentLayer = self.layer.extent()
        resX = self.layer.rasterUnitsPerPixelX()
        resY = self.layer.rasterUnitsPerPixelY()

        if self.layer.crs() != crsCanvas:
            extentCanvas = mapSettings.mapToLayerCoordinates(self.layer, extentCanvas)

        if not extentCanvas.intersects(extentLayer):
            self.printMsgBar("View not intersects Raster '%s'" % self.layer.name, QgsMessageBar.WARNING)
            return

        keysLegend = range(len(self.worker.legendAll))  # [ idClass1, idClass2, ... ] [ 0..N-1]

        if extentCanvas == extentLayer or extentCanvas.contains(extentLayer):
            legendsView = map(lambda x: "(%s)%s" % (x, self.worker.legendAll[x]), keysLegend)
            msg = "[%d] = %s" % (len(legendsView), " ".join(legendsView))
            self.printMsgBar(msg)
            return

        extent = extentCanvas.intersect(extentLayer)
        widthRead = int(extent.width() / resX) + 1
        heightRead = int(extent.height() / resY) + 1

        self.worker.setProcessImage(extent, widthRead, heightRead)
        self.thread.start()
예제 #46
0
class AbstractBuildRunner(QObject):
    """
    Base class to run a build.

    Create the required test runner and build manager, along with a thread
    that should be used for blocking tasks.
    """
    running_state_changed = Signal(bool)
    worker_created = Signal(object)
    worker_class = None

    def __init__(self, mainwindow):
        QObject.__init__(self)
        self.mainwindow = mainwindow
        self.thread = None
        self.worker = None
        self.pending_threads = []
        self.test_runner = None
        self.download_manager = None
        self.options = None
        self.stopped = False

    def init_worker(self, fetch_config, options):
        """
        Create and initialize the worker.

        Should be subclassed to configure the worker, and should return the
        worker method that should start the work.
        """
        self.options = options

        # global preferences
        global_prefs = get_prefs()
        self.global_prefs = global_prefs
        # apply the global prefs now
        apply_prefs(global_prefs)

        if fetch_config.is_nightly():
            fetch_config.set_base_url(global_prefs['archive_base_url'])

        download_dir = global_prefs['persist']
        if not download_dir:
            download_dir = self.mainwindow.persist
        persist_limit = int(
            abs(global_prefs['persist_size_limit']) * 1073741824)
        self.download_manager = GuiBuildDownloadManager(
            download_dir, persist_limit)
        self.test_runner = GuiTestRunner()
        self.thread = QThread()

        # options for the app launcher
        launcher_kwargs = {}
        for name in ('profile', 'preferences'):
            if name in options:
                value = options[name]
                if value:
                    launcher_kwargs[name] = value

        # add add-ons paths to the app launcher
        launcher_kwargs['addons'] = options['addons']
        self.test_runner.launcher_kwargs = launcher_kwargs

        if options['profile_persistence'] in ('clone-first',
                                              'reuse') or options['profile']:
            launcher_kwargs['cmdargs'] = launcher_kwargs.get(
                'cmdargs', []) + ['--allow-downgrade']

        self.worker = self.worker_class(fetch_config, self.test_runner,
                                        self.download_manager)
        # Move self.bisector in the thread. This will
        # allow to the self.bisector slots (connected after the move)
        # to be automatically called in the thread.
        self.worker.moveToThread(self.thread)
        self.worker_created.emit(self.worker)

    def start(self, fetch_config, options):
        action = self.init_worker(fetch_config, options)
        assert callable(action), "%s should be callable" % action
        self.thread.start()
        # this will be called in the worker thread.
        QTimer.singleShot(0, action)
        self.stopped = False
        self.running_state_changed.emit(True)

    @Slot()
    def stop(self, wait=True):
        self.stopped = True
        if self.options:
            if self.options['profile'] and \
               self.options['profile_persistence'] == 'clone-first':
                self.options['profile'].cleanup()
        if self.download_manager:
            self.download_manager.cancel()
        if self.thread:
            self.thread.quit()

        if wait:
            if self.download_manager:
                self.download_manager.wait(raise_if_error=False)
            if self.thread:
                # wait for thread(s) completion - this is the case when
                # user close the application
                self.thread.wait()
                for thread in self.pending_threads:
                    thread.wait()
            self.thread = None
        elif self.thread:
            # do not block, just keep track of the thread - we got here
            # when user uses the stop button.
            self.pending_threads.append(self.thread)
            self.thread.finished.connect(self._remove_pending_thread)

        if self.test_runner:
            self.test_runner.finish(None)
        self.running_state_changed.emit(False)
        log('Stopped')

    @Slot()
    def _remove_pending_thread(self):
        for thread in self.pending_threads[:]:
            if thread.isFinished():
                self.pending_threads.remove(thread)
예제 #47
0
class XdkWindow(QMainWindow):
    """ """
    loadFileRequested = Signal(str)
    
    def __init__( self, parent = None ):
        super(XdkWindow, self).__init__( parent )
        
        # load the user interface
        projexui.loadUi(__file__, self)
        
        # define custom properties
        self._currentContentsIndex = -1
        self._worker = XdkWorker()
        self._workerThread = QThread()
        self._worker.moveToThread(self._workerThread)
        self._workerThread.start()
        
        # set default properties
        self.setAcceptDrops(True)
        self.setAttribute( Qt.WA_DeleteOnClose )
        self.uiFindNextBTN.setDefaultAction(self.uiFindNextACT)
        self.uiFindPrevBTN.setDefaultAction(self.uiFindPrevACT)
        self.uiFindWIDGET.setVisible(False)
        self.uiSearchWEB.page().setLinkDelegationPolicy(
                                            QWebPage.DelegateAllLinks)
        
        self.refreshUi()
        
        # connect widgets
        self.uiContentsTAB.currentChanged.connect(self.refreshUi)
        self.uiContentsTAB.tabCloseRequested.connect(self.closeContentsWidget)
        self.uiContentsTREE.itemExpanded.connect(self.loadItem)
        self.uiContentsTREE.itemSelectionChanged.connect(self.refreshContents)
        self.uiSearchTXT.returnPressed.connect(self.search)
        self.uiSearchWEB.linkClicked.connect(self.gotoUrl)
        self.uiIndexTREE.itemSelectionChanged.connect(self.refreshFromIndex)
        
        # connect find actions
        self.uiBackACT.triggered.connect(self.goBack)
        self.uiForwardACT.triggered.connect(self.goForward)
        self.uiHomeACT.triggered.connect(self.goHome )
        self.uiFindTXT.textChanged.connect( self.findNext )
        self.uiFindTXT.returnPressed.connect( self.findNext )
        self.uiFindNextACT.triggered.connect( self.findNext )
        self.uiFindPrevACT.triggered.connect( self.findPrev )
        self.uiFindACT.triggered.connect(self.showFind)
        self.uiFindCloseBTN.clicked.connect(self.uiFindWIDGET.hide)
        self.uiCopyTextACT.triggered.connect( self.copyText )
        
        # connect zoom actions
        self.uiZoomResetACT.triggered.connect( self.zoomReset )
        self.uiZoomInACT.triggered.connect( self.zoomIn )
        self.uiZoomOutACT.triggered.connect( self.zoomOut )
        
        # connect file actions
        self.uiLoadACT.triggered.connect( self.loadFilename )
        self.uiNewTabACT.triggered.connect( self.addContentsWidget )
        self.uiCloseTabACT.triggered.connect( self.closeContentsWidget )
        self.uiQuitACT.triggered.connect( self.close )
        
        # connect the signals
        self.loadFileRequested.connect(self._worker.loadFile)
        self._worker.loadingFinished.connect(self.__addXdkItem)
        QApplication.instance().aboutToQuit.connect(self.__cleanupWorker)
    
    def __del__(self):
        self.__cleanupWorker()
    
    def __addXdkItem(self, filename):
        item = XdkItem(filename)
        
        # add the xdk content item
        self.uiContentsTREE.addTopLevelItem(item)
        
        # add the index list items
        self.uiIndexTREE.blockSignals(True)
        self.uiIndexTREE.setUpdatesEnabled(False)
        for name, url in item.indexlist():
            item = XTreeWidgetItem([name])
            item.setToolTip(0, url)
            item.setFixedHeight(22)
            self.uiIndexTREE.addTopLevelItem(item)
        self.uiIndexTREE.blockSignals(False)
        self.uiIndexTREE.setUpdatesEnabled(True)
        self.uiIndexTREE.sortByColumn(0, Qt.AscendingOrder)
        
        self.unsetCursor()
    
    def __cleanupWorker(self):
        if self._workerThread is None:
            return
            
        self._workerThread.quit()
        self._workerThread.wait()
        
        self._worker.deleteLater()
        self._workerThread.deleteLater()
        
        self._worker = None
        self._workerThread = None
    
    def __gotoUrl(self, url):
        if url.toLocalFile():
            self.gotoUrl(url.toString())
        else:
            webbrowser.open(str(url.toString()))
    
    def addContentsWidget( self ):
        """
        Adds a new contents widget tab into the contents tab.
        
        :return     <QWebView>
        """
        curr_widget = self.currentContentsWidget()
        widget = QWebView(self)
        page = widget.page()
        page.setLinkDelegationPolicy(page.DelegateAllLinks)
            
        self.uiContentsTAB.blockSignals(True)
        self.uiContentsTAB.addTab(widget, 'Documentation')
        self.uiContentsTAB.setCurrentIndex(self.uiContentsTAB.count() - 1)
        self.uiContentsTAB.blockSignals(False)
        
        self._currentContentsIndex = self.uiContentsTAB.count() - 1
        
        if curr_widget:
            widget.setUrl(curr_widget.url())
        
        widget.titleChanged.connect(self.refreshUi)
        widget.linkClicked.connect(self.__gotoUrl)
        
        return widget
    
    def closeContentsWidget( self ):
        """
        Closes the current contents widget.
        """
        widget = self.currentContentsWidget()
        if ( not widget ):
            return
            
        widget.close()
        widget.setParent(None)
        widget.deleteLater()
    
    def copyText( self ):
        """
        Copies the selected text to the clipboard.
        """
        view = self.currentWebView()
        QApplication.clipboard().setText(view.page().selectedText())
    
    def currentContentsIndex( self ):
        """
        Returns the last index used for the contents widgets.
        
        :return     <int>
        """
        return self._currentContentsIndex
    
    def currentContentsWidget( self, autoadd = False ):
        """
        Returns the current contents widget based on the cached index.  If \
        no widget is specified and autoadd is True, then a new widget will \
        be added to the tab.
        
        :param      autoadd | <bool>
        
        :return     <QWebView>
        """
        widget = self.uiContentsTAB.widget(self.currentContentsIndex())
        if ( not isinstance(widget, QWebView) ):
            widget = None
        
        if ( not widget and autoadd ):
            widget = self.addContentsWidget()
        
        return widget
    
    def currentWebView(self):
        return self.uiContentsTAB.currentWidget()
    
    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
    
    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
    
    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            for url in event.mimeData().urls():
                self.loadFilename(str(url.toLocalFile()))
    
    def findNext( self ):
        """
        Looks for the previous occurance of the current search text.
        """
        text = self.uiFindTXT.text()
        view = self.currentWebView()
        
        options =  QWebPage.FindWrapsAroundDocument
        
        if ( self.uiCaseSensitiveCHK.isChecked() ):
            options |= QWebPage.FindCaseSensitively
        
        view.page().findText(text, options)
    
    def findPrev( self ):
        """
        Looks for the previous occurance of the current search text.
        """
        text = self.uiFindTXT.text()
        view = self.currentWebView()
        
        options =  QWebPage.FindWrapsAroundDocument
        options |= QWebPage.FindBackward
        
        if ( self.uiCaseSensitiveCHK.isChecked() ):
            options |= QWebPage.FindCaseSensitively
        
        view.page().findText(text, options)
    
    def findXdk( self, name ):
        """
        Looks up the xdk item based on the current name.
        
        :param      name | <str>
        
        :return     <XdkItem> || None
        """
        for i in range(self.uiContentsTREE.topLevelItemCount()):
            item = self.uiContentsTREE.topLevelItem(i)
            if ( item.text(0) == name ):
                return item
        return None
    
    def goBack( self ):
        widget = self.currentContentsWidget()
        if ( widget ):
            widget.page().history().back()
    
    def goForward( self ):
        widget = self.currentContentsWidget()
        if ( widget ):
            widget.page().history().forward()
    
    def goHome( self ):
        widget = self.currentContentsWidget()
        if ( widget ):
            widget.history().goHome()
    
    def gotoUrl(self, url):
        if not QApplication.keyboardModifiers() == Qt.ControlModifier:
            widget = self.currentContentsWidget(autoadd = True)
        else:
            widget = self.addContentsWidget()
        
        index = self.uiContentsTAB.indexOf(widget)
        self.uiContentsTAB.setCurrentIndex(index)
        widget.setUrl(QUrl(url))
    
    def gotoItem(self, path):
        """
        Goes to a particular path within the XDK.
        
        :param      path | <str>
        """
        if not path:
            return
        
        sections = str(path).split('/')
        check = projex.text.underscore(sections[0])
        
        for i in range(self.uiContentsTREE.topLevelItemCount()):
            item = self.uiContentsTREE.topLevelItem(i)
            if projex.text.underscore(item.text(1)) == check:
                item.gotoItem('/'.join(sections[1:]))
                break
    
    def loadItem( self, item ):
        """
        Loads the inputed item.
        
        :param      item | <QTreeWidgetItem>
        """
        if isinstance(item, XdkEntryItem):
            item.load()
    
    def loadedFilenames( self ):
        """
        Returns a list of all the xdk files that are currently loaded.
        
        :return     [<str>, ..]
        """
        output = []
        for i in range(self.uiContentsTREE.topLevelItemCount()):
            item = self.uiContentsTREE.topLevelItem(i)
            output.append(str(item.filepath()))
        return output
    
    def loadFilename( self, filename = '' ):
        """
        Loads a new XDK file into the system.
        
        :param      filename | <str>
        
        :return     <bool> | success
        """
        if ( not (filename and isinstance(filename, basestring)) ):
            filename = QFileDialog.getOpenFileName( self,
                                                    'Open XDK File',
                                                    QDir.currentPath(),
                                                    'XDK Files (*.xdk)' )
            
            if type(filename) == tuple:
                filename = str(filename[0])
            
            if not filename:
                return False
        
        if not (filename and os.path.exists(filename)):
            return False
        
        elif filename in self.loadedFilenames():
            return False
        
        self.loadFileRequested.emit(filename)
        self.setCursor(Qt.WaitCursor)
        
        return True
    
    def refreshFromIndex( self ):
        """
        Refreshes the documentation from the selected index item.
        """
        item = self.uiIndexTREE.currentItem()
        if ( not item ):
            return
        
        self.gotoUrl(item.toolTip(0))
    
    def refreshContents( self ):
        """
        Refreshes the contents tab with the latest selection from the browser.
        """
        item = self.uiContentsTREE.currentItem()
        if not isinstance(item, XdkEntryItem):
           return
        
        item.load()
        url = item.url()
        if url:
            self.gotoUrl(url)
    
    def refreshUi( self ):
        """
        Refreshes the interface based on the current settings.
        """
        widget      = self.uiContentsTAB.currentWidget()
        is_content  = isinstance(widget, QWebView)
        
        if is_content:
            self._currentContentsIndex = self.uiContentsTAB.currentIndex()
            history = widget.page().history()
        else:
            history = None
        
        self.uiBackACT.setEnabled(is_content and history.canGoBack())
        self.uiForwardACT.setEnabled(is_content and history.canGoForward())
        self.uiHomeACT.setEnabled(is_content)
        self.uiNewTabACT.setEnabled(is_content)
        self.uiCopyTextACT.setEnabled(is_content)
        self.uiCloseTabACT.setEnabled(is_content and
                                      self.uiContentsTAB.count() > 2)
        
        for i in range(1, self.uiContentsTAB.count()):
            widget = self.uiContentsTAB.widget(i)
            self.uiContentsTAB.setTabText(i, widget.title())
    
    def search( self ):
        """
        Looks up the current search terms from the xdk files that are loaded.
        """
        QApplication.instance().setOverrideCursor(Qt.WaitCursor)
        
        terms = str(self.uiSearchTXT.text())
        
        html = []
        
        entry_html = '<a href="%(url)s">%(title)s</a><br/>'\
                     '<small>%(url)s</small>'
        
        for i in range(self.uiContentsTREE.topLevelItemCount()):
            item = self.uiContentsTREE.topLevelItem(i)
            
            results = item.search(terms)
            results.sort(lambda x, y: cmp(y['strength'], x['strength']))
            for item in results:
                html.append( entry_html % item )
        
        if ( not html ):
            html.append('<b>No results were found for %s</b>' % terms)
        
        self.uiSearchWEB.setHtml(SEARCH_HTML % '<br/><br/>'.join(html))
        
        QApplication.instance().restoreOverrideCursor()
    
    def showFind( self ):
        self.uiFindWIDGET.show()
        self.uiFindTXT.setFocus()
        self.uiFindTXT.selectAll()
    
    def zoomIn( self ):
        view = self.currentWebView()
        view.setZoomFactor(view.zoomFactor() + 0.1)
    
    def zoomOut( self ):
        view = self.currentWebView()
        view.setZoomFactor(view.zoomFactor() - 0.1)
    
    def zoomReset( self ):
        view = self.currentWebView()
        view.setZoomFactor(1)
    
    @staticmethod
    def browse( parent, filename = '' ):
        """
        Creates a new XdkWidnow for browsing an XDK file.
        
        :param      parent      | <QWidget>
                    filename    | <str>
        """
        dlg = XdkWindow(parent)
        dlg.show()
        
        if ( filename ):
            dlg.loadFilename(filename)
예제 #48
0
class AbbyyOcr(QObject):
    # Signals
    error = pyqtSignal(str)

    def __init__(self, abbyy_path, parent=None):
        super(AbbyyOcr, self).__init__(parent)

        self.abbyy_path = abbyy_path
        self.app_watcher = None
        self.proc = None
        self.current_profile = None

    def ocr(self, path):
        options = ['/OptionsFile', self.current_profile] if self.current_profile else []
        args = [self.abbyy_path, path] + options + ['/send', 'Acrobat']

        startup_info = subprocess.STARTUPINFO()
        startup_info.dwFlags |= subprocess.STARTF_USESHOWWINDOW

        self.proc = subprocess.Popen(args, startupinfo=startup_info)

        self.app_watcher_thread = QThread()

        self.app_watcher = AppWatcher(self.proc)
        self.app_watcher.moveToThread(self.app_watcher_thread)
        self.app_watcher.error.connect(self.emit_error)

        self.app_watcher_thread.started.connect(self.app_watcher.start)
        self.app_watcher_thread.finished.connect(self.app_watcher_thread.deleteLater)
        self.app_watcher_thread.start()

    def kill(self):
        print 'Killing...'
        try:
            abbyy_temp_path = self.app_watcher.current_temp_path
            if not abbyy_temp_path:
                abbyy_temp_path = get_abbyy_temp_folder(self.pid)
            self.proc.kill()
            self.proc.wait()
            self.proc = None
        except AttributeError:
            # The process has already been deleted.
            abbyy_temp_path = None

        try:
            self.app_watcher.deleteLater()
            self.app_watcher_thread.quit()
            self.app_watcher_thread.wait()
        except (RuntimeError, AttributeError):
            # self.app_watcher already deleted.
            pass

        # Try to remove temp files.
        if abbyy_temp_path:
            print 'Removing', abbyy_temp_path
            os.chmod(abbyy_temp_path, stat.S_IWRITE)
            try:
                rmtree(abbyy_temp_path)
                map(os.remove, glob.glob('{0:s}/*.tmp'.format(os.path.join(tempfile.gettempdir(), 'FineReader10'))))
            except (OSError, IOError, WindowsError):
                pass
        print 'Killed'

    def emit_error(self, error_message):
        self.kill()
        self.error.emit(error_message)
예제 #49
0
class CatalogOTF(QObject):

    # Signals
    settedLayer = pyqtSignal("QgsVectorLayer")
    removedLayer = pyqtSignal(str)
    killed = pyqtSignal(str)
    changedNameLayer = pyqtSignal(str, str)
    changedTotal = pyqtSignal(str, str)
    changedIconRun = pyqtSignal(str, bool)

    def __init__(self, iface, tableCOTF):
        def connecTableCOTF():
            self.settedLayer.connect(tableCOTF.insertRow)
            self.removedLayer.connect(tableCOTF.removeRow)
            self.changedNameLayer.connect(tableCOTF.changedNameLayer)
            self.changedTotal.connect(tableCOTF.changedTotal)
            self.changedIconRun.connect(tableCOTF.changedIconRun)
            self.killed.connect(tableCOTF.killed)

        super(CatalogOTF, self).__init__()
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self.ltv = iface.layerTreeView()
        self.model = self.ltv.layerTreeModel()
        self.ltgRoot = QgsProject.instance().layerTreeRoot()
        self.msgBar = iface.messageBar()
        self.legendTMS = LegendTMS('Catalog OTF')
        self.legendRaster = LegendRaster('Catalog OTF')

        self._initThread()

        connecTableCOTF()
        self.model.dataChanged.connect(self.dataChanged)
        QgsMapLayerRegistry.instance().layersWillBeRemoved.connect(
            self.layersWillBeRemoved)  # Catalog layer removed

        self.layer = self.layerName = self.nameFieldSource = self.nameFieldDate = None
        self.ltgCatalog = self.ltgCatalogName = self.visibleSourceLayers = self.hasCanceled = None

    def __del__(self):
        self._finishThread()
        del self.legendTMS
        del self.legendRaster
        QgsMapLayerRegistry.instance().layersWillBeRemoved.disconnect(
            self.layersWillBeRemoved)  # Catalog layer removed

    def _initThread(self):
        self.thread = QThread(self)
        self.thread.setObjectName("QGIS_Plugin_%s" %
                                  NAME_PLUGIN.replace(' ', '_'))
        self.worker = WorkerPopulateGroup(self.addLegendLayerWorker)
        self.worker.moveToThread(self.thread)
        self._connectWorker()

    def _finishThread(self):
        self._connectWorker(False)
        self.worker.deleteLater()
        self.thread.wait()
        self.thread.deleteLater()
        self.thread = self.worker = None

    def _connectWorker(self, isConnect=True):
        ss = [{
            'signal': self.thread.started,
            'slot': self.worker.run
        }, {
            'signal': self.worker.finished,
            'slot': self.finishedPG
        }, {
            'signal': self.worker.messageStatus,
            'slot': self.messageStatusPG
        }, {
            'signal': self.worker.messageError,
            'slot': self.messageErrorPG
        }]
        if isConnect:
            for item in ss:
                item['signal'].connect(item['slot'])
        else:
            for item in ss:
                item['signal'].disconnect(item['slot'])

    def addLegendLayerWorker(self, layer):
        if layer.type() == QgsMapLayer.RasterLayer:
            metadata = layer.metadata()
            if metadata.find("GDAL provider") != -1:
                if metadata.find("OGC Web Map Service") != -1:
                    if self.legendTMS.hasTargetWindows(layer):
                        self.legendTMS.setLayer(layer)
                else:
                    self.legendRaster.setLayer(layer)

    def run(self):
        self.hasCanceled = False  # Check in finishedPG

        if self.thread.isRunning():
            self.worker.kill()
            self.hasCanceled = True
            msgtrans = QCoreApplication.translate(
                "CatalogOTF", "Canceled search for image from layer %s")
            msg = msgtrans % self.layerName
            self.msgBar.pushMessage(NAME_PLUGIN, msg, QgsMessageBar.WARNING, 2)
            self.changedTotal.emit(self.layer.id(), "Canceling processing")
            self.killed.emit(self.layer.id())
            return

        if self.layer is None:
            msgtrans = QCoreApplication.translate("CatalogOTF",
                                                  "Need define layer catalog")
            self.msgBar.pushMessage(NAME_PLUGIN, msgtrans,
                                    QgsMessageBar.WARNING, 2)
            return

        self._setGroupCatalog()
        self.ltgCatalogName = self.ltgCatalog.name()

        renderFlag = self.canvas.renderFlag()
        if renderFlag:
            self.canvas.setRenderFlag(False)
            self.canvas.stopRendering()

        self._populateGroupCatalog()

        if renderFlag:
            self.canvas.setRenderFlag(True)
            self.canvas.refresh()

    def _populateGroupCatalog(self):
        def getSourceVisibleLayers():
            def hasVisibleRaster(ltl):
                return ltl.isVisible() == Qt.Checked and ltl.layer().type(
                ) == QgsMapLayer.RasterLayer

            l_ltlVisible = filter(lambda item: hasVisibleRaster(item),
                                  self.ltgCatalog.findLayers())
            return map(lambda item: item.layer().source(), l_ltlVisible)

        def runWorker():
            data = {}
            data['nameFieldDate'] = self.nameFieldDate
            data['nameFieldSource'] = self.nameFieldSource
            data['layer'] = self.layer
            data['ltgCatalog'] = self.ltgCatalog
            self.worker.setData(data)
            self.thread.start()
            #self.worker.run() # DEBUG

        self.visibleSourceLayers = getSourceVisibleLayers()
        self.ltgCatalog.removeAllChildren()
        runWorker()  # See finishPG

    def _setGroupCatalog(self):
        self.ltgCatalogName = "%s - Catalog" % self.layer.name()
        self.ltgCatalog = self.ltgRoot.findGroup(self.ltgCatalogName)
        if self.ltgCatalog is None:
            self.ltgCatalog = self.ltgRoot.addGroup(self.ltgCatalogName)

    @pyqtSlot(bool)
    def finishedPG(self, isKilled):
        def setSourceVisibleLayers():
            l_ltlVisible = filter(
                lambda item: item.layer().source() in self.visibleSourceLayers,
                self.ltgCatalog.findLayers())
            map(lambda item: item.setVisible(Qt.Checked), l_ltlVisible)

        self.thread.quit()

        if not self.layer is None:
            self.changedIconRun.emit(self.layer.id(),
                                     self.layer.selectedFeatureCount() > 0)
            if self.hasCanceled:
                self.changedTotal.emit(self.layer.id(), '0')
            else:
                setSourceVisibleLayers()

        del self.visibleSourceLayers[:]

    @pyqtSlot(str)
    def messageStatusPG(self, msg):
        self.changedTotal.emit(self.layer.id(), msg)

    @pyqtSlot(str)
    def messageErrorPG(self, msg):
        self.msgBar.pushMessage(NAME_PLUGIN, msg, QgsMessageBar.CRITICAL, 8)

    @pyqtSlot('QModelIndex', 'QModelIndex')
    def dataChanged(self, idTL, idBR):
        if idTL != idBR:
            return

        if not self.ltgCatalog is None and self.ltgCatalog == self.model.index2node(
                idBR):
            name = self.ltgCatalog.name()
            if self.ltgCatalogName != name:
                self.ltgCatalogName = name
                return

        if not self.layer is None and self.ltgRoot.findLayer(
                self.layer.id()) == self.model.index2node(idBR):
            name = self.layer.name()
            if self.layerName != name:
                self.changedNameLayer.emit(self.layer.id(), name)
                self.layerName = name

    @pyqtSlot(list)
    def layersWillBeRemoved(self, layerIds):
        if self.layer is None:
            return
        if self.layer.id() in layerIds:
            self.removedLayer.emit(self.layer.id())
            self.removeLayerCatalog()

    @staticmethod
    def getNameFieldsCatalog(layer):
        def getFirstFeature():
            f = QgsFeature()
            #
            fr = QgsFeatureRequest(
            )  # First FID can be 0 or 1 depend of provider type
            it = layer.getFeatures(fr)
            isOk = it.nextFeature(f)
            it.close()
            #
            if not isOk or not f.isValid():
                del f
                return None
            else:
                return f

        def hasAddress(feature, nameField):
            def asValidUrl(url):
                isOk = True
                try:
                    urllib2.urlopen(url)
                except urllib2.HTTPError, e:
                    isOk = False
                except urllib2.URLError, e:
                    isOk = False
                #
                return isOk

            value = feature.attribute(nameField)
            if value is None or type(value) == QPyNullVariant:
                return False

            isUrl = value.find('http://') == 0 or value.find('https://') == 0
            lenSource = len(value)
            isUrl = isUrl and value.rfind(
                'xml', lenSource - len('xml')) == lenSource - len('xml')
            if isUrl:
                return asValidUrl(value)
            #
            fileInfo = QFileInfo(value)
            return fileInfo.isFile()
예제 #50
0
파일: threads.py 프로젝트: 3vi1/vintel
 def quit(self):
     self.active = False
     self.queue.put(None)
     QThread.quit(self)
class Gui(QtGui.QMainWindow,QtGui.QWidget):

	def __init__(self):
		super(Gui, self).__init__()
		self.speaker = ""
		self.directory = ""
		self.type = ""
		self.line=0
		self.text=[]
		self.decode=""
		self.fname="output"
		self.rec=0
		self.initUI()
		self.file = ""

	def initUI(self):
		self.setWindowIcon(QtGui.QIcon('logo.png'))
		self.vr = VoiceRec()
		self.pl = Play()
		self.vrThread = QThread()
		self.plThread = QThread()
		self.vr.moveToThread(self.vrThread)
		self.pl.moveToThread(self.plThread)

		self.figure = plt.figure(1)
		self.canvas = FigureCanvas(self.figure)
		self.toolbar = NavigationToolbar(self.canvas, self)
		self.centralwidget = QtGui.QWidget(self)
		self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
		self.verticalLayout.addWidget(self.toolbar)
		self.verticalLayout.addWidget(self.canvas)
		self.centralwidget.setGeometry(10,10,825,330)

		openFile = QtGui.QAction(QtGui.QIcon('open.png'), '&Open', self)
		openFile.setShortcut('Ctrl+O')
		openFile.setStatusTip('Open new File')
		openFile.triggered.connect(self.showDialogOpen)

		chUser = QtGui.QAction('&Change Speaker', self)
		chUser.setStatusTip('Change Speaker')
		chUser.triggered.connect(self.changeUser)

		exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Exit', self)
		exitAction.setShortcut('Ctrl+Q')
		exitAction.setStatusTip('Exit application')
		exitAction.triggered.connect(self.closeEvent)

		utf_8 = QtGui.QAction('&UTF-8', self)
		utf_8.setStatusTip('utf-8')
		utf_8.triggered.connect(self.encodeUTF8)

		utf_16 = QtGui.QAction('&UTF-16', self)
		utf_16.setStatusTip('utf-16')
		utf_16.triggered.connect(self.encodeUTF16)

		Ascii = QtGui.QAction('&ASCII', self)
		Ascii.setStatusTip('ascii')
		Ascii.triggered.connect(self.encodeASCII)

		about = QtGui.QAction('&About', self)
		about.setStatusTip('More About Voice Recorder')
		about.triggered.connect(self.showAbout)

		self.textEdit = QtGui.QTextEdit(self)
		self.textEdit.setGeometry(10,360,825,104)
		self.textEdit.setStyleSheet("QTextEdit {font-size: 14pt}")
		self.textEdit.setText("Please Open a File...")
		self.textEdit.setReadOnly(True)

		self.Open = QtGui.QPushButton('Open', self)
		self.Open.move(10,480)
		self.Open.clicked.connect(self.showDialogOpen)

		self.Record = QtGui.QPushButton('Record', self)
		self.Record.move(155,480)
		self.Record.setEnabled(False)
		self.Record.clicked.connect(self.record)

		self.Stop = QtGui.QPushButton('Stop', self)
		self.Stop.move(300,480)
		self.Stop.setEnabled(False)
		self.Stop.clicked.connect(self.stop)

		self.Play = QtGui.QPushButton('Play', self)
		self.Play.move(445,480)
		self.Play.setEnabled(False)
		self.Play.clicked.connect(self.play)

		self.Back = QtGui.QPushButton('Back', self)
		self.Back.move(590,480)
		self.Back.setEnabled(False)
		self.Back.clicked.connect(self.showBack)

		self.Next = QtGui.QPushButton('Next', self)
		self.Next.move(735,480)
		self.Next.setEnabled(False)
		self.Next.clicked.connect(self.showNext)

		menubar = self.menuBar()
		fileMenu = menubar.addMenu('&File')
		fileMenu.addAction(openFile)
		fileMenu.addAction(chUser)
		fileMenu.addAction(exitAction)
		encodeMenu = menubar.addMenu('&Encoding')
		encodeMenu.addAction(Ascii)
		encodeMenu.addAction(utf_8)
		encodeMenu.addAction(utf_16)
		helpMenu = menubar.addMenu('&Help')
		helpMenu.addAction(about)

		self.setGeometry(200,200, 845, 550)
		self.setFixedSize(845 , 550)
		self.setWindowTitle('Akshar Voice Recorder')
		self.user = User(self)

	def showDialogOpen(self):
		plt.clf()
		self.canvas.draw()
		self.statusBar().showMessage('Open a File')
		self.fname = QtGui.QFileDialog.getOpenFileName(self, 'Open file')
		if(self.fname!=""):
			self.Record.setEnabled(True)
			self.Play.setEnabled(True)
			self.Next.setEnabled(True)
			self.Back.setEnabled(True)
			self.directory=str(self.file)+"/"+str(self.speaker)+"_"+str(self.type)+"_"+str(self.fname).split("/")[-1]
			if not os.path.exists(self.directory):
				os.makedirs(self.directory)
			del self.text[:]
			f = open(self.fname, 'r')
			for lines in f:
				self.text.append(lines)
			f.close
			if(self.decode!=""):
				self.textEdit.setText(self.text[self.line].decode(self.decode))
			else:
				self.textEdit.setText(self.text[self.line].decode('ascii'))
			self.line=0
		else:
			self.Record.setEnabled(False)
			self.Play.setEnabled(False)
			self.Next.setEnabled(False)
			self.Back.setEnabled(False)
		self.statusBar().showMessage('')

	def showNext(self):
		plt.clf()
		self.canvas.draw()
		self.line+=1
		if(len(self.text)>self.line):
			if(self.decode!=""):
				self.textEdit.setText(self.text[self.line].decode(self.decode))
			else:
				self.textEdit.setText(self.text[self.line].decode('utf-8'))
		else:
			self.showDialogOpen()

	def showBack(self):
		plt.clf()
		self.canvas.draw()
		self.line-=1
		if(len(self.text)>=self.line and self.line>=0):
			if(self.decode!=""):
				self.textEdit.setText(self.text[self.line].decode(self.decode))
			else:
				self.textEdit.setText(self.text[self.line].decode('utf-8'))
		else:
			self.showDialogOpen()

	def showAbout(self):
		self.popup1=About()
		self.popup1.exec_()

	def encodeUTF8(self):
		self.decode="utf-8"

	def encodeUTF16(self):
		self.decode="utf-16"

	def encodeASCII(self):
		self.decode="ascii"

	def changeUser(self):
		self.user.__init__(self)

	def record(self):
		plt.clf()
		self.canvas.draw()
		self.statusBar().showMessage('Recording')
		self.rec=1
		self.Record.setEnabled(False)
		self.Stop.setEnabled(True)
		self.Open.setEnabled(False)
		self.Play.setEnabled(False)
		self.Next.setEnabled(False)
		self.Back.setEnabled(False)
		self.vrThread.start()
		self.vr.record(self.directory, self.text[self.line].split(")")[0], self)

	def stop(self):
		self.statusBar().showMessage('')
		if self.rec == 1:
			self.vr.stop()
			self.vrThread.exit()
			self.vrThread.wait()
			self.vrThread.quit()
		elif self.rec == 2:
			self.pl.stop()
			self.plThread.exit()
			self.plThread.wait()
			self.plThread.quit()
		self.Record.setEnabled(True)
		self.Open.setEnabled(True)
		self.Play.setEnabled(True)
		self.Next.setEnabled(True)
		self.Back.setEnabled(True)
		self.rec=0

	def play(self):
		self.statusBar().showMessage('Playing')
		self.rec=2
		self.Record.setEnabled(False)
		self.Stop.setEnabled(True)
		self.Open.setEnabled(False)
		self.Play.setEnabled(False)
		self.Next.setEnabled(False)
		self.Back.setEnabled(False)
		self.plThread.start()
		self.pl.play(self.text[self.line].split(")")[0], self)
예제 #52
0
 def quit(self):
     self.jobs = {}
     QThread.quit(self)
예제 #53
0
 def quit(self):
     QThread.quit(self)
예제 #54
0
class MainWindow(QMainWindow):
    """
    MainWindow widget.
    Connects GUI and worker threads.

    Inherits from:
    QMainWindow

    Buttons:
    None

    Signals:
    None
    """
    def __init__(self,
                 content_gui,
                 content_pipeline,
                 settings_folder,
                 mount_directory,
                 version,
                 parent=None):
        """
        Setup the layout for the widget

        Arguments:
        content_gui - Content used to create the GUI outfit.
        content_pipeline - Content used to start processing threads.
        settings_folder - Name of the folder containing settings.
        mount_directory - Name of the folder containing mount points.
        version - Version of TranSPHIRE.
        parent - Parent widget (default None)

        Return:
        None
        """
        super(MainWindow, self).__init__(parent)

        # Ask for sudo password if needed
        self.password = ''
        need_sudo_password = False
        for content in content_gui:
            if content['name'] == 'Status':
                for entry in content['content']:
                    for widget in entry:
                        for key in widget:
                            if key == 'Mount/umount needs sudo password?':
                                if widget[key][0] == 'True':
                                    need_sudo_password = True
                                else:
                                    pass
                            else:
                                pass
            elif content['name'] == 'Mount':
                for entry in content['content_mount']:
                    for widget in entry:
                        for key in widget:
                            if key == 'Need sudo for copy?':
                                if widget[key][0] == 'True':
                                    need_sudo_password = True
                                else:
                                    pass
                            else:
                                pass
            else:
                pass

        if need_sudo_password:
            dialog = SudoPasswordDialog(self)
            dialog.exec_()
            if not dialog.result():
                QCoreApplication.instance().quit()
                sys.exit()
            else:
                self.password = dialog.password
        else:
            pass

        # Start TranSPHIRE from HOME directory.
        self.path = os.environ['HOME']

        # Window title
        self.setWindowTitle('{0} v{1} - {2} - {3}'.format(
            'TranSPHIRE', version, self.path,
            os.uname()[1]))

        # Initiate contents
        self.central_widget = None
        self.content = None
        self.layout = None

        # Settings folder
        self.settings_folder = settings_folder
        self.mount_directory = mount_directory
        self.temp_save = '{0}/temp_save'.format(settings_folder)

        # Threads
        self.mount_worker = None
        self.process_worker = None
        self.plot_worker = None
        self.mount_calculation_ssh = None
        self.mount_calculation_get = None
        self.mount_calculation_df = None
        self.thread_mount = None
        self.thread_process = None
        self.thread_plot = None
        self.mount_thread_list = None

        # Fill GUI
        self.reset_gui(content_gui=content_gui,
                       content_pipeline=content_pipeline)

    def start_threads(self, content_pipeline):
        """
        Start threads used in TranSPHIRE.

        Arguments:
        content_pipeline - Content used to start processing threads.

        Return:
        None
        """
        # Stop threads if already started.
        if self.mount_worker is not None:
            self.mount_worker.setParent(None)
        if self.process_worker is not None:
            self.process_worker.setParent(None)
        if self.plot_worker is not None:
            self.plot_worker.setParent(None)
        if self.thread_mount is not None:
            self.thread_mount.quit()
            self.thread_mount.wait()
            self.thread_mount.setParent(None)
        if self.thread_process is not None:
            self.thread_process.quit()
            self.thread_process.wait()
            self.thread_process.setParent(None)
        if self.thread_plot is not None:
            self.thread_plot.quit()
            self.thread_plot.wait()
            self.thread_plot.setParent(None)
        if self.mount_thread_list is not None:
            for setting in self.content['Mount'].get_settings():
                for key in setting:
                    thread = self.mount_thread_list[key]['thread']
                    calculator = self.mount_thread_list[key]['object']
                    calculator.kill_thread = True
                    thread.quit()
                    thread.wait()

        # Create objects used in threads
        self.mount_worker = MountWorker(password=self.password,
                                        settings_folder=self.settings_folder,
                                        mount_directory=self.mount_directory)
        self.process_worker = ProcessWorker(
            password=self.password,
            content_process=content_pipeline,
            mount_directory=self.mount_directory)
        self.plot_worker = PlotWorker()

        # Create threads
        self.thread_mount = QThread(self)
        self.thread_process = QThread(self)
        self.thread_plot = QThread(self)

        # Start threads
        self.thread_mount.start()
        self.thread_process.start()
        self.thread_plot.start()

        # Start objects in threads
        self.mount_worker.moveToThread(self.thread_mount)
        self.process_worker.moveToThread(self.thread_process)
        self.plot_worker.moveToThread(self.thread_plot)

    def reset_gui(self, content_gui, content_pipeline, load_file=None):
        """
        Reset the content of the mainwindow.

        Arguments:
        content_gui - Content used to fill the GUI.
        content_pipeline - Content used to start processing threads.
        load_file - Settings file (default None).

        Return:
        None
        """
        # Fill MainWindow
        self.set_central_widget()
        self.set_layout_structure()
        self.start_threads(content_pipeline=content_pipeline)
        postprocess_content = self.fill_content(content_gui=content_gui)
        self.postprocess_content(postprocess_content)

        for content in content_gui:
            if content['name'] == 'Status':
                for entry in content['content']:
                    for widget in entry:
                        for key in widget:
                            if key == 'Project name pattern':
                                self.project_name_pattern = widget[key][0]
                            elif key == 'Project name pattern example':
                                self.project_name_pattern_example = widget[
                                    key][0]
                            else:
                                pass
            else:
                pass

        # Load settings saved in load_file
        if load_file is not None:
            self.load(file_name=load_file)
            os.remove('{0}.txt'.format(load_file))
        elif os.path.exists('{0}.txt'.format(self.temp_save)):
            # Result is True if answer is No
            result = tu.question(head='Restore previous session.',
                                 text='Restore previous session?',
                                 parent=self)
            if result:
                pass
            else:
                self.load(file_name=self.temp_save)
        else:
            pass
        self.mount_worker.sig_load_save.emit()

    def save_temp_settings(self):
        """
        Save the status of the GUI in a temp file.

        Arguments:
        None

        Return:
        True, if saving was succesful.
        """
        if os.path.exists('{0}.txt'.format(self.temp_save)):
            os.remove('{0}.txt'.format(self.temp_save))
        else:
            pass
        value = self.save(file_name=self.temp_save, temp=True)
        return value

    def postprocess_content(self, error_list):
        """
        Do postprocessing of creating GUI content, like connecting signals.

        Arguments:
        error_list - List of errors that occured.

        Return:
        True, if saving was succesful.
        """
        for entry in error_list:
            tu.message(entry)

        self.process_worker.sig_finished.connect(self._finished)
        self.process_worker.sig_plot_ctf.connect(
            self.plot_worker.calculate_array_ctf)
        self.process_worker.sig_plot_motion.connect(
            self.plot_worker.calculate_array_motion)
        self.plot_worker.sig_message.connect(lambda msg: tu.message(msg))

        self.mount_thread_list = {}
        for key in self.content['Mount'].content:
            thread = QThread(self)
            thread.start()
            mount_calculator = MountCalculator(name=key)
            mount_calculator.moveToThread(thread)
            self.mount_thread_list[key] = {
                'thread': thread,
                'object': mount_calculator
            }
            mount_calculator.sig_finished.connect(
                self.content['Status'].refresh_quota)
            mount_calculator.sig_finished.connect(self.abort_finished)
            self.mount_worker.sig_calculate_ssh_quota.connect(
                mount_calculator.calculate_ssh_quota)
            self.mount_worker.sig_calculate_df_quota.connect(
                mount_calculator.calculate_df_quota)
            self.mount_worker.sig_calculate_get_quota.connect(
                mount_calculator.calculate_get_quota)
        self.content['Mount'].set_threadlist(
            thread_list=self.mount_thread_list)

    def abort_finished(self, *args, **kwargs):
        """
        Set the mount worker abort variable to True.

        Arguments:
        None

        Return:
        None
        """
        self.mount_worker.abort_finished = True

    def set_central_widget(self):
        """
        Reset the central widget of the MainWindow.

        Arguments:
        None

        Return:
        None
        """
        if self.central_widget is not None:
            self.central_widget.setParent(None)
        else:
            pass

        self.central_widget = QWidget(self)
        self.central_widget.setObjectName('central')
        self.setCentralWidget(self.central_widget)

    def set_layout_structure(self):
        """
        Setup the layout structure for the central widget.

        Arguments:
        None

        Return:
        None
        """
        # Layout dictionary
        self.layout = {}
        self.layout['h1'] = QHBoxLayout(self.central_widget)
        self.layout['h2'] = QHBoxLayout()
        self.layout['h3'] = QHBoxLayout()
        self.layout['v'] = QVBoxLayout()

        # Layout architecture
        self.layout['h1'].addLayout(self.layout['v'], stretch=1)
        self.layout['v'].addLayout(self.layout['h2'], stretch=0)
        self.layout['v'].addWidget(Separator(typ='horizontal', color='grey'),
                                   stretch=0)
        self.layout['v'].addLayout(self.layout['h3'], stretch=1)

    def fill_content(self, content_gui):
        """
        Fill the layouts of the central widget.

        Arguments:
        content_gui - Content used to create the GUI outfit.

        Return:
        List of errors that occured.
        """
        self.content = {}
        exclude_set = tu.get_exclude_set(content=content_gui)
        error_list = []
        tab_list = []
        for entry in content_gui:
            key = entry['name']

            if key in exclude_set:
                continue
            elif entry['layout'] in exclude_set:
                continue
            elif key == 'Stretch':
                layout = entry['layout']
                self.layout[layout].addStretch(1)
                continue
            elif key == 'Separator':
                layout = entry['layout']
                separator = entry['separator']
                self.layout[layout].addWidget(separator)
                continue
            elif key == 'Path':
                tu.reduce_path_widget(exclude_set=exclude_set,
                                      content=entry['content'])
            elif key == 'Copy':
                tu.reduce_copy_entries(exclude_set=exclude_set,
                                       content=entry['content'])
            else:
                pass

            layout = entry['layout']
            plot_labels = ''
            plot_name = ''
            try:
                plot_name = layout.replace('Plot ', '')
                plot_labels = ti.get_dtype_dict()[tu.get_function_dict()
                                                  [plot_name]['typ']]
            except KeyError:
                pass

            # Create widget
            self.content[key] = entry['widget'](
                mount_worker=self.mount_worker,
                process_worker=self.process_worker,
                plot_worker=self.plot_worker,
                settings_folder=self.settings_folder,
                plot_labels=plot_labels,
                plot_name=plot_name,
                parent=self,
                **entry)

            if isinstance(self.content[key], TabDocker):
                tab_list.append(key)
            else:
                pass

            if layout in tab_list:
                self.content[layout].add_tab(self.content[key], key)
            else:
                self.layout[layout].addWidget(self.content[key])

            if key == 'Button':
                self.content[key].sig_load.connect(self.load)
                self.content[key].sig_save.connect(self.save)
                self.content[key].sig_start.connect(self.start)
                self.content[key].sig_stop.connect(self.stop_dialog)
                self.content[key].sig_check_quota.connect(self.check_quota)
            else:
                pass

            if key == 'Notification':
                self.content[key].update_telegram()
                self.content[key].update_email()
                self.content[key].update()
                self.content[key].sig_stop.connect(self.stop)
                timer = QTimer(self)
                timer.setInterval(20000)
                timer.timeout.connect(self.content[key].get_telegram_messages)
                timer.start()
            else:
                pass

            if key == 'Plot per micrograph' or key == 'Plot histogram':
                self.plot_worker.sig_data.connect(
                    self.content[key].update_figure)
            else:
                pass

        return error_list

    def check_quota(self):
        """
        Check the quota for the project and scratch directory.

        Arguments:
        None

        Return:
        None
        """
        global_settings = self.content['General'].get_settings()
        global_settings = {'General': global_settings[0]}
        self.mount_worker.sig_set_settings.emit(global_settings)

    def load(self, file_name=None):
        """
        Load settings from settings file.

        Arguments:
        file_name - Name of the file (default None)

        Return:
        None
        """
        if file_name is None:
            file_name = QFileDialog.getOpenFileName(
                caption='Load settings',
                directory=self.path,
                options=QFileDialog.DontUseNativeDialog)

            if QT_VERSION == 4:
                file_name = file_name
            elif QT_VERSION == 5:
                file_name = file_name[0]
            else:
                raise ImportError(
                    'QT version unknown! Please contact the transphire authors!'
                )

            if not file_name:
                return
            else:
                pass

        if file_name.endswith('.txt'):
            pass
        elif os.path.exists(file_name):
            pass
        else:
            file_name = '{0}.txt'.format(file_name)

        settings = []
        with open(file_name, 'r') as read:
            for line in read:
                line = line.replace('\n', '')
                key, *value = line.split('\t')
                if isinstance(value, list):
                    settings.append([key, *value])
                else:
                    settings.append([key, value])

        settings = self.settings_to_dict(settings=settings)
        self.set_settings(settings=settings)

    def set_settings(self, settings):
        """
        Load settings from settings file.

        Arguments:
        settings - Settings as dictionary.

        Return:
        None
        """
        for key in settings:
            if key == 'End':
                continue
            else:
                try:
                    self.content[key].set_settings(settings[key])
                except KeyError:
                    print('Key', key, 'no longer exists')
                    continue

    @staticmethod
    def settings_to_dict(settings):
        """
        Make the settings readable for the widgets set settings method.

        Arguments:
        settings - Settings as dictionary.

        Return:
        None
        """
        settings_dict = {}
        idx = -1
        while idx < len(settings) - 1:
            idx += 1
            if settings[idx][0] == '###':
                key = settings[idx][1]
                if key == 'Frames':
                    settings_dict[key] = []
                else:
                    settings_dict[key] = {}
                continue

            if len(settings[idx]) == 1:
                settings[idx].append('')

            if key == 'Frames':
                setting = {}
                setting[settings[idx][0]] = settings[idx][1]
                for i in range(3):
                    idx += 1
                    setting[settings[idx][0]] = settings[idx][1]
                settings_dict[key].append(setting)
            else:
                if key == 'Notification':
                    settings_dict[key].update({
                        settings[idx][0]: [settings[idx][1], settings[idx][2]]
                    })
                else:
                    settings_dict[key].update(
                        {settings[idx][0]: settings[idx][1]})

        return settings_dict

    def save(self, file_name=None, temp=False):
        """
        Save GUI status to file.

        Arguments:
        file_name - File name to save settings to.
        temp - File is a temporary save file.

        Return:
        True, if saving was succesful.
        """
        if file_name is None:
            file_name = QFileDialog.getSaveFileName(
                caption='Save settings',
                directory=self.path,
                options=QFileDialog.DontUseNativeDialog,
                filter="Text files (*.txt)")

            if QT_VERSION == 4:
                file_name = file_name
            elif QT_VERSION == 5:
                file_name = file_name[0]
            else:
                raise ImportError(
                    'QT version unknown! Please contact the transphire authors!'
                )

            if not file_name:
                return None
            else:
                pass
        else:
            pass

        if file_name.endswith('.txt'):
            pass
        else:
            file_name = '{0}.txt'.format(file_name)

        # Do not override settings
        if os.path.exists(file_name):
            old_filename = file_name
            for number in range(9999):
                file_name = '{0}_{1}'.format(old_filename, number)
                if os.path.exists(file_name):
                    continue
                else:
                    break
        else:
            pass

        error = False
        with open(file_name, 'w') as write:
            for key in self.content:
                if key == 'Mount':
                    continue
                else:
                    pass
                try:
                    settings = self.content[key].get_settings()
                except AttributeError:
                    continue
                if settings is not None:
                    write.write('###\t{0}\n'.format(key))
                    for entry in settings:
                        for key_entry in entry:
                            write.write('{0}\t{1}\n'.format(
                                key_entry, entry[key_entry]))
                else:
                    error = True
                    message = 'Setting of {0} not valid!'.format(key)
                    tu.message(message)
                    continue
            write.write('###\tEnd\n')
            write.write('The\tEnd\n')

        message_pass = '******'.format(file_name)
        message_error = 'Invalid setting detected! Saveing failed!'
        if error:
            os.remove(file_name)
            tu.message(message_error)
            print(message_error)
            return False
        else:
            if temp:
                pass
            else:
                tu.message(message_pass)
            print(message_pass)
            return True

    @pyqtSlot()
    def start(self):
        """
        Start TranSPHIRE processing.

        Arguments:
        None

        Return:
        None
        """
        self.enable(False)
        settings = {}
        # Load settings to pass them to the working threads
        error_list = []
        skip_list = ['Mount', 'Notification', 'Path', 'Frames']
        for key in self.content:
            try:
                settings_widget = self.content[key].get_settings()
            except AttributeError:
                continue
            else:
                settings[key] = {}

            if settings_widget is None:
                self.enable(True)
                return None
            elif key == 'Frames':
                settings_motion = {}
            else:
                pass

            if key == 'Frames':
                skip_name_list = []
            else:
                skip_name_list = tu.get_function_dict()[key]['allow_empty']

            for entry in settings_widget:
                if key not in skip_list:
                    for name in entry:
                        if not entry[name] and name not in skip_name_list:
                            error_list.append(
                                '{0}:{1} is not allowed to be emtpy!'.format(
                                    key, name))
                        else:
                            pass
                else:
                    pass

            for idx, entry in enumerate(settings_widget):
                if key == 'Frames':
                    settings_motion[idx] = entry
                else:
                    settings[key].update(entry)

            if key == 'Frames':
                settings['motion_frames'] = settings_motion
            else:
                pass

        if error_list:
            tu.message('\n'.join(error_list))
            self.enable(True)
            return None
        else:
            pass

        # Get mount information
        for key in settings['Mount']:
            device_name = key.replace(' ', '_')
            save_file = os.path.join(self.settings_folder, device_name)
            try:
                with open(save_file, 'r') as read:
                    lines = read.readlines()
            except FileNotFoundError:
                continue
            for line in lines:
                name = line.split('\t')[0]
                settings['user_{0}'.format(device_name)] = name
        settings['user_Later'] = None

        if not re.match(self.project_name_pattern,
                        settings['General']['Project name']):
            self.enable(True)
            tu.message(
                'Project name needs to match pattern:\n{0}\n For example: {1}'.
                format(self.project_name_pattern,
                       self.project_name_pattern_example))
            return None
        else:
            pass

        # Project folder names
        settings['project_folder'] = os.path.join(
            settings['General']['Project directory'],
            settings['General']['Project name'])
        settings['compress_folder'] = os.path.join(
            settings['General']['Project directory'],
            settings['General']['Project name'])
        settings['motion_folder'] = os.path.join(
            settings['General']['Project directory'],
            settings['General']['Project name'])
        settings['ctf_folder'] = os.path.join(
            settings['General']['Project directory'],
            settings['General']['Project name'])
        settings['scratch_folder'] = os.path.join(
            settings['General']['Scratch directory'],
            settings['General']['Project name'])
        settings['Copy_hdd_folder'] = self.mount_directory
        settings['Copy_backup_folder'] = self.mount_directory
        settings['Copy_work_folder'] = self.mount_directory
        settings['settings_folder'] = os.path.join(settings['project_folder'],
                                                   'settings')
        settings['queue_folder'] = os.path.join(settings['project_folder'],
                                                'queue')
        settings['error_folder'] = os.path.join(settings['project_folder'],
                                                'error')

        # Check for continue mode
        if os.path.exists(settings['project_folder']):
            result = self.continue_dialog(
                text1='Output project folder already exists!',
                text2='Do you really want to continue the old run?\nType: YES!'
            )
            if result:
                result_session = self.continue_dialog(
                    text1='Software metafiles',
                    text2='Software metafiles (Atlas, ...) might be already copied!\n' + \
                        'Do you want to copy them again?\nType: YES!'
                    )
                settings['Copy_software_meta'] = bool(result_session)
            else:
                settings['Copy_software_meta'] = True
        else:
            settings['Copy_software_meta'] = True
            result = True

        # Create project and settings folder
        for name in [
                'project_folder', 'settings_folder', 'scratch_folder',
                'queue_folder', 'error_folder'
        ]:
            try:
                tu.mkdir_p(settings[name])
            except FileNotFoundError:
                tu.message('Project name cannot be empty')
                self.enable(True)
                return None

        # Start or stop procedure
        if result:
            self.content['Button'].start_button.setText('Stop')
            self.plot_worker.settings = settings
            self.process_worker.sig_start.emit(settings)
            self.mount_worker.set_settings(settings=settings)
            self.save(
                file_name=os.path.join(settings['settings_folder'],
                                       settings['General']['Project name']))
            self.save_temp_settings()
        else:
            tu.message('Input needs to be "YES!" to work')
            self.enable(True)

    def continue_dialog(self, text1, text2):
        """
        Check if the user wants to run the continue mode.

        Arguments:
        text1 - Dialog window name.
        text2 - Text of the dialog.

        Return:
        True, if the input is YES!
        """
        dialog = QInputDialog(self)
        result = dialog.getText(self, text1, text2)
        return bool(result[0] == 'YES!')

    @pyqtSlot()
    def stop_dialog(self):
        """
        Check if the user really wants to stop the process.

        Arguments:
        None

        Return:
        None
        """
        result = self.continue_dialog(
            text1='Do you really want to stop?',
            text2='Do you really want to stop!\nType: YES!')
        if result:
            self.stop()
        else:
            tu.message('Input needs to be "YES!" to work')

    @pyqtSlot()
    def stop(self):
        """
        Stop the process.

        Arguments:
        None

        Return:
        None
        """
        self.process_worker.stop = True
        self.content['Button'].start_button.setEnabled(False)

    @pyqtSlot()
    def _finished(self):
        """
        Rename the Stop Button to start and enable everything.

        Arguments:
        None

        Return:
        None
        """
        self.enable(True)
        self.content['Button'].start_button.setText('Start')
        self.content['Button'].start_button.setEnabled(True)

    @pyqtSlot(bool)
    def enable(self, var, use_all=False):
        """Enable or disable widgets

        Arguments:
        var - Enable status of the widgets.
        use_all - Disable/Enable everything (Default False)

        Return:
        None
        """
        for key in self.content:
            try:
                self.content[key].enable(var=var, use_all=use_all)
            except AttributeError:
                continue

    def closeEvent(self, event):
        """
        Quit threads before close and check if the process is still running

        Arguments:
        event - QCloseEvent.

        Return:
        None
        """
        if self.content['Button'].start_button.text() == 'Stop':
            event.ignore()
            tu.message('First stop the program before closing')
            return None
        elif not self.save_temp_settings():
            result = tu.question(
                head='Error saving file!',
                text='Wrong setting detected! Quit without saving?',
            )
            # Result is true if the answer is No
            if not result:
                pass
            else:
                event.ignore()
                return None
        else:
            pass

        self.thread_mount.quit()
        self.thread_mount.wait()
        self.thread_process.quit()
        self.thread_process.wait()
        self.thread_plot.quit()
        self.thread_plot.wait()
        for key in self.content['Mount'].content:
            thread = self.mount_thread_list[key]['thread']
            calculator = self.mount_thread_list[key]['object']
            calculator.kill_thread = True
            thread.quit()
            thread.wait()
        message = 'Bye Bye'
        print(message)
        super(MainWindow, self).closeEvent(event)
예제 #55
0
class GCode(object):

    def __init__(self, filename, controller, done_loading_callback, done_writing_callback):
        self.controller = controller
        self.done_loading_callback = done_loading_callback
        self.writing_done_callback = done_writing_callback
        self.data = defaultdict(list)
        self.all_data = []
        self.data_keys = set()
        self.color_change_data = []
        self.actual_z = '0.0'
        self.speed = 0.0
        self.z_hop = False
        self.last_point = np.array([0.0, 0.0, 0.0])
        self.actual_point = [0.0, 0.0, 0.0]

        self.printing_time = 0.0
        self.filament_length = 0.0
        #print("Filename type: " + str(type(filename)))
        #print("Filename: " + filename)
        #if type(filename)==:
        #self.filename = u'c:\\models\\super mega testovací Jindřich šložka čěýáéůú\\anubis_PLA_OPTIMAL.gcode'
        self.filename = filename

        self.is_loaded = False

        self.gcode_parser = GcodeParserRunner(controller, self.filename)
        self.gcode_parser_thread = QThread()

        self.gcode_copy = GcodeCopyRunner(self.filename, "", color_change_lst=self.color_change_data)
        self.gcode_copy_thread = QThread()


    def cancel_parsing_gcode(self):
        print("Cancel presset")
        if self.gcode_parser and self.gcode_parser_thread and self.gcode_parser_thread.isRunning():
            self.gcode_parser.is_running = False
            self.gcode_parser_thread.quit()
            self.gcode_parser_thread.wait()
            self.is_loaded = False
            self.data = {}
            self.all_data = []
            self.data_keys = []
        self.controller.set_progress_bar(0)

    def cancel_writing_gcode(self):
        print("Cancel writing gcode")
        if self.gcode_copy and self.gcode_copy_thread and self.gcode_copy_thread.isRunning():
            self.gcode_copy.quit()
            self.gcode_copy_thread.wait()

    def get_first_extruding_line_number_of_gcode_for_layers(self, layers_keys_lst):
        lines_number = []
        for i in layers_keys_lst:
            line = self.data[i]
            for o in line:
                _a, _b, type, _speed, _extr, line_n = o
                if 'E' in type:
                    lines_number.append(line_n)
                    break

        return lines_number



    def read_in_thread(self, update_progressbar_function, after_done_function):
        print("reading in thread")
        self.gcode_parser.moveToThread(self.gcode_parser_thread)
        self.done_loading_callback = after_done_function

        # connect all signals to thread class
        self.gcode_parser_thread.started.connect(self.gcode_parser.load_gcode_file)
        # connect all signals to parser class
        self.gcode_parser.finished.connect(self.set_finished_read)
        self.gcode_parser.update_progressbar=True
        self.gcode_parser.set_update_progress.connect(update_progressbar_function)
        self.gcode_parser.set_data_keys.connect(self.set_data_keys)
        self.gcode_parser.set_data.connect(self.set_data)
        self.gcode_parser.set_all_data.connect(self.set_all_data)
        self.gcode_parser.set_printing_time.connect(self.set_printig_time)

        self.gcode_parser_thread.start()


    def read_in_realtime(self):
        print("Read in realtime")
        self.gcode_parser.set_data_keys.connect(self.set_data_keys)
        self.gcode_parser.set_data.connect(self.set_data)
        self.gcode_parser.set_all_data.connect(self.set_all_data)
        self.gcode_parser.set_printing_time.connect(self.set_printig_time)
        self.gcode_parser.update_progressbar=False

        print("start read procedure")
        self.gcode_parser.load_gcode_file()

        self.is_loaded = True


    def set_printig_time(self, time):
        self.printing_time = time

    def set_data_keys(self, data_keys):
        self.data_keys = data_keys

    def set_all_data(self, all_data):
        self.all_data = all_data

    def set_data(self, data):
        self.data = data

    def set_finished_read(self):
        self.gcode_parser_thread.quit()
        self.is_loaded = True
        self.done_loading_callback()
        #self.controller.set_gcode()

    def set_finished_copy(self):
        self.gcode_copy_thread.quit()
        #print(str(self.writing_done_callback))
        self.writing_done_callback()

    def set_color_change_data(self, data):
        self.color_change_data = data


    def write_with_changes_in_thread(self, filename_in, filename_out, update_function):
        self.gcode_copy.filename_in = filename_in
        self.gcode_copy.filename_out = filename_out
        self.gcode_copy.color_change_lst = self.color_change_data
        self.gcode_copy.moveToThread(self.gcode_copy_thread)

        self.gcode_copy_thread.started.connect(self.gcode_copy.write_file)

        self.gcode_copy.finished.connect(self.set_finished_copy)
        self.gcode_copy.set_update_progress.connect(update_function)

        self.gcode_copy_thread.start()
예제 #56
0
class AbstractBuildRunner(QObject):
    """
    Base class to run a build.

    Create the required test runner and build manager, along with a thread
    that should be used for blocking tasks.
    """
    running_state_changed = Signal(bool)
    worker_created = Signal(object)
    worker_class = None

    def __init__(self, mainwindow):
        QObject.__init__(self)
        self.mainwindow = mainwindow
        self.thread = None
        self.worker = None
        self.pending_threads = []
        self.test_runner = None
        self.download_manager = None
        self.options = None
        self.stopped = False

    def init_worker(self, fetch_config, options):
        """
        Create and initialize the worker.

        Should be subclassed to configure the worker, and should return the
        worker method that should start the work.
        """
        self.options = options

        # global preferences
        global_prefs = get_prefs()
        self.global_prefs = global_prefs
        # apply the global prefs now
        apply_prefs(global_prefs)

        download_dir = global_prefs['persist']
        if not download_dir:
            download_dir = self.mainwindow.persist
        persist_limit = int(abs(global_prefs['persist_size_limit']) *
                            1073741824)
        self.download_manager = GuiBuildDownloadManager(download_dir,
                                                        persist_limit)
        self.test_runner = GuiTestRunner()
        self.thread = QThread()

        # options for the app launcher
        launcher_kwargs = {}
        for name in ('profile', 'preferences'):
            if name in options:
                value = options[name]
                if value:
                    launcher_kwargs[name] = value

        # add add-ons paths to the app launcher
        launcher_kwargs['addons'] = options['addons']
        self.test_runner.launcher_kwargs = launcher_kwargs

        self.worker = self.worker_class(fetch_config, self.test_runner,
                                        self.download_manager)
        # Move self.bisector in the thread. This will
        # allow to the self.bisector slots (connected after the move)
        # to be automatically called in the thread.
        self.worker.moveToThread(self.thread)
        self.worker_created.emit(self.worker)

    def start(self, fetch_config, options):
        action = self.init_worker(fetch_config, options)
        assert callable(action), "%s should be callable" % action
        self.thread.start()
        # this will be called in the worker thread.
        QTimer.singleShot(0, action)
        self.stopped = False
        self.running_state_changed.emit(True)

    @Slot()
    def stop(self, wait=True):
        self.stopped = True
        if self.options:
            if self.options['profile'] and \
               self.options['profile_persistence'] == 'clone-first':
                self.options['profile'].cleanup()
        if self.download_manager:
            self.download_manager.cancel()
        if self.thread:
            self.thread.quit()

        if wait:
            if self.download_manager:
                self.download_manager.wait(raise_if_error=False)
            if self.thread:
                # wait for thread(s) completion - this is the case when
                # user close the application
                self.thread.wait()
                for thread in self.pending_threads:
                    thread.wait()
            self.thread = None
        elif self.thread:
            # do not block, just keep track of the thread - we got here
            # when user uses the stop button.
            self.pending_threads.append(self.thread)
            self.thread.finished.connect(self._remove_pending_thread)

        if self.test_runner:
            self.test_runner.finish(None)
        self.running_state_changed.emit(False)
        log('Stopped')

    @Slot()
    def _remove_pending_thread(self):
        for thread in self.pending_threads[:]:
            if thread.isFinished():
                self.pending_threads.remove(thread)
예제 #57
0
class private_messages(iface_gui_plugin):
    VERSION_INITIAL = 0
    VERSION_CURRENT = VERSION_INITIAL
    
    def __init__(self):
        super(private_messages, self).__init__()
        self.options = [((u"prev_messages", u"Number of previous messages to display"), 5),
                        ((u"enable_markdown", u"Enable Markdown annotations", self._enableMarkdownChanged), False)]
        self.hidden_options = {u"ack_timeout" : 3, # seconds until message delivery is marked as timed out
                               u"next_msgid" : -1} # next free message ID. -1 = not initialized
        
        self._storage = None
        
    def get_displayed_name(self):
        return u"Chat"
    
    def activate(self):
        iface_gui_plugin.activate(self)
        if lunchinator_has_gui():
            self._sendMessageAction = _SendMessageAction()
            self._openChatAction = _OpenChatAction(self._sendMessageAction)
            self._peerActions = [self._openChatAction, _BlockAction(self._sendMessageAction), self._sendMessageAction]
        else:
            self._peerActions = None
        
    def create_widget(self, parent):
        from private_messages.chat_history_view import ChatHistoryWidget
        
        self._lock = loggingMutex("Private Messages", logging=get_settings().get_verbose())
        
        from PyQt4.QtCore import QThread
        from private_messages.chat_messages_handler import ChatMessagesHandler
        if canUseBackgroundQThreads():
            self._messagesThread = QThread()
        else:
            self._messagesThread = None
            
        self._messagesHandler = ChatMessagesHandler(self.logger, self, self.hidden_options[u"ack_timeout"], self.hidden_options[u"next_msgid"])
        if self._messagesThread is not None:
            self._messagesHandler.moveToThread(self._messagesThread)
            self._messagesThread.start()
        
        self._messagesHandler.delayedDelivery.connect(self._delayedDelivery)
        self._messagesHandler.messageIDChanged.connect(self._messageIDChanged)
        self._messagesHandler.displayOwnMessage.connect(self._displayOwnMessage)
        self._messagesHandler.newMessage.connect(self._displayMessage)
        
        self._openChats = {} # mapping peer ID -> ChatDockWidget
        self._history = ChatHistoryWidget(self, parent, self.logger)
        return self._history
    
    def destroy_widget(self):
        for chatWindow in self._openChats.values():
            chatWindow.close()
            
        self.set_hidden_option(u"next_msgid", self._messagesHandler.getNextMessageIDForStorage(), convert=False)
        self._messagesHandler.deactivate()
        if self._messagesThread is not None:
            self._messagesThread.quit()
            self._messagesThread.wait()
            self._messagesThread.deleteLater()
            self._messagesThread = None
        self._messagesHandler = None
        self._storage = None
        self._lock = None
            
        iface_gui_plugin.destroy_widget(self)
        
    def _enableMarkdownChanged(self, _setting, newVal):
        for chatWindow in self._openChats.values():
            chatWindow.getChatWidget().setMarkdownEnabled(newVal)
    
    def extendsInfoDict(self):
        return lunchinator_has_gui()
        
    def extendInfoDict(self, infoDict):
        infoDict[u"PM_v"] = self.VERSION_CURRENT
        
    def get_peer_actions(self):
        return self._peerActions
        
    def process_event(self, cmd, value, _ip, peerInfo, _prep):
        if not cmd.startswith(u"HELO_PM"):
            return
        
        peerID = peerInfo[u"ID"]
        
        subcmd = cmd[7:]
        if subcmd == u"_ACK":
            self._messagesHandler.processAck(peerID, value)
        elif subcmd == u"_TYPING":
            if peerID in self._openChats:
                self._openChats[peerID].getChatWidget().otherIsTyping()
        elif subcmd == u"_CLEARED":
            if peerID in self._openChats:
                self._openChats[peerID].getChatWidget().otherCleared()
        elif subcmd == u"_ERROR":
            self._messagesHandler.processAck(peerID, value, error=True)
        elif subcmd == u"":
            self._messagesHandler.processMessage(peerID, value)
    
    def getStorage(self):
        if self._storage == None:
            with self._lock:
                if self._storage == None:
                    from private_messages.chat_messages_storage import ChatMessagesStorage
                    self._storage = ChatMessagesStorage(self.logger)
        return self._storage
    
    @loggingFunc
    def _displayOwnMessage(self, otherID, msgID, recvTime, msgHTML, msgTime, status, errorMsg):
        otherID = convert_string(otherID)
        msgHTML = convert_string(msgHTML)
        errorMsg = convert_string(errorMsg)
        if recvTime == -1:
            recvTime = None
        if not errorMsg:
            errorMsg = None
        
        if otherID in self._openChats:
            chatWindow = self._openChats[otherID]
            chatWindow.getChatWidget().addOwnMessage(msgID, recvTime, msgHTML, msgTime, status, errorMsg)
    
    def _activateChat(self, chatWindow, forceForeground=True):
        chatWindow.showNormal()
        if forceForeground:
            chatWindow.raise_()
            chatWindow.activateWindow()
        return chatWindow
    
    def _openChat(self, myName, otherName, myAvatar, otherAvatar, otherID):
        from private_messages.chat_window import ChatWindow
        newWindow = ChatWindow(None, self.logger, myName, otherName, myAvatar, otherAvatar, otherID, self._sendMessageAction)
        newWindow.getChatWidget().setMarkdownEnabled(self.get_option(u"enable_markdown"))
        
        newWindow.windowClosing.connect(self._chatClosed)
        newWindow.getChatWidget().sendMessage.connect(self._messagesHandler.sendMessage)
        newWindow.getChatWidget().typing.connect(partial(self._messagesHandler.sendTyping, otherID))
        newWindow.getChatWidget().cleared.connect(partial(self._messagesHandler.sendCleared, otherID))
        self._openChats[otherID] = newWindow
        
        prevMessages = self.getStorage().getPreviousMessages(otherID, self.get_option(u"prev_messages"))
        from private_messages.chat_messages_storage import ChatMessagesStorage
        for row in reversed(prevMessages):
            # partner, ID, own, time, status, text
            isOwnMessage = row[ChatMessagesStorage.MSG_IS_OWN_MESSAGE_COL] != 0
            if isOwnMessage:
                newWindow.getChatWidget().addOwnMessage(row[ChatMessagesStorage.MSG_ID_COL],
                                                        row[ChatMessagesStorage.MSG_RECV_TIME_COL],
                                                        row[ChatMessagesStorage.MSG_TEXT_COL],
                                                        row[ChatMessagesStorage.MSG_TIME_COL],
                                                        row[ChatMessagesStorage.MSG_STATUS_COL])
            else:
                newWindow.getChatWidget().addOtherMessage(row[ChatMessagesStorage.MSG_TEXT_COL],
                                                          row[ChatMessagesStorage.MSG_TIME_COL],
                                                          row[ChatMessagesStorage.MSG_RECV_TIME_COL])
        return self._activateChat(newWindow)
        
    @loggingFunc
    def _chatClosed(self, pID):
        pID = convert_string(pID)
        if pID in self._openChats:
            chatWindow = self._openChats[pID]
            chatWindow.deleteLater()
            del self._openChats[pID]
        else:
            self.logger.error("Closed chat window was not maintained: %s", pID)
        
    def getOpenChatAction(self):
        return self._openChatAction
    
    def openChat(self, pID, forceForeground=True):
        pID = convert_string(pID)
        
        if pID in self._openChats:
            return self._activateChat(self._openChats[pID], forceForeground)
        
        otherName = get_peers().getDisplayedPeerName(pID=pID)
        if otherName == None:
            self.logger.error("Could not get info of chat partner %s", pID)
            return
        otherAvatar = get_peers().getPeerAvatarFile(pID=pID)
        
        myName = get_settings().get_user_name()
        myAvatar = get_peers().getPeerAvatarFile(pID=get_settings().get_ID())
        
        return self._openChat(myName, otherName, myAvatar, otherAvatar, pID)

    @loggingFunc
    def _delayedDelivery(self, otherID, msgID, recvTime, error, errorMessage):
        otherID = convert_string(otherID)
        errorMessage = convert_string(errorMessage)
        
        if otherID in self._openChats:
            chatWindow = self._openChats[otherID]
            chatWindow.getChatWidget().delayedDelivery(msgID, recvTime, error, errorMessage)

    @loggingFunc
    def _messageIDChanged(self, otherID, oldID, newID):
        otherID = convert_string(otherID)
        if otherID in self._openChats:
            chatWindow = self._openChats[otherID]
            chatWindow.getChatWidget().messageIDChanged(oldID, newID)

    @loggingFunc
    def _displayMessage(self, otherID, msgHTML, msgTime, msgDict):
        try:
            recvTime = time()
            chatWindow = self.openChat(otherID, False)
            chatWindow.getChatWidget().addOtherMessage(msgHTML, msgTime, recvTime)
            self._messagesHandler.receivedSuccessfully(otherID, msgHTML, msgTime, msgDict, recvTime)
        except:
            excType, excValue, _tb = sys.exc_info()
            errorMsg = u"Error processing message (%s: %s)" % (unicode(excType.__name__), unicode(excValue))
            self._messagesHandler.errorReceivingMessage(otherID, msgDict, errorMsg)
        
        if not chatWindow.isActiveWindow():
            from PyQt4.QtGui import QTextDocument
            doc = QTextDocument()
            doc.setHtml(msgHTML)
            displayNotification(chatWindow.getChatWidget().getOtherName(),
                                convert_string(doc.toPlainText()),
                                self.logger,
                                chatWindow.getChatWidget().getOtherIconPath())