1# -*- coding: utf-8 -*- 2""" 3*************************************************************************** 4 OtbChoiceWidget.py 5 ------------------ 6 Date : June 2017 7 Copyright : (C) 2017 by CS Systemes d'Information (CS SI) 8 Email : rashad dot kanavath at c-s fr 9 10*************************************************************************** 11* * 12* This program is free software; you can redistribute it and/or modify * 13* it under the terms of the GNU General Public License as published by * 14* the Free Software Foundation; either version 2 of the License, or * 15* (at your option) any later version. * 16* * 17*************************************************************************** 18""" 19 20__author__ = 'Rashad Kanavath' 21__date__ = 'June 2017' 22__copyright__ = "(C) 2017,2018 by CS Systemes d'information (CS SI)" 23 24from qgis.PyQt.QtWidgets import QComboBox 25from qgis.core import (QgsProcessingParameterString, 26 QgsProcessingOutputString, 27 QgsProcessingParameterDefinition) 28from qgis.gui import QgsProcessingModelerParameterWidget 29from processing.gui.wrappers import (WidgetWrapper, 30 DIALOG_STANDARD, 31 DIALOG_BATCH, 32 DIALOG_MODELER) 33 34 35# TODO: QGIS 3.8 move this class to processing/gui/ 36# OtbChoiceWidget is a crucial parameter type in otb provider 37# It is the one that can handles required parameters are run-time depending on user input!. 38# This idea is indeed different from static list of required/optional parameters from a descriptor file. 39# So this class (if treated as first class citizen in processing/gui) have potential 40# to be reused in existing or future processing providers. 41 42 43class OtbChoiceWidgetWrapper(WidgetWrapper): 44 45 def __init__(self, param, dialog, row=0, col=0, **kwargs): 46 self.flagsModified = {} 47 super().__init__(param, dialog, row=0, col=0, **kwargs) 48 self.updateAllParameters(None) 49 50 def createWidget(self): 51 widget = QComboBox() 52 widget.addItems(self.param.options) 53 if self.dialogType in (DIALOG_MODELER, DIALOG_STANDARD): 54 widget.currentIndexChanged.connect(self.updateAllParameters) 55 return widget 56 57 def get_algorithm(self): 58 if self.dialogType == DIALOG_MODELER: 59 return self.dialog._alg 60 else: 61 return self.dialog.algorithm() 62 63 def __updateWrapper(self, name, visible): 64 if self.dialogType == DIALOG_BATCH: 65 return 66 elif self.dialogType == DIALOG_STANDARD: 67 if self.dialog.mainWidget() is None: 68 return 69 if name in self.dialog.mainWidget().wrappers: 70 self.__setWrapperVisibility(self.dialog.mainWidget().wrappers[name], visible) 71 72 # For QGIS modeler 73 else: 74 try: 75 if name in self.dialog.widget.widget.wrappers: 76 self.__setWrapperVisibility(self.dialog.widget.widget.wrappers[name], visible) 77 if name in self.dialog.widget.widget.widget_labels: 78 self.dialog.widget.widget.widget_labels[name].setVisible(visible) 79 except AttributeError: 80 pass 81 82 def __setWrapperVisibility(self, wrapper, v): 83 # For compatibility with 3.x API, we need to check whether the wrapper is 84 # the deprecated WidgetWrapper class. If not, it's the newer 85 # QgsAbstractProcessingParameterWidgetWrapper class 86 # TODO QGIS 4.0 - remove is_python_wrapper logic 87 if issubclass(wrapper.__class__, WidgetWrapper): 88 wrapper.widget.setVisible(v) 89 if wrapper.label: 90 wrapper.label.setVisible(v) 91 elif issubclass(wrapper.__class__, QgsProcessingModelerParameterWidget): 92 wrapper.setVisible(v) 93 else: 94 wrapper.wrappedWidget().setVisible(v) 95 if wrapper.wrappedLabel(): 96 wrapper.wrappedLabel().setVisible(v) 97 98 def updateAllParameters(self, current_value): 99 for parameter in self.get_algorithm().parameterDefinitions(): 100 if 'group_key' not in parameter.metadata() or parameter.metadata()['group_key'] != self.param.name(): 101 continue 102 name = parameter.name() 103 choice_key = parameter.metadata()['group_key'] 104 if choice_key and choice_key + "." in name: 105 choice_param = self.get_algorithm().parameterDefinition(choice_key) 106 if current_value is None: 107 current_value = choice_param.defaultValue() 108 pattern = "{}.{}.".format(choice_key, choice_param.getValueAsText(current_value)) 109 if pattern not in name: 110 flags = self.get_algorithm().parameterDefinition(name).flags() 111 if not flags & QgsProcessingParameterDefinition.FlagOptional: 112 self.flagsModified[name] = True 113 self.get_algorithm().parameterDefinition(name).setFlags(QgsProcessingParameterDefinition.FlagOptional) 114 self.__updateWrapper(name, False) 115 else: 116 if name in self.flagsModified.keys(): 117 self.get_algorithm().parameterDefinition(name).setFlags(QgsProcessingParameterDefinition.FlagAdvanced) 118 self.__updateWrapper(name, True) 119 120 def setValue(self, value): 121 if value in self.param.options: 122 index = self.param.options.index(value) 123 else: 124 index = int(value) 125 self.widget.setCurrentIndex(index) 126 127 def value(self): 128 return self.widget.currentText() 129 130 def postInitialize(self, wrappers): 131 # if self.dialogType == DIALOG_BATCH: 132 # return 133 self.updateAllParameters(current_value=None) 134 for parameter in self.get_algorithm().parameterDefinitions(): 135 if 'group_key' not in parameter.metadata() or parameter.metadata()['group_key'] != self.param.name(): 136 continue 137 for wrapper in wrappers: 138 if wrapper.param.name() == parameter.name(): 139 v = self.value() == parameter.metadata()['group_value'] 140 self.__setWrapperVisibility(wrapper, v) 141 142 143from qgis.core import QgsProcessingParameterDefinition 144 145 146class OtbParameterChoice(QgsProcessingParameterDefinition): 147 148 def __init__(self, name='', description='', options=[], default=None, isSource=False, 149 multiple=False, optional=False): 150 151 QgsProcessingParameterDefinition.__init__(self, name, description, default, optional) 152 153 self.setMetadata({ 154 'widget_wrapper': { 155 'class': 'otbprovider.OtbChoiceWidget.OtbChoiceWidgetWrapper'}}) 156 self.options = options 157 158 if default is not None: 159 try: 160 self.default = int(default) 161 except Exception: 162 self.default = 0 163 self.value = self.default 164 165 def getValueAsText(self, value): 166 if value not in self.options: 167 value = self.options[int(value)] 168 return value 169 170 def setValue(self, value): 171 if value is None: 172 self.value = 0 173 else: 174 self.value = int(value) 175 return True 176 177 def type(self): 178 # This value is written by otbQgisDescriptor. 179 return 'OTBParameterChoice' 180