def __init__(self, parent): QWidget.__init__(self, parent) self.parent = parent self.panel = self.parent.parent.panel self.canvas = self.panel.canvas self.islabel = self.parent.parent.islabel self.objets = parent.objets self.sizer = QVBoxLayout() self.changements = {} # ce dictionnaire contiendra tous les styles modifiés encadre = QHBoxLayout() if not self.islabel: proprietes = {'fixe': u'Objet fixe', 'visible': u'Objet visible', 'trace': u'Laisser une trace'} for propriete, titre in proprietes.items(): self.add_checkbox(encadre, propriete, titre) encadre1 = QVBoxLayout() if not self.islabel: ligne = QHBoxLayout() if len(self.objets) == 1: self.etiquette = etiquette = QLineEdit() etiquette.setText(self.objets[0].style("label")) etiquette.setMinimumWidth(200) etiquette.editingFinished.connect(self.EvtEtiquette) ligne.addWidget(etiquette) if [objet for objet in self.objets if objet.etiquette is not None]: editer = QPushButton(u"Style") editer.clicked.connect(self.EvtLabelStyle) ligne.addWidget(editer) encadre1.addLayout(ligne) objets = [objet for objet in self.objets if objet.style("legende") is not None] if objets: leg = objets[0].style("legende") legende = QHBoxLayout() self.radio_nom = QRadioButton("Nom") ##self.radio_nom.SetValue(0) self.radio_etiquette = QRadioButton(u"Texte") ##self.radio_etiquette.SetValue(0) self.radio_formule = QRadioButton(u"Formule") ##self.radio_formule.SetValue(0) self.radio_aucun = QRadioButton(u"Aucun") ##self.radio_aucun.SetValue(0) if all(objet.style("legende") == leg for objet in objets): if leg == NOM: self.radio_nom.setChecked(True) elif leg == TEXTE: self.radio_etiquette.setChecked(True) elif leg == FORMULE: self.radio_formule.setChecked(True) elif leg == RIEN: self.radio_aucun.setChecked(True) self.radio_nom.toggled.connect(partial(self.EvtLegende, NOM)) self.radio_etiquette.toggled.connect(partial(self.EvtLegende, TEXTE)) self.radio_formule.toggled.connect(partial(self.EvtLegende, FORMULE)) self.radio_aucun.toggled.connect(partial(self.EvtLegende, RIEN)) legende.addWidget(self.radio_nom) legende.addWidget(self.radio_etiquette) legende.addWidget(self.radio_formule) legende.addWidget(self.radio_aucun) encadre1.addWidget(QLabel(u"Afficher : ")) encadre1.addLayout(legende) encadre2 = QVBoxLayout() objets = [objet for objet in self.objets if objet.style("style") is not None] # on ne peut regler les styles simultanement que pour des objets de meme categorie categorie = objets and objets[0].style("categorie") or None if objets and categorie and all(objet.style("categorie") == categorie for objet in objets): choix = QHBoxLayout() choix.addWidget(QLabel(u"Style de l'objet : ")) #categorie = objets[0].style("categorie") or "lignes" self.liste_styles = getattr(param, "styles_de_" + categorie, []) self.style = QComboBox() self.style.addItems(self.liste_styles) self.style.currentIndexChanged.connect(self.EvtStyle) style = objets[0].style("style") if style in self.liste_styles and all(objet.style("style") == style for objet in objets): self.style.setCurrentIndex(self.liste_styles.index(style)) # on sélectionne le style actuel choix.addWidget(self.style) encadre2.addLayout(choix) objets = [objet for objet in self.objets if objet.style("hachures") is not None] if objets: choix = QHBoxLayout() choix.addWidget(QLabel(u"Style des hâchures : ")) self.types_de_hachures = getattr(param, "types_de_hachures", []) self.hachures = QComboBox() self.hachures.addItems(self.types_de_hachures) self.hachure.currentIndexChanged.connect(self.EvtHachures) hachures = objets[0].style("hachures") if hachures in self.types_de_hachures and all(objet.style("hachures") == hachures for objet in objets): self.hachures.setCurrentIndex(self.types_de_hachures.index(hachures)) # on sélectionne les hachures actuelles choix.addWidget(self.hachures) encadre2.addLayout(choix) objets = [objet for objet in self.objets if objet.style("famille") is not None] categorie = objets and objets[0].style("categorie") or None if objets and categorie and all(objet.style("categorie") == categorie for objet in objets): choix = QHBoxLayout() choix.addWidget(QLabel("Police : ")) #categorie = self.objet.style("categorie") or "lignes" self.liste_familles = getattr(param, "familles_de_" + categorie, []) self.famille = QComboBox() self.famille.addItems(self.liste_familles) self.famille.currentIndexChanged.connect(self.EvtFamille) famille = objets[0].style("famille") if famille in self.liste_familles and all(objet.style("famille") == famille for objet in objets): self.famille.setCurrentIndex(self.liste_familles.index(famille)) # on sélectionne la famille actuelle choix.addWidget(self.famille) encadre2.addLayout(choix) objets = [objet for objet in self.objets if objet.style("couleur") is not None] if objets: couleur = objets[0].style("couleur") choix = QHBoxLayout() choix.addWidget(QLabel(u"Couleur de l'objet : ")) if all(objet.style("couleur") == couleur for objet in objets): # conversion du format matplotlib au format Qt r, g, b = colorConverter.to_rgb(couleur) couleur = QColor(int(255*r), int(255*g), int(255*b)) else: couleur = None b = ColorSelecter(self, color=couleur) b.colorSelected.connect(self.OnSelectColour) choix.addWidget(b) encadre2.addLayout(choix) objets = [objet for objet in self.objets if objet.style("epaisseur") is not None] if objets: epaiss = objets[0].style("epaisseur") epaisseur = QHBoxLayout() epaisseur.addWidget(QLabel(u"Epaisseur (en 10e de pixels) : ")) self.epaisseur = QSpinBox() self.epaisseur.setMinimumSize(30, 50) self.epaisseur.setRange(1,10000) if all(objet.style("epaisseur") == epaiss for objet in objets): self.epaisseur.setValue(10*epaiss) else: self.epaisseur.setSpecialValueText(' ') print(u'FIXME: cas non géré.') self.epaisseur.valueChanged.connect(self.EvtEpaisseur) epaisseur.addWidget(self.epaisseur) encadre2.addLayout(epaisseur) objets = [objet for objet in self.objets if objet.style("taille") is not None] if objets: tail = objets[0].style("taille") taille = QHBoxLayout() taille.addWidget(QLabel(u"Taille (en 10e de pixels) : ")) self.taille = QSpinBox() self.taille.setMinimumSize(30, 50) self.taille.setRange(1,10000) if all(objet.style("taille") == tail for objet in objets): self.taille.setValue(10*tail) else: self.taille.setSpecialValueText(' ') print(u'FIXME: cas non géré.') self.taille.valueChanged.connect(self.EvtTaille) taille.addWidget(self.taille) encadre2.addLayout(taille) objets = [objet for objet in self.objets if objet.style("position") is not None] if objets: pos = objets[0].style("position") position = QHBoxLayout() position.addWidget(QLabel(u"Position de la flêche : ")) self.position = QSpinBox() self.position.setMinimumSize(30, 50) self.position.setRange(0, 100) if all(objet.style("position") == pos for objet in objets): self.position.setValue(100*pos) else: self.position.setSpecialValueText(' ') print(u'FIXME: cas non géré.') self.position.valueChanged.connect(self.EvtPosition) position.addWidget(self.position) encadre2.addLayout(position) objets = [objet for objet in self.objets if objet.style("angle") is not None] if objets: ang = objets[0].style("angle") angle = QHBoxLayout() angle.addWidget(QLabel(u"Angle (en degré) : ")) self.angle = QSpinBox() self.angle.setMinimumSize(30, 50) self.angle.setRange(0, 360) if all(objet.style("angle") == ang for objet in objets): self.angle.setValue(ang) else: self.angle.setSpecialValueText(' ') print(u'FIXME: cas non géré.') self.angle.valueChanged.connect(self.EvtAngle) angle.addWidget(self.angle) encadre2.addLayout(angle) self.add_checkbox(encadre, 'double_fleche', u"Flêche double") objets = [objet for objet in self.objets if objet.style("codage") is not None] # on ne peut regler les codages simultanement que pour des objets de meme categorie categorie = objets and objets[0].style("categorie") or None if objets and categorie and all(objet.style("categorie") == categorie for objet in objets): choix = QHBoxLayout() choix.addWidget(QLabel("Codage : ")) #categorie = objets[0].style("categorie") or "lignes" self.liste_codages = getattr(param, "codage_des_" + categorie, []) self.codage = QComboBox() self.codage.addItems(self.liste_codages) self.codage.currentIndexChanged.connect(self.EvtCodage) codage = objets[0].style("codage") if codage in self.liste_codages and all(objet.style("codage") == codage for objet in objets): self.codage.setCurrentIndex(self.liste_codages.index(codage)) # on sélectionne le codage actuel choix.addWidget(self.codage) encadre2.addLayout(choix) boutons = QHBoxLayout() ok = QPushButton('OK') ok.clicked.connect(self.EvtOk) boutons.addWidget(ok) appliquer = QPushButton(u"Appliquer") appliquer.clicked.connect(self.EvtAppliquer) boutons.addWidget(appliquer) if not self.islabel: supprimer = QPushButton(u"Supprimer") supprimer.clicked.connect(self.EvtSupprimer) boutons.addWidget(supprimer) annuler = QPushButton(u"Annuler") annuler.clicked.connect(self.EvtAnnuler) boutons.addWidget(annuler) if encadre.count(): # ne pas afficher une rubrique vide ! encadre_box = QGroupBox(u"Mode d'affichage") encadre_box.setLayout(encadre) self.sizer.addWidget(encadre_box) if encadre1.count(): encadre1_box = QGroupBox(u"Etiquette") encadre_box.setLayout(encadre1) self.sizer.addWidget(encadre1_box) if encadre2.count(): encadre2_box = QGroupBox(u"Styles") encadre_box.setLayout(encadre2) self.sizer.addWidget(encadre2_box) self.sizer.addLayout(boutons) self.setLayout(self.sizer)
class ParameterContainer(QWidget, object): """Container to hold Parameter Widgets.""" def __init__(self, parameters=None, description_text='', extra_parameters=None, parent=None, vertical=True): """Constructor .. versionadded:: 2.2 :param parameters: List of Parameter Widget :type parameters: list :param description_text: Text for description of the parameter container. :type description_text: str """ QWidget.__init__(self, parent) # attributes if not parameters: self.parameters = [] else: self.parameters = parameters self.description_text = description_text self.extra_parameters = extra_parameters self.parent = parent self.validators = [] self.validators_kwargs = [] # UI if vertical: self.vertical_layout = QVBoxLayout() else: self.vertical_layout = QHBoxLayout() self.widget = QWidget() self.description_label = QLabel() self.description_label.setWordWrap(True) self.scroll_area = QScrollArea() self.group_frame = QFrame() self.qt4_parameter_factory = Qt4ParameterFactory() self.main_layout = QGridLayout() # NOTES(IS) : These functions are commented since the architecture is not # ready yet. # def register_widget(self, parameter, parameter_widget): # """Register new custom widget. # # :param parameter: # :type parameter: GenericParameter # # :param parameter_widget: # :type parameter_widget: GenericParameterWidget # """ # self.qt4_parameter_factory.register_widget( # parameter, parameter_widget) # # def remove_widget(self, parameter): # """Register new custom widget. # # :param parameter: # :type parameter: GenericParameter # """ # if parameter.__name__ in self.dict_widget.keys(): # self.dict_widget.pop(parameter.__name__) def get_parameters(self, validate=True): """Return list of parameters from the current state of widget. :param validate: If true, run validator, else no. :type validate: bool :returns: List of parameter :rtype: list """ if validate: validation_result = self.validate() if not validation_result['valid']: raise InvalidValidationException(validation_result['message']) parameter_widgets = self.get_parameter_widgets() parameters = [] for widget_item in parameter_widgets: parameter_widget = widget_item.widget() parameter = parameter_widget.get_parameter() parameters.append(parameter) # returns based on the object type of self.parameters if isinstance(self.parameters, list): return parameters else: # just return single parameter return parameters[0] def get_parameter_widgets(self): """Return list of parameter widgets from the current state of widget. :returns: List of parameter widget :rtype: list """ parameter_widgets = [ self.vertical_layout.itemAt(i) for i in range(self.vertical_layout.count()) ] return parameter_widgets def setup_ui(self, must_scroll=True): """Setup the UI of this parameter container. """ # Vertical layout to place the parameter widgets self.vertical_layout.setContentsMargins(0, 0, 0, 0) self.vertical_layout.setSpacing(0) # Widget to hold the vertical layout self.widget = QWidget() self.widget.setLayout(self.vertical_layout) # Label for description self.description_label.setText(self.description_text) self.group_frame.setLineWidth(0) self.group_frame.setFrameStyle(QFrame.NoFrame) vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.setSpacing(0) self.group_frame.setLayout(vlayout) if must_scroll: vlayout.addWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) self.scroll_area.setWidget(self.widget) else: vlayout.addWidget(self.widget) # Main layout of the container if self.description_text: self.main_layout.addWidget(self.description_label) self.main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.main_layout) self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) if not isinstance(self.parameters, list): parameters = [self.parameters] else: parameters = self.parameters if len(parameters) == 0: self.set_empty_parameters() return self.main_layout.addWidget(self.group_frame) self.qt4_parameter_factory = Qt4ParameterFactory() if self.extra_parameters is not None: for extra_parameter in self.extra_parameters: if (type(extra_parameter) == tuple and len(extra_parameter) == 2): self.qt4_parameter_factory.register_widget( extra_parameter[0], extra_parameter[1]) color_odd = QColor(220, 220, 220) color_even = QColor(192, 192, 192) i = 0 for parameter in parameters: parameter_widget = self.qt4_parameter_factory.get_widget(parameter) if i % 2: color = color_even else: color = color_odd i += 1 parameter_widget.setAutoFillBackground(True) # palette = parameter_widget.palette() # palette.setColor(parameter_widget.backgroundRole(), color) # parameter_widget.setPalette(palette) self.vertical_layout.addWidget(parameter_widget) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) def set_description(self, description): """Set description of the parameter container. :param description: A new description fot the parameter container. :type description: str """ self.description_text = description self.description_label.setText(self.description_text) def set_empty_parameters(self): """Update UI if there is no parameters in the container. """ new_description = self.description_text new_description += '\n' new_description += 'But, currently there is no parameters available.' self.description_label.setText(new_description) def add_validator(self, validator, **kwargs): """Add validator for this parameter container. :param validator: validator function for this parameter container. :type validator: function """ validator.parent = self self.validators.append(validator) if kwargs: self.validators_kwargs.append(kwargs) else: self.validators_kwargs.append({}) def validate(self): """Validate of all rule for all parameter in this container. :return: True if all valid, False :rtype: dict """ for i in range(len(self.validators)): validator = self.validators[i] validator_kwargs = self.validators_kwargs[i] validation_result = validator(self, **validator_kwargs) if not validation_result['valid']: return validation_result return {'valid': True, 'message': ''} def get_parameter_by_guid(self, parameter_guid): """Return a parameter based on its uuid :param parameter_guid: The parameter uuid :type parameter_guid: str :returns: The parameter or None if not exist :rtype: GenericParameter, None """ parameters = self.get_parameters(validate=False) for parameter in parameters: if parameter.guid == parameter_guid: return parameter return None def get_parameter_widget_by_guid(self, parameter_guid): """Return a parameter widget based on its uuid :param parameter_guid: The parameter uuid :type parameter_guid: str :returns: The parameter widget or None if not exist :rtype: GenericParameterWidget, None """ parameter_widgets = self.get_parameter_widgets() for parameter_widget in parameter_widgets: if (parameter_widget.widget().get_parameter().guid == parameter_guid): return parameter_widget.widget() return None
class ParameterContainer(QWidget, object): """Container to hold Parameter Widgets.""" def __init__( self, parameters=None, description_text='', extra_parameters=None, parent=None, vertical=True): """Constructor .. versionadded:: 2.2 :param parameters: List of Parameter Widget :type parameters: list :param description_text: Text for description of the parameter container. :type description_text: str """ QWidget.__init__(self, parent) # attributes if not parameters: self.parameters = [] else: self.parameters = parameters self.description_text = description_text self.extra_parameters = extra_parameters self.parent = parent self.validators = [] self.validators_kwargs = [] # UI if vertical: self.vertical_layout = QVBoxLayout() else: self.vertical_layout = QHBoxLayout() self.widget = QWidget() self.description_label = QLabel() self.description_label.setWordWrap(True) self.scroll_area = QScrollArea() self.group_frame = QFrame() self.qt4_parameter_factory = Qt4ParameterFactory() self.main_layout = QGridLayout() # NOTES(IS) : These functions are commented since the architecture is not # ready yet. # def register_widget(self, parameter, parameter_widget): # """Register new custom widget. # # :param parameter: # :type parameter: GenericParameter # # :param parameter_widget: # :type parameter_widget: GenericParameterWidget # """ # self.qt4_parameter_factory.register_widget( # parameter, parameter_widget) # # def remove_widget(self, parameter): # """Register new custom widget. # # :param parameter: # :type parameter: GenericParameter # """ # if parameter.__name__ in self.dict_widget.keys(): # self.dict_widget.pop(parameter.__name__) def get_parameters(self, validate=True): """Return list of parameters from the current state of widget. :param validate: If true, run validator, else no. :type validate: bool :returns: List of parameter :rtype: list """ if validate: validation_result = self.validate() if not validation_result['valid']: raise InvalidValidationException(validation_result['message']) parameter_widgets = self.get_parameter_widgets() parameters = [] for widget_item in parameter_widgets: parameter_widget = widget_item.widget() parameter = parameter_widget.get_parameter() parameters.append(parameter) # returns based on the object type of self.parameters if isinstance(self.parameters, list): return parameters else: # just return single parameter return parameters[0] def get_parameter_widgets(self): """Return list of parameter widgets from the current state of widget. :returns: List of parameter widget :rtype: list """ parameter_widgets = [self.vertical_layout.itemAt(i) for i in range( self.vertical_layout.count())] return parameter_widgets def setup_ui(self, must_scroll=True): """Setup the UI of this parameter container. """ # Vertical layout to place the parameter widgets self.vertical_layout.setContentsMargins(0, 0, 0, 0) self.vertical_layout.setSpacing(0) # Widget to hold the vertical layout self.widget = QWidget() self.widget.setLayout(self.vertical_layout) # Label for description self.description_label.setText(self.description_text) self.group_frame.setLineWidth(0) self.group_frame.setFrameStyle(QFrame.NoFrame) vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.setSpacing(0) self.group_frame.setLayout(vlayout) if must_scroll: vlayout.addWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) self.scroll_area.setWidget(self.widget) else: vlayout.addWidget(self.widget) # Main layout of the container if self.description_text: self.main_layout.addWidget(self.description_label) self.main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.main_layout) self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) if not isinstance(self.parameters, list): parameters = [self.parameters] else: parameters = self.parameters if len(parameters) == 0: self.set_empty_parameters() return self.main_layout.addWidget(self.group_frame) self.qt4_parameter_factory = Qt4ParameterFactory() if self.extra_parameters is not None: for extra_parameter in self.extra_parameters: if (type(extra_parameter) == tuple and len(extra_parameter) == 2): self.qt4_parameter_factory.register_widget( extra_parameter[0], extra_parameter[1]) color_odd = QColor(220, 220, 220) color_even = QColor(192, 192, 192) i = 0 for parameter in parameters: parameter_widget = self.qt4_parameter_factory.get_widget(parameter) if i % 2: color = color_even else: color = color_odd i += 1 parameter_widget.setAutoFillBackground(True) # palette = parameter_widget.palette() # palette.setColor(parameter_widget.backgroundRole(), color) # parameter_widget.setPalette(palette) self.vertical_layout.addWidget(parameter_widget) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) def set_description(self, description): """Set description of the parameter container. :param description: A new description fot the parameter container. :type description: str """ self.description_text = description self.description_label.setText(self.description_text) def set_empty_parameters(self): """Update UI if there is no parameters in the container. """ new_description = self.description_text new_description += '\n' new_description += 'But, currently there is no parameters available.' self.description_label.setText(new_description) def add_validator(self, validator, **kwargs): """Add validator for this parameter container. :param validator: validator function for this parameter container. :type validator: function """ validator.parent = self self.validators.append(validator) if kwargs: self.validators_kwargs.append(kwargs) else: self.validators_kwargs.append({}) def validate(self): """Validate of all rule for all parameter in this container. :return: True if all valid, False :rtype: dict """ for i in range(len(self.validators)): validator = self.validators[i] validator_kwargs = self.validators_kwargs[i] validation_result = validator(self, **validator_kwargs) if not validation_result['valid']: return validation_result return { 'valid': True, 'message': '' } def get_parameter_by_guid(self, parameter_guid): """Return a parameter based on its uuid :param parameter_guid: The parameter uuid :type parameter_guid: str :returns: The parameter or None if not exist :rtype: GenericParameter, None """ parameters = self.get_parameters(validate=False) for parameter in parameters: if parameter.guid == parameter_guid: return parameter return None def get_parameter_widget_by_guid(self, parameter_guid): """Return a parameter widget based on its uuid :param parameter_guid: The parameter uuid :type parameter_guid: str :returns: The parameter widget or None if not exist :rtype: GenericParameterWidget, None """ parameter_widgets = self.get_parameter_widgets() for parameter_widget in parameter_widgets: if (parameter_widget.widget().get_parameter().guid == parameter_guid): return parameter_widget.widget() return None
class TaskGeneratorDialog(QDialog): def __init__(self, nbprocessors): QDialog.__init__(self) self.layout = QVBoxLayout(self) self.taskset = None # Utilizations: vbox_utilizations = QVBoxLayout() group = QGroupBox("Task Utilizations:") hbox = QHBoxLayout() hbox.addWidget(QLabel("Generator:", self)) self.comboGenerator = QComboBox() self.comboGenerator.addItem("RandFixedSum") self.comboGenerator.addItem("UUniFast-Discard") self.comboGenerator.addItem("Kato's method") self.comboGenerator.currentIndexChanged.connect(self.generator_changed) hbox.addWidget(self.comboGenerator) vbox_utilizations.addLayout(hbox) # Load slider + spinner: hbox_load = QHBoxLayout() sld = _DoubleSlider(QtCore.Qt.Horizontal, self) sld.setMinimum(0) sld.setMaximum(32) self.spin_load = QDoubleSpinBox(self) self.spin_load.setMinimum(0) self.spin_load.setMaximum(32) self.spin_load.setSingleStep(0.1) hbox_load.addWidget(QLabel("Total utilization: ", self)) hbox_load.addWidget(sld) hbox_load.addWidget(self.spin_load) sld.doubleValueChanged.connect(self.spin_load.setValue) self.spin_load.valueChanged.connect(sld.setValue) self.spin_load.setValue(nbprocessors / 2.) vbox_utilizations.addLayout(hbox_load) # Number of periodic tasks: self.hbox_tasks = QHBoxLayout() self.spin_tasks = QSpinBox(self) self.spin_tasks.setMinimum(0) self.spin_tasks.setMaximum(999) # That's arbitrary. self.hbox_tasks.addWidget(QLabel("Number of periodic tasks: ", self)) self.hbox_tasks.addStretch(1) self.hbox_tasks.addWidget(self.spin_tasks) vbox_utilizations.addLayout(self.hbox_tasks) # Number of sporadic tasks: self.hbox_sporadic_tasks = QHBoxLayout() self.spin_sporadic_tasks = QSpinBox(self) self.spin_sporadic_tasks.setMinimum(0) self.spin_sporadic_tasks.setMaximum(999) # That's arbitrary. self.hbox_sporadic_tasks.addWidget( QLabel("Number of sporadic tasks: ", self)) self.hbox_sporadic_tasks.addStretch(1) self.hbox_sporadic_tasks.addWidget(self.spin_sporadic_tasks) vbox_utilizations.addLayout(self.hbox_sporadic_tasks) # Min / Max utilizations self.hbox_utilizations = QHBoxLayout() self.hbox_utilizations.addWidget(QLabel("Min/Max utilizations: ", self)) self.interval_utilization = IntervalSpinner(self, min_=0, max_=1, step=.01, round_option=False) self.hbox_utilizations.addWidget(self.interval_utilization) vbox_utilizations.addLayout(self.hbox_utilizations) group.setLayout(vbox_utilizations) self.layout.addWidget(group) # Periods: vbox_periods = QVBoxLayout() group = QGroupBox("Task Periods:") # Log uniform self.lunif = QRadioButton("log-uniform distribution between:") vbox_periods.addWidget(self.lunif) self.lunif.setChecked(True) self.lunif_interval = IntervalSpinner(self) self.lunif_interval.setEnabled(self.lunif.isChecked()) self.lunif.toggled.connect(self.lunif_interval.setEnabled) vbox_periods.addWidget(self.lunif_interval) # Uniform self.unif = QRadioButton("uniform distribution between:") vbox_periods.addWidget(self.unif) self.unif_interval = IntervalSpinner(self) self.unif_interval.setEnabled(self.unif.isChecked()) self.unif.toggled.connect(self.unif_interval.setEnabled) vbox_periods.addWidget(self.unif_interval) # Discrete discrete = QRadioButton("chosen among these (space separated) values:") vbox_periods.addWidget(discrete) self.periods = QLineEdit(self) self.periods.setValidator( QRegExpValidator(QRegExp("^\\d*(\.\\d*)?( \\d*(\.\\d*)?)*$"))) vbox_periods.addWidget(self.periods) self.periods.setEnabled(discrete.isChecked()) discrete.toggled.connect(self.periods.setEnabled) vbox_periods.addStretch(1) group.setLayout(vbox_periods) self.layout.addWidget(group) buttonBox = QDialogButtonBox() cancel = buttonBox.addButton(QDialogButtonBox.Cancel) generate = buttonBox.addButton("Generate", QDialogButtonBox.AcceptRole) cancel.clicked.connect(self.reject) generate.clicked.connect(self.generate) self.layout.addWidget(buttonBox) self.show_randfixedsum_options() def generator_changed(self, value): if value == 2: self.show_kato_options() else: self.show_randfixedsum_options() def show_randfixedsum_options(self): for i in range(self.hbox_utilizations.count()): self.hbox_utilizations.itemAt(i).widget().hide() for i in range(self.hbox_tasks.count()): if self.hbox_tasks.itemAt(i).widget(): self.hbox_tasks.itemAt(i).widget().show() for i in range(self.hbox_sporadic_tasks.count()): if self.hbox_sporadic_tasks.itemAt(i).widget(): self.hbox_sporadic_tasks.itemAt(i).widget().show() def show_kato_options(self): for i in range(self.hbox_utilizations.count()): if self.hbox_utilizations.itemAt(i).widget(): self.hbox_utilizations.itemAt(i).widget().show() for i in range(self.hbox_tasks.count()): if self.hbox_tasks.itemAt(i).widget(): self.hbox_tasks.itemAt(i).widget().hide() for i in range(self.hbox_sporadic_tasks.count()): if self.hbox_sporadic_tasks.itemAt(i).widget(): self.hbox_sporadic_tasks.itemAt(i).widget().hide() def get_min_utilization(self): return self.interval_utilization.getMin() def get_max_utilization(self): return self.interval_utilization.getMax() def generate(self): if self.comboGenerator.currentIndex() == 0: n = self.get_nb_tasks() u = StaffordRandFixedSum(n, self.get_utilization(), 1) elif self.comboGenerator.currentIndex() == 1: n = self.get_nb_tasks() u = UUniFastDiscard(n, self.get_utilization(), 1) else: u = gen_kato_utilizations(1, self.get_min_utilization(), self.get_max_utilization(), self.get_utilization()) n = len(u[0]) p_types = self.get_periods() if p_types[0] == "unif": p = gen_periods_uniform(n, 1, p_types[1], p_types[2], p_types[3]) elif p_types[0] == "lunif": p = gen_periods_loguniform(n, 1, p_types[1], p_types[2], p_types[3]) else: p = gen_periods_discrete(n, 1, p_types[1]) if u and p: self.taskset = gen_tasksets(u, p)[0] self.accept() elif not u: QMessageBox.warning( self, "Generation failed", "Please check the utilization and the number of tasks.") else: QMessageBox.warning(self, "Generation failed", "Pleache check the periods.") def get_nb_tasks(self): return self.spin_tasks.value() + self.spin_sporadic_tasks.value() def get_nb_periodic_tasks(self): return self.spin_tasks.value() def get_nb_sporadic_tasks(self): return self.spin_sporadic_tasks.value() def get_utilization(self): return self.spin_load.value() def get_periods(self): if self.unif.isChecked(): return ("unif", self.unif_interval.getMin(), self.unif_interval.getMax(), self.unif_interval.getRound()) elif self.lunif.isChecked(): return ("lunif", self.lunif_interval.getMin(), self.lunif_interval.getMax(), self.lunif_interval.getRound()) else: return ("discrete", map(float, str(self.periods.text()).split()))
class ProfileDockWidget(QDockWidget): """ DockWidget class to display the profile """ closeSignal = pyqtSignal() def __init__(self, iface): """ Constructor :param iface: interface """ QDockWidget.__init__(self) self.setWindowTitle(QCoreApplication.translate("VDLTools", "Profile Tool")) self.resize(1024, 400) self.__iface = iface self.__canvas = self.__iface.mapCanvas() self.__types = ['PDF', 'PNG'] # ], 'SVG', 'PS'] self.__libs = [] if Qwt5_loaded: self.__lib = 'Qwt5' self.__libs.append('Qwt5') if matplotlib_loaded: self.__libs.append('Matplotlib') elif matplotlib_loaded: self.__lib = 'Matplotlib' self.__libs.append('Matplotlib') else: self.__lib = None self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "No graph lib available (qwt5 or matplotlib)"), level=QgsMessageBar.CRITICAL, duration=0) self.__doTracking = False self.__vline = None self.__profiles = None self.__numLines = None self.__mntPoints = None self.__marker = None self.__tabmouseevent = None self.__contentWidget = QWidget() self.setWidget(self.__contentWidget) self.__boxLayout = QHBoxLayout() self.__contentWidget.setLayout(self.__boxLayout) self.__plotFrame = QFrame() self.__frameLayout = QHBoxLayout() self.__plotFrame.setLayout(self.__frameLayout) self.__printLayout = QHBoxLayout() self.__printLayout.addWidget(self.__plotFrame) self.__legendLayout = QVBoxLayout() self.__printLayout.addLayout(self.__legendLayout) self.__printWdg = QWidget() self.__printWdg.setLayout(self.__printLayout) self.__plotWdg = None self.__changePlotWidget() size = QSize(150, 20) self.__boxLayout.addWidget(self.__printWdg) self.__vertLayout = QVBoxLayout() self.__libCombo = QComboBox() self.__libCombo.setFixedSize(size) self.__libCombo.addItems(self.__libs) self.__vertLayout.addWidget(self.__libCombo) self.__libCombo.currentIndexChanged.connect(self.__setLib) self.__maxLabel = QLabel("y max") self.__maxLabel.setFixedSize(size) self.__vertLayout.addWidget(self.__maxLabel) self.__maxSpin = QSpinBox() self.__maxSpin.setFixedSize(size) self.__maxSpin.setRange(-10000, 10000) self.__maxSpin.valueChanged.connect(self.__reScalePlot) self.__vertLayout.addWidget(self.__maxSpin) self.__vertLayout.insertSpacing(10, 20) self.__minLabel = QLabel("y min") self.__minLabel.setFixedSize(size) self.__vertLayout.addWidget(self.__minLabel) self.__minSpin = QSpinBox() self.__minSpin.setFixedSize(size) self.__minSpin.setRange(-10000, 10000) self.__minSpin.valueChanged.connect(self.__reScalePlot) self.__vertLayout.addWidget(self.__minSpin) self.__vertLayout.insertSpacing(10, 40) self.__typeCombo = QComboBox() self.__typeCombo.setFixedSize(size) self.__typeCombo.addItems(self.__types) self.__vertLayout.addWidget(self.__typeCombo) self.__saveButton = QPushButton(QCoreApplication.translate("VDLTools", "Save")) self.__saveButton.setFixedSize(size) self.__saveButton.clicked.connect(self.__save) self.__vertLayout.addWidget(self.__saveButton) self.__boxLayout.addLayout(self.__vertLayout) self.__maxSpin.setEnabled(False) self.__minSpin.setEnabled(False) self.__colors = [] for cn in QColor.colorNames(): qc = QColor(cn) val = qc.red() + qc.green() + qc.blue() if 0 < val < 450: self.__colors.append(cn) def __changePlotWidget(self): """ When plot widget is change (qwt <-> matplotlib) """ self.__activateMouseTracking(False) while self.__frameLayout.count(): child = self.__frameLayout.takeAt(0) child.widget().deleteLater() self.__plotWdg = None if self.__lib == 'Qwt5': self.__plotWdg = QwtPlot(self.__plotFrame) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(10) sizePolicy.setVerticalStretch(0) self.__plotWdg.setSizePolicy(sizePolicy) self.__plotWdg.setAutoFillBackground(False) # Decoration self.__plotWdg.setCanvasBackground(Qt.white) self.__plotWdg.plotLayout().setAlignCanvasToScales(False) self.__plotWdg.plotLayout().setSpacing(100) self.__plotWdg.plotLayout().setCanvasMargin(10, QwtPlot.xBottom) self.__plotWdg.plotLayout().setCanvasMargin(10, QwtPlot.yLeft) title = QwtText(QCoreApplication.translate("VDLTools", "Distance [m]")) title.setFont(QFont("Helvetica", 10)) self.__plotWdg.setAxisTitle(QwtPlot.xBottom, title) title.setText(QCoreApplication.translate("VDLTools", "Elevation [m]")) title.setFont(QFont("Helvetica", 10)) self.__plotWdg.setAxisTitle(QwtPlot.yLeft, title) self.__zoomer = QwtPlotZoomer(QwtPlot.xBottom, QwtPlot.yLeft, QwtPicker.DragSelection, QwtPicker.AlwaysOff, self.__plotWdg.canvas()) self.__zoomer.setRubberBandPen(QPen(Qt.blue)) grid = QwtPlotGrid() grid.setPen(QPen(QColor('grey'), 0, Qt.DotLine)) grid.attach(self.__plotWdg) self.__frameLayout.addWidget(self.__plotWdg) elif self.__lib == 'Matplotlib': # __plotWdg.figure : matplotlib.figure.Figure fig = Figure((1.0, 1.0), linewidth=0.0, subplotpars=SubplotParams(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)) font = {'family': 'arial', 'weight': 'normal', 'size': 12} rc('font', **font) rect = fig.patch rect.set_facecolor((0.9, 0.9, 0.9)) self.__axes = fig.add_axes((0.07, 0.16, 0.92, 0.82)) self.__axes.set_xbound(0, 1000) self.__axes.set_ybound(0, 1000) self.__manageMatplotlibAxe(self.__axes) self.__plotWdg = FigureCanvasQTAgg(fig) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) self.__plotWdg.setSizePolicy(sizePolicy) self.__frameLayout.addWidget(self.__plotWdg) def setProfiles(self, profiles, numLines): """ To set the profiles :param profiles: profiles : positions with elevations (for line and points) :param numLines: number of selected connected lines """ self.__numLines = numLines self.__profiles = profiles if self.__lib == 'Matplotlib': self.__prepare_points() def __getLinearPoints(self): """ To extract the linear points of the profile """ profileLen = 0 self.__profiles[0]['l'] = profileLen for i in range(0, len(self.__profiles)-1): x1 = float(self.__profiles[i]['x']) y1 = float(self.__profiles[i]['y']) x2 = float(self.__profiles[i+1]['x']) y2 = float(self.__profiles[i+1]['y']) profileLen += sqrt(((x2-x1)*(x2-x1)) + ((y2-y1)*(y2-y1))) self.__profiles[i+1]['l'] = profileLen def __getMnt(self, settings): """ To get the MN data for the profile :param settings: settings containing MN url """ if settings is None or settings.mntUrl is None or settings.mntUrl == "None": url = 'http://map.lausanne.ch/main/wsgi/profile.json' elif settings.mntUrl == "": return else: url = settings.mntUrl names = ['mnt', 'mns', 'toit_rocher'] url += '?layers=' pos = 0 for name in names: if pos > 0: url += ',' pos += 1 url += name url += '&geom={"type":"LineString","coordinates":[' pos = 0 for i in range(len(self.__profiles)): if pos > 0: url += ',' pos += 1 url += '[' + str(self.__profiles[i]['x']) + ',' + str(self.__profiles[i]['y']) + ']' url = url + ']}&nbPoints=' + str(int(self.__profiles[len(self.__profiles)-1]['l'])) try: response = urlopen(url) j = response.read() j_obj = json.loads(j) profile = j_obj['profile'] self.__mntPoints = [] self.__mntPoints.append(names) mnt_l = [] mnt_z = [] for p in range(len(names)): z = [] mnt_z.append(z) for pt in profile: mnt_l.append(float(pt['dist'])) values = pt['values'] for p in range(len(names)): if names[p] in values: mnt_z[p].append(float(values[names[p]])) else: mnt_z[p].append(None) self.__mntPoints.append(mnt_l) self.__mntPoints.append(mnt_z) except HTTPError as e: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "HTTP Error"), QCoreApplication.translate("VDLTools", "status error [" + str(e.code) + "] : " + e.reason), level=QgsMessageBar.CRITICAL, duration=0) except URLError as e: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "URL Error"), e.reason, level=QgsMessageBar.CRITICAL, duration=0) def attachCurves(self, names, settings, usedMnts): """ To attach the curves for the layers to the profile :param names: layers names """ if (self.__profiles is None) or (self.__profiles == 0): return self.__getLinearPoints() if usedMnts is not None and (usedMnts[0] or usedMnts[1] or usedMnts[2]): self.__getMnt(settings) c = 0 if self.__mntPoints is not None: for p in range(len(self.__mntPoints[0])): if usedMnts[p]: legend = QLabel("<font color='" + self.__colors[c] + "'>" + self.__mntPoints[0][p] + "</font>") self.__legendLayout.addWidget(legend) if self.__lib == 'Qwt5': xx = [list(g) for k, g in itertools.groupby(self.__mntPoints[1], lambda x: x is None) if not k] yy = [list(g) for k, g in itertools.groupby(self.__mntPoints[2][p], lambda x: x is None) if not k] for j in range(len(xx)): curve = QwtPlotCurve(self.__mntPoints[0][p]) curve.setData(xx[j], yy[j]) curve.setPen(QPen(QColor(self.__colors[c]), 3)) curve.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': qcol = QColor(self.__colors[c]) self.__plotWdg.figure.get_axes()[0].plot(self.__mntPoints[1], self.__mntPoints[2][p], gid=self.__mntPoints[0][p], linewidth=3) tmp = self.__plotWdg.figure.get_axes()[0].get_lines() for t in range(len(tmp)): if self.__mntPoints[0][p] == tmp[t].get_gid(): tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0), old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0))) self.__plotWdg.draw() break c += 1 if 'z' in self.__profiles[0]: for i in range(len(self.__profiles[0]['z'])): if i < self.__numLines: v = 0 else: v = i - self.__numLines + 1 name = names[v] xx = [] yy = [] for prof in self.__profiles: xx.append(prof['l']) yy.append(prof['z'][i]) for j in range(len(yy)): if yy[j] is None: xx[j] = None if i == 0 or i > (self.__numLines-1): legend = QLabel("<font color='" + self.__colors[c] + "'>" + name + "</font>") self.__legendLayout.addWidget(legend) if self.__lib == 'Qwt5': # Split xx and yy into single lines at None values xx = [list(g) for k, g in itertools.groupby(xx, lambda x: x is None) if not k] yy = [list(g) for k, g in itertools.groupby(yy, lambda x: x is None) if not k] # Create & attach one QwtPlotCurve per one single line for j in range(len(xx)): curve = QwtPlotCurve(name) curve.setData(xx[j], yy[j]) curve.setPen(QPen(QColor(self.__colors[c]), 3)) if i > (self.__numLines-1): curve.setStyle(QwtPlotCurve.Dots) pen = QPen(QColor(self.__colors[c]), 8) pen.setCapStyle(Qt.RoundCap) curve.setPen(pen) curve.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': qcol = QColor(self.__colors[c]) if i < self.__numLines: self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=3) else: self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=5, marker='o', linestyle='None') tmp = self.__plotWdg.figure.get_axes()[0].get_lines() for t in range(len(tmp)): if name == tmp[t].get_gid(): tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0), old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0))) self.__plotWdg.draw() break c += 1 # scaling this try: self.__reScalePlot(None, True) except: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Rescale problem... (trace printed)"), level=QgsMessageBar.CRITICAL, duration=0) print( QCoreApplication.translate("VDLTools", "rescale problem : "), sys.exc_info()[0], traceback.format_exc()) if self.__lib == 'Qwt5': self.__plotWdg.replot() elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].redraw_in_frame() self.__plotWdg.draw() self.__activateMouseTracking(True) self.__marker.show() def __reScalePlot(self, value=None, auto=False): """ To rescale the profile plot depending to the bounds """ if (self.__profiles is None) or (self.__profiles == 0): self.__plotWdg.replot() return maxi = 0 for i in range(len(self.__profiles)): if (int(self.__profiles[i]['l'])) > maxi: maxi = int(self.__profiles[i]['l']) + 1 if self.__lib == 'Qwt5': self.__plotWdg.setAxisScale(2, 0, maxi, 0) elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].set_xbound(0, maxi) minimumValue = self.__minSpin.value() maximumValue = self.__maxSpin.value() # to set max y and min y displayed if auto: minimumValue = 1000000000 maximumValue = -1000000000 for i in range(len(self.__profiles)): if 'z' in self.__profiles[i]: mini = self.__minTab(self.__profiles[i]['z']) if int(mini) < minimumValue: minimumValue = int(mini) - 1 maxi = self.__maxTab(self.__profiles[i]['z']) if int(maxi) > maximumValue: maximumValue = int(maxi) + 1 if self.__mntPoints is not None: for pts in self.__mntPoints[2]: miniMnt = self.__minTab(pts) if int(miniMnt) < minimumValue: minimumValue = int(miniMnt) - 1 maxiMnt = self.__maxTab(pts) if int(maxiMnt) > maximumValue: maximumValue = int(maxiMnt) + 1 self.__maxSpin.setValue(maximumValue) self.__minSpin.setValue(minimumValue) self.__maxSpin.setEnabled(True) self.__minSpin.setEnabled(True) if self.__lib == 'Qwt5': rect = QRectF(0, minimumValue, maxi, maximumValue-minimumValue) self.__zoomer.setZoomBase(rect) # to draw vertical lines for i in range(len(self.__profiles)): zz = [] for j in range(self.__numLines): if self.__profiles[i]['z'][j] is not None: zz.append(j) color = None if len(zz) == 2: width = 3 color = QColor('red') else: width = 1 if self.__lib == 'Qwt5': vertLine = QwtPlotMarker() vertLine.setLineStyle(QwtPlotMarker.VLine) pen = vertLine.linePen() pen.setWidth(width) if color is not None: pen.setColor(color) vertLine.setLinePen(pen) vertLine.setXValue(self.__profiles[i]['l']) label = vertLine.label() label.setText(str(i)) vertLine.setLabel(label) vertLine.setLabelAlignment(Qt.AlignLeft) vertLine.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].vlines(self.__profiles[i]['l'], minimumValue, maximumValue, linewidth=width) if minimumValue < maximumValue: if self.__lib == 'Qwt5': self.__plotWdg.setAxisScale(0, minimumValue, maximumValue, 0) self.__plotWdg.replot() elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].set_ybound(minimumValue, maximumValue) self.__plotWdg.figure.get_axes()[0].redraw_in_frame() self.__plotWdg.draw() @staticmethod def __minTab(tab): """ To get the minimum value in a table :param tab: table to scan :return: minimum value """ mini = 1000000000 for t in tab: if t is None: continue if t < mini: mini = t return mini @staticmethod def __maxTab(tab): """ To get the maximum value in a table :param tab: table to scan :return: maximum value """ maxi = -1000000000 for t in tab: if t is None: continue if t > maxi: maxi = t return maxi def __setLib(self): """ To set the new widget library (qwt <-> matplotlib) """ self.__lib = self.__libs[self.__libCombo.currentIndex()] self.__changePlotWidget() def __save(self): """ To save the profile in a file, on selected format """ idx = self.__typeCombo.currentIndex() if idx == 0: self.__outPDF() elif idx == 1: self.__outPNG() else: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Invalid index ") + str(idx), level=QgsMessageBar.CRITICAL, duration=0) def __outPDF(self): """ To save the profile as pdf file """ fileName = QFileDialog.getSaveFileName( self.__iface.mainWindow(), QCoreApplication.translate("VDLTools", "Save As"), QCoreApplication.translate("VDLTools", "Profile.pdf"),"Portable Document Format (*.pdf)") if fileName is not None: if self.__lib == 'Qwt5': printer = QPrinter() printer.setCreator(QCoreApplication.translate("VDLTools", "QGIS Profile Plugin")) printer.setOutputFileName(fileName) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOrientation(QPrinter.Landscape) self.__plotWdg.print_(printer) elif self.__lib == 'Matplotlib': self.__plotWdg.figure.savefig(str(fileName)) # printer = QPrinter() # printer.setCreator(QCoreApplication.translate("VDLTools", "QGIS Profile Plugin")) # printer.setOutputFileName(fileName) # printer.setOutputFormat(QPrinter.PdfFormat) # printer.setOrientation(QPrinter.Landscape) # printer.setPaperSize(QSizeF(self.__printWdg.size()), QPrinter.Millimeter) # printer.setFullPage(True) # self.__printWdg.render(printer) def __outPNG(self): """ To save the profile as png file """ fileName = QFileDialog.getSaveFileName( self.__iface.mainWindow(), QCoreApplication.translate("VDLTools", "Save As"), QCoreApplication.translate("VDLTools", "Profile.png"),"Portable Network Graphics (*.png)") if fileName is not None: QPixmap.grabWidget(self.__printWdg).save(fileName, "PNG") def clearData(self): """ To clear the displayed data """ if self.__profiles is None: return if self.__lib == 'Qwt5': self.__plotWdg.clear() self.__profiles = None temp1 = self.__plotWdg.itemList() for j in range(len(temp1)): if temp1[j].rtti() == QwtPlotItem.Rtti_PlotCurve: temp1[j].detach() elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].cla() self.__manageMatplotlibAxe(self.__plotWdg.figure.get_axes()[0]) self.__maxSpin.setEnabled(False) self.__minSpin.setEnabled(False) self.__maxSpin.setValue(0) self.__minSpin.setValue(0) # clear legend while self.__legendLayout.count(): child = self.__legendLayout.takeAt(0) child.widget().deleteLater() def __manageMatplotlibAxe(self, axe): """ To manage the axes for matplotlib library :param axe: the axes element """ axe.grid() axe.tick_params(axis="both", which="major", direction="out", length=10, width=1, bottom=True, top=False, left=True, right=False) axe.minorticks_on() axe.tick_params(axis="both", which="minor", direction="out", length=5, width=1, bottom=True, top=False, left=True, right=False) axe.set_xlabel(QCoreApplication.translate("VDLTools", "Distance [m]")) axe.set_ylabel(QCoreApplication.translate("VDLTools", "Elevation [m]")) def __activateMouseTracking(self, activate): """ To (de)activate the mouse tracking on the profile for matplotlib library :param activate: true to activate, false to deactivate """ if activate: self.__doTracking = True self.__loadRubber() self.cid = self.__plotWdg.mpl_connect('motion_notify_event', self.__mouseevent_mpl) elif self.__doTracking: self.__doTracking = False self.__plotWdg.mpl_disconnect(self.cid) if self.__marker is not None: self.__canvas.scene().removeItem(self.__marker) try: if self.__vline is not None: self.__plotWdg.figure.get_axes()[0].lines.remove(self.__vline) self.__plotWdg.draw() except Exception as e: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Tracking exception : ") + str(e), level=QgsMessageBar.CRITICAL, duration=0) def __mouseevent_mpl(self, event): """ To manage matplotlib mouse tracking event :param event: mouse tracking event """ if event.xdata is not None: try: if self.__vline is not None: self.__plotWdg.figure.get_axes()[0].lines.remove(self.__vline) except Exception as e: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Mouse event exception : ") + str(e), level=QgsMessageBar.CRITICAL, duration=0) xdata = float(event.xdata) self.__vline = self.__plotWdg.figure.get_axes()[0].axvline(xdata, linewidth=2, color='k') self.__plotWdg.draw() i = 1 while i < len(self.__tabmouseevent)-1 and xdata > self.__tabmouseevent[i][0]: i += 1 i -= 1 x = self.__tabmouseevent[i][1] + (self.__tabmouseevent[i + 1][1] - self.__tabmouseevent[i][1]) / ( self.__tabmouseevent[i + 1][0] - self.__tabmouseevent[i][0]) * (xdata - self.__tabmouseevent[i][0]) y = self.__tabmouseevent[i][2] + (self.__tabmouseevent[i + 1][2] - self.__tabmouseevent[i][2]) / ( self.__tabmouseevent[i + 1][0] - self.__tabmouseevent[i][0]) * (xdata - self.__tabmouseevent[i][0]) self.__marker.show() self.__marker.setCenter(QgsPoint(x, y)) def __loadRubber(self): """ To load te rubber band for mouse tracking on map """ self.__marker = QgsVertexMarker(self.__canvas) self.__marker.setIconSize(5) self.__marker.setIconType(QgsVertexMarker.ICON_BOX) self.__marker.setPenWidth(3) def __prepare_points(self): """ To prepare the points on map for mouse tracking on profile """ self.__tabmouseevent = [] length = 0 for i, point in enumerate(self.__profiles): if i == 0: self.__tabmouseevent.append([0, point['x'], point['y']]) else: length += ((self.__profiles[i]['x'] - self.__profiles[i-1]['x']) ** 2 + (self.__profiles[i]['y'] - self.__profiles[i-1]['y']) ** 2) ** 0.5 self.__tabmouseevent.append([float(length), float(point['x']), float(point['y'])]) def closeEvent(self, event): """ When the dock widget is closed :param event: close event """ if self.__maxSpin is not None: Signal.safelyDisconnect(self.__maxSpin.valueChanged, self.__reScalePlot) self.__maxSpin = None if self.__minSpin is not None: Signal.safelyDisconnect(self.__minSpin.valueChanged, self.__reScalePlot) self.__minSpin = None if self.__saveButton is not None: Signal.safelyDisconnect(self.__saveButton.clicked, self.__save) self.__saveButton = None if self.__libCombo is not None: Signal.safelyDisconnect(self.__libCombo.currentIndexChanged, self.__setLib) self.__libCombo = None self.closeSignal.emit() if self.__marker is not None: self.__marker.hide() QDockWidget.closeEvent(self, event)
class TerminalWidget(QWidget): def __init__(self, mainloop, addr, title, parent=None): QWidget.__init__(self, parent) self.mainloop = mainloop self.addr = addr self.title = QLabel(title) self.title.setFont(QFont('Monospace', 16)) self.message = QLabel('') self.message.setFont(QFont('Monospace', 13)) self.bt_open = self.init_button('arrow-up-icon.png', QSize(50, 50)) self.bt_close = self.init_button('arrow-down-icon.png', QSize(50, 50)) info_layout = QVBoxLayout() info_layout.addWidget(self.title) layout = QHBoxLayout() layout.addLayout(info_layout) layout.addSpacerItem(QSpacerItem(0, 0, QSizePolicy.Expanding)) self.options_layout = QHBoxLayout() layout.addLayout(self.options_layout) layout.addWidget(self.bt_open) layout.addWidget(self.bt_close) self.setLayout(layout) self.bt_open.clicked.connect(self.open) self.bt_close.clicked.connect(self.close) self.grabGesture(Qt.TapAndHoldGesture) def update_config(self): self.mainloop.update_config(self.addr) self.clear_config_layout() def init_config_layout(self): if self.options_layout.isEmpty(): config_bt = self.init_button('settings-icon.png', QSize(50, 50)) config_bt.clicked.connect(self.update_config) self.options_layout.addWidget(config_bt) def clear_config_layout(self): for i in reversed(range(self.options_layout.count())): self.options_layout.itemAt(i).widget().setParent(None) def gesture_event(self, event): #if event.gestureType() == self.tap_and_hold_type: # self.init_config_layout() # return True if event.gestureType() == Qt.TapAndHoldGesture: self.init_config_layout() return True return False def event(self, event): if event.type() == QEvent.Gesture: print self.addr, event for g in event.gestures(): if g.state() != Qt.GestureFinished: continue if self.gesture_event(g): return event.setAccepted(g, True) return QWidget.event(self, event) def init_button(self, icon_filename, size): button = QPushButton(self) button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) button.setAutoFillBackground(True) button.setMinimumSize(size) button.setIcon(QIcon(icon_filename)) button.setIconSize(size) return button def show_message(self, msg): print unicode(msg).encode('utf8') self.message.setText(msg) def set_style_color(self, color): return self.setStyleSheet(""" TerminalWidget { background-color: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.7, fy:0.7, stop:0 %s, stop:1 white); }""" % (color,)) def set_state(self, state): if not self.isEnabled(): return if state == 'active': self.set_style_color('green') elif state == 'inactive': self.set_style_color('red') elif state == 'disabled': self.set_style_color('gray') else: self.set_style_color('white') self.setAutoFillBackground(True) def open(self): self.mainloop.terminal_open(self.addr) def close(self): self.mainloop.terminal_close(self.addr)
class LineEdit(QLineEdit): inactiveText = QtDynamicProperty('inactiveText', unicode) widgetSpacing = QtDynamicProperty('widgetSpacing', int) def __init__(self, parent=None, contents=u""): QLineEdit.__init__(self, contents, parent) box_direction = QBoxLayout.RightToLeft if self.isRightToLeft() else QBoxLayout.LeftToRight self.inactiveText = u"" self.left_widget = SideWidget(self) self.left_widget.resize(0, 0) self.left_layout = QHBoxLayout(self.left_widget) self.left_layout.setContentsMargins(0, 0, 0, 0) self.left_layout.setDirection(box_direction) self.left_layout.setSizeConstraint(QLayout.SetFixedSize) self.right_widget = SideWidget(self) self.right_widget.resize(0, 0) self.right_layout = QHBoxLayout(self.right_widget) self.right_layout.setContentsMargins(0, 0, 0, 0) self.right_layout.setDirection(box_direction) self.right_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)) self.widgetSpacing = 2 self.left_widget.sizeHintChanged.connect(self._update_text_margins) self.right_widget.sizeHintChanged.connect(self._update_text_margins) @property def left_margin(self): return self.left_widget.sizeHint().width() + 2*self.right_layout.spacing() @property def right_margin(self): return self.right_widget.sizeHint().width() + 2*self.right_layout.spacing() def _update_text_margins(self): self.setTextMargins(self.left_margin, 0, self.right_margin, 0) self._update_side_widget_locations() def _update_side_widget_locations(self): option = QStyleOptionFrameV2() self.initStyleOption(option) spacing = self.right_layout.spacing() text_rect = self.style().subElementRect(QStyle.SE_LineEditContents, option, self) text_rect.adjust(spacing, 0, -spacing, 0) mid_height = text_rect.center().y() + 1 - (text_rect.height() % 2) # need -1 correction for odd heights -Dan if self.left_layout.count() > 0: left_height = mid_height - self.left_widget.height()/2 left_width = self.left_widget.width() if left_width == 0: left_height = mid_height - self.left_widget.sizeHint().height()/2 self.left_widget.move(text_rect.x(), left_height) text_rect.setX(self.left_margin) text_rect.setY(mid_height - self.right_widget.sizeHint().height()/2.0) text_rect.setHeight(self.right_widget.sizeHint().height()) self.right_widget.setGeometry(text_rect) def event(self, event): event_type = event.type() if event_type == QEvent.LayoutDirectionChange: box_direction = QBoxLayout.RightToLeft if self.isRightToLeft() else QBoxLayout.LeftToRight self.left_layout.setDirection(box_direction) self.right_layout.setDirection(box_direction) elif event_type == QEvent.DynamicPropertyChange: property_name = event.propertyName() if property_name == 'widgetSpacing': self.left_layout.setSpacing(self.widgetSpacing) self.right_layout.setSpacing(self.widgetSpacing) self._update_text_margins() elif property_name == 'inactiveText': self.update() return QLineEdit.event(self, event) def resizeEvent(self, event): self._update_side_widget_locations() QLineEdit.resizeEvent(self, event) def paintEvent(self, event): QLineEdit.paintEvent(self, event) if not self.hasFocus() and not self.text() and self.inactiveText: options = QStyleOptionFrameV2() self.initStyleOption(options) text_rect = self.style().subElementRect(QStyle.SE_LineEditContents, options, self) text_rect.adjust(self.left_margin+2, 0, -self.right_margin, 0) painter = QPainter(self) painter.setPen(self.palette().brush(QPalette.Disabled, QPalette.Text).color()) painter.drawText(text_rect, Qt.AlignLeft | Qt.AlignVCenter, self.inactiveText) def addHeadWidget(self, widget): if self.isRightToLeft(): self.right_layout.insertWidget(1, widget) else: self.left_layout.addWidget(widget) def addTailWidget(self, widget): if self.isRightToLeft(): self.left_layout.addWidget(widget) else: self.right_layout.insertWidget(1, widget) def removeWidget(self, widget): self.left_layout.removeWidget(widget) self.right_layout.removeWidget(widget) widget.hide()
class LineEdit(QLineEdit): inactiveText = QtDynamicProperty('inactiveText', unicode) widgetSpacing = QtDynamicProperty('widgetSpacing', int) def __init__(self, parent=None, contents=u""): QLineEdit.__init__(self, contents, parent) box_direction = QBoxLayout.RightToLeft if self.isRightToLeft( ) else QBoxLayout.LeftToRight self.inactiveText = u"" self.left_widget = SideWidget(self) self.left_widget.resize(0, 0) self.left_layout = QHBoxLayout(self.left_widget) self.left_layout.setContentsMargins(0, 0, 0, 0) self.left_layout.setDirection(box_direction) self.left_layout.setSizeConstraint(QLayout.SetFixedSize) self.right_widget = SideWidget(self) self.right_widget.resize(0, 0) self.right_layout = QHBoxLayout(self.right_widget) self.right_layout.setContentsMargins(0, 0, 0, 0) self.right_layout.setDirection(box_direction) self.right_layout.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)) self.widgetSpacing = 2 self.left_widget.sizeHintChanged.connect(self._update_text_margins) self.right_widget.sizeHintChanged.connect(self._update_text_margins) @property def left_margin(self): return self.left_widget.sizeHint().width( ) + 2 * self.right_layout.spacing() @property def right_margin(self): return self.right_widget.sizeHint().width( ) + 2 * self.right_layout.spacing() def _update_text_margins(self): self.setTextMargins(self.left_margin, 0, self.right_margin, 0) self._update_side_widget_locations() def _update_side_widget_locations(self): option = QStyleOptionFrameV2() self.initStyleOption(option) spacing = self.right_layout.spacing() text_rect = self.style().subElementRect(QStyle.SE_LineEditContents, option, self) text_rect.adjust(spacing, 0, -spacing, 0) mid_height = text_rect.center().y() + 1 - ( text_rect.height() % 2) # need -1 correction for odd heights -Dan if self.left_layout.count() > 0: left_height = mid_height - self.left_widget.height() / 2 left_width = self.left_widget.width() if left_width == 0: left_height = mid_height - self.left_widget.sizeHint().height( ) / 2 self.left_widget.move(text_rect.x(), left_height) text_rect.setX(self.left_margin) text_rect.setY(mid_height - self.right_widget.sizeHint().height() / 2.0) text_rect.setHeight(self.right_widget.sizeHint().height()) self.right_widget.setGeometry(text_rect) def event(self, event): event_type = event.type() if event_type == QEvent.LayoutDirectionChange: box_direction = QBoxLayout.RightToLeft if self.isRightToLeft( ) else QBoxLayout.LeftToRight self.left_layout.setDirection(box_direction) self.right_layout.setDirection(box_direction) elif event_type == QEvent.DynamicPropertyChange: property_name = event.propertyName() if property_name == 'widgetSpacing': self.left_layout.setSpacing(self.widgetSpacing) self.right_layout.setSpacing(self.widgetSpacing) self._update_text_margins() elif property_name == 'inactiveText': self.update() return QLineEdit.event(self, event) def resizeEvent(self, event): self._update_side_widget_locations() QLineEdit.resizeEvent(self, event) def paintEvent(self, event): QLineEdit.paintEvent(self, event) if not self.hasFocus() and not self.text() and self.inactiveText: options = QStyleOptionFrameV2() self.initStyleOption(options) text_rect = self.style().subElementRect(QStyle.SE_LineEditContents, options, self) text_rect.adjust(self.left_margin + 2, 0, -self.right_margin, 0) painter = QPainter(self) painter.setPen(self.palette().brush(QPalette.Disabled, QPalette.Text).color()) painter.drawText(text_rect, Qt.AlignLeft | Qt.AlignVCenter, self.inactiveText) def addHeadWidget(self, widget): if self.isRightToLeft(): self.right_layout.insertWidget(1, widget) else: self.left_layout.addWidget(widget) def addTailWidget(self, widget): if self.isRightToLeft(): self.left_layout.addWidget(widget) else: self.right_layout.insertWidget(1, widget) def removeWidget(self, widget): self.left_layout.removeWidget(widget) self.right_layout.removeWidget(widget) widget.hide()
def __init__( self, y_scale_title_text, configs, clear_button=None, parent=None, scales_visible=True, curve_outer_border_visible=True, curve_motion_granularity=10, canvas_color=QColor(245, 245, 245), external_timer=None, key="top-value", extra_key_widgets=None, update_interval=0.1, curve_start="left", ): QWidget.__init__(self, parent) self.setMinimumSize(300, 250) self.stop = True self.plot = Plot( self, y_scale_title_text, configs, scales_visible, curve_outer_border_visible, curve_motion_granularity, canvas_color, curve_start, ) self.set_fixed_y_scale = self.plot.set_fixed_y_scale self.key = key self.key_items = [] self.key_has_values = key.endswith("-value") if key != None else False self.first_show = True self.timestamp = 0 # seconds self.update_interval = update_interval # seconds self.configs = configs h1layout = QHBoxLayout() h1layout.setContentsMargins(0, 0, 0, 0) if clear_button == None: self.clear_button = QToolButton() self.clear_button.setText("Clear Graph") h1layout.addWidget(self.clear_button) else: self.clear_button = clear_button self.clear_button.clicked.connect(self.clear_clicked) h1layout.addStretch(1) v1layout = None if self.key != None: if len(self.configs) == 1: label = FixedSizeLabel(self) label.setText(self.configs[0][0]) self.key_items.append(label) else: for i, config in enumerate(self.configs): pixmap = QPixmap(10, 1) QPainter(pixmap).fillRect(0, 0, 10, 1, config[1]) button = FixedSizeToolButton(self) button.setText(config[0]) button.setIcon(QIcon(pixmap)) button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) button.setCheckable(True) button.setChecked(True) button.toggled.connect(functools.partial(self.plot.show_curve, i)) self.key_items.append(button) if self.key.startswith("top"): for key_item in self.key_items: h1layout.addWidget(key_item) elif self.key.startswith("right"): v1layout = QVBoxLayout() v1layout.setContentsMargins(0, 0, 0, 0) v1layout.addSpacing(self.plot.get_legend_offset_y()) for key_item in self.key_items: v1layout.addWidget(key_item) v1layout.addStretch(1) h1layout.addStretch(1) if extra_key_widgets != None: if self.key.startswith("top"): for widget in extra_key_widgets: h1layout.addWidget(widget) elif self.key.startswith("right"): if v1layout == None: v1layout = QVBoxLayout() v1layout.setContentsMargins(0, 0, 0, 0) v1layout.addSpacing(self.plot.get_legend_offset_y()) if self.key.startswith("top"): for widget in extra_key_widgets: v1layout.addWidget(widget) v2layout = QVBoxLayout(self) v2layout.setContentsMargins(0, 0, 0, 0) if h1layout.count() > 2: v2layout.addLayout(h1layout) if v1layout != None: h2layout = QHBoxLayout() h2layout.setContentsMargins(0, 0, 0, 0) h2layout.addWidget(self.plot) h2layout.addLayout(v1layout) v2layout.addLayout(h2layout) else: v2layout.addWidget(self.plot) if external_timer == None: self.timer = QTimer(self) self.timer.timeout.connect(self.add_new_data) self.timer.start(self.update_interval * 1000) else: # assuming that the external timer runs with the configured interval external_timer.timeout.connect(self.add_new_data)
class Step(QObject): def __init__(self, params): super(Step, self).__init__() self.parse_properties(params) self.initUI() print "Step {0} initialized".format(self.name) self.data_dict = {"name": self.name} def parse_properties(self, props): self.data_widgets = {} props.setdefault('name', "") props.setdefault('duration', "") props.setdefault('next_button', "true") props.setdefault('show_timer', "true") props.setdefault('record', "true") self.name = props['name'] self.record = props['record'] self.show_timer = (props['show_timer'] == 'true') self.duration = self.parse_duration(props['duration']) self.has_next_button = (props['next_button'] == 'true') if 'graph' in props: self.graph = True plot_params = props['graph'] self.plot = EEGPlot(plot_params) self.data_widgets['plot'] = self.plot else: self.graph = False def initUI(self): self.widget = QWidget() self.grid = QHBoxLayout() if self.duration: self.timer_widget = TimerWidget(self.duration, self.endStep) if self.show_timer: self.grid.addWidget(self.timer_widget) if self.graph: self.grid.addWidget(self.plot.pw) self.horseshoe = HorseshoeWidget(self.plot.pw) else: self.horseshoe = HorseshoeWidget(self.widget) self.widget.setLayout(self.grid) def startStep(self, callback): print "starting a step" if self.duration: self.timer_widget.start() self.horseshoe.start() if self.graph: self.plot.start() self.callback = callback def endStep(self): for i in range(self.grid.count()): self.grid.itemAt(i).widget().close() # clear the layout if self.graph: self.plot.stop() if self.record: for name, widget in self.data_widgets.iteritems(): self.data_dict[name] = widget.serialize() if self.has_next_button: self.next_button = QPushButton() self.next_button.setText("Press to Continue") self.next_button.clicked.connect(lambda: self.callback(self.data_dict)) self.grid.addWidget(self.next_button) else: self.callback(self.data_dict) def parse_duration(self, time_string): if len(time_string) == 0: return None else: times = [int(x) for x in time_string.split(":")] times.reverse() # Now we have ss:mm:hh:dd multipliers = [1, 60, 3600, 3600*24] time_in_secs = sum([unit* multiplier for unit, multiplier in zip(times, multipliers)]) return time_in_secs
class TaskGeneratorDialog(QDialog): def __init__(self, nbprocessors): QDialog.__init__(self) self.layout = QVBoxLayout(self) self.taskset = None # Utilizations: vbox_utilizations = QVBoxLayout() group = QGroupBox("Task Utilizations:") hbox = QHBoxLayout() hbox.addWidget(QLabel("Generator:", self)) self.comboGenerator = QComboBox() self.comboGenerator.addItem("RandFixedSum") self.comboGenerator.addItem("UUniFast-Discard") self.comboGenerator.addItem("Kato's method") self.comboGenerator.currentIndexChanged.connect(self.generator_changed) hbox.addWidget(self.comboGenerator) vbox_utilizations.addLayout(hbox) # Load slider + spinner: hbox_load = QHBoxLayout() sld = _DoubleSlider(QtCore.Qt.Horizontal, self) sld.setMinimum(0) sld.setMaximum(32) self.spin_load = QDoubleSpinBox(self) self.spin_load.setMinimum(0) self.spin_load.setMaximum(32) self.spin_load.setSingleStep(0.1) hbox_load.addWidget(QLabel("Total utilization: ", self)) hbox_load.addWidget(sld) hbox_load.addWidget(self.spin_load) sld.doubleValueChanged.connect(self.spin_load.setValue) self.spin_load.valueChanged.connect(sld.setValue) self.spin_load.setValue(nbprocessors / 2.) vbox_utilizations.addLayout(hbox_load) # Number of periodic tasks: self.hbox_tasks = QHBoxLayout() self.spin_tasks = QSpinBox(self) self.spin_tasks.setMinimum(0) self.spin_tasks.setMaximum(999) # That's arbitrary. self.hbox_tasks.addWidget(QLabel("Number of periodic tasks: ", self)) self.hbox_tasks.addStretch(1) self.hbox_tasks.addWidget(self.spin_tasks) vbox_utilizations.addLayout(self.hbox_tasks) # Number of sporadic tasks: self.hbox_sporadic_tasks = QHBoxLayout() self.spin_sporadic_tasks = QSpinBox(self) self.spin_sporadic_tasks.setMinimum(0) self.spin_sporadic_tasks.setMaximum(999) # That's arbitrary. self.hbox_sporadic_tasks.addWidget( QLabel("Number of sporadic tasks: ", self)) self.hbox_sporadic_tasks.addStretch(1) self.hbox_sporadic_tasks.addWidget(self.spin_sporadic_tasks) vbox_utilizations.addLayout(self.hbox_sporadic_tasks) # Min / Max utilizations self.hbox_utilizations = QHBoxLayout() self.hbox_utilizations.addWidget(QLabel("Min/Max utilizations: ", self)) self.interval_utilization = IntervalSpinner( self, min_=0, max_=1, step=.01, round_option=False) self.hbox_utilizations.addWidget(self.interval_utilization) vbox_utilizations.addLayout(self.hbox_utilizations) group.setLayout(vbox_utilizations) self.layout.addWidget(group) # Periods: vbox_periods = QVBoxLayout() group = QGroupBox("Task Periods:") # Log uniform self.lunif = QRadioButton("log-uniform distribution between:") vbox_periods.addWidget(self.lunif) self.lunif.setChecked(True) self.lunif_interval = IntervalSpinner(self) self.lunif_interval.setEnabled(self.lunif.isChecked()) self.lunif.toggled.connect(self.lunif_interval.setEnabled) vbox_periods.addWidget(self.lunif_interval) # Uniform self.unif = QRadioButton("uniform distribution between:") vbox_periods.addWidget(self.unif) self.unif_interval = IntervalSpinner(self) self.unif_interval.setEnabled(self.unif.isChecked()) self.unif.toggled.connect(self.unif_interval.setEnabled) vbox_periods.addWidget(self.unif_interval) # Discrete discrete = QRadioButton("chosen among these (space separated) values:") vbox_periods.addWidget(discrete) self.periods = QLineEdit(self) self.periods.setValidator(QRegExpValidator( QRegExp("^\\d*(\.\\d*)?( \\d*(\.\\d*)?)*$"))) vbox_periods.addWidget(self.periods) self.periods.setEnabled(discrete.isChecked()) discrete.toggled.connect(self.periods.setEnabled) vbox_periods.addStretch(1) group.setLayout(vbox_periods) self.layout.addWidget(group) buttonBox = QDialogButtonBox() cancel = buttonBox.addButton(QDialogButtonBox.Cancel) generate = buttonBox.addButton("Generate", QDialogButtonBox.AcceptRole) cancel.clicked.connect(self.reject) generate.clicked.connect(self.generate) self.layout.addWidget(buttonBox) self.show_randfixedsum_options() def generator_changed(self, value): if value == 2: self.show_kato_options() else: self.show_randfixedsum_options() def show_randfixedsum_options(self): for i in range(self.hbox_utilizations.count()): self.hbox_utilizations.itemAt(i).widget().hide() for i in range(self.hbox_tasks.count()): if self.hbox_tasks.itemAt(i).widget(): self.hbox_tasks.itemAt(i).widget().show() for i in range(self.hbox_sporadic_tasks.count()): if self.hbox_sporadic_tasks.itemAt(i).widget(): self.hbox_sporadic_tasks.itemAt(i).widget().show() def show_kato_options(self): for i in range(self.hbox_utilizations.count()): if self.hbox_utilizations.itemAt(i).widget(): self.hbox_utilizations.itemAt(i).widget().show() for i in range(self.hbox_tasks.count()): if self.hbox_tasks.itemAt(i).widget(): self.hbox_tasks.itemAt(i).widget().hide() for i in range(self.hbox_sporadic_tasks.count()): if self.hbox_sporadic_tasks.itemAt(i).widget(): self.hbox_sporadic_tasks.itemAt(i).widget().hide() def get_min_utilization(self): return self.interval_utilization.getMin() def get_max_utilization(self): return self.interval_utilization.getMax() def generate(self): if self.comboGenerator.currentIndex() == 0: n = self.get_nb_tasks() u = StaffordRandFixedSum(n, self.get_utilization(), 1) elif self.comboGenerator.currentIndex() == 1: n = self.get_nb_tasks() u = UUniFastDiscard(n, self.get_utilization(), 1) else: u = gen_kato_utilizations(1, self.get_min_utilization(), self.get_max_utilization(), self.get_utilization()) n = len(u[0]) p_types = self.get_periods() if p_types[0] == "unif": p = gen_periods_uniform(n, 1, p_types[1], p_types[2], p_types[3]) elif p_types[0] == "lunif": p = gen_periods_loguniform(n, 1, p_types[1], p_types[2], p_types[3]) else: p = gen_periods_discrete(n, 1, p_types[1]) if u and p: self.taskset = gen_tasksets(u, p)[0] self.accept() elif not u: QMessageBox.warning( self, "Generation failed", "Please check the utilization and the number of tasks.") else: QMessageBox.warning( self, "Generation failed", "Pleache check the periods.") def get_nb_tasks(self): return self.spin_tasks.value() + self.spin_sporadic_tasks.value() def get_nb_periodic_tasks(self): return self.spin_tasks.value() def get_nb_sporadic_tasks(self): return self.spin_sporadic_tasks.value() def get_utilization(self): return self.spin_load.value() def get_periods(self): if self.unif.isChecked(): return ("unif", self.unif_interval.getMin(), self.unif_interval.getMax(), self.unif_interval.getRound()) elif self.lunif.isChecked(): return ("lunif", self.lunif_interval.getMin(), self.lunif_interval.getMax(), self.lunif_interval.getRound()) else: return ("discrete", map(float, str(self.periods.text()).split()))
class ProfileDockWidget(QDockWidget): """ DockWidget class to display the profile """ closeSignal = pyqtSignal() def __init__(self, iface, geometry, mntButton=False, zerosButton=False): """ Constructor :param iface: interface :param width: dock widget geometry """ QDockWidget.__init__(self) self.setWindowTitle(QCoreApplication.translate("VDLTools", "Profile Tool")) self.__iface = iface self.__geom = geometry self.__canvas = self.__iface.mapCanvas() self.__types = ['PDF', 'PNG'] # ], 'SVG', 'PS'] self.__libs = [] if Qwt5_loaded: self.__lib = 'Qwt5' self.__libs.append('Qwt5') if matplotlib_loaded: self.__libs.append('Matplotlib') elif matplotlib_loaded: self.__lib = 'Matplotlib' self.__libs.append('Matplotlib') else: self.__lib = None self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "No graph lib available (qwt5 or matplotlib)"), level=QgsMessageBar.CRITICAL, duration=0) self.__doTracking = False self.__vline = None self.__profiles = None self.__numLines = None self.__mntPoints = None self.__marker = None self.__tabmouseevent = None if self.__geom is not None: self.setGeometry(self.__geom) self.__contentWidget = QWidget() self.setWidget(self.__contentWidget) self.__boxLayout = QHBoxLayout() self.__contentWidget.setLayout(self.__boxLayout) self.__plotFrame = QFrame() self.__frameLayout = QHBoxLayout() self.__plotFrame.setLayout(self.__frameLayout) self.__printLayout = QHBoxLayout() self.__printLayout.addWidget(self.__plotFrame) self.__legendLayout = QVBoxLayout() self.__printLayout.addLayout(self.__legendLayout) self.__printWdg = QWidget() self.__printWdg.setLayout(self.__printLayout) self.__plotWdg = None self.__changePlotWidget() size = QSize(150, 20) self.__boxLayout.addWidget(self.__printWdg) self.__vertLayout = QVBoxLayout() self.__libCombo = QComboBox() self.__libCombo.setFixedSize(size) self.__libCombo.addItems(self.__libs) self.__vertLayout.addWidget(self.__libCombo) self.__libCombo.currentIndexChanged.connect(self.__setLib) if mntButton: self.__displayMnt = False self.__mntButton = QPushButton(QCoreApplication.translate("VDLTools", "Display MNT")) self.__mntButton.setFixedSize(size) self.__mntButton.clicked.connect(self.__mnt) self.__vertLayout.addWidget(self.__mntButton) if zerosButton: self.__displayZeros = False self.__zerosButton = QPushButton(QCoreApplication.translate("VDLTools", "Display Zeros")) self.__zerosButton.setFixedSize(size) self.__zerosButton.clicked.connect(self.__zeros) self.__vertLayout.addWidget(self.__zerosButton) else: self.__displayZeros = True self.__maxLabel = QLabel("y max") self.__maxLabel.setFixedSize(size) self.__vertLayout.addWidget(self.__maxLabel) self.__maxSpin = QSpinBox() self.__maxSpin.setFixedSize(size) self.__maxSpin.setRange(-10000, 10000) self.__maxSpin.valueChanged.connect(self.__reScalePlot) self.__vertLayout.addWidget(self.__maxSpin) self.__vertLayout.insertSpacing(10, 20) self.__minLabel = QLabel("y min") self.__minLabel.setFixedSize(size) self.__vertLayout.addWidget(self.__minLabel) self.__minSpin = QSpinBox() self.__minSpin.setFixedSize(size) self.__minSpin.setRange(-10000, 10000) self.__minSpin.valueChanged.connect(self.__reScalePlot) self.__vertLayout.addWidget(self.__minSpin) self.__vertLayout.insertSpacing(10, 40) self.__typeCombo = QComboBox() self.__typeCombo.setFixedSize(size) self.__typeCombo.addItems(self.__types) self.__vertLayout.addWidget(self.__typeCombo) self.__saveButton = QPushButton(QCoreApplication.translate("VDLTools", "Save")) self.__saveButton.setFixedSize(size) self.__saveButton.clicked.connect(self.__save) self.__vertLayout.addWidget(self.__saveButton) self.__boxLayout.addLayout(self.__vertLayout) self.__maxSpin.setEnabled(False) self.__minSpin.setEnabled(False) self.__colors = [] for cn in QColor.colorNames(): qc = QColor(cn) val = qc.red() + qc.green() + qc.blue() if 0 < val < 450: self.__colors.append(cn) def mntButton(self): """ To get the mnt button instance :return: mnt button instance """ return self.__mntButton def zerosButton(self): """ To get the zeros button instance :return: zeros button instance """ return self.__zerosButton def displayMnt(self): """ To get if we want to display mnt :return: true or false """ return self.__displayMnt def __mnt(self): """ To toggle mnt display choice """ if self.__displayMnt: self.__displayMnt = False self.__mntButton.setText(QCoreApplication.translate("VDLTools", "Display MNT")) else: self.__displayMnt = True self.__mntButton.setText(QCoreApplication.translate("VDLTools", "Remove MNT")) def __zeros(self): """ To toggle if we want to display zero elevations or not """ if self.__displayZeros: self.__displayZeros = False self.__zerosButton.setText(QCoreApplication.translate("VDLTools", "Display Zeros")) else: self.__displayZeros = True self.__zerosButton.setText(QCoreApplication.translate("VDLTools", "Remove Zeros")) def __changePlotWidget(self): """ When plot widget is change (qwt <-> matplotlib) """ self.__activateMouseTracking(False) while self.__frameLayout.count(): child = self.__frameLayout.takeAt(0) child.widget().deleteLater() self.__plotWdg = None if self.__lib == 'Qwt5': self.__plotWdg = QwtPlot(self.__plotFrame) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(10) sizePolicy.setVerticalStretch(0) self.__plotWdg.setSizePolicy(sizePolicy) self.__plotWdg.setAutoFillBackground(False) # Decoration self.__plotWdg.setCanvasBackground(Qt.white) self.__plotWdg.plotLayout().setAlignCanvasToScales(False) self.__plotWdg.plotLayout().setSpacing(100) self.__plotWdg.plotLayout().setCanvasMargin(10, QwtPlot.xBottom) self.__plotWdg.plotLayout().setCanvasMargin(10, QwtPlot.yLeft) title = QwtText(QCoreApplication.translate("VDLTools", "Distance [m]")) title.setFont(QFont("Helvetica", 10)) self.__plotWdg.setAxisTitle(QwtPlot.xBottom, title) title.setText(QCoreApplication.translate("VDLTools", "Elevation [m]")) title.setFont(QFont("Helvetica", 10)) self.__plotWdg.setAxisTitle(QwtPlot.yLeft, title) self.__zoomer = QwtPlotZoomer(QwtPlot.xBottom, QwtPlot.yLeft, QwtPicker.DragSelection, QwtPicker.AlwaysOff, self.__plotWdg.canvas()) self.__zoomer.setRubberBandPen(QPen(Qt.blue)) grid = QwtPlotGrid() grid.setPen(QPen(QColor('grey'), 0, Qt.DotLine)) grid.attach(self.__plotWdg) self.__frameLayout.addWidget(self.__plotWdg) elif self.__lib == 'Matplotlib': fig = Figure((1.0, 1.0), linewidth=0.0, subplotpars=SubplotParams(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)) font = {'family': 'arial', 'weight': 'normal', 'size': 12} rc('font', **font) rect = fig.patch rect.set_facecolor((0.9, 0.9, 0.9)) self.__axes = fig.add_axes((0.07, 0.16, 0.92, 0.82)) self.__axes.set_xbound(0, 1000) self.__axes.set_ybound(0, 1000) self.__manageMatplotlibAxe(self.__axes) self.__plotWdg = FigureCanvasQTAgg(fig) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) self.__plotWdg.setSizePolicy(sizePolicy) self.__frameLayout.addWidget(self.__plotWdg) def setProfiles(self, profiles, numLines): """ To set the profiles :param profiles: profiles : positions with elevations (for line and points) :param numLines: number of selected connected lines """ self.__numLines = numLines self.__profiles = profiles if self.__lib == 'Matplotlib': self.__prepare_points() def __getLinearPoints(self): """ To extract the linear points of the profile """ profileLen = 0 self.__profiles[0]['l'] = profileLen for i in range(0, len(self.__profiles)-1): x1 = float(self.__profiles[i]['x']) y1 = float(self.__profiles[i]['y']) x2 = float(self.__profiles[i+1]['x']) y2 = float(self.__profiles[i+1]['y']) profileLen += sqrt(((x2-x1)*(x2-x1)) + ((y2-y1)*(y2-y1))) self.__profiles[i+1]['l'] = profileLen def __getMnt(self, settings): """ To get the MN data for the profile :param settings: settings containing MN url """ if settings is None or settings.mntUrl is None or settings.mntUrl == "None": url = 'https://map.lausanne.ch/prod/wsgi/profile.json' elif settings.mntUrl == "": return else: url = settings.mntUrl names = ['MNT', 'MNS', 'Rocher (approx.)'] data = "layers=MNT%2CMNS%2CRocher%20(approx.)&geom=%7B%22type%22%3A%22LineString%22%2C%22coordinates%22%3A%5B" pos = 0 for i in range(len(self.__profiles)): if pos > 0: data += "%2C" pos += 1 data += "%5B" + str(self.__profiles[i]['x']) + "%2C" + str(self.__profiles[i]['y']) + "%5D" data += "%5D%7D&nbPoints=" + str(int(self.__profiles[len(self.__profiles)-1]['l']+1)) try: response = requests.post(url, data=data) j = response.text j_obj = json.loads(j) profile = j_obj['profile'] self.__mntPoints = [] self.__mntPoints.append(names) mnt_l = [] mnt_z = [] for p in range(len(names)): z = [] mnt_z.append(z) for pt in profile: mnt_l.append(float(pt['dist'])) values = pt['values'] for p in range(len(names)): if names[p] in values: mnt_z[p].append(float(values[names[p]])) else: mnt_z[p].append(None) self.__mntPoints.append(mnt_l) self.__mntPoints.append(mnt_z) except HTTPError as e: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "HTTP Error"), QCoreApplication.translate("VDLTools", "status error") + "[" + str(e.code) + "] : " + e.reason, level=QgsMessageBar.CRITICAL, duration=0) except URLError as e: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "URL Error"), e.reason, level=QgsMessageBar.CRITICAL, duration=0) except ValueError as e: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "No MNT values here"), level=QgsMessageBar.CRITICAL, duration=0) def attachCurves(self, names, settings, usedMnts): """ To attach the curves for the layers to the profile :param names: layers names """ if (self.__profiles is None) or (self.__profiles == 0): return self.__getLinearPoints() if usedMnts is not None and (usedMnts[0] or usedMnts[1] or usedMnts[2]): self.__getMnt(settings) c = 0 if self.__mntPoints is not None: for p in range(len(self.__mntPoints[0])): if usedMnts[p]: legend = QLabel("<font color='" + self.__colors[c] + "'>" + self.__mntPoints[0][p] + "</font>") self.__legendLayout.addWidget(legend) if self.__lib == 'Qwt5': xx = [list(g) for k, g in itertools.groupby(self.__mntPoints[1], lambda x: x is None) if not k] yy = [list(g) for k, g in itertools.groupby(self.__mntPoints[2][p], lambda x: x is None) if not k] for j in range(len(xx)): curve = QwtPlotCurve(self.__mntPoints[0][p]) curve.setData(xx[j], yy[j]) curve.setPen(QPen(QColor(self.__colors[c]), 3)) curve.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': qcol = QColor(self.__colors[c]) self.__plotWdg.figure.get_axes()[0].plot(self.__mntPoints[1], self.__mntPoints[2][p], gid=self.__mntPoints[0][p], linewidth=3) tmp = self.__plotWdg.figure.get_axes()[0].get_lines() for t in range(len(tmp)): if self.__mntPoints[0][p] == tmp[t].get_gid(): tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0), old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0))) self.__plotWdg.draw() break c += 1 if 'z' in self.__profiles[0]: for i in range(len(self.__profiles[0]['z'])): if i < self.__numLines: v = 0 else: v = i - self.__numLines + 1 name = names[v] xx = [] yy = [] for prof in self.__profiles: xx.append(prof['l']) yy.append(prof['z'][i]) for j in range(len(yy)): if yy[j] is None: xx[j] = None if i == 0 or i > (self.__numLines-1): legend = QLabel("<font color='" + self.__colors[c] + "'>" + name + "</font>") self.__legendLayout.addWidget(legend) if self.__lib == 'Qwt5': # Split xx and yy into single lines at None values xx = [list(g) for k, g in itertools.groupby(xx, lambda x: x is None) if not k] yy = [list(g) for k, g in itertools.groupby(yy, lambda x: x is None) if not k] # Create & attach one QwtPlotCurve per one single line for j in range(len(xx)): curve = QwtPlotCurve(name) curve.setData(xx[j], yy[j]) curve.setPen(QPen(QColor(self.__colors[c]), 3)) if i > (self.__numLines-1): curve.setStyle(QwtPlotCurve.Dots) pen = QPen(QColor(self.__colors[c]), 8) pen.setCapStyle(Qt.RoundCap) curve.setPen(pen) curve.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': qcol = QColor(self.__colors[c]) if i < self.__numLines: self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=3) else: self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=5, marker='o', linestyle='None') tmp = self.__plotWdg.figure.get_axes()[0].get_lines() for t in range(len(tmp)): if name == tmp[t].get_gid(): tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0), old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0))) self.__plotWdg.draw() break c += 1 # scaling this try: self.__reScalePlot(None, True) except: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Rescale problem... (trace printed)"), level=QgsMessageBar.CRITICAL, duration=0) print(sys.exc_info()[0], traceback.format_exc()) if self.__lib == 'Qwt5': self.__plotWdg.replot() elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].redraw_in_frame() self.__plotWdg.draw() self.__activateMouseTracking(True) self.__marker.show() def __reScalePlot(self, value=None, auto=False): """ To rescale the profile plot depending to the bounds :param value: juste because connections give value :param auto: if automatic ranges calcul is wanted """ if (self.__profiles is None) or (self.__profiles == 0): self.__plotWdg.replot() return maxi = 0 for i in range(len(self.__profiles)): if (ceil(self.__profiles[i]['l'])) > maxi: maxi = ceil(self.__profiles[i]['l']) if self.__lib == 'Qwt5': self.__plotWdg.setAxisScale(2, 0, maxi, 0) elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].set_xbound(0, maxi) minimumValue = self.__minSpin.value() maximumValue = self.__maxSpin.value() # to set max y and min y displayed if auto: minimumValue = 1000000000 maximumValue = -1000000000 for i in range(len(self.__profiles)): if 'z' in self.__profiles[i]: mini = self.__minTab(self.__profiles[i]['z']) if (mini > 0 or self.__displayZeros) and mini < minimumValue: minimumValue = ceil(mini) - 1 maxi = self.__maxTab(self.__profiles[i]['z']) if maxi > maximumValue: maximumValue = floor(maxi) + 1 if self.__mntPoints is not None: for pts in self.__mntPoints[2]: miniMnt = self.__minTab(pts) if (miniMnt > 0 or self.__displayZeros) and miniMnt < minimumValue: minimumValue = ceil(miniMnt) - 1 maxiMnt = self.__maxTab(pts) if maxiMnt > maximumValue: maximumValue = floor(maxiMnt) + 1 self.__maxSpin.setValue(maximumValue) self.__minSpin.setValue(minimumValue) self.__maxSpin.setEnabled(True) self.__minSpin.setEnabled(True) if self.__lib == 'Qwt5': rect = QRectF(0, minimumValue, maxi, maximumValue-minimumValue) self.__zoomer.setZoomBase(rect) # to draw vertical lines for i in range(len(self.__profiles)): zz = [] for j in range(self.__numLines): if self.__profiles[i]['z'][j] is not None: zz.append(j) color = None if len(zz) == 2: width = 3 color = QColor('red') else: width = 1 if self.__lib == 'Qwt5': vertLine = QwtPlotMarker() vertLine.setLineStyle(QwtPlotMarker.VLine) pen = vertLine.linePen() pen.setWidth(width) if color is not None: pen.setColor(color) vertLine.setLinePen(pen) vertLine.setXValue(self.__profiles[i]['l']) label = vertLine.label() label.setText(str(i)) vertLine.setLabel(label) vertLine.setLabelAlignment(Qt.AlignLeft) vertLine.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].vlines(self.__profiles[i]['l'], minimumValue, maximumValue, linewidth=width) if minimumValue < maximumValue: if self.__lib == 'Qwt5': self.__plotWdg.setAxisScale(0, minimumValue, maximumValue, 0) self.__plotWdg.replot() elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].set_ybound(minimumValue, maximumValue) self.__plotWdg.figure.get_axes()[0].redraw_in_frame() self.__plotWdg.draw() @staticmethod def __minTab(tab): """ To get the minimum value in a table :param tab: table to scan :return: minimum value """ mini = 1000000000 for t in tab: if t is None: continue if t < mini: mini = t return mini @staticmethod def __maxTab(tab): """ To get the maximum value in a table :param tab: table to scan :return: maximum value """ maxi = -1000000000 for t in tab: if t is None: continue if t > maxi: maxi = t return maxi def __setLib(self): """ To set the new widget library (qwt <-> matplotlib) """ self.__lib = self.__libs[self.__libCombo.currentIndex()] self.__changePlotWidget() def __save(self): """ To save the profile in a file, on selected format """ idx = self.__typeCombo.currentIndex() if idx == 0: self.__outPDF() elif idx == 1: self.__outPNG() else: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Invalid index ") + str(idx), level=QgsMessageBar.CRITICAL, duration=0) def __outPDF(self): """ To save the profile as pdf file """ fileName = QFileDialog.getSaveFileName( self.__iface.mainWindow(), QCoreApplication.translate("VDLTools", "Save As"), QCoreApplication.translate("VDLTools", "Profile.pdf"),"Portable Document Format (*.pdf)") if fileName is not None: if self.__lib == 'Qwt5': printer = QPrinter() printer.setCreator(QCoreApplication.translate("VDLTools", "QGIS Profile Plugin")) printer.setOutputFileName(fileName) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOrientation(QPrinter.Landscape) self.__plotWdg.print_(printer) elif self.__lib == 'Matplotlib': self.__plotWdg.figure.savefig(str(fileName)) def __outPNG(self): """ To save the profile as png file """ fileName = QFileDialog.getSaveFileName( self.__iface.mainWindow(), QCoreApplication.translate("VDLTools", "Save As"), QCoreApplication.translate("VDLTools", "Profile.png"),"Portable Network Graphics (*.png)") if fileName is not None: QPixmap.grabWidget(self.__printWdg).save(fileName, "PNG") def clearData(self): """ To clear the displayed data """ if self.__profiles is None: return if self.__lib == 'Qwt5': self.__plotWdg.clear() self.__profiles = None temp1 = self.__plotWdg.itemList() for j in range(len(temp1)): if temp1[j].rtti() == QwtPlotItem.Rtti_PlotCurve: temp1[j].detach() elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].cla() self.__manageMatplotlibAxe(self.__plotWdg.figure.get_axes()[0]) self.__maxSpin.setEnabled(False) self.__minSpin.setEnabled(False) self.__maxSpin.setValue(0) self.__minSpin.setValue(0) # clear legend while self.__legendLayout.count(): child = self.__legendLayout.takeAt(0) child.widget().deleteLater() def __manageMatplotlibAxe(self, axe): """ To manage the axes for matplotlib library :param axe: the axes element """ axe.grid() axe.tick_params(axis="both", which="major", direction="out", length=10, width=1, bottom=True, top=False, left=True, right=False) axe.minorticks_on() axe.tick_params(axis="both", which="minor", direction="out", length=5, width=1, bottom=True, top=False, left=True, right=False) axe.set_xlabel(QCoreApplication.translate("VDLTools", "Distance [m]")) axe.set_ylabel(QCoreApplication.translate("VDLTools", "Elevation [m]")) def __activateMouseTracking(self, activate): """ To (de)activate the mouse tracking on the profile for matplotlib library :param activate: true to activate, false to deactivate """ if activate: self.__doTracking = True self.__loadRubber() self.cid = self.__plotWdg.mpl_connect('motion_notify_event', self.__mouseevent_mpl) elif self.__doTracking: self.__doTracking = False self.__plotWdg.mpl_disconnect(self.cid) if self.__marker is not None: self.__canvas.scene().removeItem(self.__marker) try: if self.__vline is not None: self.__plotWdg.figure.get_axes()[0].lines.remove(self.__vline) self.__plotWdg.draw() except Exception as e: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Tracking exception : ") + str(e), level=QgsMessageBar.CRITICAL, duration=0) def __mouseevent_mpl(self, event): """ To manage matplotlib mouse tracking event :param event: mouse tracking event """ if event.xdata is not None: try: if self.__vline is not None: self.__plotWdg.figure.get_axes()[0].lines.remove(self.__vline) except Exception as e: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Mouse event exception : ") + str(e), level=QgsMessageBar.CRITICAL, duration=0) xdata = float(event.xdata) self.__vline = self.__plotWdg.figure.get_axes()[0].axvline(xdata, linewidth=2, color='k') self.__plotWdg.draw() i = 1 while i < len(self.__tabmouseevent)-1 and xdata > self.__tabmouseevent[i][0]: i += 1 i -= 1 x = self.__tabmouseevent[i][1] + (self.__tabmouseevent[i + 1][1] - self.__tabmouseevent[i][1]) / ( self.__tabmouseevent[i + 1][0] - self.__tabmouseevent[i][0]) * (xdata - self.__tabmouseevent[i][0]) y = self.__tabmouseevent[i][2] + (self.__tabmouseevent[i + 1][2] - self.__tabmouseevent[i][2]) / ( self.__tabmouseevent[i + 1][0] - self.__tabmouseevent[i][0]) * (xdata - self.__tabmouseevent[i][0]) self.__marker.show() self.__marker.setCenter(QgsPoint(x, y)) def __loadRubber(self): """ To load te rubber band for mouse tracking on map """ self.__marker = QgsVertexMarker(self.__canvas) self.__marker.setIconSize(5) self.__marker.setIconType(QgsVertexMarker.ICON_BOX) self.__marker.setPenWidth(3) def __prepare_points(self): """ To prepare the points on map for mouse tracking on profile """ self.__tabmouseevent = [] length = 0 for i, point in enumerate(self.__profiles): if i == 0: self.__tabmouseevent.append([0, point['x'], point['y']]) else: length += ((self.__profiles[i]['x'] - self.__profiles[i-1]['x']) ** 2 + (self.__profiles[i]['y'] - self.__profiles[i-1]['y']) ** 2) ** 0.5 self.__tabmouseevent.append([float(length), float(point['x']), float(point['y'])]) def closeEvent(self, event): """ When the dock widget is closed :param event: close event """ if self.__maxSpin is not None: Signal.safelyDisconnect(self.__maxSpin.valueChanged, self.__reScalePlot) self.__maxSpin = None if self.__minSpin is not None: Signal.safelyDisconnect(self.__minSpin.valueChanged, self.__reScalePlot) self.__minSpin = None if self.__saveButton is not None: Signal.safelyDisconnect(self.__saveButton.clicked, self.__save) self.__saveButton = None if self.__libCombo is not None: Signal.safelyDisconnect(self.__libCombo.currentIndexChanged, self.__setLib) self.__libCombo = None self.closeSignal.emit() if self.__marker is not None: self.__marker.hide() QDockWidget.closeEvent(self, event)