예제 #1
0
    def test_task(self):
        results = []

        task = Task(function=QThread.currentThread)
        task.resultReady.connect(results.append)

        task.start()
        self.app.processEvents()

        self.assertSequenceEqual(results, [QThread.currentThread()])

        results = []

        thread = QThread()
        thread.start()

        task = Task(function=QThread.currentThread)

        task.moveToThread(thread)

        self.assertIsNot(task.thread(), QThread.currentThread())
        self.assertIs(task.thread(), thread)

        task.resultReady.connect(results.append, Qt.DirectConnection)
        task.start()

        f = task.future()

        self.assertIsNot(f.result(3), QThread.currentThread())

        self.assertIs(f.result(3), results[-1])
예제 #2
0
 def start(self, ser, cmd="", priority=QThread.InheritPriority):
     self.ser = ser
     #print(self.ser)
     print(cmd)
     self.cmd = str(cmd) + "\r"
     QThread.start(self, priority)
     print(self.cmd)
예제 #3
0
파일: sourcedocument.py 프로젝트: gltn/stdm
    def uploadDoc(self):
        """
        Upload the file to the central repository in a separate thread using the specified file manager
        """
        if isinstance(self.fileManager, NetworkFileManager):
            self.pgBar.setVisible(True)
            self._docSize = self.fileInfo.size()
            '''
            Create document transfer helper for multi-threading capabilities.
            Use of queued connections will guarantee that signals and slots are captured
            in any thread.
            '''
            workerThread = QThread(self)
            docWorker = DocumentTransferWorker(
                self.fileManager,
                self.fileInfo,
                "%s"%(self._source_entity),
                "%s"%(self._doc_type),
                self
            )
            docWorker.moveToThread(workerThread)

            workerThread.started.connect(docWorker.transfer)
            docWorker.blockWrite.connect(self.onBlockWritten)
            docWorker.complete.connect(self.onCompleteTransfer)
            workerThread.finished.connect(docWorker.deleteLater)
            workerThread.finished.connect(workerThread.deleteLater)

            workerThread.start()
            # Call transfer() to get fileUUID early
            #docWorker.transfer()
            self.fileUUID = docWorker.file_uuid
	def start(self):
		"""Reimplemented method QThread.start

		@param	self		A ThreadedExport instance
		"""
		self.pause = False
		QThread.start(self)
    def startWorker(self):
        # create a new worker instance

        if self.worker is None:

            worker = UpdateRegistryWorker()

            # configure the QgsMessageBar
            messageBar = self.iface.messageBar().createMessage(u"Update Image Registry", u"Dieser Vorgang kann einige Minute dauern, bitte haben Sie geduld!")
            progressBar = QProgressBar()
            progressBar.setMinimum(0)
            progressBar.setMaximum(0)
            progressBar.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
            cancelButton = QPushButton()
            cancelButton.setText('Cancel')
            cancelButton.clicked.connect(self.killWorker)
            messageBar.layout().addWidget(progressBar)
            self.progressBar = progressBar
            messageBar.layout().addWidget(cancelButton)
            self.iface.messageBar().pushWidget(messageBar, self.iface.messageBar().INFO)
            #self.iface.messageBar().widgetRemoved
            # messageBar

            self.messageBar = messageBar

            # start the worker in a new thread
            thread = QThread()
            worker.moveToThread(thread)
            worker.finished.connect(self.workerFinished)
            worker.error.connect(self.workerError)
            #worker.progress.connect(progressBar.setValue)
            thread.started.connect(worker.run)
            thread.start()
            self.thread = thread
            self.worker = worker
예제 #6
0
 def start(self):
     """
     Reimplemented from `QThread.start`
     """
     QThread.start(self)
     # Need to also handle method invoke from this thread
     self.moveToThread(self)
예제 #7
0
    def search(self, text):
        logging.debug('Doing search.')
        thread = QThread()

        worker = SearchWorker(text, time.time())
        worker.moveToThread(thread)

        thread.started.connect(worker.process)
        worker.finished.connect(thread.quit)
        worker.finished.connect(worker.deleteLater)
        worker.new_items.connect(functools.partial(self.repopulate, worker))
        thread.finished.connect(thread.deleteLater)

        self._threads.append(thread)
        self.workers.append(worker)
        thread.start()

        # Revert search bar color.
        palette = main_window.palette()
        brush = palette.brush(QPalette.Highlight).color()
        palette.setBrush(QPalette.Base, QBrush(brush))
        search_bar.setPalette(palette)

        # Clean up old threads.
        self._threads = [thread for thread in self._threads
                         if not sip.isdeleted(thread)]
        self.workers = [worker for worker in self.workers
                        if not sip.isdeleted(worker)]
예제 #8
0
	def startWorker(self, ExtrairShape, CalcShape, OutShape, Ref, TypeUnits):
			
			# create a new worker instance
			worker = Worker(ExtrairShape, CalcShape, OutShape, Ref, TypeUnits)

			# configure the QgsMessageBar
			qgis.utils.iface.messageBar().clearWidgets() 
			progressMessageBar = qgis.utils.iface.messageBar().createMessage('Calculating area...')
			progressBar = QProgressBar()
			progressBar.setMaximum(100)
			progressMessageBar.layout().addWidget(progressBar)
			qgis.utils.iface.messageBar().pushWidget(progressMessageBar)
			self.progressMessageBar = progressMessageBar

			# start the worker in a new thread
			thread = QThread()
			worker.moveToThread(thread)
			worker.finished.connect(self.workerFinished)
			worker.error.connect(self.workerError)
			worker.progress.connect(progressBar.setValue)
			thread.started.connect(worker.runCalc)
			thread.start()
			self.thread = thread
			self.worker = worker
			self.output = OutShape
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
파일: thumbnail.py 프로젝트: arxsys/dff-api
    class __ThumbnailManager(QObject):
        def __init__(self):
            QObject.__init__(self)
            self.pixmapCache = QPixmapCache()
            self.pixmapCache.setCacheLimit(61440)
            self.thread = QThread()
            self.scaler = Scaler()
            self.scaler.moveToThread(self.thread)
            self.connect(self.scaler, SIGNAL("scaledFinished"), self.finished)
            self.thread.start()
            self.thumbnailers = []
            self.handledRequest = set()
            self.corruptionHandler = CorruptedPictureHandler()
            self.pixmapCorrupted = QPixmap(":file_broken.png")

        def register(self, thumbnailer):
            self.thumbnailers.append(thumbnailer)

        def unregister(self, thumbnailer):
            try:
                self.thumbnailers.remove(thumbnailer)
            except:
                pass

        def generate(self, config):
            pixmap = self.pixmapCache.find(str(config))
            if pixmap:
                return pixmap
            elif self.corruptionHandler.isCorrupted(config.node):
                return self.pixmapCorrupted
            else:
                if config not in self.handledRequest:
                    QApplication.postEvent(self.scaler, ScaleEvent(config))
                    self.handledRequest.add(config)

        def finished(self, config, scaledImage):
            if scaledImage:
                pixmap = QPixmap().fromImage(scaledImage)
                self.pixmapCache.insert(str(config), pixmap)
                self.emitUpdate(config, pixmap)
            else:
                self.corruptionHandler.setAttributes(config.node)
                self.emitUpdate(config, self.pixmapCorrupted)

        def emitUpdate(self, config, pixmap):
            for thumbnailer in self.thumbnailers:
                try:
                    if thumbnailer.request(config):
                        thumbnailer.emit(SIGNAL("ThumbnailUpdate"), config.node, pixmap)
                        thumbnailer.requestRemove(config)
                except:
                    pass
            try:
                self.handledRequest.remove(config)
            except KeyError:
                pass
예제 #11
0
 def start(self):
     if self.isRunning():
         assert not self.rendering_all, "Cannot run twice the rendering of all images with the same object."
         return
     if parameters.instance.use_thread:
         log_debug("Starting rendering thread.")
         QThread.start(self)
         return False
     else:
         self.run()
         return True
예제 #12
0
class ProcTableWidget(QTreeView):
    def __init__(self, model, parent=None):
        super().__init__(parent)
        self.setSelectionBehavior(QTreeView.SelectRows)

        # setting uniform row heights allows optimization of the view
        self.setUniformRowHeights(True)
        self.model = model
        self.setModel(self.model)
        self.expandAll()

        # resize the column to fit all process names
        self.resizeColumnToContents(0)

        # keeps track of the previous sort order shown by the sort indicator.
        # this allows for a third state for the sort order: no sort
        self.prevSortOrder = None
        self.header().setClickable(True)
        self.header().sectionClicked.connect(self.setSortIndicator)

        # this worker thread grabs the latest process properties
        # so the GUI doesn't lag when it needs to update process data
        self.refreshThread = QThread(self)
        self.modelRefresher = ProcTableModelRefresher(self.model)
        self.modelRefresher.moveToThread(self.refreshThread)
        self.modelRefresher.modelRefresh.connect(self.model.update)
        self.refreshThread.started.connect(self.modelRefresher.startRefreshTimer)
        self.refreshThread.start()

    @pyqtSlot(int)
    def setSortIndicator(self, columnIdx):
        if self.isSortingEnabled():
            # the 'no sort' state is only accessible by changing
            # the sort order of the process name column
            if columnIdx == 0 and self.prevSortOrder == Qt.DescendingOrder:
                self.header().setSortIndicatorShown(False)
                self.setSortingEnabled(False)
                self.model.removeSort()
                # setClickable() has to be set to True again after
                # calling setSortingEnabled(False) otherwise, the headers
                # cannot be clicked and the columns cannot be sorted
                self.header().setClickable(True)
        else:
            self.header().setSortIndicatorShown(True)
            # force the sort indicator to start with ascendingorder
            # so the cycling of sort order is predictable otherwise,
            # the sort order can start with DescendingOrder and vice versa
            # which makes it hard to detect when it's time to set the
            # 'no sort' state
            self.header().setSortIndicator(columnIdx, Qt.AscendingOrder)
            self.setSortingEnabled(True)

        self.prevSortOrder = self.header().sortIndicatorOrder()
예제 #13
0
class TargetThread(QObject):
    """ Simple QThread subclass made to support the ThreadPool interface,
        this thread uses the standard python approach to threading, of passing
        a callable to a Thread class.
    """
    finished = pyqtSignal()

    def __init__(self, target, *args, **kwargs):
        """ TargetThread constructor.

            :param target: callable that gets called in the new thread of execution.
            :param args: var-args to pass to the target callable.
            :param kwargs: keyword-args to pass to the target callable.
        """
        QObject.__init__(self)

        self.target = target
        self.args = args
        self.kwargs = kwargs

        self._thread = QThread()
        self.moveToThread(self._thread)
        self._connect_slots()

    def _connect_slots(self):
        self._thread.started.connect(self.run)

    def wait(self, timeout):
        """ Wait a given time, in seconds, for our thread to terminate.

            :param timeout: The time, in seconds, to wait.
        """
        self._thread.wait(timeout)

    def start(self):
        """ Start our QThread instance, beginning execution of our target thread.
        """
        self._thread.start()

    def run(self):
        """ Override of QThread run method that gets called from the new thread of execution,
            this is responsible for evoking the target callable with the args and kwargs given
            in the constructor. Lastly, it emits the finished signal to notify whom it may
            concern that our job is done.
        """
        self.target(*self.args, **self.kwargs)
        self.finished.emit()
        self._thread.finished.emit()

    def terminate(self):
        """ Terminate this thread of execution abruptly.
        """
        self._thread.terminate()
예제 #14
0
class Window(QtGui.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()

        self.commandDialog = CommandDialog()

        self.exitAction = self.create_action('Q', self.close_me)

        self.test_launcher = QThread()
        self.test_launcher.run = keyM.monitor
        keyM.launcher = self.test_launcher
        keyM.launcher.connect(keyM.launcher, QtCore.SIGNAL('unhook(int)'),
                              keyM.unhook)
        keyM.launcher.connect(keyM.launcher, QtCore.SIGNAL('keyPress(QString)'),
                              self.key_press)
        self.test_launcher.start()

        self.trayIconMenu = QtGui.QMenu(self)
        self.trayIconMenu.addAction(self.exitAction)

        self.trayIcon = QtGui.QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.setIcon(QtGui.QIcon('images/heart.png'))
        self.trayIcon.activated.connect(self.on_activated)
        self.trayIcon.show()

        State.trayIconDisplayed=True

    def key_press(self, value):
        print value

    def close_me(self):
        print 'close test_launcher..'
        self.test_launcher.emit(QtCore.SIGNAL('unhook(int)'), 0)
        print 'close application..'

        self.commandDialog.close()
        self.close()
        # ctypes.windll.user32.PostQuitMessage(0)

    def create_action(self, name, handler):
        _v = QAction(name, self)
        _v.triggered.connect(handler)
        return _v

    def on_activated(self, e):
        print type(e), e
        if e == 3:
            self.commandDialog.show()
            self.commandDialog.activateWindow()
            self.commandDialog.textEdit.setFocus()
            # self.commandDialog.textEdit.clear()
            self.commandDialog.textEdit.setEditable(True)
예제 #15
0
    def start(self, tiling):
        self._queue = deque()
        self._tiling = tiling
        self._stopped = False

        self._numLayers = len(self._stackedIms)

        shape = (self._numLayers, len(self._tiling))
        self._imageLayersNext    = numpy.ndarray(shape, dtype = object)
        self._compositeCurrent    = numpy.ndarray((len(self._tiling),), dtype = object)
        self._compositeNext       = numpy.ndarray((len(self._tiling),), dtype = object)

        QThread.start(self)
예제 #16
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)



    '''
예제 #17
0
    def add_projector(self, projector, start=False):
        """
        Builds manager list item, projector thread, and timer for projector instance.


        :param projector: Projector instance to add
        :param start: Start projector if True
        """
        item = ProjectorItem(link=self._add_projector(projector))
        item.db_item = projector
        icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[S_NOT_CONNECTED]))
        item.icon = icon
        widget = QtGui.QListWidgetItem(icon,
                                       item.link.name,
                                       self.projector_list_widget
                                       )
        widget.setData(QtCore.Qt.UserRole, item)
        item.link.db_item = item.db_item
        item.widget = widget
        thread = QThread(parent=self)
        thread.my_parent = self
        item.moveToThread(thread)
        thread.started.connect(item.link.thread_started)
        thread.finished.connect(item.link.thread_stopped)
        thread.finished.connect(thread.deleteLater)
        item.link.projectorNetwork.connect(self.update_status)
        item.link.changeStatus.connect(self.update_status)
        item.link.projectorAuthentication.connect(self.authentication_error)
        item.link.projectorNoAuthentication.connect(self.no_authentication_error)
        item.link.projectorUpdateIcons.connect(self.update_icons)
        timer = QtCore.QTimer(self)
        timer.setInterval(self.poll_time)
        timer.timeout.connect(item.link.poll_loop)
        item.timer = timer
        # Timeout in case of brain-dead projectors or cable disconnected
        socket_timer = QtCore.QTimer(self)
        socket_timer.setInterval(11000)
        socket_timer.timeout.connect(item.link.socket_abort)
        item.socket_timer = socket_timer
        thread.start()
        item.thread = thread
        item.link.timer = timer
        item.link.socket_timer = socket_timer
        item.link.widget = item.widget
        self.projector_list.append(item)
        if start:
            item.link.connect_to_host()
        for item in self.projector_list:
            log.debug('New projector list - item: (%s) %s' % (item.link.ip, item.link.name))
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
예제 #19
0
 def parserFinished(self, success):
     if success:
         #Create a thread to parse the data
         thread = QThread(self)
         worker = self.worker = ffaWorker()
         worker.moveToThread(thread)
         thread.started.connect(worker.run)
         #Print the periodic status messages to the text browser
         worker.status.connect(self.dlg.addToTextBrowser)
         worker.error.connect(self.workerError)
         #Connect these signals so we know when the thread finishes
         worker.finished.connect(self.ffaFinished)
         worker.finished.connect(worker.deleteLater)
         thread.finished.connect(thread.deleteLater)
         thread.finished.connect(thread.quit)
         thread.start()
예제 #20
0
class MyWindowClass(QtGui.QMainWindow, form_class):




	
	def __init__(self, parent=None):
		QtGui.QMainWindow.__init__(self, parent)
		self.setupUi(self)
		self.StartButton.clicked.connect(self.ButtonUpdate_start_clicked)# Bind the event handlers
		self.comboSerialBox.addItems(serial_ports('freq')) #Gets a list of avaliable serial ports to connect to and adds to combo box
		self.comboSerialBox_2.addItems(serial_ports('detector'))
		self.StopButton.clicked.connect(self.ButtonUpdate_stop_clicked)
		self.pen = pg.mkPen(color=(0,0,0), width=2)
		self.plotWidget.plotItem.getAxis('left').setPen(self.pen)
		self.plotWidget.plotItem.getAxis('bottom').setPen(self.pen)
		self.plotWidget.setLabel('left', 'Amp', 'arb')
		self.plotWidget.setLabel('bottom', 'Freq', 'MHz')
		self.plt = self.plotWidget



			
	
	def ButtonUpdate_start_clicked(self):
		self.ScanThread = QThread(self)
		self.scandata = [float(self.StartSpinBox.text()),float(self.StopSpinBox.text()),float(self.StepSpinBox.text())]
		self.freq_device = str(self.comboSerialBox.currentText())
		self.detector_device = str(self.comboSerialBox_2.currentText())
		self.ScanRunner = ScanRunner(self.scandata,self.freq_device,self.detector_device)
		self.ScanRunner.devicestatus.connect(self.control_label.setText)
		self.ScanRunner.moveToThread(self.ScanThread)
		self.ScanThread.started.connect(self.ScanRunner.run)
		self.ScanRunner.freqIncreased.connect(self.label_Freq.setText)
		self.ScanRunner.stepIncreased.connect(self.label_Step.setText)
		self.ScanRunner.devicestatus.connect(self.control_label_2.setText)
		self.ScanRunner.plotUpdate.connect(self.update_plot)
		self.ScanThread.finished.connect(self.ScanThread.quit)
		self.ScanThread.start()
		
	def ButtonUpdate_stop_clicked(self):
		self.ScanRunner.stop()

		
	def update_plot(self,data):
		self.plt.plot(data[0],data[1],clear=True,pen={'color':'k','width':2})
예제 #21
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
예제 #22
0
 def pointWorkerFinish(self, success, inputs):
     #Create a new thread to call the point index service
     if success:
         thread = QThread(self)
         worker = self.worker = NavigationWorker(inputs, self.navMutex)
         worker.moveToThread(thread)
         #Connect the slots
         thread.started.connect(worker.run)
         #Print the periodic status messages to the text browser
         worker.status.connect(self.dlg.setTextBrowser)
         worker.error.connect(self.workerError)
         #When done, call the pointWOrkerFinish to go to the next task
         worker.finished.connect(self.navWorkerFinish)
         #Clean up the thread
         worker.finished.connect(worker.deleteLater)
         thread.finished.connect(thread.deleteLater)
         worker.finished.connect(thread.quit)
         thread.start()
예제 #23
0
파일: Main2.py 프로젝트: witmicko/VISE
def runner():
    app = QApplication(sys.argv)
    window = QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(window)
    cam = CameraDevice()
    thread = QThread()
    cam.moveToThread(thread)
    thread.start()
    thread.setPriority(QThread.LowestPriority)
    atexit.register(cam.capture.release)
    cam.video_signal.connect(ui.set_image)
    ui.preview_on.clicked.connect(cam.preview_on)
    ui.preview_on.clicked.connect(cam.startVideo)
    ui.preview_off.clicked.connect(cam.preview_off)
    # ui.preview_off.clicked.disconnect(cam.startVideo)
    window.show()
    sys.exit(app.exec_())
예제 #24
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()
예제 #25
0
class StopperWidget(QWidget):
    def __init__(self):
        super(QWidget, self).__init__()

        self.stopper = Stopper()
        self.timer_thread = QThread()
        print "w.timer_thread: %r" % self.timer_thread
        self.timer_thread.start()
        self.stopper.moveToThread(self.timer_thread)
        self.stopper.start_timer.emit()

        self.button = QPushButton(self)
        self.button.setText("Stop timer")
        self.button.clicked.connect(self.stopper.stop_timer)

    def __del__(self):
        print QThread.currentThread()
        print self.thread()
        print self.timer_thread
        self.stopper.stop_timer.emit()
def start_worker(worker, iface, message, with_progress=True):
    # configure the QgsMessageBar
    message_bar = iface.messageBar().createMessage(message)
    progress_bar = QProgressBar()
    progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
    if not with_progress:
        progress_bar.setMinimum(0)
        progress_bar.setMaximum(0)
    cancel_button = QPushButton()
    cancel_button.setText('Cancel')
    cancel_button.clicked.connect(worker.kill)
    message_bar.layout().addWidget(progress_bar)
    message_bar.layout().addWidget(cancel_button)
    iface.messageBar().pushWidget(message_bar, iface.messageBar().INFO)

    # start the worker in a new thread
    # let Qt take ownership of the QThread
    thread = QThread(iface.mainWindow())
    worker.moveToThread(thread)
    
    worker.set_message.connect(lambda message: set_worker_message(
        message, message_bar_item))

    worker.toggle_show_progress.connect(lambda show: toggle_worker_progress(
        show, progress_bar))
        
    worker.toggle_show_cancel.connect(lambda show: toggle_worker_cancel(
        show, cancel_button))
        
    worker.finished.connect(lambda result: worker_finished(
        result, thread, worker, iface, message_bar))
        
    worker.error.connect(lambda e, exception_str: worker_error(
        e, exception_str, iface))
        
    worker.progress.connect(progress_bar.setValue)
    
    thread.started.connect(worker.run)
    
    thread.start()
    return thread, message_bar
예제 #27
0
    def handleMouseDown(self, point, button):
        #QMessageBox.information( self.iface.mainWindow(), "Info", "X,Y = %s,%s"%( str(point.x()), str(point.y()) ) )
        self.dlg.clearTextBrowser()
        self.dlg.setTextBrowser( str(point.x())+' , '+str(point.y()) )

        #Create a new thread to call the point index service
        thread = QThread(self)
        worker = self.worker = PointWorker(point)
        worker.moveToThread(thread)
        #Connect the slots
        thread.started.connect(worker.run)
        #Print the periodic status messages to the text browser
        worker.status.connect(self.dlg.setTextBrowser)
        worker.error.connect(self.workerError)
        #When done, call the pointWOrkerFinish to go to the next task
        worker.finished.connect(self.pointWorkerFinish)
        #Clean up the thread
        worker.finished.connect(worker.deleteLater)
        thread.finished.connect(thread.deleteLater)
        worker.finished.connect(thread.quit)
        thread.start()
예제 #28
0
    def worker_start(self, layer, field_name, iterations):
        """Start a worker instance on a background thread."""

        worker = CartogramWorker(layer, field_name, iterations)

        message_bar = self.iface.messageBar().createMessage('')

        label = QLabel('Creating cartogram...')
        label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)

        progress_bar = QProgressBar()
        progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        progress_bar.setMaximum(iterations * layer.featureCount())

        cancel_button = QPushButton()
        cancel_button.setText(self.tr('Cancel'))
        cancel_button.clicked.connect(worker.kill)

        message_bar.layout().addWidget(label)
        message_bar.layout().addWidget(progress_bar)
        message_bar.layout().addWidget(cancel_button)

        self.iface.messageBar().pushWidget(message_bar,
            self.iface.messageBar().INFO)
        self.message_bar = message_bar

        # start the worker in a new thread
        thread = QThread()
        worker.moveToThread(thread)

        # connect some odds and ends
        worker.finished.connect(self.worker_finished)
        worker.error.connect(self.worker_error)
        worker.progress.connect(progress_bar.setValue)
        thread.started.connect(worker.run)

        thread.start()

        self.thread = thread
        self.worker = worker
예제 #29
0
 class QHamegLCR(QObject, HamegLCR):
     """ 
         Extension of the HamegLCR class. It enables a number of
         nonblocking functionalities by employing the Qt signal-slot
         mechanism. Note that even though the object is self moved in 
         its separate thread, direct calling of it methods does not execute
         in this thread but in the thread from which the method was called.
     """
     values_signal = pyqtSignal(float, float)
     
     def __init__(self, *args, **kwargs):
         self.__lock = threading.Lock()
         
         QObject.__init__(self)
         HamegLCR.__init__(self, *args, **kwargs)
         
         self._thread = QThread()
         self._thread.start()
         
         self.moveToThread(self._thread)
    
     @pyqtSlot()
     def nonblockingGetValues(self):
         self.triggerAndWait()
             
         x1 = self.getMainValue()
         x2 = self.getSecondaryValue()
         
         self.values_signal.emit(x1, x2)
         
     def read(self):
         self.__lock.acquire()
         val = HamegLCR.read(self)
         self.__lock.release()
         return val
     
     def write(self, string):
         self.__lock.acquire()
         HamegLCR.write(self, string)
         self.__lock.release()        
    def worker_start(self, dir, url, id):
        """Start a worker instance on a background thread."""

        worker = NaturalEarthRasterWorker(dir, url, id)

        message_bar = self.iface.messageBar().createMessage('')

        label = QLabel('Downloading theme {}...'.format(id))
        label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)

        progress_bar = QProgressBar()
        progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        progress_bar.setMaximum(100)

        cancel_button = QPushButton()
        cancel_button.setText(self.tr('Cancel'))
        cancel_button.clicked.connect(worker.kill)

        message_bar.layout().addWidget(label)
        message_bar.layout().addWidget(progress_bar)
        message_bar.layout().addWidget(cancel_button)

        self.iface.messageBar().pushWidget(message_bar,
            self.iface.messageBar().INFO)
        self.message_bar = message_bar

        # start the worker in a new thread
        thread = QThread()
        worker.moveToThread(thread)

        # connect some odds and ends
        worker.finished.connect(self.worker_finished)
        worker.error.connect(self.worker_error)
        worker.progress.connect(progress_bar.setValue)
        thread.started.connect(worker.run)

        thread.start()

        self.thread = thread
        self.worker = worker
예제 #31
0
파일: addons.py 프로젝트: Python3pkg/OASYS1
class AddonManagerDialog(QDialog):
    def __init__(self, parent=None, **kwargs):
        super(AddonManagerDialog, self).__init__(parent, **kwargs)
        self.setLayout(QVBoxLayout())

        self.addonwidget = AddonManagerWidget()
        self.addonwidget.layout().setContentsMargins(0, 0, 0, 0)
        self.layout().addWidget(self.addonwidget)
        buttons = QDialogButtonBox(orientation=Qt.Horizontal,
                                   standardButtons=QDialogButtonBox.Ok
                                   | QDialogButtonBox.Cancel)
        buttons.accepted.connect(self.__accepted)
        buttons.rejected.connect(self.reject)

        self.layout().addWidget(buttons)

        self.__progress = QProgressDialog(
            self,
            Qt.Sheet,
            minimum=0,
            maximum=0,
            labelText=self.tr("Retrieving package list"),
            sizeGripEnabled=False,
            windowTitle="Progress")
        self.__progress.canceled.connect(self.reject)

        # The installer thread
        self.__thread = None
        # The installer object
        self.__installer = None

    @Slot(list)
    def setItems(self, items):
        self.addonwidget.setItems(items)

    def progressDialog(self):
        return self.__progress

    def done(self, retcode):
        super(AddonManagerDialog, self).done(retcode)
        if self.__thread is not None:
            self.__thread.quit()
            self.__thread.wait(1000)

    def closeEvent(self, event):
        super(AddonManagerDialog, self).closeEvent(event)
        if self.__thread is not None:
            self.__thread.quit()
            self.__thread.wait(1000)

    def __accepted(self):
        steps = self.addonwidget.itemState()

        if steps:
            # Move all uninstall steps to the front
            steps = sorted(steps,
                           key=lambda step: 0 if step[0] == Uninstall else 1)
            self.__installer = Installer(steps=steps)
            self.__thread = QThread(self)
            self.__thread.start()

            self.__installer.moveToThread(self.__thread)
            self.__installer.finished.connect(self.__on_installer_finished)
            self.__installer.error.connect(self.__on_installer_error)
            self.__installer.installStatusChanged.connect(
                self.__progress.setLabelText)

            self.__progress.show()
            self.__progress.setLabelText("Installing")

            self.__installer.start()

        else:
            self.accept()

    def __on_installer_error(self, command, pkg, retcode, output):
        message_error(
            "An error occurred while running a subprocess",
            title="Error",
            informative_text="{} exited with non zero status.".format(command),
            details="".join(output),
            parent=self)
        self.reject()

    def __on_installer_finished(self):
        message_information(
            "Please restart the application for changes to take effect.",
            parent=self)
        self.accept()
예제 #32
0
class XOrbRecordBox(XComboBox):
    __designer_group__ = 'ProjexUI - ORB'
    """ Defines a combo box that contains records from the ORB system. """
    loadRequested = Signal(object)

    loadingStarted = Signal()
    loadingFinished = Signal()
    currentRecordChanged = Signal(object)
    currentRecordEdited = Signal(object)
    initialized = Signal()

    def __init__(self, parent=None):
        # needs to be defined before the base class is initialized or the
        # event filter won't work
        self._treePopupWidget = None

        super(XOrbRecordBox, self).__init__(parent)

        # define custom properties
        self._currentRecord = None  # only used while loading
        self._changedRecord = -1

        self._tableTypeName = ''
        self._tableLookupIndex = ''
        self._baseHints = ('', '')
        self._tableType = None
        self._order = None
        self._query = None
        self._iconMapper = None
        self._labelMapper = str
        self._required = True
        self._loaded = False
        self._showTreePopup = False
        self._autoInitialize = False
        self._threadEnabled = True
        self._specifiedColumns = None
        self._specifiedColumnsOnly = False

        # create threading options
        self._worker = XOrbLookupWorker()
        self._workerThread = QThread()
        self._worker.moveToThread(self._workerThread)
        self._worker.setBatched(False)
        self._workerThread.start()

        # create connections
        self.loadRequested.connect(self._worker.loadRecords)
        self.lineEdit().textEntered.connect(self.assignCurrentRecord)
        self.lineEdit().editingFinished.connect(self.emitCurrentRecordEdited)
        self.lineEdit().returnPressed.connect(self.emitCurrentRecordEdited)

        self._worker.loadingStarted.connect(self.markLoadingStarted)
        self._worker.loadingFinished.connect(self.markLoadingFinished)
        self._worker.loadedRecords.connect(self.addRecordsFromThread)

        self.currentIndexChanged.connect(self.emitCurrentRecordChanged)
        QApplication.instance().aboutToQuit.connect(self.__cleanupWorker)

    def __del__(self):
        self.__cleanupWorker()

    def __cleanupWorker(self):
        if not self._workerThread:
            return

        thread = self._workerThread
        worker = self._worker

        self._workerThread = None
        self._worker = None

        worker.deleteLater()

        thread.finished.connect(thread.deleteLater)
        thread.quit()
        thread.wait()

    def addRecord(self, record):
        """
        Adds the given record to the system.
        
        :param      record | <str>
        """
        label_mapper = self.labelMapper()
        icon_mapper = self.iconMapper()

        self.addItem(label_mapper(record))
        self.setItemData(self.count() - 1, wrapVariant(record), Qt.UserRole)

        # load icon
        if icon_mapper:
            self.setItemIcon(self.count() - 1, icon_mapper(record))

        if self.showTreePopup():
            XOrbRecordItem(self.treePopupWidget(), record)

    def addRecords(self, records):
        """
        Adds the given record to the system.
        
        :param      records | [<orb.Table>, ..]
        """
        label_mapper = self.labelMapper()
        icon_mapper = self.iconMapper()

        # create the items to display
        tree = None
        if self.showTreePopup():
            tree = self.treePopupWidget()
            tree.blockSignals(True)
            tree.setUpdatesEnabled(False)

        # add the items to the list
        start = self.count()
        self.addItems(map(label_mapper, records))

        # update the item information
        for i, record in enumerate(records):
            index = start + i

            self.setItemData(index, wrapVariant(record), Qt.UserRole)

            if icon_mapper:
                self.setItemIcon(index, icon_mapper(record))

            if tree:
                XOrbRecordItem(tree, record)

        if tree:
            tree.blockSignals(False)
            tree.setUpdatesEnabled(True)

    def addRecordsFromThread(self, records):
        """
        Adds the given record to the system.
        
        :param      records | [<orb.Table>, ..]
        """
        label_mapper = self.labelMapper()
        icon_mapper = self.iconMapper()

        tree = None
        if self.showTreePopup():
            tree = self.treePopupWidget()

        # add the items to the list
        start = self.count()

        # update the item information
        blocked = self.signalsBlocked()
        self.blockSignals(True)
        for i, record in enumerate(records):
            index = start + i
            self.addItem(label_mapper(record))
            self.setItemData(index, wrapVariant(record), Qt.UserRole)

            if icon_mapper:
                self.setItemIcon(index, icon_mapper(record))

            if record == self._currentRecord:
                self.setCurrentIndex(self.count() - 1)

            if tree:
                XOrbRecordItem(tree, record)
        self.blockSignals(blocked)

    def acceptRecord(self, item):
        """
        Closes the tree popup and sets the current record.
        
        :param      record | <orb.Table>
        """
        record = item.record()
        self.treePopupWidget().close()
        self.setCurrentRecord(record)

    def assignCurrentRecord(self, text):
        """
        Assigns the current record from the inputed text.
        
        :param      text | <str>
        """
        if self.showTreePopup():
            item = self._treePopupWidget.currentItem()
            if item:
                self._currentRecord = item.record()
            else:
                self._currentRecord = None
            return

        # look up the record for the given text
        if text:
            index = self.findText(text)
        elif self.isRequired():
            index = 0
        else:
            index = -1

        # determine new record to look for
        record = self.recordAt(index)
        if record == self._currentRecord:
            return

        # set the current index and record for any changes
        self._currentRecord = record
        self.setCurrentIndex(index)

    def autoInitialize(self):
        """
        Returns whether or not this record box should auto-initialize its
        records.
        
        :return     <bool>
        """
        return self._autoInitialize

    def batchSize(self):
        """
        Returns the batch size to use when processing this record box's list
        of entries.
        
        :return     <int>
        """
        return self._worker.batchSize()

    def checkedRecords(self):
        """
        Returns a list of the checked records from this combo box.
        
        :return     [<orb.Table>, ..]
        """
        indexes = self.checkedIndexes()
        return map(self.recordAt, indexes)

    def currentRecord(self):
        """
        Returns the record found at the current index for this combo box.
        
        :rerturn        <orb.Table> || None
        """
        if self._currentRecord is None and self.isRequired():
            self._currentRecord = self.recordAt(self.currentIndex())
        return self._currentRecord

    def dragEnterEvent(self, event):
        """
        Listens for query's being dragged and dropped onto this tree.
        
        :param      event | <QDragEnterEvent>
        """
        data = event.mimeData()
        if data.hasFormat('application/x-orb-table') and \
           data.hasFormat('application/x-orb-query'):
            tableName = self.tableTypeName()
            if str(data.data('application/x-orb-table')) == tableName:
                event.acceptProposedAction()
                return
        elif data.hasFormat('application/x-orb-records'):
            event.acceptProposedAction()
            return

        super(XOrbRecordBox, self).dragEnterEvent(event)

    def dragMoveEvent(self, event):
        """
        Listens for query's being dragged and dropped onto this tree.
        
        :param      event | <QDragEnterEvent>
        """
        data = event.mimeData()
        if data.hasFormat('application/x-orb-table') and \
           data.hasFormat('application/x-orb-query'):
            tableName = self.tableTypeName()
            if str(data.data('application/x-orb-table')) == tableName:
                event.acceptProposedAction()
                return
        elif data.hasFormat('application/x-orb-records'):
            event.acceptProposedAction()
            return

        super(XOrbRecordBox, self).dragMoveEvent(event)

    def dropEvent(self, event):
        """
        Listens for query's being dragged and dropped onto this tree.
        
        :param      event | <QDropEvent>
        """
        # overload the current filtering options
        data = event.mimeData()
        if data.hasFormat('application/x-orb-table') and \
           data.hasFormat('application/x-orb-query'):
            tableName = self.tableTypeName()
            if str(data.data('application/x-orb-table')) == tableName:
                data = str(data.data('application/x-orb-query'))
                query = Q.fromXmlString(data)
                self.setQuery(query)
                return

        elif self.tableType() and data.hasFormat('application/x-orb-records'):
            from projexui.widgets.xorbtreewidget import XOrbTreeWidget
            records = XOrbTreeWidget.dataRestoreRecords(data)

            for record in records:
                if isinstance(record, self.tableType()):
                    self.setCurrentRecord(record)
                    return

        super(XOrbRecordBox, self).dropEvent(event)

    def emitCurrentRecordChanged(self):
        """
        Emits the current record changed signal for this combobox, provided \
        the signals aren't blocked.
        """
        record = unwrapVariant(self.itemData(self.currentIndex(), Qt.UserRole))
        if not Table.recordcheck(record):
            record = None

        self._currentRecord = record
        if not self.signalsBlocked():
            self._changedRecord = record
            self.currentRecordChanged.emit(record)

    def emitCurrentRecordEdited(self):
        """
        Emits the current record edited signal for this combobox, provided the
        signals aren't blocked and the record has changed since the last time.
        """
        if self._changedRecord == -1:
            return

        if self.signalsBlocked():
            return

        record = self._changedRecord
        self._changedRecord = -1
        self.currentRecordEdited.emit(record)

    def eventFilter(self, object, event):
        """
        Filters events for the popup tree widget.
        
        :param      object | <QObject>
                    event  | <QEvent>
        
        :retuen     <bool> | consumed
        """
        if not (object and object == self._treePopupWidget):
            return super(XOrbRecordBox, self).eventFilter(object, event)

        elif event.type() == event.KeyPress:
            # accept lookup
            if event.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab,
                               Qt.Key_Backtab):

                item = object.currentItem()
                text = self.lineEdit().text()

                if not text:
                    record = None
                    item = None

                elif isinstance(item, XOrbRecordItem):
                    record = item.record()

                if record and item.isSelected() and not item.isHidden():
                    self.hidePopup()
                    self.setCurrentRecord(record)
                    event.accept()
                    return True

                else:
                    self.setCurrentRecord(None)
                    self.hidePopup()
                    self.lineEdit().setText(text)
                    self.lineEdit().keyPressEvent(event)
                    event.accept()
                    return True

            # cancel lookup
            elif event.key() == Qt.Key_Escape:
                text = self.lineEdit().text()
                self.setCurrentRecord(None)
                self.lineEdit().setText(text)
                self.hidePopup()
                event.accept()
                return True

            # update the search info
            else:
                self.lineEdit().keyPressEvent(event)

        elif event.type() == event.Show:
            object.resizeToContents()
            object.horizontalScrollBar().setValue(0)

        elif event.type() == event.KeyRelease:
            self.lineEdit().keyReleaseEvent(event)

        elif event.type() == event.MouseButtonPress:
            local_pos = object.mapFromGlobal(event.globalPos())
            in_widget = object.rect().contains(local_pos)

            if not in_widget:
                text = self.lineEdit().text()
                self.setCurrentRecord(None)
                self.lineEdit().setText(text)
                self.hidePopup()
                event.accept()
                return True

        return super(XOrbRecordBox, self).eventFilter(object, event)

    def focusNextChild(self, event):
        if not self.isLoading():
            self.assignCurrentRecord(self.lineEdit().text())

        return super(XOrbRecordBox, self).focusNextChild(event)

    def focusNextPrevChild(self, event):
        if not self.isLoading():
            self.assignCurrentRecord(self.lineEdit().text())

        return super(XOrbRecordBox, self).focusNextPrevChild(event)

    def focusInEvent(self, event):
        """
        When this widget loses focus, try to emit the record changed event
        signal.
        """
        self._changedRecord = -1
        super(XOrbRecordBox, self).focusInEvent(event)

    def focusOutEvent(self, event):
        """
        When this widget loses focus, try to emit the record changed event
        signal.
        """
        if not self.isLoading():
            self.assignCurrentRecord(self.lineEdit().text())

        super(XOrbRecordBox, self).focusOutEvent(event)

    def hidePopup(self):
        """
        Overloads the hide popup method to handle when the user hides
        the popup widget.
        """
        if self._treePopupWidget and self.showTreePopup():
            self._treePopupWidget.close()

        super(XOrbRecordBox, self).hidePopup()

    def iconMapper(self):
        """
        Returns the icon mapping method to be used for this combobox.
        
        :return     <method> || None
        """
        return self._iconMapper

    def isLoading(self):
        """
        Returns whether or not this combobox is loading records.
        
        :return     <bool>
        """
        return self._worker.isRunning()

    def isRequired(self):
        """
        Returns whether or not this combo box requires the user to pick a
        selection.
        
        :return     <bool>
        """
        return self._required

    def isThreadEnabled(self):
        """
        Returns whether or not threading is enabled for this combo box.
        
        :return     <bool>
        """
        return self._threadEnabled

    def labelMapper(self):
        """
        Returns the label mapping method to be used for this combobox.
        
        :return     <method> || None
        """
        return self._labelMapper

    @Slot(object)
    def lookupRecords(self, record):
        """
        Lookups records based on the inputed record.  This will use the 
        tableLookupIndex property to determine the Orb Index method to
        use to look up records.  That index method should take the inputed
        record as an argument, and return a list of records.
        
        :param      record | <orb.Table>
        """
        table_type = self.tableType()
        if not table_type:
            return

        index = getattr(table_type, self.tableLookupIndex(), None)
        if not index:
            return

        self.setRecords(index(record))

    def markLoadingStarted(self):
        """
        Marks this widget as loading records.
        """
        if self.isThreadEnabled():
            XLoaderWidget.start(self)

        if self.showTreePopup():
            tree = self.treePopupWidget()
            tree.setCursor(Qt.WaitCursor)
            tree.clear()
            tree.setUpdatesEnabled(False)
            tree.blockSignals(True)

            self._baseHints = (self.hint(), tree.hint())
            tree.setHint('Loading records...')
            self.setHint('Loading records...')
        else:
            self._baseHints = (self.hint(), '')
            self.setHint('Loading records...')

        self.setCursor(Qt.WaitCursor)
        self.blockSignals(True)
        self.setUpdatesEnabled(False)

        # prepare to load
        self.clear()
        use_dummy = not self.isRequired() or self.isCheckable()
        if use_dummy:
            self.addItem('')

        self.loadingStarted.emit()

    def markLoadingFinished(self):
        """
        Marks this widget as finished loading records.
        """
        XLoaderWidget.stop(self, force=True)

        hint, tree_hint = self._baseHints
        self.setHint(hint)

        # set the tree widget
        if self.showTreePopup():
            tree = self.treePopupWidget()
            tree.setHint(tree_hint)
            tree.unsetCursor()
            tree.setUpdatesEnabled(True)
            tree.blockSignals(False)

        self.unsetCursor()
        self.blockSignals(False)
        self.setUpdatesEnabled(True)
        self.loadingFinished.emit()

    def order(self):
        """
        Returns the ordering for this widget.
        
        :return     [(<str> column, <str> asc|desc, ..] || None
        """
        return self._order

    def query(self):
        """
        Returns the query used when querying the database for the records.
        
        :return     <Query> || None
        """
        return self._query

    def records(self):
        """
        Returns the record list that ist linked with this combo box.
        
        :return     [<orb.Table>, ..]
        """
        records = []
        for i in range(self.count()):
            record = self.recordAt(i)
            if record:
                records.append(record)
        return records

    def recordAt(self, index):
        """
        Returns the record at the inputed index.
        
        :return     <orb.Table> || None
        """
        return unwrapVariant(self.itemData(index, Qt.UserRole))

    def refresh(self, records):
        """
        Refreshs the current user interface to match the latest settings.
        """
        self._loaded = True

        if self.isLoading():
            return

        # load the information
        if RecordSet.typecheck(records):
            table = records.table()
            self.setTableType(table)

            if self.order():
                records.setOrder(self.order())

            # load specific data for this record box
            if self.specifiedColumnsOnly():
                records.setColumns(
                    map(lambda x: x.name(), self.specifiedColumns()))

            # load the records asynchronously
            if self.isThreadEnabled() and \
               table and \
               table.getDatabase().isThreadEnabled():
                # assign ordering based on tree table
                if self.showTreePopup():
                    tree = self.treePopupWidget()
                    if tree.isSortingEnabled():
                        col = tree.sortColumn()
                        colname = tree.headerItem().text(col)
                        column = table.schema().column(colname)

                        if column:
                            if tree.sortOrder() == Qt.AscendingOrder:
                                sort_order = 'asc'
                            else:
                                sort_order = 'desc'

                            records.setOrder([(column.name(), sort_order)])

                self.loadRequested.emit(records)
                return

        # load the records synchronously
        self.loadingStarted.emit()
        curr_record = self.currentRecord()
        self.blockSignals(True)
        self.setUpdatesEnabled(False)
        self.clear()
        use_dummy = not self.isRequired() or self.isCheckable()
        if use_dummy:
            self.addItem('')
        self.addRecords(records)
        self.setUpdatesEnabled(True)
        self.blockSignals(False)
        self.setCurrentRecord(curr_record)
        self.loadingFinished.emit()

    def setAutoInitialize(self, state):
        """
        Sets whether or not this combo box should auto initialize itself
        when it is shown.
        
        :param      state | <bool>
        """
        self._autoInitialize = state

    def setBatchSize(self, size):
        """
        Sets the batch size of records to look up for this record box.
        
        :param      size | <int>
        """
        self._worker.setBatchSize(size)

    def setCheckedRecords(self, records):
        """
        Sets the checked off records to the list of inputed records.
        
        :param      records | [<orb.Table>, ..]
        """
        QApplication.sendPostedEvents(self, -1)
        indexes = []

        for i in range(self.count()):
            record = self.recordAt(i)
            if record is not None and record in records:
                indexes.append(i)

        self.setCheckedIndexes(indexes)

    def setCurrentRecord(self, record, autoAdd=False):
        """
        Sets the index for this combobox to the inputed record instance.
        
        :param      record      <orb.Table>
        
        :return     <bool> success
        """
        if record is not None and not Table.recordcheck(record):
            return False

        # don't reassign the current record
        # clear the record
        if record is None:
            self._currentRecord = None
            blocked = self.signalsBlocked()
            self.blockSignals(True)
            self.setCurrentIndex(-1)
            self.blockSignals(blocked)

            if not blocked:
                self.currentRecordChanged.emit(None)

            return True

        elif record == self.currentRecord():
            return False

        self._currentRecord = record
        found = False

        blocked = self.signalsBlocked()
        self.blockSignals(True)
        for i in range(self.count()):
            stored = unwrapVariant(self.itemData(i, Qt.UserRole))
            if stored == record:
                self.setCurrentIndex(i)
                found = True
                break

        if not found and autoAdd:
            self.addRecord(record)
            self.setCurrentIndex(self.count() - 1)

        self.blockSignals(blocked)

        if not blocked:
            self.currentRecordChanged.emit(record)
        return False

    def setIconMapper(self, mapper):
        """
        Sets the icon mapping method for this combobox to the inputed mapper. \
        The inputed mapper method should take a orb.Table instance as input \
        and return a QIcon as output.
        
        :param      mapper | <method> || None
        """
        self._iconMapper = mapper

    def setLabelMapper(self, mapper):
        """
        Sets the label mapping method for this combobox to the inputed mapper.\
        The inputed mapper method should take a orb.Table instance as input \
        and return a string as output.
        
        :param      mapper | <method>
        """
        self._labelMapper = mapper

    def setOrder(self, order):
        """
        Sets the order for this combo box to the inputed order.  This will
        be used in conjunction with the query when loading records to the
        combobox.
        
        :param      order | [(<str> column, <str> asc|desc), ..] || None
        """
        self._order = order

    def setQuery(self, query, autoRefresh=True):
        """
        Sets the query for this record box for generating records.
        
        :param      query | <Query> || None
        """
        self._query = query

        tableType = self.tableType()
        if not tableType:
            return False

        if autoRefresh:
            self.refresh(tableType.select(where=query))

        return True

    def setRecords(self, records):
        """
        Sets the records on this combobox to the inputed record list.
        
        :param      records | [<orb.Table>, ..]
        """
        self.refresh(records)

    def setRequired(self, state):
        """
        Sets the required state for this combo box.  If the column is not
        required, a blank record will be included with the choices.
        
        :param      state | <bool>
        """
        self._required = state

    def setShowTreePopup(self, state):
        """
        Sets whether or not to use an ORB tree widget in the popup for this
        record box.
        
        :param      state | <bool>
        """
        self._showTreePopup = state

    def setSpecifiedColumns(self, columns):
        """
        Sets the specified columns for this combobox widget.
        
        :param      columns | [<orb.Column>, ..] || [<str>, ..] || None
        """
        self._specifiedColumns = columns
        self._specifiedColumnsOnly = columns is not None

    def setSpecifiedColumnsOnly(self, state):
        """
        Sets whether or not only specified columns should be
        loaded for this record box.
        
        :param      state | <bool>
        """
        self._specifiedColumnsOnly = state

    def setTableLookupIndex(self, index):
        """
        Sets the name of the index method that will be used to lookup
        records for this combo box.
        
        :param    index | <str>
        """
        self._tableLookupIndex = str(index)

    def setTableType(self, tableType):
        """
        Sets the table type for this record box to the inputed table type.
        
        :param      tableType | <orb.Table>
        """
        self._tableType = tableType

        if tableType:
            self._tableTypeName = tableType.schema().name()
        else:
            self._tableTypeName = ''

    def setTableTypeName(self, name):
        """
        Sets the table type name for this record box to the inputed name.
        
        :param      name | <str>
        """
        self._tableTypeName = str(name)
        self._tableType = None

    def setThreadEnabled(self, state):
        """
        Sets whether or not threading should be enabled for this widget.  
        Actual threading will be determined by both this property, and whether
        or not the active ORB backend supports threading.
        
        :param      state | <bool>
        """
        self._threadEnabled = state

    def setVisible(self, state):
        """
        Sets the visibility for this record box.
        
        :param      state | <bool>
        """
        super(XOrbRecordBox, self).setVisible(state)

        if state and not self._loaded:
            if self.autoInitialize():
                table = self.tableType()
                if not table:
                    return

                self.setRecords(table.select(where=self.query()))
            else:
                self.initialized.emit()

    def showPopup(self):
        """
        Overloads the popup method from QComboBox to display an ORB tree widget
        when necessary.
        
        :sa     setShowTreePopup
        """
        if not self.showTreePopup():
            return super(XOrbRecordBox, self).showPopup()

        tree = self.treePopupWidget()

        if tree and not tree.isVisible():
            tree.move(self.mapToGlobal(QPoint(0, self.height())))
            tree.resize(self.width(), 250)
            tree.resizeToContents()
            tree.filterItems('')
            tree.setFilteredColumns(range(tree.columnCount()))
            tree.show()

    def showTreePopup(self):
        """
        Sets whether or not to use an ORB tree widget in the popup for this
        record box.
        
        :return     <bool>
        """
        return self._showTreePopup

    def specifiedColumns(self):
        """
        Returns the list of columns that are specified based on the column
        view for this widget.
        
        :return     [<orb.Column>, ..]
        """
        columns = []
        table = self.tableType()
        tree = self.treePopupWidget()
        schema = table.schema()

        if self._specifiedColumns is not None:
            colnames = self._specifiedColumns
        else:
            colnames = tree.columns()

        for colname in colnames:
            if isinstance(colname, Column):
                columns.append(colname)
            else:
                col = schema.column(colname)
                if col and not col.isProxy():
                    columns.append(col)

        return columns

    def specifiedColumnsOnly(self):
        """
        Returns whether or not only specified columns should be loaded
        for this record box.
        
        :return     <int>
        """
        return self._specifiedColumnsOnly

    def tableLookupIndex(self):
        """
        Returns the name of the index method that will be used to lookup
        records for this combo box.
        
        :return     <str>
        """
        return self._tableLookupIndex

    def tableType(self):
        """
        Returns the table type for this instance.
        
        :return     <subclass of orb.Table> || None
        """
        if not self._tableType:
            if self._tableTypeName:
                self._tableType = Orb.instance().model(str(
                    self._tableTypeName))

        return self._tableType

    def tableTypeName(self):
        """
        Returns the table type name that is set for this combo box.
        
        :return     <str>
        """
        return self._tableTypeName

    def treePopupWidget(self):
        """
        Returns the popup widget for this record box when it is supposed to
        be an ORB tree widget.
        
        :return     <XTreeWidget>
        """
        if not self._treePopupWidget:
            # create the treewidget
            tree = XTreeWidget(self)
            tree.setWindowFlags(Qt.Popup)
            tree.setFocusPolicy(Qt.StrongFocus)
            tree.installEventFilter(self)
            tree.setAlternatingRowColors(True)
            tree.setShowGridColumns(False)
            tree.setRootIsDecorated(False)
            tree.setVerticalScrollMode(tree.ScrollPerPixel)

            # create connections
            tree.itemClicked.connect(self.acceptRecord)

            self.lineEdit().textEdited.connect(tree.filterItems)
            self.lineEdit().textEdited.connect(self.showPopup)

            self._treePopupWidget = tree

        return self._treePopupWidget

    def worker(self):
        """
        Returns the worker object for loading records for this record box.
        
        :return     <XOrbLookupWorker>
        """
        return self._worker

    x_batchSize = Property(int, batchSize, setBatchSize)
    x_required = Property(bool, isRequired, setRequired)
    x_tableTypeName = Property(str, tableTypeName, setTableTypeName)
    x_tableLookupIndex = Property(str, tableLookupIndex, setTableLookupIndex)
    x_showTreePopup = Property(bool, showTreePopup, setShowTreePopup)
    x_threadEnabled = Property(bool, isThreadEnabled, setThreadEnabled)
예제 #33
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()
예제 #34
0
class SearchPlugin(widget, base, Page):
    title = "Search"
    icon = resolve("search.svg")

    def __init__(self, api, parent=None):
        super(SearchPlugin, self).__init__(parent)
        self.setupUi(self)
        self.api = api
        self.project = None
        self.dbpath = None
        self.flickcharm = FlickCharm()
        self.flickcharm.activateOn(self.resultsView)
        self.searchbox.textChanged.connect(self.search)
        self.searchbox.installEventFilter(self)
        self.resultsView.itemClicked.connect(self.jump_to)
        self.rebuildLabel.linkActivated.connect(self.rebuild_index)
        self.fuzzyCheck.stateChanged.connect(self.fuzzy_changed)
        self.indexbuilder = None
        self.indexthread = None

    def fuzzy_changed(self, state):
        self.search(self.searchbox.text())

    def index_built(self, dbpath, timing):
        self.dbpath = dbpath
        self.resultsView.clear()
        self.searchbox.setEnabled(True)
        print "Index built in: {} seconds".format(timing)

    def eventFilter(self, object, event):
        if event.type() == QEvent.FocusIn:
            RoamEvents.openkeyboard.emit()
        return False

    @property
    def db(self):
        db = sqlite3.connect(self.dbpath)
        db.create_function("rank", 1, make_rank_func((1., .1, 0, 0)))
        return db

    def project_loaded(self, project):
        self.project = project
        self.build_index(project)

    def rebuild_index(self):
        self.build_index(self.project)

    def build_index(self, project):
        self.searchbox.setEnabled(False)
        self.resultsView.setEnabled(False)
        self.resultsView.addItem("Just let me build the search index first....")

        validformat, settings = valid_search_settings(project.settings)
        if not validformat:
            RoamEvents.raisemessage("Searching", "Invalid search config.", level=1)
            self.searchbox.hide()
            self.resultsView.clear()
            self.resultsView.addItem("Invalid search config found")
            return

        self.indexthread = QThread()
        self.indexbuilder = IndexBuilder(project.folder, settings)
        self.indexbuilder.moveToThread(self.indexthread)

        self.indexbuilder.indexBuilt.connect(self.index_built)
        self.indexbuilder.finished.connect(self.indexthread.quit)
        self.indexthread.started.connect(self.indexbuilder.build_index)
        self.indexthread.finished.connect(self.indexbuilder.quit)

        self.indexthread.start()

    def search(self, text):
        db = self.db
        c = db.cursor()
        self.resultsView.clear()
        self.resultsView.setEnabled(False)
        if not text:
            return

        if self.fuzzyCheck.isChecked():
            search = "* ".join(text.split()) + "*"
        else:
            search = text
        query = c.execute("""SELECT layer, featureid, snippet(search, '[',']') as snippet
                            FROM search
                            JOIN featureinfo on search.docid = featureinfo.id
                            WHERE search match '{}' LIMIT 100""".format(search)).fetchall()
        for layer, featureid, snippet in query:
            item = QListWidgetItem()
            text = "{}\n {}".format(layer, snippet.replace('\n', ' '))
            item.setText(text)
            item.setData(Qt.UserRole, (layer, featureid, snippet))
            self.resultsView.addItem(item)

        self.resultsView.setEnabled(True)

        if self.resultsView.count() == 0:
            self.resultsView.addItem("No Results")
        db.close()

    def jump_to(self, item):
        data = item.data(32)
        layername, fid = data[0], data[1]
        layer = roam.api.utils.layer_by_name(layername)
        layer.select(fid)
        feature = layer.selectedFeatures()[0]
        self.api.mainwindow.canvas.zoomToSelected(layer)
        layer.removeSelection()
        self.api.mainwindow.showmap()
        RoamEvents.selectionchanged.emit({layer: [feature]})
    transmitter = Transmitter()
    debug_object(transmitter)
    transmitter.moveToThread(tx_thread)
    debug_object(transmitter)

    rx_thread = QThread()
    debug_thread("rx_thread", rx_thread)
    if USE_DERIVED:
        receiver = Derived()
    else:
        receiver = Base()
    debug_object(receiver)
    receiver.moveToThread(rx_thread)
    debug_object(receiver)

    # Signals: startup
    tx_thread.started.connect(transmitter.start)
    rx_thread.started.connect(receiver.start)
    # ... shutdown
    transmitter.finished.connect(tx_thread.quit)
    tx_thread.finished.connect(rx_thread.quit)
    rx_thread.finished.connect(app.quit)
    # ... action
    transmitter.transmit.connect(receiver.receive)

    # Go
    rx_thread.start()
    tx_thread.start()
    report("Starting app")
    app.exec_()
예제 #36
0
class Runner:
    """A wrapper around thread and worker objects

    Correctly starts a new thread and moves worker to it.
    """
    def __init__(self, cls):
        """Store worker class in instance"""
        self.cls = cls
        self.running = False

    def start(self, *args, **kwargs):
        """Starts worker in separate thread"""
        # stop any previously running workers
        self.stop()
        self.result = None
        self.error = None
        self.running = True

        self.thread = QThread()
        self.worker = self.cls(*args, **kwargs)
        self.worker.moveToThread(self.thread)

        self.thread.started.connect(self.worker.start)
        # graceful stop does not work without direct connection (?)
        self.worker.finished.connect(self.thread.quit, Qt.DirectConnection)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)

        # also save result/error on finish (useful for testing)
        self.worker.finished.connect(self.handlefinished, Qt.DirectConnection)
        self.worker.raised.connect(self.handleraised, Qt.DirectConnection)
        self.worker.completed.connect(self.handlecompleted,
                                      Qt.DirectConnection)
        self.worker.killed.connect(self.handlekilled, Qt.DirectConnection)

        self.thread.start()

        # returns worker so caller can connect signals, etc.
        return self.worker

    def stop(self):
        """Attempts to gracefully stop worker

        Forcefully terminates otherwise."""
        logging.debug('Worker: trying to stop gracefully')
        if not self.running:
            logging.debug('Worker was not running')
            return
        try:
            self.worker.kill()
            if not self.thread.wait(settings.KILL_TIMEOUT):
                raise KillTimeoutError()
        except KillTimeoutError:
            logging.warn('Worker: kill timed out, force terminating...')
            self.thread.terminate()
            self.thread.wait()
        except Exception as e:
            logging.warn('Worker: terminate failed!?')
            logging.warn(e)

    # The following methods are for testing
    @pyqtSlot(str)
    def handleraised(self, error):
        """Slot that saves error, useful for testing"""
        logging.warn('[WORKER] raised: {}'.format(error))
        self.error = error

    @pyqtSlot(object)
    def handlefinished(self):
        logging.debug('[WORKER] finished')
        self.running = False

    @pyqtSlot(object)
    def handlecompleted(self, result):
        """Slot that saves result, useful for testing"""
        logging.debug('[WORKER] completed')
        self.result = result

    @pyqtSlot(object)
    def handlekilled(self):
        logging.debug('[WORKER] killed')

    def wait(self, timeout):
        """Wait for thread to end, and return result

        Useful for testing.
        """
        try:
            self.thread.wait(timeout)
            return self.result
        except:
            return None
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)
예제 #38
0
                             input_AH_path=self.lqf_path,
                             output_path=self.save_refined_file,
                             lat=self.lat,
                             lon=self.lon,
                             hgt=self.site_height,
                             UTC_offset_h=UTC_offset_h,
                             rainAmongN=self.rainy_hours)

        thr = QThread(self.dlg)
        worker.moveToThread(thr)
        worker.finished.connect(self.refine_worker_finished)
        worker.error.connect(self.refine_worker_error)
        worker.update.connect(self.update_progress)

        thr.started.connect(worker.run)
        thr.start()
        self.refine_thread = thr
        self.refine_worker = worker
        self.dlg.progressBar.setValue(0)

    def select_point(self):  # Connected to "Seelct Point on Canves"
        self.canvas.setMapTool(self.pointTool)  # Calls a canvas click and create_point
        self.dlg.setEnabled(False)

    def create_point(self, point):  # Var kommer point ifran???
        # report map coordinates from a canvas click
        self.dlg.setEnabled(True)
        self.dlg.activateWindow()

        canvas = self.iface.mapCanvas()
        srs = canvas.mapSettings().destinationCrs()
예제 #39
0
class MainWindow(QMainWindow):

    def __init__(self, width=None, height=None):
        super(QMainWindow, self).__init__()

        self.requested_width = width
        self.requested_height = height
        if self.requested_width and self.requested_height:
            self.resize(self.requested_width, self.requested_height)
        self.setWindowTitle(Constants.APP_TITLE)
        self.setWindowIcon(QIcon(Constants.intpath(Constants.PNG_ICON)))
        self.setWindowFlags(Qt.WindowMinimizeButtonHint)
        self.reset()

        QMessageBox.information(
            self,
            Constants.APP_TITLE,
            "Cette application vous permet d'exporter les données d'une "
            "collecte mobile effectuée avec ODK Collect et ODK Aggregate.\n\n"
            "Commencez par exporter vos données au format JSON depuis "
            "l'interface web d'ODK Aggregate ({odk_url}) puis utilisez cette "
            "application pour générer les formulaires d'enquêtes remplis.\n\n"
            "Ils seront ensuite disponible au format PDF pour impression et "
            "seront accompagnés de tous les médias (photos) pour transfert "
            "aux autres département par clé USB.\n\n"
            "{author} - {email} - {phone}\n{copy} - {date}"
            .format(author=Constants.AUTHOR,
                    copy=Constants.AUTHOR_COPY,
                    date=Constants.APP_DATE,
                    email=Constants.AUTHOR_EMAIL,
                    phone=Constants.AUTHOR_PHONE,
                    odk_url=Constants.AGGREGATE_URL),
            QMessageBox.Ok,
            QMessageBox.NoButton)

    def change_context(self, context_widget, *args, **kwargs):
        self.view_widget = context_widget(parent=self, *args, **kwargs)
        self.setCentralWidget(self.view_widget)

    def open_dialog(self, dialog, modal=False, opacity=0.98, *args, **kwargs):
        d = dialog(parent=self, *args, **kwargs)
        d.setModal(modal)
        d.setWindowOpacity(opacity)
        d.exec_()

    # override
    def closeEvent(self, event):
        if self.exporter.is_running:
            event.ignore()

            logger.debug("exporter running, cancelling...")
            self.exporter.cancel()

            # wait for canceled signal to exit (after warning popup)
            self.is_exiting = True
            return
        super(MainWindow, self).closeEvent(event)

    def do_close(self):
        self.is_exiting = False
        self.close()

    def reset(self):
        self.statusbar = StatusBar(self)
        self.setStatusBar(self.statusbar)
        self.change_context(HomeWidget)

        # exporter
        self.exporter = RamedExporter(main_window=self)
        self.exporter_thread = QThread()
        self.exporter.moveToThread(self.exporter_thread)
        self.exporter.export_ended.connect(self.exporter_thread.quit)
        self.exporter.export_canceled.connect(self.exporter_thread.quit)
        self.exporter_thread.started.connect(self.exporter.start)
        self.is_exiting = False

    def resizeEvent(self, event):
        """lancé à chaque redimensionnement de la fenêtre"""
        # Ajustement en fonction du container
        self.wc = self.width()
        self.hc = self.height()

    @pyqtSlot()
    def check_started(self):
        logger.debug("check started")

    @pyqtSlot(bool, str)
    def check_ended(self, succeeded, error_message):
        logger.debug("check ended: {}, {}".format(succeeded, error_message))
        if succeeded:
            self.view_widget.start_export()
        else:
            self.view_widget.display_missing_aggregate_confirmation()

    @pyqtSlot()
    def parsing_started(self):
        logger.debug("parsing started")

    @pyqtSlot(bool, int, str)
    def parsing_ended(self, succeeded, nb_instances, error_message):
        logger.debug("parsing ended: {}, {}, {}"
                     .format(succeeded, nb_instances, error_message))
        if succeeded:
            self.exporter_thread.start()

    @pyqtSlot(str)
    def export_started(self):
        logger.debug("export_started")

    @pyqtSlot(str, int)
    def exporting_instance(self, ident, index):
        logger.debug("exporting_instance")
        self.statusbar.showMessage(ident)

    @pyqtSlot(bool, int)
    def instance_completed(self, succeeded, index):
        logger.debug("instance_completed")

    @pyqtSlot(int, int, int, int)
    def export_ended(self,
                     nb_instances_successful, nb_instances_failed,
                     nb_medias_successful, nb_medias_failed):
        logger.debug("export_ended: {}, {}"
                     .format(nb_instances_successful, nb_instances_failed))
        self.statusbar.reset()
        self.change_context(ConfirmationWidget,
                            nb_instances_successful=nb_instances_successful,
                            nb_instances_failed=nb_instances_failed,
                            nb_medias_successful=nb_medias_successful,
                            nb_medias_failed=nb_medias_failed,
                            from_date=self.view_widget.from_date,
                            to_date=self.view_widget.to_date)

    @pyqtSlot()
    def export_canceled(self):
        self.statusbar.reset()

    @pyqtSlot(str)
    def export_error_raised(self, error_message):
        logger.debug("export_error_raised: {}".format(error_message))
예제 #40
0
class Photo2ShapeDialog(BASE, WIDGET):
    def __init__(self, iface, parent=None):
        super(Photo2ShapeDialog, self).__init__(parent)
        self.setupUi(self)

        self.iface = iface

        self.settings = QSettings('alexbruy', 'photo2shape')

        self.thread = QThread()
        self.importer = PhotoImporter()

        self.btnOk = self.buttonBox.button(QDialogButtonBox.Ok)
        self.btnClose = self.buttonBox.button(QDialogButtonBox.Close)

        self.btnSelectInput.clicked.connect(self.selectDirectory)
        self.btnSelectOutput.clicked.connect(self.selectFile)

        self.importer.moveToThread(self.thread)
        self.importer.importError.connect(self.thread.quit)
        self.importer.importError.connect(self.importCanceled)
        self.importer.importMessage.connect(self.logMessage)
        self.importer.importFinished.connect(self.thread.quit)
        self.importer.importFinished.connect(self.importCompleted)
        self.importer.photoProcessed.connect(self.updateProgress)

        self.thread.started.connect(self.importer.importPhotos)

        self.manageGui()

    def manageGui(self):
        self.chkRecurse.setChecked(self.settings.value('recurse', True, bool))
        self.chkAppend.setChecked(self.settings.value('append', True, bool))
        self.chkLoadLayer.setChecked(
            self.settings.value('loadLayer', True, bool))

    def closeEvent(self, event):
        self._saveSettings()
        QDialog.closeEvent(self, event)

    def selectDirectory(self):
        lastDir = self.settings.value('lastPhotosDir', '.')
        dirName = QFileDialog.getExistingDirectory(self,
                                                   self.tr('Select directory'),
                                                   lastDir)

        if dirName == '':
            return

        self.lePhotosPath.setText(dirName)
        self.settings.setValue('lastPhotosDir', os.path.dirname(dirName))

    def selectFile(self):
        lastDir = self.settings.value('lastShapeDir', '.')
        shpFilter = self.tr('ESRI Shapefiles (*.shp *.SHP)')
        self.encoding = self.settings.value('encoding', 'System')

        fileDialog = QgsEncodingFileDialog(self, self.tr('Save file'), lastDir,
                                           shpFilter, self.encoding)

        fileDialog.setDefaultSuffix('shp')
        fileDialog.setFileMode(QFileDialog.AnyFile)
        fileDialog.setAcceptMode(QFileDialog.AcceptSave)
        fileDialog.setConfirmOverwrite(True)

        if fileDialog.exec_():
            fileName = fileDialog.selectedFiles()[0]
            self.encoding = fileDialog.encoding()

            self.leOutputShape.setText(fileName)
            self.settings.setValue(
                'lastShapeDir',
                QFileInfo(fileName).absoluteDir().absolutePath())
            self.settings.setValue('encoding', self.encoding)

    def reject(self):
        self._saveSettings()
        QDialog.reject(self)

    def accept(self):
        self._saveSettings()

        dirName = self.lePhotosPath.text()
        if dirName == '':
            self.iface.messageBar().pushWarning(
                self.tr('Path not set'),
                self.tr('Path to photos is not set. Please specify directory '
                        'with photos and try again.'))
            return

        fileName = self.leOutputShape.text()
        if fileName == '':
            self.iface.messageBar().pushWarning(
                self.tr('Output file is not set'),
                self.tr('Output file name is missing. Please specify correct '
                        'output file and try again.'))
            return

        self.importer.setPhotosDirectory(dirName)
        self.importer.setOutputPath(fileName)
        self.importer.setEncoding(self.encoding)
        self.importer.setRecurseDirs(self.chkRecurse.isChecked())
        self.importer.setAppendFile(self.chkAppend.isChecked())

        self.thread.start()

        self.btnOk.setEnabled(False)
        self.btnClose.setEnabled(False)

    def updateProgress(self, value):
        self.progressBar.setValue(value)

    def logMessage(self, message, level=QgsMessageLog.INFO):
        QgsMessageLog.logMessage(message, 'Photo2Shape', level)

    def importCanceled(self, message):
        self.iface.messageBar().pushWarning(message)
        self._restoreGui()

    def importCompleted(self):
        self.iface.messageBar().pushSuccess(
            self.tr('Import completed'),
            self.tr('Shapefile from photos sucessfully created'))
        if self.chkLoadLayer.isChecked():
            self._loadLayer()

        self._restoreGui()

    def _loadLayer(self):
        fName = self.leOutputShape.text()
        layer = QgsVectorLayer(fName, QFileInfo(fName).baseName(), 'ogr')

        if layer.isValid():
            layer.loadNamedStyle(
                os.path.join(pluginPath, 'resources', 'photos.qml'))
            QgsMapLayerRegistry.instance().addMapLayer(layer)
        else:
            self.iface.messageBar().pushWarning(
                self.tr('No output'), self.tr('Cannot load output shapefile'))

    def _restoreGui(self):
        self.progressBar.setValue(0)
        self.btnOk.setEnabled(True)
        self.btnClose.setEnabled(True)

    def _saveSettings(self):
        self.settings.setValue('recurse', self.chkRecurse.isChecked())
        self.settings.setValue('append', self.chkAppend.isChecked())
        self.settings.setValue('loadLayer', self.chkLoadLayer.isChecked())
예제 #41
0
파일: threads.py 프로젝트: MagSec-Arts/enki
 def start(self):
     """Ensure thread is stopped, and start it
     """
     self.stop()
     self._exit = False
     QThread.start(self)
예제 #42
0
파일: addons.py 프로젝트: asenzh/orange3
class AddonManagerDialog(QDialog):
    _packages = None

    def __init__(self, parent=None, **kwargs):
        super().__init__(parent, acceptDrops=True, **kwargs)
        self.setLayout(QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)

        self.addonwidget = AddonManagerWidget()
        self.layout().addWidget(self.addonwidget)

        info_bar = QWidget()
        info_layout = QHBoxLayout()
        info_bar.setLayout(info_layout)
        self.layout().addWidget(info_bar)

        buttons = QDialogButtonBox(orientation=Qt.Horizontal,
                                   standardButtons=QDialogButtonBox.Ok
                                   | QDialogButtonBox.Cancel)
        buttons.accepted.connect(self.__accepted)
        buttons.rejected.connect(self.reject)

        self.layout().addWidget(buttons)

        # No system access => install into user site-packages
        self.user_install = not os.access(sysconfig.get_path("purelib"),
                                          os.W_OK)

        self._executor = concurrent.futures.ThreadPoolExecutor(max_workers=1)
        if AddonManagerDialog._packages is None:
            self._f_pypi_addons = self._executor.submit(list_pypi_addons)
        else:
            self._f_pypi_addons = concurrent.futures.Future()
            self._f_pypi_addons.set_result(AddonManagerDialog._packages)

        self._f_pypi_addons.add_done_callback(
            method_queued(self._set_packages, (object, )))

        self.__progress = QProgressDialog(
            self,
            Qt.Sheet,
            minimum=0,
            maximum=0,
            labelText=self.tr("Retrieving package list"),
            sizeGripEnabled=False,
            windowTitle="Progress")

        self.__progress.rejected.connect(self.reject)
        self.__thread = None
        self.__installer = None

    @Slot(object)
    def _set_packages(self, f):
        if self.__progress.isVisible():
            self.__progress.close()

        try:
            packages = f.result()
        except (IOError, OSError) as err:
            message_warning("Could not retrieve package list",
                            title="Error",
                            informative_text=str(err),
                            parent=self)
            packages = []
        except Exception:
            raise
        else:
            AddonManagerDialog._packages = packages

        installed = list_installed_addons()
        dists = {dist.project_name: dist for dist in installed}
        packages = {pkg.name: pkg for pkg in packages}

        # For every pypi available distribution not listed by
        # list_installed_addons, check if it is actually already
        # installed.
        ws = pkg_resources.WorkingSet()
        for pkg_name in set(packages.keys()).difference(set(dists.keys())):
            try:
                d = ws.find(pkg_resources.Requirement.parse(pkg_name))
            except pkg_resources.VersionConflict:
                pass
            except ValueError:
                # Requirements.parse error ?
                pass
            else:
                if d is not None:
                    dists[d.project_name] = d

        project_names = unique(itertools.chain(packages.keys(), dists.keys()))

        items = []
        for name in project_names:
            if name in dists and name in packages:
                item = Installed(packages[name], dists[name])
            elif name in dists:
                item = Installed(None, dists[name])
            elif name in packages:
                item = Available(packages[name])
            else:
                assert False
            items.append(item)

        self.addonwidget.set_items(items)

    def showEvent(self, event):
        super().showEvent(event)

        if not self._f_pypi_addons.done():
            QTimer.singleShot(0, self.__progress.show)

    def done(self, retcode):
        super().done(retcode)
        self._f_pypi_addons.cancel()
        self._executor.shutdown(wait=False)
        if self.__thread is not None:
            self.__thread.quit()
            self.__thread.wait(1000)

    def closeEvent(self, event):
        super().closeEvent(event)
        self._f_pypi_addons.cancel()
        self._executor.shutdown(wait=False)

        if self.__thread is not None:
            self.__thread.quit()
            self.__thread.wait(1000)

    ADDON_EXTENSIONS = ('.zip', '.whl', '.tar.gz')

    def dragEnterEvent(self, event):
        urls = event.mimeData().urls()
        if any((OSX_NSURL_toLocalFile(url) or url.toLocalFile()
                ).endswith(self.ADDON_EXTENSIONS) for url in urls):
            event.acceptProposedAction()

    def dropEvent(self, event):
        """Allow dropping add-ons (zip or wheel archives) on this dialog to
        install them"""
        packages = []
        names = []
        for url in event.mimeData().urls():
            path = OSX_NSURL_toLocalFile(url) or url.toLocalFile()
            if path.endswith(self.ADDON_EXTENSIONS):
                name, vers, summary, descr = (get_meta_from_archive(path)
                                              or (os.path.basename(path), '',
                                                  '', ''))
                names.append(name)
                packages.append(
                    Installable(name, vers, summary, descr or summary, path,
                                [path]))
        future = concurrent.futures.Future()
        future.set_result((AddonManagerDialog._packages or []) + packages)
        self._set_packages(future)
        self.addonwidget.set_install_projects(names)

    def __accepted(self):
        steps = self.addonwidget.item_state()

        if steps:
            # Move all uninstall steps to the front
            steps = sorted(steps,
                           key=lambda step: 0 if step[0] == Uninstall else 1)
            self.__installer = Installer(steps=steps,
                                         user_install=self.user_install)
            self.__thread = QThread(self)
            self.__thread.start()

            self.__installer.moveToThread(self.__thread)
            self.__installer.finished.connect(self.__on_installer_finished)
            self.__installer.error.connect(self.__on_installer_error)
            self.__installer.installStatusChanged.connect(
                self.__progress.setLabelText)

            self.__progress.show()
            self.__progress.setLabelText("Installing")

            self.__installer.start()

        else:
            self.accept()

    def __on_installer_error(self, command, pkg, retcode, output):
        message_error(
            "An error occurred while running a subprocess",
            title="Error",
            informative_text="{} exited with non zero status.".format(command),
            details="".join(output),
            parent=self)
        self.reject()

    def __on_installer_finished(self):
        message = (
            ("Changes successfully applied in <i>{}</i>.<br>".format(USER_SITE)
             if self.user_install else '') +
            "Please restart Orange for changes to take effect.")
        message_information(message, parent=self)
        self.accept()
예제 #43
0
def init_resync_manager():
    global resync_manager
    if resync_manager is None:
        resync_manager = QThread()
        resync_manager.start()
예제 #44
0
    app = QApplication(sys.argv)
    t = QThread()
    w = MTWorker()
    dlg = MTDialog()

    # ensure no premature exit of the application event loop
    app.setQuitOnLastWindowClosed(False)

    # application dependent start of worker, or quit
    dlg.accepted.connect(w.start)
    dlg.rejected.connect(t.quit)
    dlg.rejected.connect(app.quit)

    # this is boiler plate, clean-up and quit
    w.finished.connect(w.deleteLater)
    w.finished.connect(t.quit)
    w.finished.connect(app.quit)
    app.aboutToQuit.connect(t.wait)

    # move worker to thread
    w.moveToThread(t)

    # start worker thread (event loop)
    t.start()

    # main application thread (event loop)
    logger.info('starting application')
    dlg.show()
    sys.exit(app.exec_())
예제 #45
0
    def startMeasurement(self):
        sampleRate = self.sampleRateSb.value()*1E3
        deviceName = str(self.deviceCombo.currentText())
        aoChannel = str(self.aoChannelCombo.currentText())
        aiChannel = str(self.aiChannelCombo.currentText())
        aiTerminalConfig = self.terminalConfiguration()
        aiRange = self.aiRanges[self.aiRangeCombo.currentIndex()]
        aoRange = self.aoRanges[self.aoRangeCombo.currentIndex()]
        offset = self.offsetSb.value()
        amplitude = self.amplitudeSb.value()
        fStart = self.fStartSb.value()
        fStop = self.fStopSb.value()
        fSteps = self.fStepsSb.value()
        settlePeriods = self.settlePeriodsSb.value(); measurePeriods = self.measurePeriodsSb.value()
        minSettleTime = self.minSettleTimeSb.value(); minMeasureTime = self.minMeasureTimeSb.value()

        s = QSettings('WiscXrayAstro', application='ADR3RunInfo')
        path = str(s.value('runPath', '', type=str))
        fileName = path+'/TF/%s_%s.h5' % (self.sampleLe.text(), time.strftime('%Y%m%d_%H%M%S'))
        self._fileName = fileName
        hdfFile = hdf.File(fileName, mode='w')
        hdfFile.attrs['Program'] = ApplicationName
        hdfFile.attrs['Version'] = Version
        hdfFile.attrs['Sample'] = str(self.sampleLe.text())
        hdfFile.attrs['Comment'] = str(self.commentLe.text())
        hdfFile.attrs['StartTimeLocal'] = time.strftime('%Y-%m-%d %H:%M:%S')
        hdfFile.attrs['StartTimeUTC'] =  time.strftime('%Y-%m-%d %H:%M:%SZ', time.gmtime())
        hdfFile.attrs['sampleRate'] = sampleRate
        hdfFile.attrs['offset'] = offset
        hdfFile.attrs['amplitude'] = amplitude
        hdfFile.attrs['fStart'] = fStart
        hdfFile.attrs['fStop'] = fStop
        hdfFile.attrs['fSteps'] = fSteps
        hdfFile.attrs['settlePeriods'] = settlePeriods
        hdfFile.attrs['measurePeriods'] = measurePeriods
        hdfFile.attrs['minSettleTime'] = minSettleTime
        hdfFile.attrs['minMeasureTime'] = minMeasureTime
        hdfFile.attrs['deviceName'] = deviceName
        hdfFile.attrs['aoChannel'] = aoChannel
        hdfFile.attrs['aoRangeMin'] = aoRange.min; hdfFile.attrs['aoRangeMax'] = aoRange.max
        hdfFile.attrs['aiChannel'] = aiChannel
        hdfFile.attrs['aiRangeMin'] = aiRange.min; hdfFile.attrs['aiRangeMax'] = aiRange.max
        hdfFile.attrs['aiTerminalConfig'] = str(self.aiTerminalConfigCombo.currentText())
        
        if self.auxAoTask is not None:
            hdfFile.attrs['auxAoChannel'] = str(self.auxAoTask.channels[0])
            auxAoRange = self.aoRanges[self.auxAoRangeCombo.currentIndex()]
            hdfFile.attrs['auxAoRangeMin'] = auxAoRange.min; hdfFile.attrs['auxAoRangeMax'] = auxAoRange.max 
            hdfFile.attrs['auxAoValue'] = self.auxAoSb.value()

        hkGroup = hdfFile.require_group('HK')
        self.hkLogger = HkLogger(hkGroup, self.hkSub) # Should remove stuff below soon - only kept for backwards compatibility
        self.dsTimeStamps = hdfFile.create_dataset('AdrResistance_TimeStamps', (0,), maxshape=(None,), chunks=(500,), dtype=np.float64)
        self.dsTimeStamps.attrs['units'] = 's'
        self.dsAdrResistance = hdfFile.create_dataset('AdrResistance', (0,), maxshape=(None,), chunks=(500,), dtype=np.float64)
        self.dsAdrResistance.attrs['units'] = 'Ohms'
        self.hdfFile = hdfFile

        lia = LockIn(); self.lia = lia
        liaThread = QThread(parent=self); self.liaThread = liaThread
        lia.moveToThread(liaThread)
        lia.integrationComplete.connect(self.collectData)

#        if self.recordDriveCb.isChecked():
#            aiDriveChannel = str(self.aiDriveChannelCombo.currentText())
#            hdfFile.attrs['aiDriveChannel'] = aiDriveChannel
#            thread.enableDriveRecording(aiDriveChannel)
        
        daqThread = DaqThread(deviceName, aoChannel, aoRange, aiChannel, aiRange, aiTerminalConfig, parent=self); self.daqThread = daqThread
        daqThread.setSampleRate(sampleRate)
        daqThread.setParameters(self.fGoals, self.nSettle, self.nMeasure)
        daqThread.setExcitation(amplitude, offset)
        self.sweep = Sweep(nPoints = len(self.fGoals), parent=self)
        if self.enablePlotCb.isChecked():
            daqThread.waveformAvailable.connect(self.showWaveform)
        daqThread.waveformAvailable.connect(lia.integrateData)
        daqThread.waveformComplete.connect(lia.completeIntegration)
        daqThread.error.connect(self.reportError)
        self.enableWidgets(False)
        daqThread.finished.connect(self.daqThreadFinished)
        liaThread.finished.connect(self.liaThreadFinished)

        nCollected = gc.collect()
        print('GC collected:', nCollected)
        gc.disable()
        
        liaThread.started.connect(lambda: daqThread.start(QThread.HighestPriority)) # Start producer after consumer
        liaThread.start()
예제 #46
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()
예제 #47
0
    def startMeasurement(self):
        self.tProduce = {}
        sampleRate = int(self.sampleRateSb.value()*1E3)
        inputDecimation = int(str(self.inputDecimationCombo.currentText()))

        deviceName = str(self.deviceCombo.currentText())
        aoChannel = str(self.aoChannelCombo.currentText())
        aiChannel = str(self.aiChannelCombo.currentText())
        aiTerminalConfig = self.terminalConfiguration()
        aiRange = self.aiRanges[self.aiRangeCombo.currentIndex()]
        aoRange = self.aoRanges[self.aoRangeCombo.currentIndex()]
        offset = self.offsetSb.value()
        
        active = self.tableColumnValues('active')
        activeRows = np.where(active)[0]
        self.activeRows = activeRows
        fRefs = self.tableColumnValues('f')[activeRows]
        As = self.tableColumnValues('A')[activeRows]
        phases = self.tableColumnValues('phase')[activeRows]*deg2rad
        bws = self.tableColumnValues('bw')[activeRows]
        orders = self.tableColumnValues('order')[activeRows]
        subtractOffset = bool(self.subtractDcOffsetCb.isChecked())
        
        self._fileName = '%s_%s.h5' % (self.sampleLe.text(), time.strftime('%Y%m%d_%H%M%S'))
        hdfFile = hdf.File(self._fileName, mode='w')
        hdfFile.attrs['Program'] = ApplicationName
        hdfFile.attrs['Copyright'] = Copyright
        hdfFile.attrs['Version'] = Version
        hdfFile.attrs['Sample'] = str(self.sampleLe.text())
        hdfFile.attrs['Comment'] = str(self.commentLe.text())
        hdfFile.attrs['StartTimeLocal'] = time.strftime('%Y-%m-%d %H:%M:%S')
        hdfFile.attrs['StartTimeUTC'] =  time.strftime('%Y-%m-%d %H:%M:%SZ', time.gmtime())
        hdfFile.attrs['sampleRate'] = sampleRate
        hdfFile.attrs['inputDecimation'] = inputDecimation
        hdfFile.attrs['offset'] = offset
        hdfFile.attrs['deviceName'] = deviceName
        hdfFile.attrs['aoChannel'] = aoChannel
        hdfFile.attrs['aoRangeMin'] = aoRange.min; hdfFile.attrs['aoRangeMax'] = aoRange.max
        hdfFile.attrs['aiChannel'] = aiChannel
        hdfFile.attrs['aiRangeMin'] = aiRange.min; hdfFile.attrs['aiRangeMax'] = aiRange.max
        hdfFile.attrs['aiTerminalConfig'] = str(self.aiTerminalConfigCombo.currentText())
        hdfFile.attrs['excitationFrequencies'] = fRefs
        hdfFile.attrs['lockinFilterBandwidths'] = bws
        hdfFile.attrs['excitationAmplitudes'] = As
        hdfFile.attrs['excitationPhases'] = phases
        hdfFile.attrs['lockinFilterOrders'] = orders
        hdfFile.attrs['rawCount']  = 0
        hdfFile.attrs['rampRate'] = self.rampRateSb.value()
        hdfFile.attrs['subtractDcOffset'] = subtractOffset
                            
        self.fs = fRefs
        
        variables = [('tGenerated', np.float64), ('tAcquired', np.float64), ('Vdc', np.float64), ('Vrms', np.float64), ('Vmin', np.float64), ('Vmax', np.float64), ('offset', np.float64)]
        self.hdfVector = HdfVectorWriter(hdfFile, variables)

        g = hdfFile.create_group('HK')
        self.hkLogger = HkLogger(g, self.hkSub)
        self.hdfFile = hdfFile
        
        sampleRateDecimated = sampleRate/inputDecimation
        self.__logger.info("Decimated sample rate %f S/s", sampleRateDecimated)
        desiredChunkSize = int(min(0.5*sampleRateDecimated, 2**18)) # Would like pretty big chunks, but update at least twice/second
            
        # Compute phase delays due to the pre-lockin FIR halfband decimator cascade
        dec = DecimatorCascade(inputDecimation, desiredChunkSize)
        phaseDelays = TwoPi*fRefs/sampleRate*(dec.sampleDelay()+1.0)
        self.__logger.info("Phase delays: %s deg", str(phaseDelays*rad2deg))
        phaseDelays = np.mod(phaseDelays, TwoPi)
        
        dcBw = self.dcBwSb.value(); dcFilterOrder = self.dcFilterOrderSb.value()
        lias = LockIns(sampleRateDecimated, fRefs, phases-phaseDelays, bws,
                       orders, desiredChunkSize=desiredChunkSize, dcBw=dcBw,
                       dcFilterOrder=dcFilterOrder, subtractOffset=subtractOffset) # Set up the lock-ins

        self.liaStreamWriters = []
        outputSampleRates = lias.outputSampleRates
        hdfFile.attrs['outputSampleRates']  = outputSampleRates
        saveRawDemod = bool(self.saveRawDemodCb.isChecked())
        hdfFile.attrs['saveRawDemod']  = saveRawDemod

        streams = [('Z',np.complex64)]
        if saveRawDemod:
            streams.append(('Xdec', np.float32))
            streams.append(('Ydec', np.float32))
            
        for i,f in enumerate(fRefs):
            grp = hdfFile.create_group('F_%02d' % i)
            grp.attrs['fRef'] = f
            grp.attrs['fs'] = outputSampleRates[i]
            streamWriter = HdfStreamsWriter(grp, streams, 
                                           scalarFields=[('tGenerated', np.float64),
                                                         ('tAcquired', np.float64),
                                                         ('A', np.float64)],
                                           compression=False, parent=self)
            self.liaStreamWriters.append(streamWriter)


        grp = hdfFile.create_group('DC')
        grp.attrs['sampleRate'] = lias.dcSampleRate
        grp.attrs['lpfBw'] = dcBw
        grp.attrs['lpfOrder'] = dcFilterOrder
        streams = [('DC', np.float)]
        if saveRawDemod:
            streams.append(('DCdec', np.float))
        self.dcStreamWriter = HdfStreamsWriter(grp, streams, 
                                              scalarFields=[('tGenerated', np.float64), 
                                                            ('tAcquired', np.float64)],
                                              compression=False, parent=self)
        
        self.lias = lias
        lias.chunkAnalyzed.connect(self.chunkAnalyzed)
        chunkSize = lias.chunkSize
        self.__logger.info("Lias chunk size: %d", chunkSize)

        self.t = np.linspace(0, chunkSize/sampleRateDecimated, chunkSize)
        self.wavePlot.setXRange(0,self.t[-1])

        daqThread = DaqThread(sampleRate, fRefs, As, phases, chunkSize*inputDecimation, inputDecimation); self.daqThread = daqThread
        daqThread.setRampRate(self.rampRateSb.value())
        daqThread.setOffset(self.offsetSb.value())
        self.rampRateSb.valueChanged.connect(daqThread.setRampRate)
        daqThread.configureDaq(deviceName, aoChannel, aoRange, aiChannel, aiRange, aiTerminalConfig)
        daqThread.chunkProduced.connect(self.chunkProduced)
        daqThread.inputOverload.connect(self.overloadLed.flashOnce)
        daqThread.error.connect(self.reportError)
        daqThread.finished.connect(self.daqThreadFinished)
        self.offsetSb.valueChanged.connect(self.daqThread.setOffset)
        
        if self.enablePlotCb.isChecked():
            daqThread.dataReady.connect(self.showWaveform)
        
        if self.saveRawDataCb.isChecked():
            self.toggleRawDataCollection(True)
        
        self.resultsCollected = 0
        self.chunksProduced = None
        liaThread = QThread(); self.liaThread = liaThread
        lias.moveToThread(liaThread)
        daqThread.dataReady.connect(lias.integrateData)
        lias.resultsAvailable.connect(self.collectLockinResults)
        liaThread.started.connect(lambda: daqThread.start(QThread.HighestPriority))
        liaThread.started.connect(lambda: self.enableWidgets(False))
        liaThread.finished.connect(self.liaThreadFinished)
        liaThread.start() # Start lock-in amplifier(s)
예제 #48
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)
예제 #49
0
 def start(self):
     from .parameters import instance
     if instance.use_thread:
         QThread.start(self)
     else:
         self.run()
예제 #50
0
    def __init__(self, font, parent=None):
        super(MainWindow, self).__init__(parent)
        self.font = font
        self.setWindowTitle("Meridien")
        central_widget = QtGui.QWidget(self)
        self.setCentralWidget(central_widget)

        #Center on screen
        resolution = QtGui.QDesktopWidget().screenGeometry()
        self.move((resolution.width() / 2) - (self.frameSize().width() / 2),
                  (resolution.height() / 2) - (self.frameSize().height() / 2))

        """
        Setting up menu bar
        """

        close_action = QtGui.QAction('Close', self)
        close_action.setShortcut("Ctrl+Q")
        close_action.setStatusTip('Leave the app')
        close_action.triggered.connect(lambda: self.close())

        open_refinement_folder = QtGui.QAction('Open Refinement Folder', self)
        open_refinement_folder.triggered.connect(self.open_refinement_folder)

        self.mainMenu = self.menuBar()
        self.fileMenu = self.mainMenu.addMenu('&File')
        self.fileMenu.addAction(open_refinement_folder)
        self.fileMenu.addAction(close_action)
        self.refinement_folder = ""

        create_new_fsc_plot = QtGui.QAction('&New FSC plot', self)
        create_new_fsc_plot.triggered.connect(self.event_ontriggered_show_fsc_plot)

        create_new_overview_plot = QtGui.QAction('&New resolution overview plot', self)
        create_new_overview_plot.triggered.connect(self.event_show_resolution_overview_plot)
        self.plotMenu = self.mainMenu.addMenu('&Plot')
        self.plotMenu.addAction(create_new_fsc_plot)
        self.plotMenu.addAction(create_new_overview_plot)

        """
        Setup other components
        """
        self.layout = QGridLayout(central_widget)
        self.setMenuBar(self.mainMenu)

        self.tree = QTreeWidget(self)
        self.tree.setHeaderHidden(True)
        self.layout.addWidget(self.tree, 1, 0)

        self.root_items_path_dictionary = {}


        # Threads
        self.threadpool = QThreadPool()
        self.thread_list = []
        thr = QThread(self)
        thr.start()

        self.reader = DriverFileReader()
        self.reader.moveToThread(thr)
        self.thread_list.append(thr)
        self.timer = QTimer(self)

        # Connect signals
        self.reader.sig_sendfolders.connect(self.fill_tree)
        self.reader.sig_sendfsc.connect(self.show_dialog_fsc)
        self.tree.itemChanged.connect(self._event_select_deselect_all)
        self.sig_update_tree.connect(self.update_tree)
        self.sig_show_overview_plot.connect(self.event_show_resolution_overview_plot)
        self.show()
        self.open_refinement_folder()

        self.monitor = None
예제 #51
0
class AddonManagerDialog(QDialog):
    _packages = None

    def __init__(self, parent=None, **kwargs):
        super().__init__(parent, **kwargs)
        self.setLayout(QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)

        self.addonwidget = AddonManagerWidget()
        self.layout().addWidget(self.addonwidget)

        info_bar = QWidget()
        info_layout = QHBoxLayout()
        info_bar.setLayout(info_layout)
        info_icon = QLabel()
        info_text = QLabel()
        info_layout.addWidget(info_icon)
        info_layout.addWidget(info_text)
        self.layout().addWidget(info_bar)

        buttons = QDialogButtonBox(
            orientation=Qt.Horizontal,
            standardButtons=QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        )
        buttons.accepted.connect(self.__accepted)
        buttons.rejected.connect(self.reject)

        self.layout().addWidget(buttons)

        if not os.access(sysconfig.get_path("purelib"), os.W_OK):
            if sysconfig.get_platform().startswith("macosx"):
                info = "You must install Orange by dragging it into" \
                       " Applications before installing add-ons."
            else:
                info = "You do not have permissions to write into Orange " \
                       "directory.\nYou may need to contact an administrator " \
                       "for assistance."
            info_text.setText(info)
            style = QApplication.instance().style()
            info_icon.setPixmap(style.standardIcon(
                QStyle.SP_MessageBoxCritical).pixmap(14, 14))
            buttons.button(QDialogButtonBox.Ok ).setEnabled(False)

        self._executor = concurrent.futures.ThreadPoolExecutor(max_workers=1)
        if AddonManagerDialog._packages is None:
            self._f_pypi_addons = self._executor.submit(list_pypi_addons)
        else:
            self._f_pypi_addons = concurrent.futures.Future()
            self._f_pypi_addons.set_result(AddonManagerDialog._packages)

        self._f_pypi_addons.add_done_callback(
            method_queued(self._set_packages, (object,))
        )

        self.__progress = QProgressDialog(
            self, Qt.Sheet,
            minimum=0, maximum=0,
            labelText=self.tr("Retrieving package list"),
            sizeGripEnabled=False,
            windowTitle="Progress"
        )

        self.__progress.rejected.connect(self.reject)
        self.__thread = None
        self.__installer = None

    @Slot(object)
    def _set_packages(self, f):
        if self.__progress.isVisible():
            self.__progress.close()

        try:
            packages = f.result()
        except (IOError, OSError) as err:
            message_warning(
                "Could not retrieve package list",
                title="Error",
                informative_text=str(err),
                parent=self
            )
            packages = []
        except Exception:
            raise
        else:
            AddonManagerDialog._packages = packages

        installed = list_installed_addons()
        dists = {dist.project_name: dist for dist in installed}
        packages = {pkg.name: pkg for pkg in packages}

        # For every pypi available distribution not listed by
        # list_installed_addons, check if it is actually already
        # installed.
        ws = pkg_resources.WorkingSet()
        for pkg_name in set(packages.keys()).difference(set(dists.keys())):
            try:
                d = ws.find(pkg_resources.Requirement.parse(pkg_name))
            except pkg_resources.VersionConflict:
                pass
            except ValueError:
                # Requirements.parse error ?
                pass
            else:
                if d is not None:
                    dists[d.project_name] = d

        project_names = unique(
            itertools.chain(packages.keys(), dists.keys())
        )

        items = []
        for name in project_names:
            if name in dists and name in packages:
                item = Installed(packages[name], dists[name])
            elif name in dists:
                item = Installed(None, dists[name])
            elif name in packages:
                item = Available(packages[name])
            else:
                assert False
            items.append(item)

        self.addonwidget.set_items(items)

    def showEvent(self, event):
        super().showEvent(event)

        if not self._f_pypi_addons.done():
            QTimer.singleShot(0, self.__progress.show)

    def done(self, retcode):
        super().done(retcode)
        self._f_pypi_addons.cancel()
        self._executor.shutdown(wait=False)
        if self.__thread is not None:
            self.__thread.quit()
            self.__thread.wait(1000)

    def closeEvent(self, event):
        super().closeEvent(event)
        self._f_pypi_addons.cancel()
        self._executor.shutdown(wait=False)

        if self.__thread is not None:
            self.__thread.quit()
            self.__thread.wait(1000)

    def __accepted(self):
        steps = self.addonwidget.item_state()

        if steps:
            # Move all uninstall steps to the front
            steps = sorted(
                steps, key=lambda step: 0 if step[0] == Uninstall else 1
            )
            self.__installer = Installer(steps=steps)
            self.__thread = QThread(self)
            self.__thread.start()

            self.__installer.moveToThread(self.__thread)
            self.__installer.finished.connect(self.__on_installer_finished)
            self.__installer.error.connect(self.__on_installer_error)
            self.__installer.installStatusChanged.connect(
                self.__progress.setLabelText)

            self.__progress.show()
            self.__progress.setLabelText("Installing")

            self.__installer.start()

        else:
            self.accept()

    def __on_installer_error(self, command, pkg, retcode, output):
        message_error(
            "An error occurred while running a subprocess", title="Error",
            informative_text="{} exited with non zero status.".format(command),
            details="".join(output),
            parent=self
        )
        self.reject()

    def __on_installer_finished(self):
        message_information(
            "Please restart Orange for changes to take effect.",
            parent=self)
        self.accept()
예제 #52
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)
예제 #53
0
 def start(self, prio=QThread.InheritPriority):
     self._shouldStop = False
     QThread.start(self, prio)
예제 #54
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)
예제 #55
0
class DrainageChannelBuilderDialog(QtGui.QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(DrainageChannelBuilderDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.iface = iface
        self.setupUi(self)

        self.resWarning = False

        self.btnOk = self.buttonBox.button(QtGui.QDialogButtonBox.Ok)
        self.btnOk.setText(self.tr("Run 2D"))
        self.btnClose = self.buttonBox.button(QtGui.QDialogButtonBox.Close)

        self.cbDEM.currentIndexChanged.connect(self.updateRasterRes)
        self.cbDEM.currentIndexChanged.connect(self.checkLayerExtents)
        self.cbCL.currentIndexChanged.connect(self.checkLayerExtents)
        self.spinElevStart.valueChanged.connect(self.calcDepth)
        self.spinElevEnd.valueChanged.connect(self.calcDepth)
        self.spinRightSideSlope.valueChanged.connect(self.updateMaxBankWidth)
        self.spinLeftSideSlope.valueChanged.connect(self.updateMaxBankWidth)
        self.spinWidth.valueChanged.connect(self.checkRes)
        self.spinRes.valueChanged.connect(self.checkRes)
        self.browseBtn.clicked.connect(self.writeDirName)
        self.btn1Dsave.clicked.connect(self.writeOut1Dresults)

        # add matplotlib figure to dialog
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        self.figure.subplots_adjust(left=.1,
                                    bottom=0.1,
                                    right=.95,
                                    top=.9,
                                    wspace=None,
                                    hspace=.2)
        self.canvas = FigureCanvas(self.figure)

        self.widgetPlotToolbar = NavigationToolbar(self.canvas,
                                                   self.widgetPlot)
        lstActions = self.widgetPlotToolbar.actions()
        self.widgetPlotToolbar.removeAction(lstActions[7])
        self.gPlot.addWidget(self.canvas)
        self.gPlot.addWidget(self.widgetPlotToolbar)
        self.figure.patch.set_visible(False)

        # and configure matplotlib params
        rcParams["font.serif"] = "Verdana, Arial, Liberation Serif"
        rcParams["font.sans-serif"] = "Tahoma, Arial, Liberation Sans"
        rcParams["font.cursive"] = "Courier New, Arial, Liberation Sans"
        rcParams["font.fantasy"] = "Comic Sans MS, Arial, Liberation Sans"
        rcParams["font.monospace"] = "Courier New, Liberation Mono"

        self.manageGui()

    def manageGui(self):
        print 'manageGui'
        self.cbCL.clear()
        self.cbCL.addItems(utils.getLineLayerNames())
        self.cbDEM.clear()
        self.cbDEM.addItems(utils.getRasterLayerNames())

    def refreshPlot(self):
        self.axes.clear()

        results1D = utils.getPlotArray(self.vLayer, self.rLayer,
                                       self.spinElevStart.value(),
                                       self.spinElevEnd.value(), self.xRes)

        self.stationA = results1D[0, :]

        self.zExistA = results1D[1, :]
        self.zPropA = results1D[2, :]
        self.xA = results1D[3, :]
        self.yA = results1D[4, :]
        self.calcCutAvgAreaEndMeth()

        self.axes.plot(self.stationA, self.zExistA)
        self.axes.plot(self.stationA, self.zPropA)
        self.axes.grid()
        formatter = ScalarFormatter(useOffset=False)
        self.axes.yaxis.set_major_formatter(formatter)

        self.axes.set_ylabel(unicode(self.tr("Elevation, z field units")))
        self.axes.set_xlabel(unicode(self.tr('Station, layer units')))
        self.axes.set_title(
            unicode(
                self.tr('Channel {} Profile and 1D Calculation Results'.format(
                    self.vLayer.name()))))
        at = AnchoredText(
            self.outText,
            prop=dict(size=12),
            frameon=True,
            loc=1,
        )
        at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")

        self.axes.add_artist(at)
        self.canvas.draw()

    def refreshPlotText(self):

        at = AnchoredText(
            self.outText,
            prop=dict(size=12),
            frameon=True,
            loc=1,
        )
        at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
        self.axes.add_artist(at)
        self.canvas.draw()

    def calcCutAvgAreaEndMeth(self):
        self.depth1D = self.zExistA - self.zPropA

        # find max bank width based on CL depth
        self.maxCLdepth = np.max(self.depth1D)
        leftSlope = self.spinLeftSideSlope.value()
        rightSlope = self.spinRightSideSlope.value()
        width = self.spinWidth.value()
        self.area = self.depth1D * (width + self.depth1D * leftSlope / 2.0 +
                                    self.depth1D * rightSlope / 2.0)
        self.length = self.stationA[1:] - self.stationA[:-1]
        self.vol1D = (self.area[1:] + self.area[:-1]) * self.length / 2.0
        self.vol1D = np.append(0, self.vol1D)
        self.totVol1D = np.sum(self.vol1D)
        self.maxDepth1D = np.max(self.depth1D)
        self.totLength = np.max(self.stationA)
        self.channelSlope = (self.zPropA[-1] - self.zPropA[0]) / self.totLength
        self.outText = 'Length: {2:.2f} layer units\nChannel Slope: {3:.6f}\n1D Max. Cut Depth: {0:,.2f} layer units\n1D Tot. Vol.: {1:,.2f} layer units$^3$'.format(
            self.maxDepth1D, self.totVol1D, self.totLength, self.channelSlope)

        #self.canvas.draw()

    def writeOut1Dresults(self):
        # assign results to numpy array for quick csv dump
        self.out1Dresults = np.zeros((self.stationA.size, 8))
        self.out1Dresults[:, 0] = self.stationA
        self.out1Dresults[:, 1] = self.vol1D
        self.out1Dresults[:, 2] = self.zExistA
        self.out1Dresults[:, 3] = self.zPropA
        self.out1Dresults[:, 4] = self.depth1D
        self.out1Dresults[:, 5] = self.area
        self.out1Dresults[:, 6] = self.xA
        self.out1Dresults[:, 7] = self.yA
        outPath = self.outputDir.text()
        home = os.path.expanduser("~")
        if outPath == '':
            outPath = os.path.join(home, 'Desktop',
                                   'QGIS2DrainageChannelBuilderFiles')
            self.outputDir.setText(outPath)
            if not os.path.exists(outPath):
                os.makedirs(outPath)

        os.chdir(outPath)
        fileName = 'Channel1Dresults_{}.txt'.format(self.vLayer.name())
        outHeader = 'DEM Layer:\t{0}\nChannel Centerline:\t{1}\nProjection (Proj4 format):\t{13}\nChannel Bottom Width:\t{3}\nChannel Start Elevation:\t{4}\nChannel End Elevation:\t{5}\nChannel Slope:\t{12:.06f}\nLeft Side Slope:\t{6}\nRight Side Slope:\t{7}\nLength:\t{9:,.2f}\n1D Max. Cut Depth:\t{10:,.2f}\n1D Tot. Vol:\t{11:,.2f}\nNote:\tAll units of length correspond to layer units, all units of area and volume are a combination of layer units and raster elevation units\n\nstation\tvol\tzExist\tzProp\tdepth\tcutArea\tx\ty\n'.format(
            self.cbDEM.currentText(), self.cbCL.currentText(),
            self.spinRes.value(), self.spinWidth.value(),
            self.spinElevStart.value(), self.spinElevEnd.value(),
            self.spinLeftSideSlope.value(), self.spinRightSideSlope.value(),
            self.spinBankWidth.value(), self.totLength, self.maxDepth1D,
            self.totVol1D, self.channelSlope,
            self.rLayer.crs().toProj4())
        np.savetxt(fileName,
                   self.out1Dresults,
                   fmt='%.3f',
                   header=outHeader,
                   delimiter='\t')
        self.canvas.print_figure('Channel1DresultsFigure_{}'.format(
            self.vLayer.name()))

    def updateMaxBankWidth(self):

        self.maxBankWidth = self.maxCLdepth * np.max(
            np.array([
                self.spinLeftSideSlope.value(),
                self.spinRightSideSlope.value()
            ]))
        self.spinBankWidth.setValue(self.maxBankWidth +
                                    self.spinRes.value() / 2.)
        self.calcCutAvgAreaEndMeth()
        self.refreshPlotText()

    def writeDirName(self):
        self.outputDir.clear()
        self.dirName = QtGui.QFileDialog.getExistingDirectory(
            self, 'Select Output Directory')
        self.outputDir.setText(self.dirName)
        self.checkBoxLoadLayers.setCheckState(True)

    def updateRasterRes(self):

        layer = utils.getRasterLayerByName(
            self.cbDEM.currentText().split(' EPSG')[0])
        if layer.isValid():
            self.xRes = layer.rasterUnitsPerPixelX()
            self.yRes = layer.rasterUnitsPerPixelY()
            self.labelDEMres.setText(
                'DEM Layer Resolution = {:.2f} X {:.2f} Y'.format(
                    self.xRes, self.yRes))

    def checkRes(self):

        if self.spinWidth.value() <= self.spinRes.value() * 10:

            self.resWarning = True
            self.errOutput()
        else:
            self.resWarning = False
            self.errOutput()
        self.calcCutAvgAreaEndMeth()
        self.refreshPlotText()

    def checkLayerExtents(self):

        self.rLayer = utils.getRasterLayerByName(
            self.cbDEM.currentText().split(' EPSG')[0])
        self.vLayer = utils.getVectorLayerByName(
            self.cbCL.currentText().split(' EPSG')[0])
        try:
            if self.rLayer.isValid() and self.vLayer.isValid():
                if self.rLayer.extent().xMaximum() >= self.vLayer.extent(
                ).xMaximum() and self.rLayer.extent().xMinimum(
                ) <= self.vLayer.extent().xMinimum() and self.rLayer.extent(
                ).yMaximum() >= self.vLayer.extent().yMaximum(
                ) and self.rLayer.extent().yMinimum() <= self.vLayer.extent(
                ).yMinimum():
                    self.layersOverlap = True
                    self.calcElev()
                    self.btn1Dsave.setEnabled(True)
                    self.btnOk.setEnabled(True)
                    self.errOutput()

                else:
                    self.btnOk.setEnabled(False)
                    self.spinElevStart.setEnabled(False)
                    self.spinElevEnd.setEnabled(False)
                    self.layersOverlap = False
                    self.errOutput()
        except:
            self.btnOk.setEnabled(False)
            self.spinElevStart.setEnabled(False)
            self.spinElevEnd.setEnabled(False)
            self.btn1Dsave.setEnabled(False)
            self.overlayError = True
            self.layersOverlap = False
            self.errOutput()
            pass

    def calcDepth(self):
        if self.layersOverlap:

            self.layersOverlap = utils.calcDepth(self)
        if self.layersOverlap:
            self.refreshPlot()

    def calcElev(self):
        if self.layersOverlap:
            self.spinElevStart.setEnabled(True)
            self.spinElevEnd.setEnabled(True)
            self.spinElevStart.setValue(utils.calcElev(self)[0])
            self.spinElevEnd.setValue(utils.calcElev(self)[1])
            self.refreshPlot()

    def updateProgressText(self, message):
        self.labelProgress.setText(message)

    def updateOutputText(self, message):
        self.textBrowser.setPlainText(message)

    def workerError(self, e, exception_string):
        print 'workerError\n{}\n'.format(exception_string)
        QgsMessageLog.logMessage(
            'Worker thread raised an exception:\n{}'.format(exception_string),
            level=QgsMessageLog.CRITICAL)
        self.iface.messageBar().pushMessage(
            "Drainge Channel Builder",
            'It didnt work, see log for details',
            level=QgsMessageBar.CRITICAL,
            duration=3)
        self.progressBar.setMaximum(100)
        self.btnOk.setEnabled(True)
        self.btn1Dsave.setEnabled(True)

    def stopWorker(self):
        self.worker.kill()
        if self.worker is not None:

            self.worker.deleteLater()
            self.thread.quit()
            self.thread.wait()
            self.thread.deleteLater()

    def errOutput(self):
        if self.resWarning and not self.layersOverlap:
            self.labelErrMessage.setText(
                'Error: Vector is not completely within raster domain\nWarning: For best 2D results, channel bottom width should be at least ten times greater than 2D grid calculation resolution'
            )
        elif self.resWarning:
            self.labelErrMessage.setText(
                'Warning: For best 2D results, channel bottom width should be at least ten times greater than 2D grid calculation resolution'
            )
        elif not self.layersOverlap:
            self.labelErrMessage.setText(
                'Error: Vector is not completely within raster domain')
        else:
            self.labelErrMessage.setText('')

    def workerFinished(self, values):
        # print 'values = ',values
        self.stopWorker()
        self.values = values
        maxCut = values[0][0]
        avgCut = values[0][1]
        totVol = values[0][2]
        self.dirName = values[0][3]
        self.outputDir.setText(self.dirName)
        demChannelPath = values[0][4]
        demCutDepth = values[0][5]
        length = values[0][6]
        outText = 'Summary of 2D Results:\nTot. Vol.\t{2:,.2f}\nLength\t{3:,.2f}\nMax. Cut Depth\t{0:.2f}\nAvg. Cut Depth\t{1:.2f}'.format(
            maxCut, avgCut, totVol, length)
        self.updateOutputText(outText)

        #            for layer in self.layers:
        #                utils.addSlLayer(self.iface,self.dbase,layer)

        self.iface.messageBar().pushMessage(
            "Drainge Channel Builder",
            'Channel elevation DEM, channel depth of cut DEM, and channel grid points located at {}.  Please delete when finished'
            .format(self.dirName),
            duration=30)

        # set channel dem qml by coping dem layer style to channel dem qml
        self.rLayer.saveNamedStyle(
            os.path.join(self.dirName,
                         demChannelPath.split('.tif')[0] + '.qml'))

        # set depth qml w/ function
        xmlString = utils.depthQMLwriter(maxCut)
        demCutDepthQML = open(demCutDepth.split('.tif')[0] + '.qml', 'w')
        demCutDepthQML.write(xmlString)
        demCutDepthQML.close()

        if self.checkBoxLoadLayers.checkState():
            for fileName in [demChannelPath, demCutDepth]:
                fileInfo = QFileInfo(fileName)
                baseName = fileInfo.baseName()
                layer = QgsRasterLayer(fileName, baseName)
                if not layer.isValid():
                    print "Layer failed to load!"
                QgsMapLayerRegistry.instance().addMapLayer(layer)

        self.progressBar.setMaximum(100)
        self.cbCL.setEnabled(True)
        self.cbDEM.setEnabled(True)
        self.spinRes.setEnabled(True)
        self.spinWidth.setEnabled(True)
        self.spinElevStart.setEnabled(True)
        self.spinElevEnd.setEnabled(True)
        self.spinLeftSideSlope.setEnabled(True)
        self.spinRightSideSlope.setEnabled(True)
        self.spinBankWidth.setEnabled(True)
        self.browseBtn.setEnabled(True)
        self.btn1Dsave.setEnabled(True)
        self.btnClose.setEnabled(True)
        self.btnOk.setEnabled(True)

        self.writeOut1Dresults()
        fileName = 'Channel2DresultsSummary_{}.txt'.format(self.vLayer.name())
        outText = 'DEM Layer:\t{0}\nChannel Centerline:\t{1}\nProjection (Proj4 format):\t{14}\n2D Grid Calc Res.:\t{2}\nChannel Bottom Width:\t{3}\nChannel Start Elevation:\t{4}\nChannel End Elevation:\t{5}\nChannel Slope:\t{13:.06f}\nLeft Side Slope:\t{6}\nRight Side Slope:\t{7}\n2D Maximum Bank Width:\t{8}\n\nLength:\t{9:,.2f}\n2D Max. Cut Depth:\t{10:,.2f}\n2D Avg. Cut Depth:\t{11:,.2f}\n2D Tot. Vol:\t{12:,.2f}\n\nNote:\tAll units of length correspond to layer units, all units of area and volume are a combination of layer units and raster elevation units\n\n'.format(
            self.cbDEM.currentText(), self.cbCL.currentText(),
            self.spinRes.value(), self.spinWidth.value(),
            self.spinElevStart.value(), self.spinElevEnd.value(),
            self.spinLeftSideSlope.value(), self.spinRightSideSlope.value(),
            self.spinBankWidth.value(), self.totLength, maxCut, avgCut, totVol,
            self.channelSlope,
            self.rLayer.crs().toProj4())
        outFile = open(fileName, 'w')
        outFile.write(outText)
        outFile.close()
        self.checkBoxLoadLayers.setCheckState(False)
        self.iface.mapCanvas().refresh()

    def accept(self):
        print 'accepted'

        args = [
            self.rLayer, self.vLayer,
            self.spinWidth.value(),
            self.spinRes.value(),
            self.spinElevStart.value(),
            self.spinElevEnd.value(),
            self.spinLeftSideSlope.value(),
            self.spinRightSideSlope.value(),
            self.spinBankWidth.value(),
            self.outputDir.text()
        ]
        self.thread = QThread()
        # create a new worker instance
        self.worker = DrainageChannelThread.DrainageChannelBuilder(args)

        # create a new worker instance
        self.worker.moveToThread(self.thread)
        self.worker.updateProgressText.connect(self.updateProgressText)

        self.worker.workerFinished.connect(self.workerFinished)
        self.worker.error.connect(self.workerError)

        self.btnClose.setEnabled(False)
        self.cbCL.setEnabled(False)
        self.cbDEM.setEnabled(False)
        self.spinRes.setEnabled(False)
        self.spinWidth.setEnabled(False)
        self.spinElevStart.setEnabled(False)
        self.spinElevEnd.setEnabled(False)
        self.spinLeftSideSlope.setEnabled(False)
        self.spinRightSideSlope.setEnabled(False)
        self.spinBankWidth.setEnabled(False)
        self.browseBtn.setEnabled(False)
        self.btn1Dsave.setEnabled(False)
        self.btnOk.setEnabled(False)
        self.tabWidgetOutput.setCurrentWidget(self.tabOutputSummary)

        #self.buttonBox.rejected.disconnect(self.reject)

        self.progressBar.setMaximum(0)
        self.thread.started.connect(self.worker.run)
        self.thread.start()

    def reject(self):
        print 'rejected'
        QtGui.QDialog.reject(self)
예제 #56
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()
예제 #57
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()
예제 #58
0
파일: geofollow.py 프로젝트: Daml/geofollow
class GeoFollow:
    def __init__(self, iface):
        self.iface = iface
        self.connectAction = None
        self.disconnectAction = None
        self.menu = u'GeoFollow'
        self.toolbar = self.iface.addToolBar(u'GeoFollow')
        self.toolbar.setObjectName(u'GeoFollow')
        self.dlg = None
        self.thread = None
        self.worker = None

    def initGui(self):
        self.connectAction = QAction(QIcon(':/plugins/GeoFollow/icon_connect.png'), 'Connect', self.iface.mainWindow())
        self.connectAction.triggered.connect(self.run)
        self.connectAction.setEnabled(True)
        self.toolbar.addAction(self.connectAction)
        self.iface.addPluginToMenu(self.menu, self.connectAction)

        self.disconnectAction = QAction(QIcon(':/plugins/GeoFollow/icon_disconnect.png'), 'Disconnect', self.iface.mainWindow())
        self.disconnectAction.triggered.connect(self.stop)
        self.disconnectAction.setEnabled(False)
        self.toolbar.addAction(self.disconnectAction)
        self.iface.addPluginToMenu(self.menu, self.disconnectAction)

    def unload(self):
        self.stop()
        self.iface.removePluginMenu(u'GeoFollow', self.connectAction)
        self.iface.removeToolBarIcon(self.connectAction)
        self.iface.removePluginMenu(u'GeoFollow', self.disconnectAction)
        self.iface.removeToolBarIcon(self.disconnectAction)
        del self.toolbar

    def run(self):
        s = QSettings()

        self.dlg = GeoFollowDialog()
        self.dlg.hostLineEdit.setText(s.value("geofollow/host", "localhost"))
        self.dlg.portLineEdit.setText(s.value("geofollow/port", "13729"))
        self.dlg.trackerLineEdit.setText(s.value("geofollow/tracker", "web"))

        self.dlg.show()
        result = self.dlg.exec_()

        if result:
            s.setValue("geofollow/host", self.dlg.hostLineEdit.text())
            s.setValue("geofollow/port", self.dlg.portLineEdit.text())
            s.setValue("geofollow/tracker", self.dlg.trackerLineEdit.text())

            self.start(self.dlg.hostLineEdit.text(), self.dlg.portLineEdit.text(), self.dlg.trackerLineEdit.text())
            pass

    def info(self, msg):
        self.iface.messageBar().pushMessage("GeoFollow", msg, level=QgsMessageBar.INFO, duration=1)

    def error(self, exception):
        if (type(exception) == socket.gaierror) or (type(exception) == socket.error):
            self.iface.messageBar().pushMessage("GeoFollow", str(exception), level=QgsMessageBar.CRITICAL, duration=0)
            QgsMessageLog.logMessage(str(exception), 'GeoFollow', QgsMessageLog.CRITICAL)
            self.stop()
        else:
            self.stop()
            raise exception


    def update(self, data):
        canvas = self.iface.mapCanvas()

        repro = QgsCoordinateTransform(
            QgsCoordinateReferenceSystem(data['c']),
            canvas.mapSettings().destinationCrs()
        )

        pos = data["b"].split(",")
        s_sw = QgsPoint(float(pos[0]), float(pos[1]))
        s_ne = QgsPoint(float(pos[2]), float(pos[3]))

        canvas.setExtent(QgsRectangle(repro.transform(s_sw), repro.transform(s_ne)))
        #cachingEnabled = self.iface.mapCanvas().isCachingEnabled()
        #for layer in self.iface.mapCanvas().layers():
        #    if cachingEnabled:
        #        layer.setCacheImage(None)
        #    layer.triggerRepaint()
        canvas.refresh()
        #self.iface.mapCanvas().refreshAllLayers()
        #qApp.processEvents

    def start(self, host, port, tracker):
        self.connectAction.setEnabled(False)
        self.thread = QThread()
        self.worker = Worker(host, port, tracker)
        self.worker.moveToThread(self.thread)

        self.worker.update.connect(self.update)
        self.worker.info.connect(self.info)
        self.worker.error.connect(self.error)

        self.thread.started.connect(self.worker.loop)

        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.reset)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)

        self.thread.start()

        self.disconnectAction.setEnabled(True)

    def reset(self):
        self.connectAction.setEnabled(True)

    def stop(self):
        self.disconnectAction.setEnabled(False)
        if self.worker:
            self.worker.kill()
예제 #59
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()
예제 #60
0
파일: updater.py 프로젝트: zoujun8666/Roam
class ProjectUpdater(QObject):
    """
    Object to handle reporting when new versions of projects are found on the update server.

    Emits foundProjects when a new projects are found
    """
    foundProjects = pyqtSignal(list, list)
    projectUpdateStatus = pyqtSignal(str, str)
    projectInstalled = pyqtSignal(str)

    def __init__(self, server=None, projects_base=''):
        super(ProjectUpdater, self).__init__()
        self.updatethread = None
        self.server = server
        self.net = QgsNetworkAccessManager.instance()
        self.projects_base = projects_base
        self.create_worker()

    def quit(self):
        self.updatethread.quit()

    def create_worker(self):
        self.updatethread = QThread()
        self.worker = UpdateWorker(self.projects_base)
        self.worker.moveToThread(self.updatethread)

        self.worker.projectUpdateStatus.connect(self.projectUpdateStatus)
        self.worker.projectInstalled.connect(self.projectInstalled)
        self.updatethread.started.connect(self.worker.run)

    @property
    def configurl(self):
        url = urlparse.urljoin(add_slash(self.server), "projects/roam.txt")
        print "URL", url
        return url

    def check_updates(self, server, installedprojects):
        if not server:
            return

        self.server = server
        req = QNetworkRequest(QUrl(self.configurl))
        reply = self.net.get(req)
        reply.finished.connect(
            functools.partial(self.list_versions, reply, installedprojects))

    def update_server(self, newserverurl, installedprojects):
        self.check_updates(newserverurl, installedprojects)

    def list_versions(self, reply, installedprojects):
        if reply.error() == QNetworkReply.NoError:
            content = reply.readAll().data()
            serverversions = parse_serverprojects(content)
            updateable = list(
                updateable_projects(installedprojects, serverversions))
            new = list(new_projects(installedprojects, serverversions))
            if updateable or new:
                self.foundProjects.emit(updateable, new)
        else:
            msg = "Error in network request for projects: {}".format(
                reply.errorString())
            roam.utils.warning(msg)
            # RoamEvents.raisemessage("Project Server Message", msg, level=RoamEvents.WARNING)

    def update_project(self, project, version):
        self.projectUpdateStatus.emit(project.name, "Pending")
        forupdate.put((project, version, self.server, False))
        self.updatethread.start()

    def install_project(self, projectinfo):
        self.projectUpdateStatus.emit(projectinfo['name'], "Pending")
        is_new = True
        forupdate.put(
            (projectinfo, projectinfo['version'], self.server, is_new))
        self.updatethread.start()