Exemplo n.º 1
0
class ReportExportProgress(QObject):
    def __init__(self, name, eventCount, eventStart, eventFinish, child=None):
        QObject.__init__(self)
        self.name = name
        self.eventCount = eventCount
        self.eventStart = eventStart
        self.eventFinish = eventFinish
        self.child = child
        self.label = QLabel()
        self.label.setWordWrap(True)
        self.bar = QProgressBar()
        self.bar.setFormat(" %v/%m (%p%)")
        self.reset()

    def reset(self):
        self.title = ""
        self.current = 0
        self.count = 0

    def event(self, event):
        if event.type == self.eventStart:
            self.title = event.value.value()
            if self.child:
                self.child.reset()
        if event.type == self.eventFinish:
            self.current += 1
            self.bar.setValue(self.current)
        if event.type == self.eventCount:
            self.count = event.value.value()
            self.bar.setValue(0)
            self.bar.setMaximum(self.count)
        self.label.setText(
            self.tr("Extraction ") + self.name + " : " + str(self.title))
Exemplo n.º 2
0
class ReportExportProgressItems(QObject):
    def __init__(self):
        QObject.__init__(self)
        self.eventCount = ReportManager.EventExportItems
        self.eventFinish = [
            ReportManager.EventExportCategoryFinish,
            ReportPage.EventExportFinish, ReportPageFragment.EventWriteFinish,
            ReportPageFragment.EventWriteElementFinish
        ]
        self.label = QLabel(self.tr("Extracting report"))
        self.bar = QProgressBar()
        self.bar.setFormat(" %v/%m (%p%)")
        self.reset()

    def reset(self):
        self.count = 0
        self.current = 0

    def event(self, event):
        if event.type == self.eventCount:
            self.count = event.value.value()
            self.bar.setValue(0)
            self.bar.setMaximum(self.count)
        if event.type in self.eventFinish:
            self.current += 1
            self.bar.setValue(self.current)
Exemplo n.º 3
0
class TrackProgressDialog(QDialog):
    finished = pyqtSignal()

    def __init__(self, parent=None, numStages=1):
        QDialog.__init__(self, parent)

        self.currentStep = 0
        self.progress = None

        l = QVBoxLayout()
        self.setLayout(l)

        self.overallProgress = QProgressBar()
        self.overallProgress.setRange(0, numStages)
        self.overallProgress.setFormat("step %v of " + str(numStages))

        self.currentStepProgress = QProgressBar()
        self.currentStepProgress.setRange(0, 100)
        self.currentStepProgress.setFormat("%p %")

        self.overallLabel = QLabel("Overall progress")
        self.currentStepLabel = QLabel("Current step")

        l.addWidget(self.overallLabel)
        l.addWidget(self.overallProgress)
        l.addWidget(self.currentStepLabel)
        l.addWidget(self.currentStepProgress)
        l.maximumSize()

        self.update()

    def __onNewStep(self, description):
        self.currentStep += 1
        self.currentStepProgress.setValue(0)
        self.overallProgress.setValue(self.currentStep)
        self.currentStepLabel.setText(description)
        self.update()

    def __onCurrentStepProgressChanged(self, progress):
        timesHundred = round(1000.0 * progress)
        timesTen = round(100.0 * progress)
        if (not self.currentStepProgress.value()
                == timesTen) and (timesHundred - 10 * timesTen) == 0:
            self.currentStepProgress.setValue(timesTen)
            self.update()

    def run(self):
        self.trackProgress = TrackProgress(self)
        self.trackProgress.progress.connect(
            self.__onCurrentStepProgressChanged, Qt.BlockingQueuedConnection)
        self.trackProgress.newStep.connect(self.__onNewStep,
                                           Qt.BlockingQueuedConnection)
        self.trackProgress.done.connect(self.onTrackDone)
        self.trackProgress.start()

    def onTrackDone(self):
        self.trackProgress.wait(
        )  # Join the extractor thread so its safe to immediately destroy the window
        self.finished.emit()
        self.close()
Exemplo n.º 4
0
class SeekOverlay(Overlay):
   def __init__(self, keyPressHandler, parent = None):
      Overlay.__init__(self, keyPressHandler, parent)
      
      self.setupUI()
      
      
   def setupUI(self):
      self.layout = QHBoxLayout(self)
      
      self.timeBar = QProgressBar()
      self.layout.addWidget(self.timeBar)
      
      
   def resizeEvent(self, event):
      textHeight = event.size().height() * .4
      self.timeBar.setStyleSheet('QProgressBar {font-size: %dpt;}' % textHeight)
      
      
   def setTime(self, current, total):
      current = int(current)
      total = int(total)
      self.timeBar.setMaximum(total)
      self.timeBar.setValue(current)
      self.timeBar.setFormat(MPlayer.formatTime(current) + '/' + MPlayer.formatTime(total))
Exemplo n.º 5
0
class BusyBar(QThread):
    """
    Adapted from: http://stackoverflow.com/questions/8007602/
    looping-qprogressbar-gives-error-qobjectinstalleventfilter-cannot-filter-e  
           
    Looping progress bar
    create the signal that the thread will emit
    
    .. note::
       This function creates a busy bar but I have not figured out how to \
       attach it to a process. Therefore, it is currently functionally \
       useless.
    """
    changeValue = pyqtSignal(int)

    def __init__(self, text=""):
        QThread.__init__(self, parent=None)
        self.text = text
        self.stop = False
        self.proBar = QProgressBar()
        self.proBar.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.SplashScreen)
        self.proBar.setRange(0, 100)
        self.proBar.setTextVisible(True)
        self.proBar.setFormat(self.text)
        self.proBar.setValue(0)
        self.proBar.setFixedSize(300, 40)
        self.proBar.setAlignment(Qt.AlignCenter)
        self.proBar.show()

        #self.changeValue.connect(self.proBar.setValue, Qt.QueuedConnection)
        # Make the Busybar delete itself and the QProgressBar when done
        self.finished.connect(self.onFinished)

    def run(self):
        """
        """
        while not self.stop:
            # keep looping while self is visible
            # Loop sending mail
            for i in range(100):
                # emit the signal instead of calling setValue
                # also we can't read the progress bar value from the thread
                self.changeValue.emit(i)
                time.sleep(0.01)
            self.changeValue.emit(0)

    def onFinished(self):
        """
        """
        self.proBar.deleteLater()
        self.deleteLater()

    def Kill(self):
        """
        """
        self.stop = True
Exemplo n.º 6
0
class BusyBar(QThread):        
    """
    Adapted from: http://stackoverflow.com/questions/8007602/
    looping-qprogressbar-gives-error-qobjectinstalleventfilter-cannot-filter-e  
           
    Looping progress bar
    create the signal that the thread will emit
    
    .. note::
       This function creates a busy bar but I have not figured out how to \
       attach it to a process. Therefore, it is currently functionally \
       useless.
    """
    changeValue = pyqtSignal(int)
    def __init__(self, text = "" ):
        QThread.__init__(self, parent = None)
        self.text = text
        self.stop = False
        self.proBar = QProgressBar()
        self.proBar.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.SplashScreen )
        self.proBar.setRange( 0, 100 )
        self.proBar.setTextVisible( True )
        self.proBar.setFormat( self.text )
        self.proBar.setValue( 0 )
        self.proBar.setFixedSize( 300 , 40 )
        self.proBar.setAlignment(Qt.AlignCenter)
        self.proBar.show()

        #self.changeValue.connect(self.proBar.setValue, Qt.QueuedConnection)
        # Make the Busybar delete itself and the QProgressBar when done        
        self.finished.connect(self.onFinished)

    def run(self):
        """
        """
        while not self.stop:                
            # keep looping while self is visible
            # Loop sending mail 
            for i in range(100):
                # emit the signal instead of calling setValue
                # also we can't read the progress bar value from the thread
                self.changeValue.emit( i )
                time.sleep(0.01)
            self.changeValue.emit( 0 )

    def onFinished(self):
        """
        """
        self.proBar.deleteLater()
        self.deleteLater()

    def Kill(self):
        """
        """
        self.stop = True
Exemplo n.º 7
0
class ProgressView(QWidget):
    def __init__(self, parent=None):
        super(ProgressView, self).__init__(parent)

        self._progressBar = QProgressBar()

        layout = QVBoxLayout(self)
        layout.addWidget(self._progressBar)

    def setRunner(self, runner):
        self.show()
        self._progressBar.setMaximum(0)
        runner.progress.connect(self._showProgress)
        runner.done.connect(self.hide)

    def _showProgress(self, dct):
        step = dct['step']
        if step in ('install', 'remove'):
            self._progressBar.setMaximum(100)
            self._progressBar.setValue(dct['percent'])
            if step == 'install':
                self._progressBar.setFormat(i18n('Installing... %p%'))
            else:
                self._progressBar.setFormat(i18n('Removing... %p%'))
        elif step == 'acquire':
            fetched = dct['fetched_bytes']
            total = dct['total_bytes']
            self._progressBar.setMaximum(total)
            self._progressBar.setValue(fetched)
            locale = KGlobal.locale()
            self._progressBar.setFormat(i18n('Downloading... %1 / %2',
                                             locale.formatByteSize(fetched),
                                             locale.formatByteSize(total)
                                             ))
Exemplo n.º 8
0
class ExpandingProgressDialog(QProgressDialog):
    def __init__(self, parent=None):
        QProgressDialog.__init__(self, parent)

        self.progress = QProgressBar(self)
        self.progress.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

        self.setBar(self.progress)

    def set_progress_text_visible(self, visible):
        self.progress.setTextVisible(visible)

    def set_progress_text(self, text):
        self.progress.setFormat(text)

    # overrides QProgressDialog.sizeHint
    def sizeHint(self):
        size = QProgressDialog.sizeHint(self)

        if size.width() < 400:
            size.setWidth(400)

        return size
Exemplo n.º 9
0
class InputForm(QWidget):

    __instance = None

    @staticmethod
    def instance():
        return InputForm.__instance

    def __init__(self):
        if not InputForm.__instance:
            InputForm.__instance = self

        super(InputForm, self).__init__()

        Global.event.task_started.connect(self._on_task_started)
        Global.event.task_completed.connect(self._on_task_completed)
        Global.event.task_progressed.connect(self._on_task_progressed)
        Global.event.task_range_progressed.connect(self._on_task_range_progressed)
        Global.event.interface_load_task_params.connect(self._on_interface_load_task_params)

        self.vl = QVBoxLayout()
        self.vl.setContentsMargins(0,0,0,0)

        self.setLayout(self.vl)
        self.setFixedWidth(290)

        self.tab = QTabWidget()
        self.vl.addWidget(self.tab)

        self.input_parameters = InputParameters()
        self.input_parameters.ranges_state_changed.connect(self._on_ranges_state_changed)
        self.tab.addTab(self.input_parameters, 'Parameters')

        self.import_parameters = ImportParameters()
        self.tab.addTab(self.import_parameters, 'Observation')

        control_buttons = QWidget()
        control_buttons.setLayout(QVBoxLayout())
        control_buttons.layout().setContentsMargins(0, 0, 0, 0)
        control_buttons.layout().setAlignment(Qt.AlignBottom)

        self._progress = QProgressBar()
        self._progress.setValue(0)
        self._progress.setTextVisible(True)
        self._progress.setAlignment(Qt.AlignCenter)
        self._progress.hide()
        control_buttons.layout().addWidget(self._progress)

        self._range_progress = QProgressBar()
        self._range_progress.setValue(0)
        self._range_progress.setTextVisible(True)
        self._range_progress.setAlignment(Qt.AlignCenter)
        self._range_progress.hide()
        control_buttons.layout().addWidget(self._range_progress)

        self._calculate = QPushButton('Calculate')
        self._calculate.clicked.connect(self._on_calculate)
        control_buttons.layout().addWidget(self._calculate)

        self._cancel = QPushButton('Cancel')
        self._cancel.hide()
        self._cancel.clicked.connect(self._on_cancel)
        control_buttons.layout().addWidget(self._cancel)

        self.vl.addWidget(control_buttons)

        if exists("./config/last-session.ini") :
            self.load_params("./config/last-session.ini")

    def _on_ranges_state_changed(self, parameters):
        Global.task_range().reset()

        if len(parameters):
            keys = parameters.keys()
            for key in parameters:
                Global.task_range().set_range(key, copy(parameters[key].range.values))

            self._calculate.setText('Calculate ' + str(Global.task_range()._total_count) + ' variations')
        else:
            self._calculate.setText('Calculate')

    def _on_calculate(self):
        self.import_parameters.import_observation()

        combination = Global.task_range().get_next_combination()

        Global.task().input.semi_major_axis = self.input_parameters.semi_major_axis.getValue()
        Global.task().input.star_radius = self.input_parameters.star_radius.getValue()
        Global.task().input.planet_radius = self.input_parameters.planet_radius.getValue()
        Global.task().input.star_temperature = self.input_parameters.star_temperature.getValue()
        Global.task().input.planet_temperature = self.input_parameters.planet_temperature.getValue()
        Global.task().input.darkening_law = self.input_parameters.darkening_law.value.itemData(self.input_parameters.darkening_law.value.currentIndex()).toString()
        Global.task().input.darkening_1 = self.input_parameters.darkening_coefficient_1.getValue()
        Global.task().input.darkening_2 = self.input_parameters.darkening_coefficient_2.getValue()
        Global.task().input.inclination = self.input_parameters.inclination.getValue()
        Global.task().input.phase_start = 0
        Global.task().input.phase_end = self.input_parameters.phase_end.getValue()
        Global.task().input.phase_step = self.input_parameters.phase_step.getValue()
        Global.task().input.precision = 10**self.input_parameters.integration_precision.getValue()

        if combination:
            for param in combination:
                setattr(Global.task().input, param[0], param[1])

        Global.task().start()

    def _on_task_range_progressed(self, progress):
        self._range_progress.setFormat( str(Global.task_range().completed_count()) + ' of ' + str(Global.task_range().total_count()))
        self._range_progress.setValue(math.ceil(((float(Global.task_range().completed_count()))/Global.task_range().total_count())*100))
        self._on_calculate()

    def _on_task_started(self, task):
        self._calculate.hide()
        self._progress.show()
        self._progress.setValue(0)
        self._cancel.show()
        self.tab.setDisabled(True)

        if Global.task_range().total_count():
            self._range_progress.show()
            if Global.task_range().completed_count() == 0:
                self._range_progress.setFormat('0 of ' + str(Global.task_range().total_count()))
                self._range_progress.setValue(0)

    def _on_task_progressed(self, task, progress):
        self._progress.setValue(progress)

    def _on_task_completed(self, task):
        if Global.task_range().total_count() and Global.task_range().completed_count():
            return

        self._calculate.show()
        self._progress.hide()
        self._progress.setValue(0)
        self._cancel.hide()
        self.tab.setDisabled(False)
        self._range_progress.hide()
        self._range_progress.setValue(0)

    def _on_cancel(self):
        Global.task().stop()

        self._calculate.show()
        self._progress.hide()
        self._progress.setValue(0)
        self._range_progress.hide()
        self._range_progress.setValue(0)
        self._cancel.hide()
        self.tab.setDisabled(False)

    def _on_interface_load_task_params(self, task):
        self.input_parameters.semi_major_axis.value.setValue(task.input.semi_major_axis)
        self.input_parameters.star_radius.value.setValue(task.input.star_radius)
        self.input_parameters.planet_radius.value.setValue(task.input.planet_radius)
        self.input_parameters.star_temperature.value.setValue(task.input.star_temperature)
        self.input_parameters.planet_temperature.value.setValue(task.input.planet_temperature)
        self.input_parameters.inclination.value.setValue(task.input.inclination)

        darkening_law_index = 0
        for item in DarkeningLaw.items:
            if item[1] == task.input.darkening_law:
                break
            darkening_law_index += 1

        self.input_parameters.darkening_law.value.setCurrentIndex(darkening_law_index)
        self.input_parameters.darkening_coefficient_1.value.setValue(task.input.darkening_1)
        self.input_parameters.darkening_coefficient_2.value.setValue(task.input.darkening_2)
        self.input_parameters.phase_end.value.setValue(task.input.phase_end)
        self.input_parameters.phase_step.value.setValue(task.input.phase_step)
        self.input_parameters.integration_precision.value.setValue(log10(task.input.precision))

        for parameter_name in copy(self.input_parameters.range_parameters):
            parameter = getattr(self.input_parameters, parameter_name)
            if parameter.range:
                parameter.range.set_active(False)

        self.repaint()

    def load_params(self, filename):
        config = ConfigParser()
        config.read(filename)

        self._normalize_config(config)

        # Input Parameters
        self._load_config_param(config, 'input', 'semi_major_axis')
        self._load_config_param(config, 'input', 'star_radius')
        self._load_config_param(config, 'input', 'planet_radius')
        self._load_config_param(config, 'input', 'star_temperature')
        self._load_config_param(config, 'input', 'planet_temperature')
        self._load_config_param(config, 'input', 'inclination')
        self._load_config_param(config, 'input', 'darkening_law')
        self._load_config_param(config, 'input', 'darkening_coefficient_1')
        self._load_config_param(config, 'input', 'darkening_coefficient_2')
        self._load_config_param(config, 'input', 'phase_end')
        self._load_config_param(config, 'input', 'phase_step')
        self._load_config_param(config, 'input', 'integration_precision')

        # Import Parameters
        if config.has_option('import', 'filename') and config.get('import', 'filename'):
            if '/data/' in config.get('import', 'filename') and config.get('import', 'filename').index('/data/') == 0:
                self.import_parameters.filename = os.getcwd().replace('\\', '/') + config.get('import', 'filename')
            else:
                self.import_parameters.filename = config.get('import', 'filename')

        self.import_parameters.update_file_label()

        if config.has_option('import', 'jd2phase') and config.getboolean('import', 'jd2phase') == True :
            self.import_parameters.hjd_to_phases.setCheckState(Qt.Checked)

        if config.has_option('import', 'jd2phase_tzero') :
            self.import_parameters.time_zero.setValue(config.getfloat('import', 'jd2phase_tzero'))

        if config.has_option('import', 'jd2phase_period') :
            self.import_parameters.period.setValue(config.getfloat('import', 'jd2phase_period'))

        if config.has_option('import', 'mag2flux') and config.getboolean('import', 'mag2flux') == True :
            self.import_parameters.magnitude_to_flux.setCheckState(Qt.Checked)

        if config.has_option('import', 'mag2flux_mag') :
            self.import_parameters.magnitude_max.setValue(config.getfloat('import', 'mag2flux_mag'))

        # Fixes painting bug with range buttons when loading new file
        # the active ranges stayed active even if they are inactive
        self.repaint()

    def _normalize_config(self, config):
        if config.has_option('input', 'darkening_1'):
            config.set('input', 'darkening_coefficient_1', config.get('input', 'darkening_1'))
            config.remove_option('input', 'darkening_1')

        if config.has_option('input', 'darkening_2'):
            config.set('input', 'darkening_coefficient_2', config.get('input', 'darkening_2'))
            config.remove_option('input', 'darkening_2')

        if config.has_option('input', 'precision'):
            config.set('input', 'integration_precision', config.get('input', 'precision'))
            config.remove_option('input', 'precision')

    def _load_config_param(self, config, section, name):
        param = getattr(self.input_parameters, name)

        if config.has_option(section, name):
            if type(param.value) is QComboBox:
                param.value.setCurrentIndex(config.getint(section, name))
            else:
                param.value.setValue(literal_eval(config.get(section, name)))

        if param.range:
            _from = _to = _step = _values = None
            _active = False

            if config.has_option(section, name + '_range_from'):
                _from = literal_eval(config.get(section, name + '_range_from'))

            if config.has_option(section, name + '_range_to'):
                _to = literal_eval(config.get(section, name + '_range_to'))

            if config.has_option(section, name + '_range_step'):
                _step = literal_eval(config.get(section, name + '_range_step'))

            if config.has_option(section, name + '_range_values'):
                _values = literal_eval(config.get(section, name + '_range_values'))

            if config.has_option(section, name + '_range_active'):
                _active = config.getboolean(section, name + '_range_active')

            if _values:
                param.range.set_range(_values)
            elif _from and _to and _step:
                param.range.set_range(_from, _to, _step)

            param.range.set_active(_active)

    def _save_config_param(self, config, section, name):
        param = getattr(self.input_parameters, name)

        if type(param.value) is QComboBox:
            config.set(section, name, param.value.currentIndex())
        else:
            config.set(section, name, param.getValue())

        if param.range:
            if param.range.range_from and param.range.range_to and param.range.range_step:
                config.set(section, name + '_range_from', param.range.range_from)
                config.set(section, name + '_range_to', param.range.range_to)
                config.set(section, name + '_range_step', param.range.range_step)
            elif param.range.values:
                config.set(section, name + '_range_values', param.range.values)

            if param.range.is_active():
                config.set(section, name + '_range_active', param.range.is_active())

    def save_params(self, filename):
        config = ConfigParser()
        config.add_section('input')

        # Input Parameters
        self._save_config_param(config, 'input', 'semi_major_axis')
        self._save_config_param(config, 'input', 'star_radius')
        self._save_config_param(config, 'input', 'planet_radius')
        self._save_config_param(config, 'input', 'star_temperature')
        self._save_config_param(config, 'input', 'planet_temperature')
        self._save_config_param(config, 'input', 'inclination')
        self._save_config_param(config, 'input', 'darkening_law')
        self._save_config_param(config, 'input', 'darkening_coefficient_1')
        self._save_config_param(config, 'input', 'darkening_coefficient_2')
        self._save_config_param(config, 'input', 'phase_end')
        self._save_config_param(config, 'input', 'phase_step')
        self._save_config_param(config, 'input', 'integration_precision')

        config.add_section('import')

        if os.getcwd().replace('\\', '/') in str(self.import_parameters.filename) and str(self.import_parameters.filename).index(os.getcwd().replace('\\', '/')) == 0 :
            save_file_path = str(self.import_parameters.filename).replace(os.getcwd().replace('\\', '/'), '')
        else:
            save_file_path = str(self.import_parameters.filename)

        config.set('import', 'filename', save_file_path)
        config.set('import', 'jd2phase', self.import_parameters.hjd_to_phases.checkState() == Qt.Checked)
        config.set('import', 'jd2phase_tzero', self.import_parameters.time_zero.value())
        config.set('import', 'jd2phase_period', self.import_parameters.period.value())
        config.set('import', 'mag2flux', self.import_parameters.magnitude_to_flux.checkState() == Qt.Checked)
        config.set('import', 'mag2flux_mag', self.import_parameters.magnitude_max.value())

        with open(filename, 'wb') as configfile:
            config.write(configfile)
        pass
Exemplo n.º 10
0
class UploadDialog(QDialog):


    def __init__(self, tracks, device_info=None, username=None, password=None, auth_token=None, parent=None):
        super(UploadDialog, self).__init__(parent)

        self.tracks = tracks

        self.username = username
        self.password = password
        self._first_auth = True

        self.total_progress = QProgressBar(self)
        self.total_progress.setRange(0, len(tracks))
        self.total_progress.setValue(0)
        self.total_progress.setFormat('%v of %m tracks uploaded')

        self.item_progress = QProgressBar(self)
        self.item_progress.setRange(0, 100)
        self.item_progress.setValue(0)
        self.item_progress.setFormat('%p%')

        self.buttons = QDialogButtonBox(QDialogButtonBox.Cancel)
        self.buttons.rejected.connect(self.reject)

        self.status_msg = QLabel('Starting upload', self)


        self.setWindowTitle('Uploading')


        self._createLayout()


        self.upload = StravaUpload(tracks, device_info=device_info, parent=self, auth_token=auth_token)

        self.upload.authNeeded.connect(self._onAuthNeeded)
        self.upload.itemProgress.connect(self.item_progress.setValue)
        self.upload.totalProgress.connect(self.total_progress.setValue)
        self.upload.statusMessage.connect(self.status_msg.setText)
        self.upload.finished.connect(self._onFinished)



        self.rejected.connect(self._onCanceled)

        QTimer.singleShot(100, self.upload.start)

    def _createLayout(self):

        l = QVBoxLayout()

        l.addWidget(self.status_msg)
        l.addWidget(self.item_progress)
        l.addWidget(self.total_progress)
        l.addWidget(self.buttons)

        self.setLayout(l)



    def _onAuthNeeded(self):


        if self._first_auth and self.username is not None and self.password is not None:
            self._first_auth = False
            self.upload.authenticate(self.username, self.password)
            return

        d = AuthDialog(self)
        if d.exec_() == QDialog.Accepted:
            u, p = d.getValues()
            self.upload.authenticate(u, p)
        else:
            log.debug('Auth dialog rejected')
            self._onCanceled()

    def _onFinished(self):

        res = self.upload.results

        if len(res) != len(self.tracks):
            res.extend([{'status' : 'ERROR', 'msg' : 'Canceled'}] * (len(self.tracks) - len(res)))

        log.debug('Upload finished')

        d = ResultDialog(zip(self.tracks, res), self)

        d.exec_()
        self.accept()


    def _onCanceled(self):
        log.debug('Upload canceled')
        self.upload.cancel()

        self._onFinished()
Exemplo n.º 11
0
class SoilErosionDockWidget(QtGui.QDockWidget, FORM_CLASS):

    closingPlugin = pyqtSignal()

    def __init__(self, parent=None):
        """Constructor."""
        super(SoilErosionDockWidget, 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.setupUi(self)

        self.settings = QSettings("CTU", "Soil_Erosion_Plugin")

        self.iface = iface

        # Define first computation, no results in map window
        self._first_computation = True

        # Read code tables
        self._factors = {}
        self._readFactorCodes()

        # Fill C combobox
        self.combobox_c.clear()
        list = self._factors['C'].list()
        self.combobox_c.addItems(list)

        # Set filters for QgsMapLayerComboBoxes
        self.shp_box_euc.setFilters(QgsMapLayerProxyModel.PolygonLayer)
        self.load_shp_euc.clicked.connect(self.onLoadShapefile)
        
        self.raster_box.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.load_raster.clicked.connect(self.onLoadRaster)

        self.shp_box_bpej.setFilters(QgsMapLayerProxyModel.PolygonLayer)
        self.load_shp_bpej.clicked.connect(self.onLoadShapefile)

        self.shp_box_lpis.setFilters(QgsMapLayerProxyModel.PolygonLayer)
        self.load_lpis.clicked.connect(self.onLoadShapefile)

        # Set functions for buttons
        self.compute_k_button.clicked.connect(self.onAddKFactor)
        self.compute_c_button.clicked.connect(self.onAddCFactor)

        self.set_button.clicked.connect(self.onCompute)


    def closeEvent(self, event):
        self.closingPlugin.emit()
        event.accept()

    def onLoadRaster(self):
        """Open 'Add raster layer dialog'."""
        sender = '{}-lastUserFilePath'.format(self.sender().objectName())
        lastUsedFilePath = self.settings.value(sender, '')

        fileName = QFileDialog.getOpenFileName(self,self.tr(u'Open Raster'), 
                                               u'{}'.format(lastUsedFilePath),
                                               QgsProviderRegistry.instance().fileRasterFilters())
        if fileName:
            self.iface.addRasterLayer(fileName, QFileInfo(fileName).baseName())
            self.settings.setValue(sender, os.path.dirname(fileName))

    def onLoadShapefile(self):
        """Open 'Add shapefile layer dialog'."""
        sender = '{}-lastUserFilePath'.format(self.sender().objectName())
        lastUsedFilePath = self.settings.value(sender, '')
        
        fileName = QFileDialog.getOpenFileName(self,self.tr(u'Open Shapefile'),
                                               u'{}'.format(lastUsedFilePath),
                                               QgsProviderRegistry.instance().fileVectorFilters())
        if fileName:
            self.iface.addVectorLayer(fileName, QFileInfo(fileName).baseName(), "ogr")
            self.settings.setValue(sender, os.path.dirname(fileName))

    def onAddKFactor(self):
        bpej_layer = self.shp_box_bpej.currentLayer()
        bpej_error = self.tr(u'layer must contain field \'BPEJ\'(format:\'X.XX.XX\' or  value \'99\' for NoData)')
        try:
            if bpej_layer is None:
                self.showError(self.tr(u'You have to choose or load BPEJ layer.\n This ') + bpej_error)
                return
            elif bpej_layer.fieldNameIndex('BPEJ') == -1:
                self.showError(self.tr(u'BPEJ ') + bpej_error)
                return
            else:
                bpej_layer.startEditing()
                self._addColumn(bpej_layer, 'K')
                bpej_layer.commitChanges()
        except:
            bpej_layer.rollBack()
            self.showError(self.tr(u'Error during add \'K\' field, please check BPEJ layer.'))
        try:
            bpej_layer.startEditing()
            idx = bpej_layer.fieldNameIndex('BPEJ')
            for feature in bpej_layer.getFeatures():
                bpej = feature.attributes()[idx]
                fid = feature.id()
                if bpej == '99':
                    k_value = None
                else:
                    k_value = self._factors['K'].value(bpej[2] + bpej[3])
                self.setFieldValue(bpej_layer, 'K', k_value, fid)
            bpej_layer.commitChanges()
            self.setBpejStyle(bpej_layer)
            self.iface.messageBar().pushMessage(self.tr('Soil Erosion Plugin'), self.tr('K factor is computed!'))
        except:
            bpej_layer.rollBack()
            self.showError(self.tr(u'BPEJ ') + bpej_error)
            return

    def onAddCFactor(self):
        lpis_layer = self.shp_box_lpis.currentLayer()
        lpis_error = self.tr(u'layer must contain field \'KULTURAKOD\'\nwith allowed codes for land:\n   R - Arable land\n' \
                     u'   T - Permanent grassland\n   S - Orchard\n   L - Forest\n   V - Vineyard\n   C - Hop-garden\n' \
                     u'At least one feature must have code \'R\'!')
        if lpis_layer is None:
            self.showError(self.tr(u'You have to choose or load LPIS layer.\nThis ') + lpis_error)
            return
        elif lpis_layer.fieldNameIndex('KULTURAKOD') == -1:
            self.showError(self.tr(u'LPIS ') + lpis_error)
            return
        else:
            lpis_layer.startEditing()
            self._addColumn(lpis_layer, 'C')
            lpis_layer.commitChanges()

        try:
            self.setLpisStyle(lpis_layer)
            lpis_layer.startEditing()
            combobox_value = self.combobox_c.currentText()
            idx = lpis_layer.fieldNameIndex('KULTURAKOD')
            for feature in lpis_layer.getFeatures():
                lpis = feature.attributes()[idx]
                fid = feature.id()
                if lpis == 'T':
                    c_value = 0.005
                elif lpis == 'S':
                    c_value = 0.45
                elif lpis == 'L':
                    c_value = 0.003
                elif lpis == 'V':
                    c_value = 0.85
                elif lpis == 'C':
                    c_value = 0.8
                elif lpis == 'R':
                    c_value = self._factors['C'].value(combobox_value)
                self.setFieldValue(lpis_layer, 'C', c_value, fid)
            lpis_layer.commitChanges()
            self.iface.messageBar().pushMessage(self.tr('Soil Erosion Plugin'), self.tr('C factor is computed!'))
        except:
            lpis_layer.rollBack()
            self.showError(self.tr(u'LPIS ') + lpis_error)
            return

    def setFieldValue(self, euc_layer, field_name, value, fid=None):
        index = euc_layer.dataProvider().fieldNameIndex(field_name)
        
        if fid is None:
            for feature in euc_layer.getFeatures():
                fid = feature.id()
                euc_layer.changeAttributeValue(fid, index, value)
        else:
            euc_layer.changeAttributeValue(fid, index, value)
        
    def _readFactorCodes(self):
        for fact in ('K','C'):
            filename = os.path.join(os.path.dirname(__file__), 'code_tables', fact + '_factor.csv')
            self._factors[fact] = ReadCSV(filename)

    def _addColumn(self, layer, name):
        for field in layer.pendingFields():
            if field.name() == name:
                return

        # column does not exists
        # TODO
        # caps & QgsVectorDataProvider.AddAttributes):
        layer.dataProvider().addAttributes(
            [QgsField(name, QVariant.Double)]
        )
        
    # def onIntersectLayers(self):
    #     euc_layer = self.shp_box_euc.currentLayer()
    #     bpej_layer = self.shp_box_bpej.currentLayer()
    #     analyzer = QgsOverlayAnalyzer()
    #     analyzer.intersection(euc_layer, bpej_layer, os.path.join(os.path.dirname(__file__), 'intersect.shp'), False, None)

    def onCompute(self):
        if hasattr(self, "computeThread"):
            return
        # remove results from map window, if it is not first computation
        if self._first_computation == False:
            try:
                QgsMapLayerRegistry.instance().removeMapLayer(self._se_layer.id())
                for field in self._euc_vector.pendingFields():
                    if field.name() == 'G':
                        field_id = self._euc_vector.fieldNameIndex(field.name())
                        fList = list()
                        fList.append(field_id)
                        self._euc_vector.dataProvider().deleteAttributes(fList)
                QgsMapLayerRegistry.instance().removeMapLayer(self._euc_vector.id())
            except:
                self.showError(self.tr(u'Error during deleting layers from previous computation.'))
                return
        # find input layers
        euc_layer = self.shp_box_euc.currentLayer()
        dmt_layer = self.raster_box.currentLayer()
        bpej_layer = self.shp_box_bpej.currentLayer()
        lpis_layer = self.shp_box_lpis.currentLayer()

        # check fields
        self._cancel = False
        self.checkField('BPEJ', bpej_layer, 'K')
        if self._cancel == True:
            return

        self.checkField('LPIS', lpis_layer, 'C')
        if self._cancel == True:
            return

        # check crs of input layers
        euc_crs = euc_layer.crs().authid()
        dmt_crs = dmt_layer.crs().authid()
        bpej_crs = bpej_layer.crs().authid()
        lpis_crs = lpis_layer.crs().authid()
        if euc_crs == dmt_crs == bpej_crs == lpis_crs:
            if not int(euc_crs[5:]) >= 100000:
                epsg = int(euc_crs[5:])
            else:
                self.showError(self.tr(u'It\'s not allow compute in own projection!\n\nSet CRS of'\
                               u' input layers: {}\n\nPlease change CRS of input layers to EPSG Code.').format(euc_crs))
                return
        else:
            self.showError(self.tr(u'All inputs have to be at the same projection!\nEUC: {}\nDMT: {}\nBPEJ: {}\nLPIS: {}\n'\
                           u'Please set only one projections for all input layers.').format(euc_crs, dmt_crs, bpej_crs, lpis_crs))
            return

        # add paths to layers to data
        data = []

        euc_path = euc_layer.dataProvider().dataSourceUri()
        data.append(euc_path[:euc_path.rfind('|')])

        dmt_path = dmt_layer.dataProvider().dataSourceUri()
        data.append(dmt_path)

        bpej_path = bpej_layer.dataProvider().dataSourceUri()
        data.append(bpej_path [:bpej_path.rfind('|')])

        lpis_path = lpis_layer.dataProvider().dataSourceUri()
        data.append(lpis_path [:lpis_path.rfind('|')])

        # find r, p factors and add them to factors
        factors = []
        r_factor = self.r_factor.text()
        p_factor = self.p_factor.text()
        factors.append(r_factor)
        factors.append(p_factor)

        self.progressBar()
        self.computeThread = ComputeThread(data, factors, epsg)
        self.computeThread.computeFinished.connect(lambda: self.importResults(epsg))
        self.computeThread.computeStat.connect(self.setStatus)
        self.computeThread.computeError.connect(self.showError)
        #self.computeThread.computeProgress.connect(self.progressBar)
        if not self.computeThread.isRunning():
            self.computeThread.start()

    def checkField(self, name_lyr, layer, field_name):
        if layer.fieldNameIndex(field_name) == -1:
            self.showError(self.tr(u'{} layer must contain field {}.\nClick on \'Compute {} factor\'')\
                           .format(name_lyr, field_name, field_name))
            self._cancel = True

    def showError(self, text):
        QMessageBox.critical(self, self.tr(u'Soil Erosion Plugin'), u"{}".format(text))

    def importResults(self, epsg):
        # if self.computeThread.aborted:
        #     return

        # Import results to QGIS
        temp_path = self.computeThread.output_path()
        for file in os.listdir(temp_path):
            if file.endswith(".tif"):
                try:
                    self._se_layer = iface.addRasterLayer(os.path.join(temp_path, file),
                                                    self.tr('G Faktor'))
                    crs = self._se_layer.crs()
                    crs.createFromId(epsg)
                    self._se_layer.setCrs(crs)
                    self.layerOnTop(self._se_layer)
                    # # Set style be renderer:
                    # self.setStyle(self._se_layer)
                    # # set style on .gml file:
                    euc = self.shp_box_euc.currentLayer()
                    self._euc_vector = iface.addVectorLayer(euc.source(), "EUC", euc.providerType())
                    self.layerOnTop(self._euc_vector)
                    se_source = self._se_layer.source()
                    self.zonalStat(self._euc_vector, se_source)
                    self.setVectorErosionStyle(self._euc_vector)
                    self._euc_vector.commitChanges()
                # for field in _euc_vector.pendingFields():
                #     if field.name() == 'C':
                #         _euc_vector.startEditing()
                #         oldname = field.name()
                #         field.setName('NewName')
                #         newname = field.name()
                #         self.showError(u'Old name: {},New name: {}'.format(oldname,newname))
                #

                except:
                    self.showError(u'Error during compute zonal statistics.')
        self._first_computation = False

        self.computeThread.cleanup()
        del self.computeThread
        # kill progress bar if it is still on (if computation is still on)
        try:
            self.progress.setParent(None)
            self.iface.messageBar().popWidget(self.progressMessageBar)
        except:
            pass
    def layerOnTop(self, layer):
        root = QgsProject.instance().layerTreeRoot()
        alayer = root.findLayer(layer.id())
        clone = alayer.clone()
        parent = alayer.parent()
        parent.insertChildNode(0, clone)
        parent.removeChildNode(alayer)

    def setBpejStyle(self, layer):
        # define ranges: label, lower value, upper value, hex value of color
        k_values = (
            (self.tr('0.0-0.1'), 0.0, 0.1, '#458b00'),
            (self.tr('0.1-0.2'), 0.1, 0.2, '#bcee68'),
            (self.tr('0.2-0.3'), 0.2, 0.3, '#eedd82'),
            (self.tr('0.3-0.4'), 0.3, 0.4, '#ffa07a'),
            (self.tr('0.4-0.5'), 0.4, 0.5, '#ff4500'),
            (self.tr('0.5 and more'), 0.5, 9999.0, '#8b2500'),
        )

        # create a category for each item in k_values
        ranges = []
        for label, lower, upper, color in k_values:
            symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
            symbol.setColor(QColor(color))
            rng = QgsRendererRangeV2(lower, upper, symbol, label)
            ranges.append(rng)

        # create the renderer and assign it to a layer
        expression = 'K'  # field name
        renderer = QgsGraduatedSymbolRendererV2(expression, ranges)
        layer.setRendererV2(renderer)

    def setLpisStyle(self, layer):
        # define a lookup: value -> (color, label)
        land_types = {
            'L': ('#005900', self.tr('Forest')),
            'R': ('#6d4237', self.tr('Arable land')),
            'S': ('#fb5858', self.tr('Orchard')),
            'V': ('#d875e4', self.tr('Vineyard')),
            'C': ('#f2d773', self.tr('Hop-garden')),
            'T': ('#329932', self.tr('Permanent grassland')),
            '': ('#808080', self.tr('Unknown')),
        }

        # create a category for each item in land_types
        categories = []
        for land_type, (color, label) in land_types.items():
            symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
            symbol.setColor(QColor(color))
            category = QgsRendererCategoryV2(land_type, symbol, label)
            categories.append(category)

        # create the renderer and assign it to a layer
        expression = 'KULTURAKOD'  # field name
        renderer = QgsCategorizedSymbolRendererV2(expression, categories)
        layer.setRendererV2(renderer)

    def setVectorErosionStyle(self, layer):
        # define ranges: label, lower value, upper value, hex value of color
        g_values = (
            (self.tr('Very weakly endangered'), 0.0, 1.0, '#458b00'),
            (self.tr('Weakly endangered'), 1.0, 2.0, '#bcee68'),
            (self.tr('Moderately endangered'), 2.0, 4.0, '#eedd82'),
            (self.tr('Severely endangered'), 4.0, 8.0, '#ffa07a'),
            (self.tr('Very severely endangered'), 8.0, 10.0, '#ff4500'),
            (self.tr('Extremely endangered'), 10.0, 999999.9, '#8b2500'),
        )

        # create a category for each item in g_values
        ranges = []
        for label, lower, upper, color in g_values:
            symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
            symbol.setColor(QColor(color))
            rng = QgsRendererRangeV2(lower, upper, symbol, label)
            ranges.append(rng)

        # create the renderer and assign it to a layer
        expression = 'G'  # field name
        renderer = QgsGraduatedSymbolRendererV2(expression, ranges)
        layer.setRendererV2(renderer)
    def progressBar(self):
        """Initializing progress bar.

        :text: message to indicate what operation is currently on
        """
        self.progressMessageBar = iface.messageBar().createMessage(self.tr(u'Soil Erosion Plugin:'), self.tr(u' Computing...'))
        self.progress = QProgressBar()
        self.progress.setMaximum(100)
        self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)

        self.cancelButton = QtGui.QPushButton()
        self.cancelButton.setText(self.tr('Cancel'))
        self.progressMessageBar.layout().addWidget(self.cancelButton)
        self.progressMessageBar.layout().addWidget(self.progress)

        msgBar = self.iface.messageBar()
        msgBar.pushWidget(self.progressMessageBar, iface.messageBar().INFO)
        msgBar.findChildren(QToolButton)[0].setHidden(True)

        self.cancelButton.clicked.connect(self.onCancelButton)

    def onCancelButton(self):
        """Show message box with question on canceling. Cancel computation."""

        reply = QMessageBox.question(self, self.tr(u'Soil Erosion Plugin'),
                                     self.tr(u'Cancel computation?{ls}').format(
                                         ls=2 * os.linesep),
                                     QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
                                     QtGui.QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            self.computeThread.terminate()
            self.computeThread.cleanup()
            del self.computeThread

            # kill progress bar if it is still on (if computation is still on)
            try:
                self.progress.setParent(None)
                self.iface.messageBar().popWidget(self.progressMessageBar)
            except:
                pass

    def setStatus(self, num, text):
        """Update progress status.

        :num: progress percent
        """
        self.progressMessageBar.setText(text)
        self.progress.setFormat('{}%'.format(num))
        self.progress.setValue(num)

    def setStyle(self, layer):
        provider = layer.dataProvider()
        extent = layer.extent()

        stats = provider.bandStatistics(1, QgsRasterBandStats.All, extent, 0)
        if stats.minimumValue < 0:
            min = 0
        else:
            min = stats.minimumValue

        max = stats.maximumValue
        range = max - min
        add = range // 2
        interval = min + add

        colDic = {'red': '#ff0000', 'yellow': '#ffff00', 'blue': '#0000ff'}

        valueList = [min, interval, max]

        lst = [QgsColorRampShader.ColorRampItem(valueList[0], QColor(colDic['red'])),
               QgsColorRampShader.ColorRampItem(valueList[1], QColor(colDic['yellow'])),
               QgsColorRampShader.ColorRampItem(valueList[2], QColor(colDic['blue']))]

        myRasterShader = QgsRasterShader()
        myColorRamp = QgsColorRampShader()

        myColorRamp.setColorRampItemList(lst)
        myColorRamp.setColorRampType(QgsColorRampShader.INTERPOLATED)
        # TODO: add classificationMode=Continuos
        # myColorRamp.setClassificationMode(QgsColorRampShader.ClassificationMode(1))
        # AttributeError: type object 'QgsColorRampShader' has no attribute 'setClassificationMode'
        myRasterShader.setRasterShaderFunction(myColorRamp)

        myPseudoRenderer = QgsSingleBandPseudoColorRenderer(layer.dataProvider(),
                                                            layer.type(),
                                                            myRasterShader)

        layer.setRenderer(myPseudoRenderer)

        layer.triggerRepaint()

    def zonalStat(self, vlayer, rlayer_source):
        prefix = 'Erosion_G_'
        zonalstats = QgsZonalStatistics(vlayer, rlayer_source, prefix, stats=QgsZonalStatistics.Statistic(4))
        zonalstats.calculateStatistics(None)
        vlayer.startEditing()
        for field in vlayer.pendingFields():
            if field.name() == 'Erosion_G_':
                idx = vlayer.fieldNameIndex(field.name())
                vlayer.renameAttribute(idx, 'G')
        vlayer.commitChanges()
class _CancellableProgressEditor(Editor):

    title = Unicode   # synced from factory.title_name 
    message = Unicode # synced from factory.message_name
    min = Int#Float   # synced from factory.min_name
    max = Int#Float   # synced from factory.max_name
    show_time = Bool  # synced from factory.show_time_name

    def _title_changed(self):
        if self._title is not None:
            self._title.setText('<B>%s</B>' % self.title)
            self._title.setVisible(len(self.title) > 0)
    
    def _message_changed(self):
        if self._message is not None:
            self._message.setText(self.message)
            self._message.setVisible(len(self.message) > 0)
        if self.factory.prefix_message:
            self.set_text()

    def _show_time_changed(self):
        if self._time_widget is not None:
            self._time_widget.setVisible(self.show_time)
    
    @on_trait_change('min, max')
    def change_range(self):
        if self._progress_bar is not None:
            self._progress_bar.setRange(self.min, self.max)
            self.update_editor()
    
    def init(self, parent):

        self.title = self.factory.title
        if len(self.factory.title_name) > 0:
            self.sync_value(self.factory.title_name, 'title')#, 'from')
        
        self.message = self.factory.message
        if len(self.factory.message_name) > 0:
            self.sync_value(self.factory.message_name, 'message')#, 'from')

        self.min = self.factory.min
        if len(self.factory.min_name) > 0:
            self.sync_value(self.factory.min_name, 'min')#, 'from')

        self.max = self.factory.max
        if len(self.factory.max_name) > 0:
            self.sync_value(self.factory.max_name, 'max')#, 'from')
        
        self.show_time = self.factory.show_time
        if len(self.factory.show_time_name) > 0:
            self.sync_value(self.factory.show_time_name, 'show_time')#, 'from')
        
        self.control = self._create_control(parent)

        self.can_cancel = self.factory.can_cancel
        if len(self.factory.can_cancel_name) > 0:
            self.sync_value(self.factory.can_cancel_name, 'can_cancel')#, 'from')
                
        self.set_tooltip()
        self.reset()

    can_cancel = Bool(False)
    from traits.api import Any
    buttons = Any
    @on_trait_change('can_cancel')
    def set_buttons_visible(self, value):
        self.buttons.setVisible(value)

    def _create_control(self, parent):
        layout = QVBoxLayout()
        
        if len(self.title) > 0:
            self._title = QLabel('<B>%s</B>' % self.title)
            layout.addWidget(self._title)
    
        if not self.factory.prefix_message and len(self.message) > 0:
            self._message = QLabel(self.message)
#            self._message = QTextEdit(self.message)
#            self._message.setReadOnly(True)
            layout.addWidget(self._message)
    
        self._progress_bar = QProgressBar()
        self._progress_bar.setRange(self.min, self.max)
        if not self.factory.can_cancel:
            layout.addWidget(self._progress_bar)
        else:
            self.buttons = QDialogButtonBox()
            self.buttons.addButton(u'Cancel', QDialogButtonBox.RejectRole)
            self.buttons.connect(self.buttons, SIGNAL('rejected()'), self.factory.cancelled)
            grid_layout = QGridLayout()
            grid_layout.addWidget(self._progress_bar, 0, 0)
            grid_layout.setColumnStretch(0, 1)
            grid_layout.addWidget(self.buttons, 0, 1)
            layout.addLayout(grid_layout)
                
        if self.factory.show_time:
            elapsed_label = QLabel('Elapsed time:')
            estimated_label = QLabel('Estimated time:')
            remaining_label = QLabel('Remaining time:')
            self._elapsed_control = QLabel('unknown')
            self._estimated_control = QLabel('unknown')
            self._remaining_control = QLabel('unknown')
            grid_layout = QGridLayout()
            grid_layout.addWidget(elapsed_label, 0, 0)
            grid_layout.addWidget(self._elapsed_control, 0, 1)
            grid_layout.addWidget(estimated_label, 1, 0)
            grid_layout.addWidget(self._estimated_control, 1, 1)
            grid_layout.addWidget(remaining_label, 2, 0)
            grid_layout.addWidget(self._remaining_control, 2, 1)
            grid_layout.setColumnStretch(1, 1)
            self._time_widget = QWidget()
            self._time_widget.setLayout(grid_layout)
            layout.addWidget(self._time_widget)
        
        if self.factory.show_text:
            self.set_text()
        else:
            self._progress_bar.setTextVisible(False)

        widget = QWidget()
        widget.setLayout(layout)
        return widget

    def set_text(self):
        if self._progress_bar is None:
            return
        if self.factory.prefix_message:
            format = self.message + ' '
        else:
            format = ''
        if self.factory.show_value:
            format += '%v'
        if self.factory.show_max:
            if self.factory.show_value:
                format += '/'
            format += '%m'
        if self.factory.show_value or self.factory.show_max:
            format += ' '
        if self.factory.show_percent:
            if self.factory.show_value or self.factory.show_max:
                format += '(%p%)'
            else:
                format += '%p%'
        self._progress_bar.setFormat(format)

    def _set_time_label(self, value, control):
        hours = value / 3600
        minutes = (value % 3600) / 60
        seconds = value % 60
        label = "%1u:%02u:%02u" % (hours, minutes, seconds)
        control.setText(control.text()[:-7] + label)

    def update_editor(self):
        if self.factory.min <= self.value <= self.factory.max:
            if self.value == self.factory.min:
                self.reset()
            self._progress_bar.setValue(self.value)

        if self.factory.show_time:
            if (self.factory.max != self.factory.min):
                percent = (float(self.value) - self.factory.min) / (self.factory.max - self.factory.min)
                # if float(<undefined>) raises an error here then probably the
                # name of the trait this is editing is mispelled or owned by
                # the handler, e.g. 'handler.progress' instead of 'progress'. 
            else:
                percent = 1.0
            if self.factory.show_time and (percent != 0):
                current_time = time.time()
                elapsed = current_time - self._start_time
                estimated = elapsed / percent
                remaining = estimated - elapsed
                self._set_time_label(elapsed, self._elapsed_control)
                self._set_time_label(estimated, self._estimated_control)
                self._set_time_label(remaining, self._remaining_control)            

    def reset(self):
        self._progress_bar.reset()
        self._start_time = time.time()
Exemplo n.º 13
0
class VmUsageBarWidget(QWidget):
    class VmUsageBarItem(QTableWidgetItem):
        def __init__(self, value, vm):
            super(VmUsageBarWidget.VmUsageBarItem, self).__init__()
            self.value = value
            self.vm = vm

        def set_value(self, value):
            self.value = value

        def __lt__(self, other):
            if self.vm.qid == 0:
                return True
            elif other.vm.qid == 0:
                return False
            elif self.value == other.value:
                return self.vm.qid < other.vm.qid
            else:
                return int(self.value) < int(other.value)

    def __init__(self,
                 min,
                 max,
                 format,
                 update_func,
                 vm,
                 load,
                 hue=210,
                 parent=None):
        super(VmUsageBarWidget, self).__init__(parent)

        self.min = min
        self.max = max
        self.update_func = update_func
        self.value = min

        self.widget = QProgressBar()
        self.widget.setMinimum(min)
        self.widget.setMaximum(max)
        self.widget.setFormat(format)

        self.widget.setStyleSheet(
                                    "QProgressBar:horizontal{" +\
                                        "border: 1px solid hsv({0}, 100, 250);".format(hue) +\
                                        "border-radius: 4px;\
                                        background: white;\
                                        text-align: center;\
                                    }\
                                    QProgressBar::chunk:horizontal {\
                                        background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, "                                                                                                      +\
                                        "stop: 0 hsv({0}, 170, 207),".format(hue) +
                                        " stop: 1 white); \
                                    }"
            )

        layout = QHBoxLayout()
        layout.addWidget(self.widget)

        self.setLayout(layout)
        self.tableItem = self.VmUsageBarItem(min, vm)

        self.update_load(vm, load)

    def update_load(self, vm, load):
        self.value = self.update_func(vm, load)
        self.widget.setValue(self.value)
        self.tableItem.set_value(self.value)
Exemplo n.º 14
0
class UploadDialog(QDialog):


    def __init__(self, bbclient, parent=None, session_id=None, username=None, password=None):
        super(UploadDialog, self).__init__(parent,
                Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowMinMaxButtonsHint)

        self.session_id = session_id
        self.username = username
        self.password = password
        self._first_auth = True


        self.total_progress = QProgressBar(self)
        self.total_progress.setRange(0, 100)
        self.total_progress.setValue(0)
        self.total_progress.setFormat('%p%')


        self.status_msg = QLabel('Starting upload', self)


        self.setWindowTitle('Uploading')


        self._createLayout()


        self.upload = BrytonSportUpload(bbclient, parent=self)

        self.upload.authNeeded.connect(self._onAuthNeeded)
        self.upload.totalProgress.connect(self.total_progress.setValue)
        self.upload.statusMessage.connect(self.status_msg.setText)
        self.upload.finished.connect(self._onFinished)
        self.upload.failed.connect(self._onError)
        # self.upload.start()

        QTimer.singleShot(100, self.upload.start)




    def _createLayout(self):

        l = QVBoxLayout()

        l.addWidget(self.status_msg)
        l.addWidget(self.total_progress)

        self.setLayout(l)



    def _onAuthNeeded(self):

        if self._first_auth and self.username is not None and self.password is not None:
            self._first_auth = False
            self.upload.authenticate(self.username, self.password)
            return


        d = AuthDialog(self)

        if d.exec_() == QDialog.Accepted:
            u, p = d.getValues()
            self.upload.authenticate(u, p)
        else:
            self.accept()


    def _onFinished(self):

        QMessageBox.information(self, 'Upload Finished', 'The tracks was successfully uploaded.')

        self.accept()

    def _onError(self):
        QMessageBox.warning(self, 'Upload Failed', 'The upload failed with an unknown error.')
        self.accept()
Exemplo n.º 15
0
class VmUsageBarWidget (QWidget):

    class VmUsageBarItem (QTableWidgetItem):
        def __init__(self, value, vm):
            super(VmUsageBarWidget.VmUsageBarItem, self).__init__()
            self.value = value
            self.vm = vm

        def set_value(self, value):
            self.value = value

        def __lt__(self, other):
            if self.vm.qid == 0:
                return True
            elif other.vm.qid == 0:
                return False
            elif self.value == other.value:
                return self.vm.qid < other.vm.qid
            else:
                return int(self.value) < int(other.value)

    def __init__(self, min, max, format, update_func, vm, load, hue=210, parent = None):
        super (VmUsageBarWidget, self).__init__(parent)


        self.min = min
        self.max = max
        self.update_func = update_func
        self.value = min

        self.widget = QProgressBar()
        self.widget.setMinimum(min)
        self.widget.setMaximum(max)
        self.widget.setFormat(format)

        self.widget.setStyleSheet(
                                    "QProgressBar:horizontal{" +\
                                        "border: 1px solid hsv({0}, 100, 250);".format(hue) +\
                                        "border-radius: 4px;\
                                        background: white;\
                                        text-align: center;\
                                    }\
                                    QProgressBar::chunk:horizontal {\
                                        background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, " +\
                                        "stop: 0 hsv({0}, 170, 207),".format(hue) +
                                        " stop: 1 white); \
                                    }"
            )

        layout = QHBoxLayout()
        layout.addWidget(self.widget)

        self.setLayout(layout)
        self.tableItem = self.VmUsageBarItem(min, vm)

        self.update_load(vm, load)



    def update_load(self, vm, load):
        self.value = self.update_func(vm, load)
        self.widget.setValue(self.value)
        self.tableItem.set_value(self.value)
class GroundRadiationMonitoringDockWidget(QtGui.QDockWidget, FORM_CLASS):

    closingPlugin = pyqtSignal()

    def __init__(self, parent=None):
        """Constructor."""
        super(GroundRadiationMonitoringDockWidget, 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.setupUi(self)

        self.settings = QSettings("CTU", "GRMplugin")

        self.iface = iface

        # Set filters for QgsMapLayerComboBoxes
        self.raster_box.setFilters(QgsMapLayerProxyModel.RasterLayer)
        self.track_box.setFilters(QgsMapLayerProxyModel.LineLayer)

        self.load_raster.clicked.connect(self.onLoadRaster)
        self.load_track.clicked.connect(self.onLoadTrack)

        self.save_button.setEnabled(False)
        self.report_button.clicked.connect(self.onReportButton)
        #self.dir_button.clicked.connect(self.onCsvButton)
        self.shp_button.clicked.connect(self.onShpButton)
        self.save_button.clicked.connect(self.onExportRasterValues)

    def closeEvent(self, event):
        self.closingPlugin.emit()
        event.accept()

    def onLoadRaster(self):
        """Open 'Add raster layer dialog'."""
        sender = u'{}-lastUserFilePath'.format(self.sender().objectName())
        lastUsedFilePath = self.settings.value(sender, '')

        fileName = QFileDialog.getOpenFileName(
            self, self.tr(u'Open raster'),
            self.tr(u'{}').format(lastUsedFilePath),
            QgsProviderRegistry.instance().fileRasterFilters())
        if fileName:
            self.iface.addRasterLayer(fileName, QFileInfo(fileName).baseName())
            self.settings.setValue(sender, os.path.dirname(fileName))

    def onLoadTrack(self):
        """Open 'Add track layer dialog'."""
        sender = u'{}-lastUserFilePath'.format(self.sender().objectName())
        lastUsedFilePath = self.settings.value(sender, '')

        fileName = QFileDialog.getOpenFileName(
            self, self.tr(u'Open track'),
            self.tr(u'{}').format(lastUsedFilePath),
            QgsProviderRegistry.instance().fileVectorFilters())
        if fileName:
            self.iface.addVectorLayer(fileName,
                                      QFileInfo(fileName).baseName(), "ogr")
            self.settings.setValue(sender, os.path.dirname(fileName))

            name, fileExtension = os.path.splitext(fileName)
            if fileExtension not in QgsProviderRegistry.instance(
            ).fileVectorFilters():
                return

            # TODO: make this work for multiple layer loading
            if self.iface.activeLayer().geometryType() != QGis.Line:
                self.sendMessage(
                    u'Info', u'{} does not have lineString type.'.format(
                        QFileInfo(fileName).baseName()), 'INFO')

    def onReportButton(self):
        """Get destination of report, csv and shape file.

        Set path and name for csv and shape file by default as file path for report file.
        
        Set default name for report file same as track layer name"""

        sender = u'{}-lastUserFilePath'.format(self.sender().objectName())
        lastUsedFilePath = self.settings.value(sender, '')

        self.saveReportName = QFileDialog.getSaveFileName(
            self,
            self.tr(u'Select destination file'),
            self.tr(u'{}{}.txt').format(lastUsedFilePath, os.path.sep),
            filter="TXT (*.txt)")
        self.saveShpName = self.tr(u'{}.shp').format(
            self.saveReportName.split('.')[0])

        self.report_file.setText(self.tr(u'{}').format(self.saveReportName))

        if self.saveReportName:
            self.shp_file.setText(self.tr(u'{}').format(self.saveShpName))
            self.settings.setValue(sender,
                                   os.path.dirname(self.saveReportName))

        # Enable the saveButton if file is chosen
        if not self.report_file.text():
            self.save_button.setEnabled(False)
        else:
            self.save_button.setEnabled(True)

    def onShpButton(self):
        """Get destination of shp file."""

        sender = u'{}-lastUserFilePath'.format(self.sender().objectName())
        lastUsedFilePath = self.settings.value(sender, '')
        self.saveShpName = QFileDialog.getSaveFileName(
            self,
            self.tr(u'Select destination file'),
            self.tr(u'{}{}.shp').format(lastUsedFilePath, os.path.sep),
            filter="ESRI Shapefile (*.shp)")

        self.shp_file.setText(u'{}'.format(self.saveShpName))

        if self.saveShpName:
            self.settings.setValue(sender, os.path.dirname(self.saveShpName))

        if not (self.report_file.text() and self.shp_file.text()):
            self.save_button.setEnabled(False)
        else:
            self.save_button.setEnabled(True)

    def onExportRasterValues(self):
        """Export sampled raster values to output CSV file.

        Prints error when user selected length of segment or speed is not positive real number
        and computation is not performed.

        When no raster or track vector layer given, than computation
        is not performed.
        
        If shapefile that will be created has the same name as one of the layers in
        map canvas, that layer will be removed from map layer registry.
        """
        noSamplingFlag = False
        if not self.vertex_dist.text().strip():
            distanceBetweenVertices = 0
            noSamplingFlag = True

        if noSamplingFlag == False:
            try:
                distanceBetweenVertices = float(
                    self.vertex_dist.text().replace(',', '.'))
            except ValueError:
                self.sendMessage(
                    u'Error',
                    u'"{}" is not a number. (distance between vertices)'.
                    format(self.vertex_dist.text()), 'CRITICAL')
                return

        if distanceBetweenVertices <= 0 and noSamplingFlag == False:
            self.sendMessage(
                u'Error',
                u'"{}" is not a positive number. (distance between vertices)'.
                format(distanceBetweenVertices), 'CRITICAL')
            return

        if not self.speed.text():
            self.sendMessage(u'Error', u'No speed given.', 'CRITICAL')
            return
        try:
            speed = float(self.speed.text().replace(',', '.'))
        except ValueError:
            self.sendMessage(
                u'Error',
                u'"{}" is not a number. (speed)'.format(self.speed.text()),
                'CRITICAL')
            return

        if speed <= 0:
            self.sendMessage(
                u'Error',
                u'"{}" is not a positive number. (speed)'.format(speed),
                'CRITICAL')
            return

        if not self.raster_box.currentLayer(
        ) or not self.track_box.currentLayer():
            self.sendMessage(u'Error', u'No raster/track layer chosen.',
                             'CRITICAL')
            return

        # remove layers with same name as newly created layer
        for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
            if lyr.source() == self.saveShpName:
                QgsMapLayerRegistry.instance().removeMapLayer(lyr.id())

        self.saveCsvName = None

        if self.create_csv.isChecked():
            self.saveCsvName = self.tr(u'{}.csv').format(
                self.saveShpName.split('.')[0])

        self.computeThread = GroundRadiationMonitoringComputation(
            self.raster_box.currentLayer().id(),
            self.track_box.currentLayer().id(), self.saveReportName,
            self.saveCsvName, self.saveShpName, distanceBetweenVertices, speed,
            self.unit_box.currentText())
        self.saveShpNameOriginal = self.saveShpName
        self.saveReportNameOriginal = self.saveReportName
        self.saveCsvNameOriginal = self.saveCsvName
        self.computeThread.computeEnd.connect(self.addNewLayer)
        self.computeThread.computeStat.connect(self.setStatus)
        self.computeThread.computeProgress.connect(self.progressBar)
        self.computeThread.computeMessage.connect(self.sendMessage)
        if not self.computeThread.isRunning():
            self.computeThread.start()

        self.save_button.setEnabled(False)

    def onCancelButton(self):
        """Show message box with question on canceling. Cancel computation."""

        reply = QMessageBox.question(
            self, u'Ground Radiation Monitoring',
            u"Cancel computation?{ls}(All created files will be lost.)".format(
                ls=2 * os.linesep),
            QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
            QtGui.QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            GroundRadiationMonitoringComputation.abortThread(
                self.computeThread)

            # kill progress bar if it is still on (if computation is still on)
            try:
                self.progress.setParent(None)
                self.iface.messageBar().popWidget(self.progressMessageBar)
            except:
                pass

            self.cleanCreatedFiles()

            if not (self.report_file.text() and self.shp_file.text()):
                self.save_button.setEnabled(False)
            else:
                self.save_button.setEnabled(True)

    def cleanCreatedFiles(self):
        """Remove created files."""

        # remove layers with same name as newly created layer (if is created
        # and added to map canvas) so shape file could be removed
        for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
            if lyr.source() == self.saveShpNameOriginal:
                QgsMapLayerRegistry.instance().removeMapLayer(lyr.id())

        # remove created files
        if os.path.isfile(self.saveReportNameOriginal):
            os.remove(self.saveReportNameOriginal)

        try:
            if os.path.isfile(self.saveCsvNameOriginal):
                os.remove(self.saveCsvNameOriginal)
        except:
            pass

        if os.path.isfile(self.saveShpNameOriginal):
            os.remove(self.saveShpNameOriginal)

        if os.path.isfile(self.saveShpNameOriginal.split('.')[0] + '.shx'):
            os.remove(self.saveShpNameOriginal.split('.')[0] + '.shx')

        if os.path.isfile(self.saveShpNameOriginal.split('.')[0] + '.dbf'):
            os.remove(self.saveShpNameOriginal.split('.')[0] + '.dbf')

        if os.path.isfile(self.saveShpNameOriginal.split('.')[0] + '.prj'):
            os.remove(self.saveShpNameOriginal.split('.')[0] + '.prj')

    def progressBar(self):
        """Initializing progress bar.
            """
        self.progressMessageBar = iface.messageBar().createMessage(
            u"Ground Radiation Monitoring:", u" Computing...")
        self.progress = QProgressBar()
        self.progress.setMaximum(100)
        self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)

        self.cancelButton = QtGui.QPushButton()
        self.cancelButton.setText('Cancel')
        self.progressMessageBar.layout().addWidget(self.cancelButton)
        self.progressMessageBar.layout().addWidget(self.progress)

        msgBar = self.iface.messageBar()
        msgBar.pushWidget(self.progressMessageBar, iface.messageBar().INFO)
        #hide x button
        msgBar.findChildren(QToolButton)[0].setHidden(True)

        self.cancelButton.clicked.connect(self.onCancelButton)

    def setStatus(self, num, text):
        """Update progress status.
        
        :num: progress percent
        """

        self.progress.setFormat(text)
        self.progress.setValue(num)

    def addNewLayer(self):
        """End computeThread.
        
        Ask to add new layer of computed points to map canvas. """

        # Message box
        reply = QMessageBox.question(
            self, u'Ground Radiation Monitoring',
            u"Add new layer to map canvas?",
            QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
            QtGui.QMessageBox.Yes)
        # add map layer to map canvas
        if reply == QMessageBox.Yes:
            newLayer = iface.addVectorLayer(
                u'{f}'.format(f=self.saveShpNameOriginal), u'{f}'.format(
                    f=QFileInfo(self.saveShpNameOriginal).baseName()), "ogr")

        self.iface.messageBar().popWidget(self.progressMessageBar)
        self.save_button.setEnabled(True)

    def sendMessage(self, caption, message, type):
        if type == 'CRITICAL':
            self.iface.messageBar().pushMessage(self.tr(u'{}').format(caption),
                                                self.tr(u'{}').format(message),
                                                level=QgsMessageBar.CRITICAL,
                                                duration=5)
        elif type == 'INFO':
            self.iface.messageBar().pushMessage(self.tr(u'{}').format(caption),
                                                self.tr(u'{}').format(message),
                                                level=QgsMessageBar.INFO,
                                                duration=5)
Exemplo n.º 17
0
class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        ec = ExplorerContainer()
        super(Main, self).initialize(*args, **kwargs)

        self.editor_s = self.locator.get_service('editor')
        # directory auto completer
        self.completer = QCompleter(self)
        self.dirs = QDirModel(self)
        self.dirs.setFilter(QDir.AllEntries | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        self.group0 = QGroupBox()
        self.group0.setTitle(' Source ')
        self.source = QComboBox()
        self.source.addItems(['Clipboard', 'Local File', 'Remote URL', 'Ninja'])
        self.source.currentIndexChanged.connect(self.on_source_changed)
        self.infile = QLineEdit(path.expanduser("~"))
        self.infile.setPlaceholderText(' /full/path/to/file.html ')
        self.infile.setCompleter(self.completer)
        self.open = QPushButton(QIcon.fromTheme("folder-open"), 'Open')
        self.open.setCursor(QCursor(Qt.PointingHandCursor))
        self.open.clicked.connect(lambda: self.infile.setText(str(
            QFileDialog.getOpenFileName(self.dock, "Open a File to read from",
            path.expanduser("~"), ';;'.join(['{}(*.{})'.format(e.upper(), e)
            for e in ['css', 'html', 'js', 'txt', '*']])))))
        self.inurl = QLineEdit('http://www.')
        self.inurl.setPlaceholderText('http://www.full/url/to/remote/file.html')
        self.output = QPlainTextEdit(SAMPLE_TEXT)
        vboxg0 = QVBoxLayout(self.group0)
        for each_widget in (self.source, self.infile, self.open, self.inurl,
            self.output, ):
            vboxg0.addWidget(each_widget)
        [a.hide() for a in iter((self.infile, self.open, self.inurl))]

        self.group1 = QGroupBox()
        self.group1.setTitle(' CSS3 ')
        self.group1.setCheckable(True)
        self.group1.setGraphicsEffect(QGraphicsBlurEffect(self))
        self.group1.graphicsEffect().setEnabled(False)
        self.group1.toggled.connect(self.toggle_css_group)
        self.ckcss1 = QCheckBox('Remove unnecessary Comments')
        self.ckcss2 = QCheckBox('Remove unnecessary Whitespace characters')
        self.ckcss3 = QCheckBox('Remove unnecessary Semicolons')
        self.ckcss4 = QCheckBox('Remove unnecessary Empty rules')
        self.ckcss5 = QCheckBox('Condense and Convert Colors from RGB to HEX')
        self.ckcss6 = QCheckBox('Condense all Zero units')
        self.ckcss7 = QCheckBox('Condense Multidimensional Zero units')
        self.ckcss8 = QCheckBox('Condense Floating point numbers')
        self.ckcss9 = QCheckBox('Condense HEX Colors')
        self.ckcss10 = QCheckBox('Condense multiple adjacent Whitespace chars')
        self.ckcss11 = QCheckBox('Condense multiple adjacent semicolon chars')
        self.ckcss12 = QCheckBox('Wrap the lines of the to 80 character length')
        self.ckcss13 = QCheckBox('Condense Font Weight values')
        self.ckcss14 = QCheckBox('Condense the 17 Standard Named Colors values')
        self.ckcss15 = QCheckBox('Condense the 124 Extra Named Colors values')
        self.ckcss16 = QCheckBox('Condense all Percentages values when posible')
        self.ckcss17 = QCheckBox('Condense all Pixels values when posible')
        self.ckcss18 = QCheckBox('Remove unnecessary quotes from url()')
        self.ckcss19 = QCheckBox('Add standard Encoding Declaration if missing')
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (self.ckcss1, self.ckcss2, self.ckcss3, self.ckcss4,
            self.ckcss5, self.ckcss6, self.ckcss7, self.ckcss8, self.ckcss9,
            self.ckcss10, self.ckcss11, self.ckcss12, self.ckcss13,
            self.ckcss14, self.ckcss15, self.ckcss16, self.ckcss17,
            self.ckcss18, self.ckcss19):
            vboxg1.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group2 = QGroupBox()
        self.group2.setTitle(' HTML5 ')
        self.group2.setCheckable(True)
        self.group2.setGraphicsEffect(QGraphicsBlurEffect(self))
        self.group2.graphicsEffect().setEnabled(False)
        self.group2.toggled.connect(self.toggle_html_group)
        self.ckhtml0 = QCheckBox('Condense Style and Script HTML Tags')
        self.ckhtml1 = QCheckBox('Condense DOCTYPE to new HTML5 Tags')
        self.ckhtml2 = QCheckBox('Condense Href and Src to protocol agnostic')
        self.ckhtml4 = QCheckBox('Remove unnecessary Tags but keep HTML valid')
        self.help1 = QLabel('''<a href=
            "https://developers.google.com/speed/articles/optimizing-html">
            <small><center>Help about Unneeded Unnecessary HTML tags ?</a>''')
        self.help1.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
        self.help1.setOpenExternalLinks(True)
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (self.ckhtml0, self.ckhtml1, self.ckhtml2,
            self.ckhtml4, self.help1, ):
            vboxg2.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group3 = QGroupBox()
        self.group3.setTitle(' Javascript ')
        self.ckjs0 = QCheckBox('Condense and Compress Javascript')
        self.ckjs1 = QCheckBox('Condense $(document).ready(function(){ });')
        vboxg2 = QVBoxLayout(self.group3)
        for each_widget in (self.ckjs0, self.ckjs1):
            vboxg2.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        self.group4 = QGroupBox()
        self.group4.setTitle(' General ')
        self.chckbx1 = QCheckBox('Lower case ALL the text')
        self.chckbx2 = QCheckBox('Remove Spaces, Tabs, New Lines, Empty Lines')
        self.befor, self.after = QProgressBar(), QProgressBar()
        self.befor.setFormat("%v Chars")
        self.after.setFormat("%v Chars")
        vboxg4 = QVBoxLayout(self.group4)
        for each_widget in (self.chckbx1, self.chckbx2,
            QLabel('<b>Before:'), self.befor, QLabel('<b>After:'), self.after):
            vboxg4.addWidget(each_widget)
            each_widget.setToolTip(each_widget.text())

        [a.setChecked(True) for a in iter((self.ckcss1, self.ckcss2,
            self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7,
            self.ckcss8, self.ckcss9, self.ckcss10, self.ckcss11, self.ckcss12,
            self.ckcss13, self.ckcss14, self.ckcss15, self.ckcss16,
            self.ckcss17, self.ckcss18, self.ckcss19, self.ckjs1, self.ckhtml0,
            self.ckhtml1, self.ckhtml2, self.ckhtml4, self.chckbx1,
            self.chckbx2))]

        self.button = QPushButton(QIcon.fromTheme("face-cool"), 'Process Text')
        self.button.setCursor(QCursor(Qt.PointingHandCursor))
        self.button.setMinimumSize(100, 50)
        self.button.clicked.connect(self.run)

        def must_glow(widget_list):
            ' apply an glow effect to the widget '
            for glow, each_widget in enumerate(widget_list):
                try:
                    if each_widget.graphicsEffect() is None:
                        glow = QGraphicsDropShadowEffect(self)
                        glow.setOffset(0)
                        glow.setBlurRadius(99)
                        glow.setColor(QColor(99, 255, 255))
                        each_widget.setGraphicsEffect(glow)
                        glow.setEnabled(True)
                except:
                    pass

        must_glow((self.button, ))

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((QLabel('<b>HTML5/CSS3/JS Optimizer Compressor'),
            self.group0, self.group1, self.group2, self.group3, self.group4,
            self.button, ))
        self.scrollable = QScrollArea()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(tw)
        self.dock = QDockWidget()
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setMinimumWidth(350)
        self.dock.setWidget(self.scrollable)
        ec.addTab(self.dock, "Web")
        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
          ).clicked.connect(lambda: QMessageBox.information(self.dock, __doc__,
            HELPMSG))

    def run(self):
        ' run the string replacing '
        if self.source.currentText() == 'Local File':
            with open(path.abspath(str(self.infile.text()).strip()), 'r') as f:
                txt = f.read()
        elif self.source.currentText() == 'Remote URL':
            txt = urlopen(str(self.inurl.text()).strip()).read()
        elif  self.source.currentText() == 'Clipboard':
            txt = str(self.output.toPlainText()) if str(self.output.toPlainText()) is not '' else str(QApplication.clipboard().text())
        else:
            txt = self.editor_s.get_text()
        self.output.clear()
        self.befor.setMaximum(len(txt) + 10)
        self.after.setMaximum(len(txt) + 10)
        self.befor.setValue(len(txt))
        txt = txt.lower() if self.chckbx1.isChecked() is True else txt
        txt = condense_style(txt) if self.ckhtml0.isChecked() is True else txt
        txt = condense_script(txt) if self.ckhtml0.isChecked() is True else txt
        txt = condense_doctype(txt) if self.ckhtml1.isChecked() is True else txt
        txt = condense_href_src(txt) if self.ckhtml2 is True else txt
        txt = clean_unneeded_tags(txt) if self.ckhtml4.isChecked() is True else txt
        txt = condense_doc_ready(txt) if self.ckjs1.isChecked() is True else txt
        txt = jsmin(txt) if self.ckjs0.isChecked() is True else txt
        txt = remove_comments(txt) if self.ckcss1.isChecked() is True else txt
        txt = condense_whitespace(txt) if self.ckcss10.isChecked() is True else txt
        txt = remove_empty_rules(txt) if self.ckcss4.isChecked() is True else txt
        txt = remove_unnecessary_whitespace(txt) if self.ckcss2.isChecked() is True else txt
        txt = remove_unnecessary_semicolons(txt) if self.ckcss3.isChecked() is True else txt
        txt = condense_zero_units(txt) if self.ckcss6.isChecked() is True else txt
        txt = condense_multidimensional_zeros(txt) if self.ckcss7.isChecked() is True else txt
        txt = condense_floating_points(txt) if self.ckcss8.isChecked() is True else txt
        txt = normalize_rgb_colors_to_hex(txt) if self.ckcss5.isChecked() is True else txt
        txt = condense_hex_colors(txt) if self.ckcss9.isChecked() is True else txt
        txt = wrap_css_lines(txt, 80) if self.ckcss12.isChecked() is True else txt
        txt = condense_semicolons(txt) if self.ckcss11.isChecked() is True else txt
        txt = condense_font_weight(txt) if self.ckcss13.isChecked() is True else txt
        txt = condense_std_named_colors(txt) if self.ckcss14.isChecked() is True else txt
        # txt = condense_xtra_named_colors(txt) if self.ckcss14.isChecked() is True else txt  # FIXME
        txt = condense_percentage_values(txt) if self.ckcss16.isChecked() is True else txt
        txt = condense_pixel_values(txt) if self.ckcss17.isChecked() is True else txt
        txt = remove_url_quotes(txt) if self.ckcss18.isChecked() is True else txt
        txt = add_encoding(txt) if self.ckcss19.isChecked() is True else txt
        txt = " ".join(txt.strip().split()) if self.chckbx2.isChecked() is True else txt
        self.after.setValue(len(txt))
        self.output.setPlainText(txt)
        self.output.show()
        self.output.setFocus()
        self.output.selectAll()

    def on_source_changed(self):
        ' do something when the desired source has changed '
        if self.source.currentText() == 'Local File':
            self.open.show()
            self.infile.show()
            self.inurl.hide()
            self.output.hide()
        elif  self.source.currentText() == 'Remote URL':
            self.inurl.show()
            self.open.hide()
            self.infile.hide()
            self.output.hide()
        elif  self.source.currentText() == 'Clipboard':
            self.output.show()
            self.open.hide()
            self.infile.hide()
            self.inurl.hide()
            self.output.setText(QApplication.clipboard().text())
        else:
            self.output.show()
            self.open.hide()
            self.infile.hide()
            self.inurl.hide()
            self.output.setText(self.editor_s.get_text())

    def toggle_css_group(self):
        ' toggle on or off the css checkboxes '
        if self.group1.isChecked() is True:
            [a.setChecked(True) for a in iter((self.ckcss1, self.ckcss2,
            self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7,
            self.ckcss8, self.ckcss9, self.ckcss10, self.ckcss11, self.ckcss12,
            self.ckcss13, self.ckcss14, self.ckcss15, self.ckcss16,
            self.ckcss17, self.ckcss18, self.ckcss19))]
            self.group1.graphicsEffect().setEnabled(False)
        else:
            [a.setChecked(False) for a in iter((self.ckcss1, self.ckcss2,
            self.ckcss3, self.ckcss4, self.ckcss5, self.ckcss6, self.ckcss7,
            self.ckcss8, self.ckcss9, self.ckcss10, self.ckcss11, self.ckcss12,
            self.ckcss13, self.ckcss14, self.ckcss15, self.ckcss16,
            self.ckcss17, self.ckcss18, self.ckcss19))]
            self.group1.graphicsEffect().setEnabled(True)

    def toggle_html_group(self):
        ' toggle on or off the css checkboxes '
        if self.group2.isChecked() is True:
            [a.setChecked(True) for a in iter((self.ckhtml0, self.ckhtml1,
                                               self.ckhtml2, self.ckhtml4))]
            self.group2.graphicsEffect().setEnabled(False)
        else:
            [a.setChecked(False) for a in iter((self.ckhtml0, self.ckhtml1,
                                                self.ckhtml2, self.ckhtml4))]
            self.group2.graphicsEffect().setEnabled(True)
Exemplo n.º 18
0
class DeviceInfoWidget(QWidget):

    DEVICE_IMAGES = {
        'rider20' : resource_path('img/rider20_icon.jpg'),
        'rider30' : resource_path('img/rider30_icon.jpg'),
        'rider35' : resource_path('img/rider35_icon.jpg'),
        'rider40' : resource_path('img/rider40_icon.jpg'),
        'rider50' : resource_path('img/rider50_icon.jpg'),
        'rider' : resource_path('img/rider_icon.jpg'),
        'cardio30' : resource_path('img/cardio30_icon.jpg'),
        'cardio35' : resource_path('img/cardio35_icon.jpg'),
        'cardio' : resource_path('img/cardio_icon.jpg'),
    }


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

        self.image = QLabel(self)
        self.image.setPixmap(QPixmap(self.DEVICE_IMAGES['rider']))

        self.image_frame = QFrame(self)
        self.image_frame.setMaximumHeight(55)
        self.image_frame.setMinimumHeight(55)
        self.image_frame.setMaximumWidth(55)
        self.image_frame.setMinimumWidth(55)
        self.image_frame.setFrameShape(QFrame.StyledPanel)
        self.image_frame.setFrameShadow(QFrame.Raised)


        self.storage_usage = QProgressBar(self)
        self.storage_usage.setFormat('Disk usage %p%')
        self.storage_usage.setRange(0, 100)
        self.storage_usage.setValue(0)


        self.device_name = QLabel(self)
        self.device_name.setText('<b>Unknown</b>')
        self.device_name.setContentsMargins(3, 0, 0, 0)

        self._createLayout()


    def setDeviceInfo(self, dev_info):


        name = dev_info['name'].lower()

        if name in self.DEVICE_IMAGES:
            img = self.DEVICE_IMAGES[name]
        elif 'rider' in name:
            img = self.DEVICE_IMAGES['rider']
        elif 'cardio' in name:
            img = self.DEVICE_IMAGES['cardio']
        else:
            img = self.DEVICE_IMAGES['rider']

        self.device_name.setText('<b>%s</b>' % dev_info['name'])

        self.image.setPixmap(QPixmap(img))

        self.storage_usage.setValue(
            float(dev_info['storage_used']) / dev_info['total_storage'] * 100
        )





    def _createLayout(self):


        l = QHBoxLayout()
        l.addWidget(self.image)
        l.setContentsMargins(1, 1, 1, 1)

        self.image_frame.setLayout(l)

        l = QHBoxLayout()

        l.addWidget(self.image_frame)

        v = QVBoxLayout()

        v.addWidget(self.device_name)
        v.addWidget(self.storage_usage, 1)

        l.addLayout(v)

        self.setLayout(l)
Exemplo n.º 19
0
class MainWindow(QMainWindow):
	def __init__(self):
		QMainWindow.__init__(self)
		
		self.setWindowTitle('%s %s' % (QApplication.applicationName(), QApplication.applicationVersion()));

		self.config = ConfigHandler(os.path.join(os.path.expanduser('~'), '.pywv/pywv.cfg'), self)

		self.setStyle(QStyleFactory.create(self.config.loadStyle()))
		if self.config.loadStyleSheet():
			self.setStyleSheet(self.config.loadStyleSheet())
		else:
			self.setStyleSheet("* {}") # without any stylesheet, windowstyles won't apply


		self.setDockOptions(QMainWindow.AnimatedDocks | QMainWindow.AllowNestedDocks | QMainWindow.AllowTabbedDocks | QMainWindow.VerticalTabs);

#		self.dummy = QWidget(self)
		self.setCentralWidget(QWidget(self))

		self.pBar = QProgressBar(self)
		self.pBar.setRange(0, self.config.loadReloadInterval())
		self.pBar.setFormat("%v Sekunden")
		if not self.config.loadAutoload():
			self.pBar.hide()

		self.statusBar = QStatusBar(self)
		self.setStatusBar(self.statusBar)
		self.statusBar.addWidget(self.pBar)

		self.reloadTimer = QTimer(self);
		self.reloadTimer.setInterval(self.config.loadReloadInterval() * 1000)
		self.connect(self.reloadTimer, SIGNAL('timeout()'), self.reload_)
		if self.config.loadAutoload():
			self.reloadTimer.start()

		self.autoloadStatusTimer = QTimer(self)
		self.autoloadStatusTimer.setInterval(1000) # 1 sec
		self.connect(self.autoloadStatusTimer, SIGNAL('timeout()'), self.onAutoloadStatus)
		self.autoloadStatusTimer.start()

		self.mAction = self.menuBar().addMenu(self.tr("&Action"))
		self.mAction.addAction(self.tr("&update"), self.reload_, QKeySequence('F5'))
		self.mAction.addAction(self.tr("e&xit"), self.onExit, 'Ctrl+Q')

		self.mStyle = QMenu(self.tr("&Style"), self)
		for s in list(QStyleFactory.keys()):#       // fill in all available Styles
			self.mStyle.addAction(s)
		self.connect(self.mStyle, SIGNAL('triggered(QAction*)'), self.onStyleMenu)

		self.mOption = self.menuBar().addMenu(self.tr("&Options"))
		self.mOption.addAction(self.tr("reloadinterval") , self.onReloadTime , 'F8')
		self.mOption.addAction(self.tr("manage links")   , self.onNewLink    , 'F6')
		self.mOption.addSeparator()

		self.ontopAction       = QAction(self.tr("always on &top")  , self)
		self.showTrayAction    = QAction(self.tr("show tray &icon") , self)
		self.closeToTrayAction = QAction(self.tr("close to &tray")  , self)
		self.autoloadAction    = QAction(self.tr("auto&load")       , self)

		self.ontopAction.setCheckable(True)
		self.showTrayAction.setCheckable(True)
		self.closeToTrayAction.setCheckable(True)
		self.autoloadAction.setCheckable(True)

		self.showTrayAction.setChecked   (self.config.loadShowTray()   )
		self.ontopAction.setChecked      (self.config.loadOntop()      )
		self.closeToTrayAction.setChecked(self.config.loadCloseToTray())
		self.autoloadAction.setChecked   (self.config.loadAutoload()   )

		self.connect(self.ontopAction       , SIGNAL('toggled(bool)') , self.onOntopAction)
		self.connect(self.showTrayAction    , SIGNAL('toggled(bool)') , self.onShowTrayAction)
		self.connect(self.closeToTrayAction , SIGNAL('toggled(bool)') , self.onCloseToTrayAction)
		self.connect(self.autoloadAction    , SIGNAL('toggled(bool)') , self.onAutoloadAction)

		self.mOption.addAction(self.ontopAction)
		self.mOption.addAction(self.showTrayAction)
		self.mOption.addAction(self.closeToTrayAction)
		self.mOption.addAction(self.autoloadAction)
		self.mOption.addSeparator()
		self.mOption.addMenu(self.mStyle)

		self.trayIcon = QSystemTrayIcon(QIcon(':/appicon'), self);
		self.trayMgr = TrayManager(self.config, self.trayIcon)
		self.connect(self.trayIcon, SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self.onTrayIcon)
		if self.config.loadShowTray(): self.trayIcon.show()

		self.trayIconMenu = QMenu()
		self.trayIconMenu.addAction(self.tr("e&xit"), self.onExit)
		self.trayIcon.setContextMenu(self.trayIconMenu)

		self.mAbout = self.menuBar().addMenu(self.tr("&about"))
		self.mAbout.addAction(QApplication.applicationName(), self.onAboutAppAction)
		self.mAbout.addAction("Qt", self.onAboutQtAction)

		self.createWidgets()

		self.resize(self.config.loadWindowSize())
		self.restoreState(self.config.loadWindowState())

		if self.config.loadIsVisible():
			self.show()
			self.reload_()

	def __del__(self):
		self.config.saveWindowState(self.saveState())

	def createSingleWidget(self, name):
#		print 'crt', name, type(name), '\n', self.widgets
#		print 'crt', name, type(name)
		links = self.config.loadLinks()
		if links[name]['type'] == 'generic':
			self.widgets[name] = GenericWidget(name, self.config, self)
		else:
			pluginsAvail = classdirPlugins().all_()
			for plugin in pluginsAvail:
				if links[name]['type'] == plugin['class']:
					pluginClass = plugin['class']
					break
				else:
					continue

			exec('self.widgets[name] = %s(name, self.config, self)' % pluginClass)
		#	print(('loaded plugin', self.widgets[name]))

		self.addDockWidget(0x4, self.widgets[name])
		self.widgets[name].reload_()

	def delWidget(self, name):
		#print 'del', name, type(name), '\n', self.widgets
		self.removeDockWidget(self.widgets[name])
		self.widgets[name].deleteLater()
		self.widgets[name] = None
		del self.widgets[name]

	def createWidgets(self):
		self.widgets = {}
		for name in self.config.loadLinks():
			self.createSingleWidget(name)


	@pyqtSlot()
	def onExit(self):
		self.config.saveWindowSize(self.size())
		QApplication.exit();

	def closeEvent(self, event):
		self.config.saveWindowSize(self.size())
#	       	QApplication.exit()
		# tray is visible -> close to tray
		# else close app
		if self.trayIcon.isVisible():
			event.accept()
		else:
			QApplication.exit()
			return
		# if close-to-tray is set, do so
		if self.config.loadCloseToTray():
			event.accept()
		else:
			QApplication.exit()
			return;
		# save this state
		if	self.trayIcon.isVisible():	self.config.saveIsVisible(False)
		else:					self.config.saveIsVisible(True);
	@pyqtSlot()
	def reload_(self):
		for name in self.widgets:
			self.widgets[name].reload_()
		self.pBar.setValue(self.config.loadReloadInterval())
		self.reloadTimer.start(self.config.loadReloadInterval()*1000)

	@pyqtSlot()
	def onAutoloadStatus(self):
		self.pBar.setValue(self.pBar.value()-1)
#		print([idx for idx in self.widgets])

	def onStyleMenu(self, a):
		QApplication.setStyle(QStyleFactory.create(a.text()))
		self.setStyle(QStyleFactory.create(a.text()))
		self.config.saveStyle(a.text())

	def onReloadTime(self):
		ok = False
		value, ok = QInputDialog.getInteger(self,
			self.tr("reloadinterval"), # title
			self.tr("insert time in s"), # text
			self.config.loadReloadInterval(), # default
			10, # minimum
			86400, # maximum (at least once a day)
			1, # step
			)
		if ok:
			self.config.saveReloadInterval(value)
			self.pBar.setRange(0,self.config.loadReloadInterval())
			self.reload_()

	def onAutoloadAction(self, b):
		if b:
			self.reloadTimer.start()
			self.pBar.show()
			self.reload_()
		else:
			self.reloadTimer.stop()
			self.pBar.hide()
		self.config.saveAutoload(b)

	def onNewLink(self):
		inp = LinkInput(self.config, self)
		if inp.exec_():
			# sync active widgets
			for name in inp.modifiedWidgets():
				if name in self.widgets:
					self.delWidget(name)
					self.createSingleWidget(name)
				else:
					self.createSingleWidget(name)

			# remove deleted
#			for name in self.widgets: print 'shown', name
#			for name in self.config.loadLinks(): print 'conf', name
			todel = []
			for name in self.widgets:
				if name not in self.config.loadLinks():
					todel.append(name)

			for widget in todel:
				self.delWidget(widget)

	def onOntopAction(self, b):
		if b:	self.setWindowFlags(Qt.Dialog | Qt.WindowStaysOnTopHint)
		else:	self.setWindowFlags(Qt.Dialog)
		self.setWindowIcon(QIcon(':/appicon'))
		self.show();
		self.config.saveOntop(b)

	def onShowTrayAction(self, b):
		if b:	self.trayIcon.show()
		else:	self.trayIcon.hide()
		self.config.saveShowTray(b)

	def onCloseToTrayAction(self, b):
		self.config.saveCloseToTray(b)

	def onTrayIcon(self, reason):
		if reason == QSystemTrayIcon.Trigger:
			if(self.isVisible()):
				self.config.saveWindowSize(self.size())
				self.hide()
				self.config.saveIsVisible(False)
			else:
				self.show()
				self.resize(self.config.loadWindowSize())
				self.config.saveIsVisible(True)

	def onAboutAppAction(self):
		QMessageBox.about(self, self.tr("&about"), self.tr("name %1 version %2").arg(QApplication.applicationName()).arg(QApplication.applicationVersion()))
	def onAboutQtAction(self):
		QMessageBox.aboutQt(self, self.tr("&about"))
Exemplo n.º 20
0
class SR785_MainWindow(QMainWindow):
    GifInfo = {
        SR785.SCREEN_ALL: (21200, 'all'),
        SR785.SCREEN_MENU: (4840, 'menu'),
        SR785.SCREEN_STATUS: (4410, 'status'),
        SR785.SCREEN_GRAPHS: (11420, 'graphs')
    }

    def __init__(self, parent=None):
        super(SR785_MainWindow, self).__init__(parent)
        centralWidget = SR785_Widget()
        self.setCentralWidget(centralWidget)

        visaResource = 'GPIB0::10'
        sr785 = SR785(visaResource)
        sr785.configureScreenDump()
        centralWidget.associateInstrument(sr785)
        self.setWindowTitle('SR785 Front Panel Emulation: %s' % sr785.visaId())
        self.progressBar = QProgressBar()
        statusBar = self.statusBar()
        statusBar.addWidget(self.progressBar)

        toolBar = QToolBar('Screen')
        toolBar.addActions(centralWidget.screenActions)
        self.addToolBar(toolBar)

        thread = centralWidget.workerThread
        thread.gifDownloadStarted.connect(self.gifDownloadStarted)
        thread.gifReceived.connect(self.gifReceived)
        thread.keyPressSimulated.connect(self.keyPressSimulated)
        thread.knobRotated.connect(self.knobRotated)

        dockWidget = QDockWidget('History')
        self.historyTe = QTextEdit()
        dockWidget.setWidget(self.historyTe)
        self.addDockWidget(Qt.TopDockWidgetArea, dockWidget)

        toolBar = self.addToolBar('File')
        action = QAction('Save screen', self)
        action.triggered.connect(self.saveScreen)
        toolBar.addAction(action)
        action = QAction('Print', self)
        action.triggered.connect(self.printScreen)
        toolBar.addAction(action)

    def saveScreen(self):
        directory = ''
        saveFile = QFileDialog.getSaveFileName(self, 'Save screen to',
                                               directory, '*.png *.gif',
                                               '*.png')
        print "saving as:", saveFile
        screenPixmap = self.centralWidget().screen.pixmap()
        screenPixmap.save(saveFile)
        self.log('Screen saved as: %s' % saveFile)

    def printScreen(self):
        pass

    def gifDownloadStarted(self, screen):
        self.progressBar.setMaximum(self.GifInfo[screen][0])
        self.progressBar.setValue(0)
        label = self.GifInfo[screen][1]
        self.progressBar.setFormat('%s %%p%%' % label)
        self.log('Downloading %s' % label)

    def gifReceived(self, screen):
        self.progressBar.setValue(self.GifInfo[screen][0])

    def keyPressSimulated(self, keyCode):
        self.log('Key %d pressed.' % keyCode)

    def knobRotated(self, steps):
        if steps > 0:
            self.log('Knob rotated CW.')
        else:
            self.log('Knob rotated CCW.')

    def log(self, message):
        self.historyTe.append(message + '\n')
        self.statusBar().showMessage(message, 2000)