ctkWorkflow_p.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. #ifndef __ctkWorkflow_p_h
  15. #define __ctkWorkflow_p_h
  16. // Qt includes
  17. #include <QObject>
  18. #include <QString>
  19. #include <QList>
  20. #include <QMap>
  21. // CTK includes
  22. #include "ctkWorkflow.h"
  23. #include "ctkWorkflowTransitions.h"
  24. class QStateMachine;
  25. class ctkWorkflowStep;
  26. //class ctkWorkflow;
  27. //enum ctkWorkflow::TransitionDirectionality;
  28. //-----------------------------------------------------------------------------
  29. /**
  30. * \ingroup Core
  31. */
  32. struct forwardAndBackwardSteps
  33. {
  34. QList<ctkWorkflowStep*> forwardSteps()
  35. {
  36. return this->ForwardSteps;
  37. }
  38. QList<ctkWorkflowStep*> backwardSteps()
  39. {
  40. return this->BackwardSteps;
  41. }
  42. QList<QString> forwardBranchIds()
  43. {
  44. return this->ForwardBranchIds;
  45. }
  46. QList<QString> backwardBranchIds()
  47. {
  48. return this->BackwardBranchIds;
  49. }
  50. void appendForwardStep(ctkWorkflowStep* step, QString id)
  51. {
  52. this->ForwardSteps.append(step);
  53. this->ForwardBranchIds.append(id);
  54. }
  55. void appendBackwardStep(ctkWorkflowStep* step, QString id)
  56. {
  57. this->BackwardSteps.append(step);
  58. this->BackwardBranchIds.append(id);
  59. }
  60. QString firstForwardBranchId()
  61. {
  62. if (this->ForwardBranchIds.isEmpty())
  63. {
  64. return QString();
  65. }
  66. else
  67. {
  68. return this->ForwardBranchIds.first();
  69. }
  70. }
  71. ctkWorkflowStep* forwardStep(QString branchId)
  72. {
  73. int index = this->ForwardBranchIds.indexOf(branchId);
  74. if (index != -1)
  75. {
  76. return ForwardSteps.at(index);
  77. }
  78. else
  79. {
  80. return 0;
  81. }
  82. }
  83. QString backwardBranchId(ctkWorkflowStep* step)
  84. {
  85. int index = this->BackwardSteps.indexOf(step);
  86. if (index != -1)
  87. {
  88. return BackwardBranchIds.at(index);
  89. }
  90. else
  91. {
  92. return QString();
  93. }
  94. }
  95. QString forwardBranchId(ctkWorkflowStep* step)
  96. {
  97. int index = this->ForwardSteps.indexOf(step);
  98. if (index != -1)
  99. {
  100. return ForwardBranchIds.at(index);
  101. }
  102. else
  103. {
  104. return QString();
  105. }
  106. }
  107. private:
  108. QList<ctkWorkflowStep*> ForwardSteps;
  109. QList<ctkWorkflowStep*> BackwardSteps;
  110. QList<QString> ForwardBranchIds;
  111. QList<QString> BackwardBranchIds;
  112. };
  113. // --------------------------------------------------------------------------
  114. /**
  115. * \ingroup Core
  116. */
  117. class ctkWorkflowPrivate : public QObject
  118. {
  119. Q_OBJECT
  120. Q_DECLARE_PUBLIC(ctkWorkflow);
  121. protected:
  122. ctkWorkflow* const q_ptr;
  123. public:
  124. ctkWorkflowPrivate(ctkWorkflow& object);
  125. ~ctkWorkflowPrivate();
  126. /// \brief Add a step to the workflow
  127. ///
  128. /// \note The step's components will be automatically be added to the state machine
  129. /// (i.e. the processingState state, validationState state, validationTransition transition
  130. /// and validationFailedtransition transition.
  131. ///
  132. /// \return True or False indicating whether the method was successful.
  133. void addStep(ctkWorkflowStep* step);
  134. /// \brief Returns whether a transition has been previously added with the same origin,
  135. /// destination and directionality
  136. bool hasDuplicateTransition(ctkWorkflowStep* origin, ctkWorkflowStep* destination,
  137. const ctkWorkflow::TransitionDirectionality directionality);
  138. /// \brief Returns whether a transition has been previously added with the same origin and branch
  139. /// id (for forward transitions) or with the same destination and branch id (for backward transitions
  140. bool hasTransitionWithSameBranchId(ctkWorkflowStep* origin, ctkWorkflowStep* destination,
  141. const QString& branchId,
  142. const ctkWorkflow::TransitionDirectionality directionality);
  143. /// \brief Creates a transition from the origin to the destinatio.
  144. ///
  145. /// More specifically, the transition is from the \a origin's validation state to the \a
  146. /// destination's processing state, and is of type ctkWorkflowTransition::TransitionToNextStep
  147. ///
  148. /// The destination step should semantically be a next step, i.e. from a workflow perspective, the
  149. /// \a destination step is meant to appear after the \a origin step.
  150. ///
  151. /// Returns true/false indicating whether the method was successful.
  152. void createTransitionToNextStep(ctkWorkflowStep* origin,
  153. ctkWorkflowStep* destination,
  154. const QString& branchId = "");
  155. /// \brief Creates a transition from the destination to the origin
  156. ///
  157. /// More specifically, the transition is from the \a destination's processing state to the \a
  158. /// origin's processing state, and is of type ctkWorkflowTransition::TransitionToPreviousStep
  159. ///
  160. /// The destination step should semantically be a next step, i.e. from a workflow perspective, the
  161. /// \a destination step is meant to appear after the \a origin step.
  162. ///
  163. /// Returns true/false indicating whether the method was successful.
  164. void createTransitionToPreviousStep(ctkWorkflowStep* origin,
  165. ctkWorkflowStep* destination,
  166. const QString& branchId = "");
  167. /// \brief Creates a transition from the goTo step to the step from which the attempt to go to the
  168. /// goTo step was initiated.
  169. ///
  170. /// More specifically, the transition is from the \a goTo step's processing state to the \a
  171. /// starting step's processing state, and is of type ctkWorkflowTransition::TransitionToPreviousStartingStep
  172. ///
  173. /// Returns true/false indicating whether the method was successful.
  174. void createTransitionToPreviousStartingStep(ctkWorkflowStep* startingStep,
  175. ctkWorkflowStep* currentStep);
  176. ///
  177. void validateInternal(ctkWorkflowStep* step);
  178. /// \brief Performs computation required when entering this step.
  179. ///
  180. /// Does some sanity checks and then either calls onEntry() or emits the invokeOnEntryCommand(),
  181. /// depending on whether the user indicates that there is an onEntryCommand.
  182. void onEntryInternal(ctkWorkflowStep* step, ctkWorkflowStep* comingFrom,
  183. const ctkWorkflowInterstepTransition::InterstepTransitionType& transitionType);
  184. /// \brief Performs computation required when exiting this step.
  185. ///
  186. /// Does some sanity checks and then either calls onExit() or emits the invokeOnExitCommand(),
  187. /// depending on whether the user indicates that there is an onExitCommand.
  188. void onExitInternal(ctkWorkflowStep* step, ctkWorkflowStep* goingTo,
  189. const ctkWorkflowInterstepTransition::InterstepTransitionType& transitionType);
  190. /// Get the step in the workflow with a given id.
  191. ctkWorkflowStep* stepFromId(const QString& id)const;
  192. /// Get the step that a state belongs to (if any)
  193. ctkWorkflowStep* stepFromState(const QAbstractState* state);
  194. /// Get the number of forward steps from the given step
  195. int numberOfForwardSteps(ctkWorkflowStep* step);
  196. /// Get the number of backward steps from the given step
  197. int numberOfBackwardSteps(ctkWorkflowStep* step);
  198. /// Get the ids of the steps that directly follow the given step.
  199. QList<QString> forwardBranchIds(ctkWorkflowStep* step)const;
  200. /// Get the ids of the steps that directly preceed the given step.
  201. QList<QString> backwardBranchIds(ctkWorkflowStep* step)const;
  202. /// Determines whether there exists a path from the origin step (the current step by default) to
  203. /// the step with the given goalId
  204. bool pathExists(const QString& goalId, ctkWorkflowStep* origin = 0)const;
  205. /// Determines whether there exists a path from the current step's next step (as given by the
  206. /// branchId) to the step with the given goalId
  207. bool pathExistsFromNextStep(const QString& goalId, const QString& branchId)const;
  208. public slots:
  209. /// \brief Workflow processing executed after a step's onEntry function is run.
  210. void processingAfterOnEntry();
  211. /// \brief Workflow processing executed after a step's onExit function is run.
  212. void processingAfterOnExit();
  213. public:
  214. QStateMachine* StateMachine;
  215. // Maintain a list of pointers to the steps in the workflow,
  216. // along with their forward and backward transitions
  217. QMap<ctkWorkflowStep*, forwardAndBackwardSteps*> StepToForwardAndBackwardStepMap;
  218. // ... and its associated convenient typedef
  219. typedef QMap<ctkWorkflowStep*, forwardAndBackwardSteps*> StepToForwardAndBackwardStepMapType;
  220. typedef QList<ctkWorkflowStep*> StepListType;
  221. // Maintain a map of <state, step> key/value pairs, to find the step
  222. // that a given state belongs to
  223. typedef QMap<const QAbstractState*, ctkWorkflowStep*> StateToStepMapType;
  224. typedef QMap<const QAbstractState*, ctkWorkflowStep*>::iterator StateToStepMapIterator;
  225. StateToStepMapType StateToStepMap;
  226. ctkWorkflowStep* InitialStep;
  227. ctkWorkflowStep* CurrentStep;
  228. QMap<ctkWorkflowStep*, ctkWorkflowStep*> StepToPreviousStepMap;
  229. // Used when performing a transition
  230. ctkWorkflowStep* OriginStep;
  231. ctkWorkflowStep* DestinationStep;
  232. ctkWorkflowInterstepTransition::InterstepTransitionType TransitionType;
  233. QString DesiredBranchId; // Desired branchId specified when invoking goForward
  234. ctkWorkflowStep* GoToStep; // Desired step when attempting to go to a finish step
  235. ctkWorkflowStep* StartingStep; // Current step when we began the attempt to go to the desired finish step
  236. // Temporary transition after successfully going to finish step, to get us back to the starting step
  237. ctkWorkflowInterstepTransition* TransitionToPreviousStartingStep;
  238. bool GoBackToOriginStepUponSuccess;
  239. QString ARTIFICIAL_BRANCH_ID_PREFIX;
  240. };
  241. #endif