Пример #1
0
class ModelerParametersWidget(QWidget):

    def __init__(self, alg, model, algName=None, configuration=None, dialog=None, context=None):
        super().__init__()
        self._alg = alg  # The algorithm to define in this dialog. It is an instance of QgsProcessingAlgorithm
        self.model = model  # The model this algorithm is going to be added to. It is an instance of QgsProcessingModelAlgorithm
        self.childId = algName  # The name of the algorithm in the model, in case we are editing it and not defining it for the first time
        self.configuration = configuration
        self.context = context
        self.dialog = dialog

        self.widget = ModelerParametersPanelWidget(alg, model, algName, configuration, dialog, context)

        class ContextGenerator(QgsProcessingContextGenerator):

            def __init__(self, context):
                super().__init__()
                self.processing_context = context

            def processingContext(self):
                return self.processing_context

        self.context_generator = ContextGenerator(self.context)

        self.setupUi()
        self.params = None

    def algorithm(self):
        return self._alg

    def switchToCommentTab(self):
        self.tab.setCurrentIndex(1)
        self.commentEdit.setFocus()
        self.commentEdit.selectAll()

    def setupUi(self):
        self.mainLayout = QVBoxLayout()
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.tab = QTabWidget()
        self.mainLayout.addWidget(self.tab)

        self.param_widget = QgsPanelWidgetStack()
        self.widget.setDockMode(True)
        self.param_widget.setMainPanel(self.widget)

        self.tab.addTab(self.param_widget, self.tr('Properties'))

        self.commentLayout = QVBoxLayout()
        self.commentEdit = QTextEdit()
        self.commentEdit.setAcceptRichText(False)
        self.commentLayout.addWidget(self.commentEdit, 1)

        hl = QHBoxLayout()
        hl.setContentsMargins(0, 0, 0, 0)
        hl.addWidget(QLabel(self.tr('Color')))
        self.comment_color_button = QgsColorButton()
        self.comment_color_button.setAllowOpacity(True)
        self.comment_color_button.setWindowTitle(self.tr('Comment Color'))
        self.comment_color_button.setShowNull(True, self.tr('Default'))
        hl.addWidget(self.comment_color_button)
        self.commentLayout.addLayout(hl)

        w2 = QWidget()
        w2.setLayout(self.commentLayout)
        self.tab.addTab(w2, self.tr('Comments'))

        self.setLayout(self.mainLayout)

    def setComments(self, text):
        self.commentEdit.setPlainText(text)

    def comments(self):
        return self.commentEdit.toPlainText()

    def setCommentColor(self, color):
        if color.isValid():
            self.comment_color_button.setColor(color)
        else:
            self.comment_color_button.setToNull()

    def commentColor(self):
        return self.comment_color_button.color() if not self.comment_color_button.isNull() else QColor()

    def getAvailableDependencies(self):
        return self.widget.getAvailableDependencies()

    def getDependenciesPanel(self):
        return self.widget.getDependenciesPanel()

    def getAvailableValuesOfType(self, paramType, outTypes=[], dataTypes=[]):
        return self.widget.getAvailableValuesOfType(paramType, outTypes, dataTypes)

    def resolveValueDescription(self, value):
        return self.widget.resolveValueDescription(value)

    def setPreviousValues(self):
        self.widget.setPreviousValues()

    def createAlgorithm(self):
        alg = self.widget.createAlgorithm()
        if alg:
            alg.comment().setDescription(self.comments())
            alg.comment().setColor(self.commentColor())
        return alg
class ModelerParameterDefinitionDialog(QDialog):
    @staticmethod
    def use_legacy_dialog(param=None, paramType=None):
        if isinstance(param, QgsProcessingDestinationParameter):
            return True

        # yay, use new API!
        return False

    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()
        settings = QgsSettings()
        self.restoreGeometry(
            settings.value(
                "/Processing/modelParametersDefinitionDialogGeometry",
                QByteArray()))

    def closeEvent(self, event):
        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())
        super(ModelerParameterDefinitionDialog, self).closeEvent(event)

    def switchToCommentTab(self):
        self.tab.setCurrentIndex(1)
        self.commentEdit.setFocus()
        self.commentEdit.selectAll()

    def setupUi(self):
        type_metadata = QgsApplication.processingRegistry().parameterType(
            self.param.type() if self.param else self.paramType)
        self.setWindowTitle(
            self.tr('{} Parameter Definition').format(type_metadata.name()))

        self.mainLayout = QVBoxLayout()
        self.tab = QTabWidget()
        self.mainLayout.addWidget(self.tab)

        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout()

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, QgsProcessingParameterDefinition):
            self.nameTextBox.setText(self.param.description())

        if isinstance(self.param, QgsProcessingDestinationParameter):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultWidget = QgsProcessingLayerOutputDestinationWidget(
                self.param, defaultSelection=True)
            self.verticalLayout.addWidget(self.defaultWidget)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(
                not self.param.flags()
                & QgsProcessingParameterDefinition.FlagOptional)
        self.verticalLayout.addWidget(self.requiredCheck)

        self.advancedCheck = QCheckBox()
        self.advancedCheck.setText(self.tr('Advanced'))
        self.advancedCheck.setChecked(False)
        if self.param is not None:
            self.advancedCheck.setChecked(
                self.param.flags()
                & QgsProcessingParameterDefinition.FlagAdvanced)
        self.verticalLayout.addWidget(self.advancedCheck)

        # If child algorithm output is mandatory, disable checkbox
        if isinstance(self.param, QgsProcessingDestinationParameter):
            child = self.alg.childAlgorithms()[self.param.metadata()
                                               ['_modelChildId']]
            model_output = child.modelOutput(
                self.param.metadata()['_modelChildOutputName'])
            param_def = child.algorithm().parameterDefinition(
                model_output.childOutputName())
            if not (param_def.flags()
                    & QgsProcessingParameterDefinition.FlagOptional):
                self.requiredCheck.setEnabled(False)
                self.requiredCheck.setChecked(True)

            self.advancedCheck.setEnabled(False)
            self.advancedCheck.setChecked(False)

        self.verticalLayout.addStretch()

        w = QWidget()
        w.setLayout(self.verticalLayout)
        self.tab.addTab(w, self.tr('Properties'))

        self.commentLayout = QVBoxLayout()
        self.commentEdit = QTextEdit()
        self.commentEdit.setAcceptRichText(False)
        self.commentLayout.addWidget(self.commentEdit, 1)

        hl = QHBoxLayout()
        hl.setContentsMargins(0, 0, 0, 0)
        hl.addWidget(QLabel(self.tr('Color')))
        self.comment_color_button = QgsColorButton()
        self.comment_color_button.setAllowOpacity(True)
        self.comment_color_button.setWindowTitle(self.tr('Comment Color'))
        self.comment_color_button.setShowNull(True, self.tr('Default'))
        hl.addWidget(self.comment_color_button)
        self.commentLayout.addLayout(hl)

        w2 = QWidget()
        w2.setLayout(self.commentLayout)
        self.tab.addTab(w2, self.tr('Comments'))

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.mainLayout.addWidget(self.buttonBox)

        self.setLayout(self.mainLayout)

    def setComments(self, text):
        self.commentEdit.setPlainText(text)

    def comments(self):
        return self.commentEdit.toPlainText()

    def setCommentColor(self, color):
        if color.isValid():
            self.comment_color_button.setColor(color)
        else:
            self.comment_color_button.setToNull()

    def commentColor(self):
        return self.comment_color_button.color(
        ) if not self.comment_color_button.isNull() else QColor()

    def accept(self):
        description = self.nameTextBox.text()
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return

        validChars = \
            'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
        safeName = ''.join(c for c in description if c in validChars)
        name = safeName.lower()

        # Destination parameter
        if (isinstance(self.param, QgsProcessingParameterFeatureSink)):
            self.param = QgsProcessingParameterFeatureSink(
                name=name,
                description=description,
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterFileDestination)):
            self.param = QgsProcessingParameterFileDestination(
                name=name,
                description=description,
                fileFilter=self.param.fileFilter(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterFolderDestination)):
            self.param = QgsProcessingParameterFolderDestination(
                name=name,
                description=description,
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterRasterDestination)):
            self.param = QgsProcessingParameterRasterDestination(
                name=name,
                description=description,
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterVectorDestination)):
            self.param = QgsProcessingParameterVectorDestination(
                name=name,
                description=description,
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.value())

        else:
            if self.paramType:
                typeId = self.paramType
            else:
                typeId = self.param.type()

            paramTypeDef = QgsApplication.instance().processingRegistry(
            ).parameterType(typeId)
            if not paramTypeDef:
                msg = self.tr(
                    'The parameter `{}` is not registered, are you missing a required plugin?'
                    .format(typeId))
                raise UndefinedParameterException(msg)
            self.param = paramTypeDef.create(name)
            self.param.setDescription(description)
            self.param.setMetadata(paramTypeDef.metadata())

        if not self.requiredCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagOptional)
        else:
            self.param.setFlags(
                self.param.flags()
                & ~QgsProcessingParameterDefinition.FlagOptional)

        if self.advancedCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagAdvanced)
        else:
            self.param.setFlags(
                self.param.flags()
                & ~QgsProcessingParameterDefinition.FlagAdvanced)

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.accept(self)

    def reject(self):
        self.param = None

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.reject(self)
class ModelerParameterDefinitionDialog(QDialog):
    @staticmethod
    def use_legacy_dialog(param=None, paramType=None):
        if paramType in (parameters.PARAMETER_TABLE_FIELD,
                         parameters.PARAMETER_BAND,
                         parameters.PARAMETER_VECTOR,
                         parameters.PARAMETER_TABLE,
                         parameters.PARAMETER_MULTIPLE,
                         parameters.PARAMETER_NUMBER,
                         parameters.PARAMETER_DISTANCE,
                         parameters.PARAMETER_SCALE,
                         parameters.PARAMETER_MAP_LAYER):
            return True
        elif isinstance(
                param,
            (QgsProcessingParameterField, QgsProcessingParameterBand,
             QgsProcessingParameterFeatureSource,
             QgsProcessingParameterVectorLayer,
             QgsProcessingParameterMultipleLayers,
             QgsProcessingParameterNumber, QgsProcessingParameterDistance,
             QgsProcessingParameterScale, QgsProcessingParameterMapLayer,
             QgsProcessingDestinationParameter)):
            return True

        # yay, use new API!
        return False

    def __init__(self, alg, paramType=None, param=None):
        self.alg = alg
        self.paramType = paramType
        self.param = param
        QDialog.__init__(self)
        self.setModal(True)
        self.setupUi()
        settings = QgsSettings()
        self.restoreGeometry(
            settings.value(
                "/Processing/modelParametersDefinitionDialogGeometry",
                QByteArray()))

    def closeEvent(self, event):
        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())
        super(ModelerParameterDefinitionDialog, self).closeEvent(event)

    def switchToCommentTab(self):
        self.tab.setCurrentIndex(1)
        self.commentEdit.setFocus()
        self.commentEdit.selectAll()

    def setupUi(self):
        type_metadata = QgsApplication.processingRegistry().parameterType(
            self.param.type() if self.param else self.paramType)
        self.setWindowTitle(
            self.tr('{} Parameter Definition').format(type_metadata.name()))

        self.mainLayout = QVBoxLayout()
        self.tab = QTabWidget()
        self.mainLayout.addWidget(self.tab)

        self.setMinimumWidth(300)

        self.verticalLayout = QVBoxLayout()

        self.label = QLabel(self.tr('Parameter name'))
        self.verticalLayout.addWidget(self.label)
        self.nameTextBox = QLineEdit()
        self.verticalLayout.addWidget(self.nameTextBox)

        if isinstance(self.param, QgsProcessingParameterDefinition):
            self.nameTextBox.setText(self.param.description())

        if self.paramType == parameters.PARAMETER_TABLE_FIELD or \
                isinstance(self.param, QgsProcessingParameterField):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterFeatureSource,
                                           QgsProcessingParameterVectorLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)

            # add the datatype selector
            self.verticalLayout.addWidget(QLabel(self.tr('Allowed data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any'), -1)
            self.datatypeCombo.addItem(self.tr('Number'), 0)
            self.datatypeCombo.addItem(self.tr('String'), 1)
            self.datatypeCombo.addItem(self.tr('Date/time'), 2)
            self.verticalLayout.addWidget(self.datatypeCombo)

            if self.param is not None and self.param.dataType() is not None:
                # QComboBoxes indexes start at 0,
                # self.param.datatype start with -1 that is why I need to do +1
                datatypeIndex = self.param.dataType() + 1
                self.datatypeCombo.setCurrentIndex(datatypeIndex)

            self.multipleCheck = QCheckBox()
            self.multipleCheck.setText(self.tr('Accept multiple fields'))
            self.multipleCheck.setChecked(False)
            if self.param is not None:
                self.multipleCheck.setChecked(self.param.allowMultiple())
            self.verticalLayout.addWidget(self.multipleCheck)

            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setToolTip(
                self.
                tr('Default field name, or ; separated list of field names for multiple field parameters'
                   ))
            if self.param is not None:
                default = self.param.defaultValue()
                if default is not None:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)

        elif self.paramType == parameters.PARAMETER_BAND or \
                isinstance(self.param, QgsProcessingParameterBand):
            self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
            self.parentCombo = QComboBox()
            idx = 0
            for param in list(self.alg.parameterComponents().values()):
                definition = self.alg.parameterDefinition(
                    param.parameterName())
                if isinstance(definition, (QgsProcessingParameterRasterLayer)):
                    self.parentCombo.addItem(definition.description(),
                                             definition.name())
                    if self.param is not None:
                        if self.param.parentLayerParameterName(
                        ) == definition.name():
                            self.parentCombo.setCurrentIndex(idx)
                    idx += 1
            self.verticalLayout.addWidget(self.parentCombo)
        elif (self.paramType
              in (parameters.PARAMETER_VECTOR, parameters.PARAMETER_TABLE)
              or isinstance(self.param, (QgsProcessingParameterFeatureSource,
                                         QgsProcessingParameterVectorLayer))):
            self.verticalLayout.addWidget(QLabel(self.tr('Geometry type')))
            self.shapetypeCombo = QComboBox()
            self.shapetypeCombo.addItem(self.tr('Geometry Not Required'),
                                        QgsProcessing.TypeVector)
            self.shapetypeCombo.addItem(self.tr('Point'),
                                        QgsProcessing.TypeVectorPoint)
            self.shapetypeCombo.addItem(self.tr('Line'),
                                        QgsProcessing.TypeVectorLine)
            self.shapetypeCombo.addItem(self.tr('Polygon'),
                                        QgsProcessing.TypeVectorPolygon)
            self.shapetypeCombo.addItem(self.tr('Any Geometry Type'),
                                        QgsProcessing.TypeVectorAnyGeometry)
            if self.param is not None:
                self.shapetypeCombo.setCurrentIndex(
                    self.shapetypeCombo.findData(self.param.dataTypes()[0]))
            self.verticalLayout.addWidget(self.shapetypeCombo)
        elif (self.paramType == parameters.PARAMETER_MULTIPLE
              or isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any Map Layer'),
                                       QgsProcessing.TypeMapLayer)
            self.datatypeCombo.addItem(
                self.tr('Vector (No Geometry Required)'),
                QgsProcessing.TypeVector)
            self.datatypeCombo.addItem(self.tr('Vector (Point)'),
                                       QgsProcessing.TypeVectorPoint)
            self.datatypeCombo.addItem(self.tr('Vector (Line)'),
                                       QgsProcessing.TypeVectorLine)
            self.datatypeCombo.addItem(self.tr('Vector (Polygon)'),
                                       QgsProcessing.TypeVectorPolygon)
            self.datatypeCombo.addItem(self.tr('Vector (Any Geometry Type)'),
                                       QgsProcessing.TypeVectorAnyGeometry)
            self.datatypeCombo.addItem(self.tr('Raster'),
                                       QgsProcessing.TypeRaster)
            self.datatypeCombo.addItem(self.tr('File'), QgsProcessing.TypeFile)
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(
                    self.datatypeCombo.findData(self.param.layerType()))
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType == parameters.PARAMETER_MAP_LAYER
              or isinstance(self.param, QgsProcessingParameterMapLayer)):
            self.verticalLayout.addWidget(QLabel(self.tr('Data type')))
            self.datatypeCombo = QComboBox()
            self.datatypeCombo.addItem(self.tr('Any Map Layer'),
                                       QgsProcessing.TypeMapLayer)
            self.datatypeCombo.addItem(self.tr('Vector (Point)'),
                                       QgsProcessing.TypeVectorPoint)
            self.datatypeCombo.addItem(self.tr('Vector (Line)'),
                                       QgsProcessing.TypeVectorLine)
            self.datatypeCombo.addItem(self.tr('Vector (Polygon)'),
                                       QgsProcessing.TypeVectorPolygon)
            self.datatypeCombo.addItem(self.tr('Vector (Any Geometry Type)'),
                                       QgsProcessing.TypeVectorAnyGeometry)
            self.datatypeCombo.addItem(self.tr('Raster'),
                                       QgsProcessing.TypeRaster)
            self.datatypeCombo.addItem(self.tr('Mesh'), QgsProcessing.TypeMesh)
            if self.param is not None:
                self.datatypeCombo.setCurrentIndex(
                    self.datatypeCombo.findData(self.param.dataTypes()[0]))
            self.verticalLayout.addWidget(self.datatypeCombo)
        elif (self.paramType
              in (parameters.PARAMETER_NUMBER, parameters.PARAMETER_DISTANCE,
                  parameters.PARAMETER_SCALE)
              or isinstance(self.param, (QgsProcessingParameterNumber,
                                         QgsProcessingParameterDistance,
                                         QgsProcessingParameterScale))):

            if (self.paramType == parameters.PARAMETER_DISTANCE
                    or isinstance(self.param, QgsProcessingParameterDistance)):
                self.verticalLayout.addWidget(QLabel(self.tr('Linked input')))
                self.parentCombo = QComboBox()
                self.parentCombo.addItem('', '')
                idx = 1
                for param in list(self.alg.parameterComponents().values()):
                    definition = self.alg.parameterDefinition(
                        param.parameterName())
                    if isinstance(definition,
                                  (QgsProcessingParameterFeatureSource,
                                   QgsProcessingParameterVectorLayer,
                                   QgsProcessingParameterMapLayer,
                                   QgsProcessingParameterCrs)):
                        self.parentCombo.addItem(definition.description(),
                                                 definition.name())
                        if self.param is not None:
                            if self.param.parentParameterName(
                            ) == definition.name():
                                self.parentCombo.setCurrentIndex(idx)
                        idx += 1
                self.verticalLayout.addWidget(self.parentCombo)
            elif (self.paramType != parameters.PARAMETER_SCALE
                  and not isinstance(self.param, QgsProcessingParameterScale)):
                self.verticalLayout.addWidget(QLabel(self.tr('Number type')))
                self.type_combo = QComboBox()
                self.type_combo.addItem(self.tr('Float'),
                                        QgsProcessingParameterNumber.Double)
                self.type_combo.addItem(self.tr('Integer'),
                                        QgsProcessingParameterNumber.Integer)
                if self.param:
                    self.type_combo.setCurrentIndex(
                        self.type_combo.findData(self.param.dataType()))
                self.verticalLayout.addWidget(self.type_combo)

            if (self.paramType != parameters.PARAMETER_SCALE and
                    not isinstance(self.param, QgsProcessingParameterScale)):
                self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
                self.minTextBox = QLineEdit()
                self.verticalLayout.addWidget(self.minTextBox)
                self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
                self.maxTextBox = QLineEdit()
                self.verticalLayout.addWidget(self.maxTextBox)
                if self.param is not None:
                    self.minTextBox.setText(str(self.param.minimum()))
                    self.maxTextBox.setText(str(self.param.maximum()))
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultTextBox = QLineEdit()
            self.defaultTextBox.setText(self.tr('0'))
            if self.param is not None:
                default = self.param.defaultValue()
                if self.param.dataType(
                ) == QgsProcessingParameterNumber.Integer:
                    default = int(math.floor(float(default)))
                if default:
                    self.defaultTextBox.setText(str(default))
            self.verticalLayout.addWidget(self.defaultTextBox)

        elif isinstance(self.param, QgsProcessingDestinationParameter):
            self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
            self.defaultWidget = QgsProcessingLayerOutputDestinationWidget(
                self.param, defaultSelection=True)
            self.verticalLayout.addWidget(self.defaultWidget)

        self.verticalLayout.addSpacing(20)
        self.requiredCheck = QCheckBox()
        self.requiredCheck.setText(self.tr('Mandatory'))
        self.requiredCheck.setChecked(True)
        if self.param is not None:
            self.requiredCheck.setChecked(
                not self.param.flags()
                & QgsProcessingParameterDefinition.FlagOptional)
        self.verticalLayout.addWidget(self.requiredCheck)

        self.advancedCheck = QCheckBox()
        self.advancedCheck.setText(self.tr('Advanced'))
        self.advancedCheck.setChecked(False)
        if self.param is not None:
            self.advancedCheck.setChecked(
                self.param.flags()
                & QgsProcessingParameterDefinition.FlagAdvanced)
        self.verticalLayout.addWidget(self.advancedCheck)

        # If child algorithm output is mandatory, disable checkbox
        if isinstance(self.param, QgsProcessingDestinationParameter):
            provider_name, child_name, output_name = self.param.name().split(
                ':')
            child = self.alg.childAlgorithms()['{}:{}'.format(
                provider_name, child_name)]
            model_output = child.modelOutput(output_name)
            param_def = child.algorithm().parameterDefinition(
                model_output.childOutputName())
            if not (param_def.flags()
                    & QgsProcessingParameterDefinition.FlagOptional):
                self.requiredCheck.setEnabled(False)
                self.requiredCheck.setChecked(True)

            self.advancedCheck.setEnabled(False)
            self.advancedCheck.setChecked(False)

        self.verticalLayout.addStretch()

        w = QWidget()
        w.setLayout(self.verticalLayout)
        self.tab.addTab(w, self.tr('Properties'))

        self.commentLayout = QVBoxLayout()
        self.commentEdit = QTextEdit()
        self.commentEdit.setAcceptRichText(False)
        self.commentLayout.addWidget(self.commentEdit, 1)

        hl = QHBoxLayout()
        hl.setContentsMargins(0, 0, 0, 0)
        hl.addWidget(QLabel(self.tr('Color')))
        self.comment_color_button = QgsColorButton()
        self.comment_color_button.setAllowOpacity(True)
        self.comment_color_button.setWindowTitle(self.tr('Comment Color'))
        self.comment_color_button.setShowNull(True, self.tr('Default'))
        hl.addWidget(self.comment_color_button)
        self.commentLayout.addLayout(hl)

        w2 = QWidget()
        w2.setLayout(self.commentLayout)
        self.tab.addTab(w2, self.tr('Comments'))

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.buttonBox.setObjectName('buttonBox')
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.mainLayout.addWidget(self.buttonBox)

        self.setLayout(self.mainLayout)

    def setComments(self, text):
        self.commentEdit.setPlainText(text)

    def comments(self):
        return self.commentEdit.toPlainText()

    def setCommentColor(self, color):
        if color.isValid():
            self.comment_color_button.setColor(color)
        else:
            self.comment_color_button.setToNull()

    def commentColor(self):
        return self.comment_color_button.color(
        ) if not self.comment_color_button.isNull() else QColor()

    def accept(self):
        description = self.nameTextBox.text()
        if description.strip() == '':
            QMessageBox.warning(self, self.tr('Unable to define parameter'),
                                self.tr('Invalid parameter name'))
            return
        if self.param is None:
            validChars = \
                'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
            safeName = ''.join(c for c in description if c in validChars)
            name = safeName.lower()
            i = 2
            while self.alg.parameterDefinition(name):
                name = safeName.lower() + str(i)
                i += 1
        else:
            name = self.param.name()
        if (self.paramType == parameters.PARAMETER_TABLE_FIELD
                or isinstance(self.param, QgsProcessingParameterField)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            datatype = self.datatypeCombo.currentData()
            default = self.defaultTextBox.text()
            if not default:
                default = None
            self.param = QgsProcessingParameterField(
                name,
                description,
                defaultValue=default,
                parentLayerParameterName=parent,
                type=datatype,
                allowMultiple=self.multipleCheck.isChecked())
        elif (self.paramType == parameters.PARAMETER_BAND
              or isinstance(self.param, QgsProcessingParameterBand)):
            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            self.param = QgsProcessingParameterBand(name, description, None,
                                                    parent)
        elif (self.paramType == parameters.PARAMETER_MAP_LAYER
              or isinstance(self.param, QgsProcessingParameterMapLayer)):
            self.param = QgsProcessingParameterMapLayer(
                name, description, types=[self.datatypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_RASTER
              or isinstance(self.param, QgsProcessingParameterRasterLayer)):
            self.param = QgsProcessingParameterRasterLayer(name, description)
        elif (self.paramType == parameters.PARAMETER_TABLE
              or isinstance(self.param, QgsProcessingParameterVectorLayer)):
            self.param = QgsProcessingParameterVectorLayer(
                name, description, [self.shapetypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_VECTOR
              or isinstance(self.param, QgsProcessingParameterFeatureSource)):
            self.param = QgsProcessingParameterFeatureSource(
                name, description, [self.shapetypeCombo.currentData()])
        elif (self.paramType == parameters.PARAMETER_MULTIPLE
              or isinstance(self.param, QgsProcessingParameterMultipleLayers)):
            self.param = QgsProcessingParameterMultipleLayers(
                name, description, self.datatypeCombo.currentData())
        elif (self.paramType == parameters.PARAMETER_DISTANCE
              or isinstance(self.param, QgsProcessingParameterDistance)):
            self.param = QgsProcessingParameterDistance(
                name, description, self.defaultTextBox.text())
            try:
                vmin = self.minTextBox.text().strip()
                if not vmin == '':
                    self.param.setMinimum(float(vmin))
                vmax = self.maxTextBox.text().strip()
                if not vmax == '':
                    self.param.setMaximum(float(vmax))
            except:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return

            if self.parentCombo.currentIndex() < 0:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return
            parent = self.parentCombo.currentData()
            if parent:
                self.param.setParentParameterName(parent)
        elif (self.paramType == parameters.PARAMETER_SCALE
              or isinstance(self.param, QgsProcessingParameterScale)):
            self.param = QgsProcessingParameterScale(
                name, description, self.defaultTextBox.text())
        elif (self.paramType == parameters.PARAMETER_NUMBER
              or isinstance(self.param, QgsProcessingParameterNumber)):

            type = self.type_combo.currentData()
            self.param = QgsProcessingParameterNumber(
                name, description, type, self.defaultTextBox.text())
            try:
                vmin = self.minTextBox.text().strip()
                if not vmin == '':
                    self.param.setMinimum(float(vmin))
                vmax = self.maxTextBox.text().strip()
                if not vmax == '':
                    self.param.setMaximum(float(vmax))
            except:
                QMessageBox.warning(
                    self, self.tr('Unable to define parameter'),
                    self.tr('Wrong or missing parameter values'))
                return

        # Destination parameter
        elif (isinstance(self.param, QgsProcessingParameterFeatureSink)):
            self.param = QgsProcessingParameterFeatureSink(
                name=name,
                description=self.param.description(),
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterFileDestination)):
            self.param = QgsProcessingParameterFileDestination(
                name=name,
                description=self.param.description(),
                fileFilter=self.param.fileFilter(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterFolderDestination)):
            self.param = QgsProcessingParameterFolderDestination(
                name=name,
                description=self.param.description(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterRasterDestination)):
            self.param = QgsProcessingParameterRasterDestination(
                name=name,
                description=self.param.description(),
                defaultValue=self.defaultWidget.value())
        elif (isinstance(self.param, QgsProcessingParameterVectorDestination)):
            self.param = QgsProcessingParameterVectorDestination(
                name=name,
                description=self.param.description(),
                type=self.param.dataType(),
                defaultValue=self.defaultWidget.value())

        else:
            if self.paramType:
                typeId = self.paramType
            else:
                typeId = self.param.type()

            paramTypeDef = QgsApplication.instance().processingRegistry(
            ).parameterType(typeId)
            if not paramTypeDef:
                msg = self.tr(
                    'The parameter `{}` is not registered, are you missing a required plugin?'
                    .format(typeId))
                raise UndefinedParameterException(msg)
            self.param = paramTypeDef.create(name)
            self.param.setDescription(description)
            self.param.setMetadata(paramTypeDef.metadata())

        if not self.requiredCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagOptional)
        else:
            self.param.setFlags(
                self.param.flags()
                & ~QgsProcessingParameterDefinition.FlagOptional)

        if self.advancedCheck.isChecked():
            self.param.setFlags(
                self.param.flags()
                | QgsProcessingParameterDefinition.FlagAdvanced)
        else:
            self.param.setFlags(
                self.param.flags()
                & ~QgsProcessingParameterDefinition.FlagAdvanced)

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.accept(self)

    def reject(self):
        self.param = None

        settings = QgsSettings()
        settings.setValue(
            "/Processing/modelParametersDefinitionDialogGeometry",
            self.saveGeometry())

        QDialog.reject(self)
Пример #4
0
class NetworkLayerDialog(QtWidgets.QDialog, FORM_CLASS):
    
    def __init__(self, parent = None, layerId=None):
        """
            @summary: Class constructor
            @param parent: Class that contains project information
            @type parent: QTranusProject class 
        """
        super(NetworkLayerDialog, self).__init__(parent)
        self.setupUi(self)
        self.project = parent.project
        self.network = Network()
        self.level = None
        self.tempLayerName = ''
        self.tempExpression = ''
        self.layerId = layerId  
        self.labelColor = QLabel("Color") 
        self.buttonColorRamp = QgsColorRampButton(self, 'Color Ramp')
        self.buttonColorRamp.hide()
        self.buttonColor = QgsColorButton(self, 'Color')
        self.buttonColor.hide()
        #self.buttonColorRamp = QgsColorRampButton(self, 'Color Ramp')

        # Linking objects with controls
        self.help = self.findChild(QtWidgets.QPushButton, 'btn_help')
        self.layerName = self.findChild(QtWidgets.QLineEdit, 'layerName')
        self.expression = self.findChild(QtWidgets.QLineEdit, 'expression')
        self.baseScenario = self.findChild(QtWidgets.QComboBox, 'base_scenario')
        self.scenarioOperator = self.findChild(QtWidgets.QComboBox, name='cb_operator')
        self.alternateScenario = self.findChild(QtWidgets.QComboBox, name='cb_alternate_scenario')
        self.variablesList = self.findChild(QtWidgets.QComboBox, name='cb_variables')
        self.method = self.findChild(QtWidgets.QComboBox, name='cb_method')
        self.total = self.findChild(QtWidgets.QRadioButton, 'rbtn_total')
        self.operators = self.findChild(QtWidgets.QRadioButton, 'rbtn_operators')
        self.routes = self.findChild(QtWidgets.QRadioButton, 'rbtn_routes')
        self.list = self.findChild(QtWidgets.QListWidget, 'list')
        self.scenarios = self.findChild(QtWidgets.QTreeView, 'scenarios')
        self.buttonBox = self.findChild(QtWidgets.QDialogButtonBox, 'buttonBox')
        self.progressBar = self.findChild(QtWidgets.QProgressBar, 'progressBar')
        

        # Control Actions
        self.help.clicked.connect(self.open_help)
        self.layerName.keyPressEvent = self.keyPressEvent
        self.expression.keyPressEvent = self.expression_key_press_event
        self.buttonBox.accepted.connect(self.create_layer)
        self.scenarioOperator.currentIndexChanged[int].connect(self.scenario_operator_changed)
        self.baseScenario.currentIndexChanged[int].connect(self.scenario_changed)
        self.variablesList.currentIndexChanged[int].connect(self.variable_changed)
        self.method.currentIndexChanged[int].connect(self.method_changed)
        self.total.clicked.connect(self.total_checked)
        self.operators.clicked.connect(self.operator_checked)
        self.routes.clicked.connect(self.routes_checked)
        self.list.itemDoubleClicked.connect(self.list_item_selected)
        #self.color.clicked.connect(self.color_picker)
        
        # Controls settings
        self.alternateScenario.setEnabled(False)
        
        # Loads combo-box controls
        self.__load_scenario_operators()
        self.__load_scenarios_combobox()
        self.__load_variable_combobox()
        self.__reload_scenarios()

        if self.layerId:
            self.__load_default_data()

    def open_help(self):
        """
            @summary: Opens QTranus users help
        """
        filename = "file:///" + os.path.join(os.path.dirname(os.path.realpath(__file__)) + "/userHelp/", 'network.html')
        webbrowser.open_new_tab(filename)
        
    def keyPressEvent(self, event):
        """
            @summary: Detects when a key is pressed
            @param event: Key press event
            @type event: Event object
        """
        QtWidgets.QLineEdit.keyPressEvent(self.layerName, event)
        if not self.validate_string(event.text()):
            messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Layer Name", "Invalid character: " + event.text() + ".", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            if self.layerName.isUndoAvailable():
                self.layerName.setText(self.tempLayerName)
        else:
            self.tempLayerName = self.layerName.text()

    def method_changed(self, event):
        if self.method.currentText() == "Color":
            self.labelColor.setText("Color Ramp")    
            self.formLayout = self.findChild(QFormLayout, 'formLayout_4')
            self.formLayout.takeAt(10)
            self.buttonColor.hide()
            self.buttonColorRamp.show()
            self.buttonColorRamp.setShowGradientOnly(True)
            self.formLayout.addRow(self.labelColor, self.buttonColorRamp)
        elif self.method.currentText() == "Size":
            self.labelColor.setText("Color")    
            self.formLayout = self.findChild(QFormLayout, 'formLayout_4')
            self.formLayout.takeAt(10)
            self.buttonColorRamp.hide()
            self.buttonColor.show()
            self.formLayout.addRow(self.labelColor, self.buttonColor)
            
    def expression_key_press_event(self, event):
        """
            @summary: Detects when a key is pressed
            @param event: Key press event
            @type event: Event object
        """
        QtWidgets.QLineEdit.keyPressEvent(self.expression, event)
        if not self.invalid_expression_characters(event.text()):
            messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Network Expression", "Invalid character: " + event.text() + ".", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            if self.expression.isUndoAvailable():
                self.expression.setText(self.tempExpression)
        else:
            self.tempExpression = self.expression.text()
    
    def validate_string(self, input):
        """
            @summary: Validates invalid characters
            @param input: Input string
            @type input: String object
            @return: Result of the evaluation
        """
        pattern = re.compile('[\\\/\:\*\?\"\<\>\|]')
        if re.match(pattern, input) is None:
            return True
        else:
            return False

    def invalid_expression_characters(self, input):
        """
            @summary: Validates invalid characters
            @param input: Input string
            @type input: String object
            @return: Result of the evaluation
        """
        pattern = re.compile('[\\\/\:\*\-\<\>\|\=]')
        if re.match(pattern, input) is None:
            return True
        else:
            return False
    
    def __load_scenarios_combobox(self):
        """
            @summary: Loads scenarios combo-box
        """
        self.network.load_network_scenarios(self.project['tranus_folder'])
        items = self.network.get_sorted_scenarios()
        if items is not None:
            self.base_scenario.addItems(items)
    
    def __load_alternate_scenario_combobox(self):
        """
            @summary: Loads alternate scenario combo-box
        """
        baseScenario = self.baseScenario.currentText()
        items = self.network.get_sorted_scenarios()
        for item in items:
            if item != baseScenario:
                self.alternateScenario.addItem(item)
    
    def __load_variable_combobox(self):
        """
            @summary: Loads data to variable combo-box control
        """
        self.project.network_model.load_dictionaries()
        items = self.project.network_model.get_sorted_variables()
        if items is None:
            messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Variables", "There are no variables to load.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print ("There are no variables to load.")
        else:
            self.variablesList.addItems(items)
            
    def scenario_changed(self, newIndex):
        """
            @summary: Detects when an scenario was changed
        """
        if self.scenarioOperator.currentText() != '':
            self.alternateScenario.clear()
            self.__load_alternate_scenario_combobox()

    def variable_changed(self, newIndex):
        """
            @summary: Detects when an scenario was changed
        """
        if self.variablesList.currentText() != '':
            method = HP.method_x_varible(self.variablesList.currentText())
            indexMethod = self.method.findText(method, Qt.MatchFixedString)
            self.method.setCurrentIndex(indexMethod)
    
    def scenario_operator_changed(self):
        """
            @summary: Detects when an operator was changed
        """
        currentOperator = self.scenarioOperator.currentText()
        if self.scenarioOperator.currentText() == '':
            self.alternateScenario.clear()
            self.alternateScenario.setEnabled(False)
        else:
            if len(self.alternateScenario) == 0:
                self.alternateScenario.setEnabled(True)
                self.alternateScenario.clear()
                self.__load_alternate_scenario_combobox()
    
    def __load_scenario_operators(self):
        """
            @summary: Loads operators combo-box
        """
        items = ["", "-"]
        self.scenarioOperator.addItems(items)
        
    def __reload_scenarios(self):
        """
            @summary: Reloads scenarios
        """
        self.scenarios_model = ScenariosModel(self)
        self.scenarios.setModel(self.scenarios_model)
        self.scenarios.setExpanded(self.scenarios_model.indexFromItem(self.scenarios_model.root_item), True)
    
    def total_checked(self):
        """
            @summary: Functionality when user click total radio button
        """
        self.list.clear()
        self.expression.clear()
        self.expression.setEnabled(False)
        self.level = Level.Total
    
    def operator_checked(self):
        """
            @summary: Functionality when user click operator radio button
        """
        if self.operators.isChecked():
            self.list.clear()
            self.expression.clear()
            self.expression.setEnabled(True)
            self.network.load_operators(self.project['tranus_folder'], self.baseScenario.currentText())
            self.level = Level.Operators
            operators = self.network.get_operators_dictionary()
            if operators is not None:
                self.list.addItem("All")
                for key, value in operators.items():
                    self.list.addItem(str(key) + ' - ' + value)
            
    def routes_checked(self):
        """
            @summary: Functionality when user click routes radio button
        """
        if self.routes.isChecked():
            self.list.clear()
            self.expression.clear()
            self.expression.setEnabled(True)
            self.network.load_routes(self.project['tranus_folder'], self.baseScenario.currentText())
            self.level = Level.Routes
            routes = self.network.get_routes_dictionary()
            if routes is not None:
                self.list.addItem("All")

                for key, value in sorted(routes.items()):
                    self.list.addItem(str(key) + ' - ' + value)
        
    def list_item_selected(self, item):
        """
            @summary: Selects item clicked from the list.
            @param item:  Item selected
            @type item: String
        """
        textToAdd = ''
        if item.text() == 'All':
            if self.level == Level.Operators:
                itemsDic = self.network.get_operators_dictionary()
            
            if self.level == Level.Routes:
                itemsDic = self.network.get_routes_dictionary()
            
            if itemsDic is not None:
                for value in itemsDic.values():
                    textToAdd = value if textToAdd.strip() == '' else textToAdd + ' + ' +  value
        else:
            posStrFound = item.text().find(" - ")
            textToAdd = item.text() if posStrFound == -1 else item.text()[posStrFound + 3:] 
            
        if self.expression.text().strip() == '':
            self.expression.setText(self.expression.text() + textToAdd)
        else:
            self.expression.setText(self.expression.text() + " + " + textToAdd)
            
        self.tempExpression = self.expression.text()
    
    def __validate_data(self):
        """
            @summary: Fields validation
            @return: Validation result, matrixExpressionResult and sectorsExpression
        """
        scenariosExpression = []
        
        if self.layerName.text().strip() == '':
            messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Layer Name", "Please write Layer Name.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print ("Please write Layer Name.")
            return False, None, None, None
        
        if self.expression.text().strip() == '' and (self.level is not Level.Total):#self.operators.isChecked() or self.routes.isChecked()):
            messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Expression", "Please write an expression to be evaluated.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print ("Please write an expression to be evaluated.")
            return False, None, None, None
        
        # Base scenario
        if len(self.base_scenario) == 0:
            messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Base Scenario", "There are no Base Scenarios loaded.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print ("There are no Base Scenarios loaded.")
            return False, None, None, None
        else:
            if self.baseScenario.currentText().strip() != '':
                scenariosExpression.append(str(self.baseScenario.currentText()))
            else:
                messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Base Scenario", "Please select a Base Scenario.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
                messagebox.exec_()
                print("Please select a Base Scenario.")
                return False, None, None, None
            
        # Validations for alternate scenario
        if self.scenarioOperator.currentText() != '':
            scenariosExpression.append(str(self.scenarioOperator.currentText()))
            if self.alternateScenario.currentText() == '':
                messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Alternate Scenario", "Please select an Alternate Scenario.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
                messagebox.exec_()
                print("Please select an Alternate Scenario.")
                return False, None, None, None
            else:
                scenariosExpression.append(str(self.alternateScenario.currentText()))
        
        if self.variablesList.currentText() == '':
            messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Variable", "Please select a variable.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print ("Please write an expression to be evaluated.")
            return False, None, None, None
        
        scenariosExpressionResult, scenariosExpressionStack = ExpressionData.validate_scenarios_expression(scenariosExpression)
        
        if scenariosExpressionResult:
            if self.level == Level.Total:
                networkExpressionResult = True
                networkExpressionList = None
            else:
                networkExpressionResult, networkExpressionList = ExpressionData.validate_sectors_expression(self.expression.text().strip())
        
        if self.level is not Level.Total:
            if scenariosExpressionStack.tp > 1 and len(networkExpressionList) > 1:
                messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Expression", "Expression with conditionals only applies for one scenario.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
                messagebox.exec_()
                print("Expression with conditionals only applies for one scenario.")
                return False, None, None, None

        if self.method.currentText()=='Color' and self.buttonColorRamp.isNull():
            messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Color Ramp", "Color Ramp is required.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("Color Ramp is NULL.")
            return False, None, None, None
        elif self.method.currentText()=='Size' and self.buttonColor.isNull():
            messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Color", "Color is required.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("Color is NULL.")
            return False, None, None, None

        return scenariosExpressionResult and networkExpressionResult, scenariosExpressionStack, networkExpressionList, self.expression.text()
      

    def create_layer(self):
        """
            @summary: Method that creates new network layer.
            @return: Result of the process
        """
        validationResult, scenariosExpression, networkExpression, expressionNetworkText = self.__validate_data()

        if validationResult:
            self.progressBar.show()
            self.progressBar.setValue(10)
            if self.method.currentText()=="Size":
                color = self.buttonColor.color()
                color = color.rgb()
            elif self.method.currentText()=="Color":
                color = self.buttonColorRamp.colorRamp()
                color = color.properties()

            # Set Custom Project Variable to save Project path
            projectPath = self.project.network_link_shape_path[0:max(self.project.network_link_shape_path.rfind('\\'), self.project.network_link_shape_path.rfind('/'))]
            tranus_dictionary = dict(project_qtranus_folder=projectPath, project_qtranus_network_shape=self.project.network_link_shape_path)
            self.project.custom_variables_dict.update(tranus_dictionary)
            QgsProject.instance().setCustomVariables(self.project.custom_variables_dict)

            if not self.layerId: 
                result = self.network.addNetworkLayer(self.progressBar, self.layerName.text(), scenariosExpression, networkExpression, self.variablesList.currentText(), self.level, self.project['tranus_folder'], self.project.get_layers_group(), self.project.network_link_shape_path, self.method.currentText(), expressionNetworkText, color)
            else:
                result = self.network.editNetworkLayer(self.progressBar, self.layerName.text(), scenariosExpression, networkExpression, self.variablesList.currentText(), self.level, self.project['tranus_folder'], self.project.get_layers_group(), self.project.network_link_shape_path, self.method.currentText(), self.layerId, expressionNetworkText, color)
            
            if not result:
                messagebox = QTranusMessageBox.set_new_message_box(QtWidgets.QMessageBox.Warning, "Network", "Could not create network layer.", ":/plugins/QTranus/icon.png", self, buttons = QtWidgets.QMessageBox.Ok)
                messagebox.exec_()
                self.project['network_links_shape_file_path'] = ''
                self.project['network_links_shape_id'] = ''

            self.accept()
        else:
            print("New network layer was not created.")
        #print("Color Ramp {} ".format(self.buttonColorRamp.colorRampName()))
        return True

    # Load data to edit the zones layer
    def __load_default_data(self):
        projectPath = self.project.shape[0:max(self.project.shape.rfind('\\'), self.project.shape.rfind('/'))]
        
        # Get data from XML File with the parameters
        expression, field, name, scenario, fieldName, method, level, color = FileM.find_layer_data(projectPath, self.layerId)
        
        self.layerName.setText(name)
        
        if level == "1":
            self.total.click()
            self.rbtn_total.setChecked(True)
        elif level == "2":
            self.rbtn_operators.setChecked(True)
            self.operators.click()
        elif level == "3":
            self.rbtn_routes.setChecked(True)
            self.routes.click()
        
        self.expression.setText(expression)
        
        scenario = scenario.split(",")
        scenario[0] = scenario[0].replace("'", "").replace("[", "").replace("]", "")

        indexBaseScenario = self.base_scenario.findText(scenario[0], Qt.MatchFixedString)
        self.base_scenario.setCurrentIndex(indexBaseScenario)

        indexVariable = self.variablesList.findText(field, Qt.MatchFixedString)
        self.variablesList.setCurrentIndex(indexVariable)

        indexMethod = self.method.findText(method, Qt.MatchFixedString)
        self.method.setCurrentIndex(indexMethod)

        if method == 'Size':
            qcolor = QColor()
            qcolor.setRgb(int(color))
            self.buttonColor.setColor(qcolor)
            
        if method == 'Color':
            color = literal_eval(color)
            arrColor1 = color['color1'].split(",")
            arrColor2 = color['color2'].split(",")
            arrColor1 = list(map(lambda x:int(x),arrColor1))
            arrColor2 = list(map(lambda x:int(x),arrColor2))

            qcolor1 = QColor(arrColor1[0], arrColor1[1], arrColor1[2])
            qcolor2 = QColor(arrColor2[0], arrColor2[1], arrColor2[2])

            qColorRamp = QgsGradientColorRamp()
            qColorRamp.setColor1(qcolor1)
            qColorRamp.setColor2(qcolor2)
            self.buttonColorRamp.setColorRamp(qColorRamp)

        if len(scenario) == 3:           
            scenario[2] = scenario[2].replace("'", "").replace("]", "").strip()
            indexOperators = self.scenarioOperator.findText(scenario[2] , Qt.MatchFixedString)
            self.scenarioOperator.setCurrentIndex(indexOperators)
            
            scenario[1] = scenario[1].replace("'", "").strip()
            indexAlternateScenario = self.alternateScenario.findText(scenario[1], Qt.MatchFixedString)
            self.alternateScenario.setCurrentIndex(indexAlternateScenario)
Пример #5
0
class MatrixLayerDialog(QtWidgets.QDialog, FORM_CLASS):
    def __init__(self, parent=None, layerId=None):
        super(MatrixLayerDialog, self).__init__(parent)
        self.setupUi(self)

        self.project = parent.project
        self.proj = QgsProject.instance()
        self.tempLayerName = ''
        self.layerId = layerId
        self.labelColor = QLabel("Color")
        self.buttonColorRamp = QgsColorRampButton(self, 'Color Ramp')
        self.buttonColorRamp.hide()
        self.buttonColor = QgsColorButton(self, 'Color')
        self.buttonColor.hide()

        # Linking objects with controls
        self.help = self.findChild(QtWidgets.QPushButton, 'btn_help')
        self.layerName = self.findChild(QtWidgets.QLineEdit, 'layerName')
        self.expression = self.findChild(QtWidgets.QLineEdit, 'expression')
        self.baseScenario = self.findChild(QtWidgets.QComboBox,
                                           'base_scenario')
        self.operators = self.findChild(QtWidgets.QComboBox,
                                        name='cb_operator')
        self.alternateScenario = self.findChild(QtWidgets.QComboBox,
                                                name='cb_alternate_scenario')
        self.method = self.findChild(QtWidgets.QComboBox, name='cb_method')
        self.originList = self.findChild(QtWidgets.QListWidget,
                                         name='lw_origin')
        self.originList.setSelectionMode(
            QtWidgets.QAbstractItemView.MultiSelection)
        self.destinationList = self.findChild(QtWidgets.QListWidget,
                                              name='lw_destination')
        self.destinationList.setSelectionMode(
            QtWidgets.QAbstractItemView.MultiSelection)
        self.filter = self.findChildren(QtWidgets.QLineEdit, name='filter')
        self.categories = self.findChild(QtWidgets.QListWidget, 'categories')
        self.scenarios = self.findChild(QtWidgets.QTreeView, 'scenarios')
        self.buttonBox = self.findChild(QtWidgets.QDialogButtonBox,
                                        'buttonBox')
        self.progressBar = self.findChild(QtWidgets.QProgressBar,
                                          'progressBar')

        # Control Actions
        self.help.clicked.connect(self.open_help)
        self.layerName.keyPressEvent = self.keyPressEvent
        self.buttonBox.accepted.connect(self.create_layer)
        self.operators.currentIndexChanged[int].connect(self.operator_changed)
        self.baseScenario.currentIndexChanged[int].connect(
            self.scenario_changed)
        self.categories.itemDoubleClicked.connect(self.category_selected)
        self.method.currentIndexChanged[int].connect(self.method_changed)

        # Controls settings
        self.alternateScenario.setEnabled(False)

        # Loads combo-box controls
        self.__load_operators()
        self.__load_scenarios_combobox()
        self.__load_zone_lists()
        self.__load_categories()
        self.__load_centroids()
        self.__reload_scenarios()
        self.method.setCurrentIndex(1)

        if self.layerId:
            self.__load_default_data()

    def open_help(self):
        """
            @summary: Opens QTranus users help
        """
        filename = "file:///" + os.path.join(
            os.path.dirname(os.path.realpath(__file__)) + "/userHelp/",
            'matrix.html')
        webbrowser.open_new_tab(filename)

    def keyPressEvent(self, event):
        """
            @summary: Detects when a key is pressed
            @param event: Key press event
            @type event: Event object
        """
        QtWidgets.QLineEdit.keyPressEvent(self.layerName, event)
        if not self.validate_string(event.text()):
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Layer Name",
                "Invalid character: " + event.text() + ".",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            if self.layerName.isUndoAvailable():
                self.layerName.setText(self.tempLayerName)
        else:
            self.tempLayerName = self.layerName.text()

    # Load data to edit the zones layer
    def __load_default_data(self):
        projectPath = self.project.shape[0:max(self.project.shape.rfind('\\'),
                                               self.project.shape.rfind('/'))]

        # Get data from XML File with the parameters
        expression, field, name, scenario, id_field_name, originZones, destinationZones, method, color = FileM.find_layer_data(
            projectPath, self.layerId)
        print(expression, field, name, scenario, id_field_name, originZones,
              destinationZones, method, color)

        scenario = scenario.split(",")
        scenario[0] = scenario[0].replace("'",
                                          "").replace("[",
                                                      "").replace("]", "")

        self.layerName.setText(name)
        self.expression.setText(expression)

        indexMethod = self.method.findText(method, Qt.MatchFixedString)
        self.method.setCurrentIndex(indexMethod)

        indexBaseScenario = self.base_scenario.findText(
            scenario[0], Qt.MatchFixedString)
        self.base_scenario.setCurrentIndex(indexBaseScenario)

        if len(scenario) == 3:
            scenario[2] = scenario[2].replace("'", "").replace("]", "").strip()
            indexOperators = self.operators.findText(scenario[2],
                                                     Qt.MatchFixedString)
            self.operators.setCurrentIndex(indexOperators)

            scenario[1] = scenario[1].replace("'", "").strip()
            indexAlternateScenario = self.alternateScenario.findText(
                scenario[1], Qt.MatchFixedString)
            self.alternateScenario.setCurrentIndex(indexAlternateScenario)

        originZones = originZones.replace("'", "").replace("[", "").replace(
            "]", "").replace(" ", "")
        originZones = originZones.split(",")

        destinationZones = destinationZones.replace("'", "").replace(
            "[", "").replace("]", "").replace(" ", "")
        destinationZones = destinationZones.split(",")

        for item in originZones:
            selectionOrigin = self.originList.findItems(
                item, Qt.MatchFixedString)
            indexOrigin = self.originList.indexFromItem(selectionOrigin[0])
            self.originList.setCurrentIndex(indexOrigin)

        for item in destinationZones:
            selectionDestination = self.destinationList.findItems(
                item, Qt.MatchFixedString)
            indexDestination = self.destinationList.indexFromItem(
                selectionDestination[0])
            self.destinationList.setCurrentIndex(indexDestination)

        if method == 'Size':
            qcolor = QColor()
            qcolor.setRgb(int(color))
            self.buttonColor.setColor(qcolor)

        if method == 'Color':
            color = literal_eval(color)
            arrColor1 = color['color1'].split(",")
            arrColor2 = color['color2'].split(",")
            arrColor1 = list(map(lambda x: int(x), arrColor1))
            arrColor2 = list(map(lambda x: int(x), arrColor2))

            qcolor1 = QColor(arrColor1[0], arrColor1[1], arrColor1[2])
            qcolor2 = QColor(arrColor2[0], arrColor2[1], arrColor2[2])

            qColorRamp = QgsGradientColorRamp()
            qColorRamp.setColor1(qcolor1)
            qColorRamp.setColor2(qcolor2)
            self.buttonColorRamp.setColorRamp(qColorRamp)

    def method_changed(self, event):
        if self.method.currentText() == "Color":
            self.labelColor.setText("Color Ramp")
            self.formLayout = self.findChild(QFormLayout, 'formLayout_8')
            self.buttonColor.hide()
            self.buttonColorRamp.show()
            self.buttonColorRamp.setShowGradientOnly(True)
            self.formLayout.addRow(self.labelColor, self.buttonColorRamp)
        elif self.method.currentText() == "Size":
            self.labelColor.setText("Color")
            self.formLayout = self.findChild(QFormLayout, 'formLayout_8')
            self.buttonColorRamp.hide()
            self.buttonColor.show()
            self.formLayout.addRow(self.labelColor, self.buttonColor)

    def validate_string(self, input):
        """
            @summary: Validates invalid characters
            @param input: Input string
            @type input: String object
        """
        pattern = re.compile('[\\\/\:\*\?\"\<\>\|]')
        if re.match(pattern, input) is None:
            return True
        else:
            return False

    def __load_scenarios_combobox(self):
        """
            @summary: Loads scenarios combo-box
        """
        items = self.project.map_data.get_sorted_scenarios()
        self.base_scenario.addItems(items)

    def __load_alternate_scenario_combobox(self):
        """
            @summary: Loads alternate scenario combo-box
        """
        baseScenario = self.baseScenario.currentText()
        items = self.project.map_data.get_sorted_scenarios()
        for item in items:
            if item != baseScenario:
                self.alternateScenario.addItem(item)

    def scenario_changed(self, newIndex):
        """
            @summary: Detects when an scenario was changed
        """
        if self.operators.currentText() != '':
            self.alternateScenario.clear()
            self.__load_alternate_scenario_combobox()

    def operator_changed(self):
        """
            @summary: Detects when an operator was changed
        """
        currentOperator = self.operators.currentText()
        if self.operators.currentText() == '':
            self.alternateScenario.clear()
            self.alternateScenario.setEnabled(False)
        else:
            if len(self.alternateScenario) == 0:
                self.alternateScenario.setEnabled(True)
                self.alternateScenario.clear()
                self.__load_alternate_scenario_combobox()

    def __load_operators(self):
        """
            @summary: Loads operators combo-box
        """
        items = ["", "-", "/"]
        self.operators.addItems(items)

    def __reload_scenarios(self):
        """
            @summary: Reloads scenarios
        """
        self.scenarios_model = ScenariosModel(self)
        self.scenarios.setModel(self.scenarios_model)
        self.scenarios.setExpanded(
            self.scenarios_model.indexFromItem(self.scenarios_model.root_item),
            True)

    def __load_zone_lists(self):
        """
            @summary: Loads zones lists
        """
        items = self.project.map_data.get_matrix_zones()
        if items is not None:
            self.originList.addItem("All")
            self.originList.addItems(items)
            self.destinationList.addItem("All")
            self.destinationList.addItems(items)

    def __load_categories(self):
        """
            @summary: Loads categories list
        """
        items = self.project.map_data.get_matrix_categories()
        if items is not None:
            self.categories.addItem("All")
            self.categories.addItems(items)

    def __load_centroids(self):
        """
            @summary: Loads centroids layer
        """
        if not self.project.centroids_file_path is None:
            self.project.load_zones_centroids_data()
        else:
            self.__create_centroids_file()

    def __create_centroids_file(self):
        """
            @summary: Creates centroids file
        """
        self.project.load_zones_centroids()

    def create_layer(self):
        """
            @summary: Creates matrix layer
        """
        validationResult, scenariosExpression, matrixExpression, matrixExpressionText = self.__validate_data(
        )

        if validationResult:
            self.progressBar.show()
            self.progressBar.setValue(20)
            method = self.method.currentText()

            if method == "Size":
                color = self.buttonColor.color()
                color = color.rgb()
            elif method == "Color":
                color = self.buttonColorRamp.colorRamp()
                color = color.properties()

            originZones = []
            destinationZones = []

            allOrigins = next((item
                               for item in self.originList.selectedItems()
                               if item.text() == 'All'), None)
            allDestinations = next(
                (item for item in self.destinationList.selectedItems()
                 if item.text() == 'All'), None)

            if allOrigins is None:
                for item in self.originList.selectedItems():
                    originZones.append(item.text())
            else:
                for index in range(self.originList.count()):
                    if self.originList.item(index).text() != 'All':
                        originZones.append(self.originList.item(index).text())

            if allDestinations is None:
                for item in self.destinationList.selectedItems():
                    destinationZones.append(item.text())
            else:
                for index in range(self.destinationList.count()):
                    if self.destinationList.item(index).text() != 'All':
                        destinationZones.append(
                            self.destinationList.item(index).text())
            method = method.strip()
            if not self.layerId:
                self.project.addMatrixLayer(self.progressBar,
                                            self.layerName.text(),
                                            scenariosExpression, originZones,
                                            destinationZones, matrixExpression,
                                            matrixExpressionText, method,
                                            color)
            else:
                self.project.editMatrixLayer(self.progressBar,
                                             self.layerName.text(),
                                             scenariosExpression, originZones,
                                             destinationZones,
                                             matrixExpression,
                                             matrixExpressionText, method,
                                             color, self.layerId)

            self.accept()
        else:
            #QMessageBox.critical(None, "New Layer", "New layer was not created.")
            print("New matrix layer was not created.")

    def category_selected(self, item):
        """
            @summary: Detects when an item in the list is double clicked
            @param item: Item selected
            @type item: QListWidget item 
        """

        textToAdd = ''
        if item.text() == 'All':
            for index in range(1, self.categories.count()):
                textToAdd = self.categories.item(
                    index).text() if textToAdd.strip(
                    ) == '' else textToAdd + ' + ' + self.categories.item(
                        index).text()
        else:
            textToAdd = item.text()

        if self.expression.text().strip() == '':
            self.expression.setText(self.expression.text() + textToAdd)
        else:
            self.expression.setText(self.expression.text() + " + " + textToAdd)

    def __validate_matrix_scenario(self, scenario):
        """
            @summary: Validates the format of the file
            @param scenario: Scenario Id
            @type scenario: String
        """
        if len(self.project.map_data.trip_matrices) > 0:
            for trip in self.project.map_data.trip_matrices:
                if trip.Id == scenario:
                    if len(trip.tripMatrix.dtype) != 7:
                        messagebox = QTranusMessageBox.set_new_message_box(
                            QtWidgets.QMessageBox.Warning,
                            "Matrix Scenario",
                            "Scenario " + scenario +
                            ", has an incorrect format.",
                            ":/plugins/QTranus/icon.png",
                            self,
                            buttons=QtWidgets.QMessageBox.Ok)
                        messagebox.exec_()
                        print("Scenario {0}, has an incorrect format.").format(
                            scenario)
                        return False
                    else:
                        return True
        else:
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Matrix Scenario",
                "There are not scenarios information.",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("Matrix Scenario", "There are not scenarios information.")
            return False

    def __validate_data(self):
        """
            @summary: Fields validation
            @return: Validation result, matrixExpressionResult and sectorsExpression
        """
        scenariosExpression = []

        if self.layerName.text().strip() == '':
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Layer Name",
                "Please write Layer Name.",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("Please write Layer Name.")
            return False, None, None, None

        if self.expression.text().strip() == '':
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Expression",
                "Please write an expression to be evaluated.",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("Please write an expression to be evaluated.")
            return False, None, None, None

        projectPath = self.project.shape[0:max(self.project.shape.rfind('\\'),
                                               self.project.shape.rfind('/'))]

        if len(self.base_scenario) == 0:
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Base Scenario",
                "There are no Base Scenarios loaded.",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("There are no Base Scenarios loaded.")
            return False, None, None, None
        else:
            if self.project.load_map_trip_structure(
                    projectPath, self.baseScenario.currentText()):
                if self.__validate_matrix_scenario(
                        self.baseScenario.currentText()) == False:
                    return False, None, None
                scenariosExpression.append(str(
                    self.baseScenario.currentText()))
            else:
                messagebox = QTranusMessageBox.set_new_message_box(
                    QtWidgets.QMessageBox.Warning,
                    "Base Scenario",
                    "Selected Base Scenario has no information.",
                    ":/plugins/QTranus/icon.png",
                    self,
                    buttons=QtWidgets.QMessageBox.Ok)
                messagebox.exec_()
                print("Selected Base Scenario has no information.")
                return False, None, None, None

        # Validations for alternate scenario
        if self.operators.currentText() != '':
            scenariosExpression.append(str(self.operators.currentText()))
            if self.alternateScenario.currentText() == '':
                messagebox = QTranusMessageBox.set_new_message_box(
                    QtWidgets.QMessageBox.Warning,
                    "Alternate Scenario",
                    "Please select an Alternate Scenario.",
                    ":/plugins/QTranus/icon.png",
                    self,
                    buttons=QtWidgets.QMessageBox.Ok)
                messagebox.exec_()
                print("Please select an Alternate Scenario.")
                return False, None, None, None
            else:
                if self.project.load_map_trip_structure(
                        projectPath, self.alternateScenario.currentText()):
                    if self.__validate_matrix_scenario(
                            self.alternateScenario.currentText()) == False:
                        return False, None, None, None
                    scenariosExpression.append(
                        str(self.alternateScenario.currentText()))
                else:
                    messagebox = QTranusMessageBox.set_new_message_box(
                        QtWidgets.QMessageBox.Warning,
                        "Alternate Scenario",
                        "Selected Alternate Scenario has no information.",
                        ":/plugins/QTranus/icon.png",
                        self,
                        buttons=QtWidgets.QMessageBox.Ok)
                    messagebox.exec_()
                    print("Selected Alternate Scenario has no information.")
                    return False, None, None, None

        originSelectedCounter = len(self.originList.selectedItems())
        destinationSelectedCounter = len(self.destinationList.selectedItems())
        if originSelectedCounter == 0:
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Origin Zones",
                "Please select at least one origin zone.",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("Please select at least one origin zone.")
            return False, None, None, None

        if destinationSelectedCounter == 0:
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Destination Zones",
                "Please select at least one destination zone.",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("Please select at least one destination zone.")
            return False, None, None, None

        if originSelectedCounter == 1 and destinationSelectedCounter == 1:
            if self.originList.selectedItems()[0].text(
            ) == self.destinationList.selectedItems()[0].text():
                if self.originList.selectedItems()[0].text() != "All":
                    messagebox = QTranusMessageBox.set_new_message_box(
                        QtWidgets.QMessageBox.Warning,
                        "Zones",
                        "You must select different origin and destination.",
                        ":/plugins/QTranus/icon.png",
                        self,
                        buttons=QtWidgets.QMessageBox.Ok)
                    messagebox.exec_()
                    print("You must select different origin and destination.")
                    return False, None, None, None

        scenariosExpressionResult, scenariosExpressionStack = ExpressionData.validate_scenarios_expression(
            scenariosExpression)

        if scenariosExpressionResult:
            matrixExpressionResult, matrixExpressionList = ExpressionData.validate_sectors_expression(
                self.expression.text().strip())

        if scenariosExpressionStack.tp > 1 and len(matrixExpressionList) > 1:
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Expression",
                "Expression with conditionals only applies for one scenario.",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print(
                "Expression with conditionals only applies for one scenario.")
            return False, None, None, None

        if self.method.currentText(
        ) == 'Color' and self.buttonColorRamp.isNull():
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Color Ramp",
                "Color Ramp is required.",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("Color Ramp is NULL.")
            return False, None, None, None

        elif self.method.currentText() == 'Size' and self.buttonColor.isNull():
            messagebox = QTranusMessageBox.set_new_message_box(
                QtWidgets.QMessageBox.Warning,
                "Color",
                "Color is required.",
                ":/plugins/QTranus/icon.png",
                self,
                buttons=QtWidgets.QMessageBox.Ok)
            messagebox.exec_()
            print("Color is NULL.")
            return False, None, None, None

        return scenariosExpressionResult and matrixExpressionResult, scenariosExpressionStack, matrixExpressionList, self.expression.text(
        )