ModelerGraphicItem.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. """
  2. ***************************************************************************
  3. ModelerGraphicItem.py
  4. ---------------------
  5. Date : August 2012
  6. Copyright : (C) 2012 by Victor Olaya
  7. Email : volayaf at gmail dot com
  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__ = 'Victor Olaya'
  18. __date__ = 'August 2012'
  19. __copyright__ = '(C) 2012, Victor Olaya'
  20. from qgis.PyQt.QtCore import QCoreApplication
  21. from qgis.core import (QgsProcessingParameterDefinition,
  22. QgsProcessingModelOutput,
  23. QgsProcessingModelAlgorithm,
  24. QgsProject,
  25. Qgis)
  26. from qgis.gui import (
  27. QgsProcessingParameterDefinitionDialog,
  28. QgsProcessingParameterWidgetContext,
  29. QgsModelParameterGraphicItem,
  30. QgsModelChildAlgorithmGraphicItem,
  31. QgsModelOutputGraphicItem,
  32. QgsProcessingContextGenerator
  33. )
  34. from processing.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog
  35. from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
  36. from processing.tools.dataobjects import createContext
  37. from qgis.utils import iface
  38. class ModelerInputGraphicItem(QgsModelParameterGraphicItem):
  39. """
  40. IMPORTANT! This is intentionally a MINIMAL class, only containing code which HAS TO BE HERE
  41. because it contains Python code for compatibility with deprecated methods ONLY.
  42. Don't add anything here -- edit the c++ base class instead!
  43. """
  44. def __init__(self, element, model):
  45. super().__init__(element, model, None)
  46. self.processing_context = createContext()
  47. class ContextGenerator(QgsProcessingContextGenerator):
  48. def __init__(self, context):
  49. super().__init__()
  50. self.processing_context = context
  51. def processingContext(self):
  52. return self.processing_context
  53. self.context_generator = ContextGenerator(self.processing_context)
  54. def create_widget_context(self):
  55. """
  56. Returns a new widget context for use in the model editor
  57. """
  58. widget_context = QgsProcessingParameterWidgetContext()
  59. widget_context.setProject(QgsProject.instance())
  60. if iface is not None:
  61. widget_context.setMapCanvas(iface.mapCanvas())
  62. widget_context.setActiveLayer(iface.activeLayer())
  63. widget_context.setModel(self.model())
  64. return widget_context
  65. def edit(self, edit_comment=False):
  66. existing_param = self.model().parameterDefinition(self.component().parameterName())
  67. old_name = existing_param.name()
  68. old_description = existing_param.description()
  69. comment = self.component().comment().description()
  70. comment_color = self.component().comment().color()
  71. new_param = None
  72. if ModelerParameterDefinitionDialog.use_legacy_dialog(param=existing_param):
  73. # boo, old api
  74. dlg = ModelerParameterDefinitionDialog(self.model(),
  75. param=existing_param)
  76. dlg.setComments(comment)
  77. dlg.setCommentColor(comment_color)
  78. if edit_comment:
  79. dlg.switchToCommentTab()
  80. if dlg.exec_():
  81. new_param = dlg.param
  82. comment = dlg.comments()
  83. comment_color = dlg.commentColor()
  84. else:
  85. # yay, use new API!
  86. context = createContext()
  87. widget_context = self.create_widget_context()
  88. dlg = QgsProcessingParameterDefinitionDialog(type=existing_param.type(),
  89. context=context,
  90. widgetContext=widget_context,
  91. definition=existing_param,
  92. algorithm=self.model())
  93. dlg.setComments(comment)
  94. dlg.setCommentColor(comment_color)
  95. dlg.registerProcessingContextGenerator(self.context_generator)
  96. if edit_comment:
  97. dlg.switchToCommentTab()
  98. if dlg.exec_():
  99. new_param = dlg.createParameter(existing_param.name())
  100. comment = dlg.comments()
  101. comment_color = dlg.commentColor()
  102. safeName = QgsProcessingModelAlgorithm.safeName(new_param.description())
  103. new_param.setName(safeName.lower())
  104. if new_param is not None:
  105. self.aboutToChange.emit(self.tr('Edit {}').format(new_param.description()))
  106. self.model().removeModelParameter(self.component().parameterName())
  107. if new_param.description() != old_description:
  108. # only update name if user has changed the description -- we don't force this, as it may cause
  109. # unwanted name updates which could potentially break the model's API
  110. name = new_param.name()
  111. base_name = name
  112. i = 2
  113. while self.model().parameterDefinition(name):
  114. name = base_name + str(i)
  115. i += 1
  116. new_param.setName(name)
  117. self.model().changeParameterName(old_name, new_param.name())
  118. self.component().setParameterName(new_param.name())
  119. self.component().setDescription(new_param.name())
  120. self.component().comment().setDescription(comment)
  121. self.component().comment().setColor(comment_color)
  122. self.model().addModelParameter(new_param, self.component())
  123. self.setLabel(new_param.description())
  124. self.requestModelRepaint.emit()
  125. self.changed.emit()
  126. def editComponent(self):
  127. self.edit()
  128. def editComment(self):
  129. self.edit(edit_comment=True)
  130. class ModelerChildAlgorithmGraphicItem(QgsModelChildAlgorithmGraphicItem):
  131. """
  132. IMPORTANT! This is intentionally a MINIMAL class, only containing code which HAS TO BE HERE
  133. because it contains Python code for compatibility with deprecated methods ONLY.
  134. Don't add anything here -- edit the c++ base class instead!
  135. """
  136. def __init__(self, element, model):
  137. super().__init__(element, model, None)
  138. def edit(self, edit_comment=False):
  139. elemAlg = self.component().algorithm()
  140. dlg = ModelerParametersDialog(elemAlg, self.model(), self.component().childId(),
  141. self.component().configuration())
  142. dlg.setComments(self.component().comment().description())
  143. dlg.setCommentColor(self.component().comment().color())
  144. if edit_comment:
  145. dlg.switchToCommentTab()
  146. if dlg.exec_():
  147. alg = dlg.createAlgorithm()
  148. alg.setChildId(self.component().childId())
  149. alg.copyNonDefinitionPropertiesFromModel(self.model())
  150. self.aboutToChange.emit(self.tr('Edit {}').format(alg.description()))
  151. self.model().setChildAlgorithm(alg)
  152. self.requestModelRepaint.emit()
  153. self.changed.emit()
  154. res, errors = self.model().validateChildAlgorithm(alg.childId())
  155. if not res:
  156. self.scene().showWarning(
  157. QCoreApplication.translate('ModelerGraphicItem', 'Algorithm “{}” is invalid').format(alg.description()),
  158. self.tr('Algorithm is Invalid'),
  159. QCoreApplication.translate('ModelerGraphicItem', "<p>The “{}” algorithm is invalid, because:</p><ul><li>{}</li></ul>").format(alg.description(), '</li><li>'.join(errors)),
  160. level=Qgis.Warning
  161. )
  162. else:
  163. self.scene().messageBar().clearWidgets()
  164. def editComponent(self):
  165. self.edit()
  166. def editComment(self):
  167. self.edit(edit_comment=True)
  168. class ModelerOutputGraphicItem(QgsModelOutputGraphicItem):
  169. """
  170. IMPORTANT! This is intentionally a MINIMAL class, only containing code which HAS TO BE HERE
  171. because it contains Python code for compatibility with deprecated methods ONLY.
  172. Don't add anything here -- edit the c++ base class instead!
  173. """
  174. def __init__(self, element, model):
  175. super().__init__(element, model, None)
  176. def edit(self, edit_comment=False):
  177. child_alg = self.model().childAlgorithm(self.component().childId())
  178. dlg = ModelerParameterDefinitionDialog(self.model(),
  179. param=self.model().modelParameterFromChildIdAndOutputName(self.component().childId(), self.component().name()))
  180. dlg.setComments(self.component().comment().description())
  181. dlg.setCommentColor(self.component().comment().color())
  182. if edit_comment:
  183. dlg.switchToCommentTab()
  184. if dlg.exec_():
  185. model_outputs = child_alg.modelOutputs()
  186. model_output = QgsProcessingModelOutput(model_outputs[self.component().name()])
  187. del model_outputs[self.component().name()]
  188. model_output.setName(dlg.param.description())
  189. model_output.setDescription(dlg.param.description())
  190. model_output.setDefaultValue(dlg.param.defaultValue())
  191. model_output.setMandatory(not (dlg.param.flags() & QgsProcessingParameterDefinition.FlagOptional))
  192. model_output.comment().setDescription(dlg.comments())
  193. model_output.comment().setColor(dlg.commentColor())
  194. model_outputs[model_output.name()] = model_output
  195. child_alg.setModelOutputs(model_outputs)
  196. self.aboutToChange.emit(self.tr('Edit {}').format(model_output.description()))
  197. self.model().updateDestinationParameters()
  198. self.requestModelRepaint.emit()
  199. self.changed.emit()
  200. def editComponent(self):
  201. self.edit()
  202. def editComment(self):
  203. self.edit(edit_comment=True)