OtbChoiceWidget.py 7.6 KB

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