ctkWorkflowWidgetTest2.cpp 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) 2010 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.commontk.org/LICENSE
  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. // QT includes
  15. #include <QApplication>
  16. #include <QTimer>
  17. #include <QPushButton>
  18. #include <QLabel>
  19. #include <QLineEdit>
  20. #include <QList>
  21. // CTK includes
  22. #include "ctkWorkflow.h"
  23. #include "ctkWorkflowWidget.h"
  24. #include "ctkWorkflowStackedWidget.h"
  25. #include "ctkWorkflowTabWidget.h"
  26. #include "ctkWorkflowWidgetStep.h"
  27. #include "ctkExampleWorkflowWidgetStepUsingSignalsAndSlots.h"
  28. // STD includes
  29. #include <cstdlib>
  30. #include <iostream>
  31. //-----------------------------------------------------------------------------
  32. bool buttonClickTest(QApplication& app, int defaultTime, ctkWorkflowWidgetStep* shown, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* shownQObject, ctkWorkflowWidgetStep* hidden, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* hiddenQObject, ctkWorkflow* workflow, ctkWorkflowWidget* workflowWidget, QPushButton* shownBackButton=0, QPushButton* shownNextButton=0, QPushButton* hiddenBackButton=0, QPushButton* hiddenNextButton=0, QPushButton* shownFinishButton=0, QPushButton* hiddenFinishButton = 0, QPushButton* shownFinishButton2=0, QPushButton* hiddenFinishButton2=0)
  33. {
  34. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  35. app.exec();
  36. // // ensure we are in the correct step
  37. if (workflow->currentStep() != shown)
  38. {
  39. std::cerr << "In incorrect step" << std::endl;
  40. return false;
  41. }
  42. // ensure that widgets of current step are visible and enabled
  43. if (!shown->stepArea()->isVisible() || (shownBackButton && !shownBackButton->isVisible()) || (shownNextButton && !shownNextButton->isVisible()) || !shownQObject->label()->isVisible() || !shownQObject->lineEdit()->isVisible() || (shownFinishButton && !shownFinishButton->isVisible()) || (shownFinishButton2 && !shownFinishButton2->isVisible()))
  44. {
  45. std::cerr << "Incorrect widget visibility - the current step's widgets are invisible" << std::endl;
  46. return false;
  47. }
  48. if ((shownBackButton && !shownBackButton->isEnabled()) || (shownNextButton && !shownNextButton->isEnabled()) || !shownQObject->lineEdit()->isEnabled() || (shownFinishButton && !shownFinishButton->isEnabled()) || (shownFinishButton2 && !shownFinishButton2->isEnabled()))
  49. {
  50. std::cerr << "Incorrect widget visibility - the current step's widgets are disabled" << std::endl;
  51. return false;
  52. }
  53. // ensure that the shown step's name and description are shown in
  54. // the widget
  55. if (shown->name() != workflowWidget->title() || shown->description() != workflowWidget->subTitle())
  56. {
  57. std::cerr << "Incorrect widget title/subtitle" << std::endl;
  58. return false;
  59. }
  60. // ensure that widgets of the other step are either invisible, or
  61. // visible but disabled
  62. if (hidden->stepArea())
  63. {
  64. if (hidden->stepArea()->isVisible() && workflowWidget->hideWidgetsOfNonCurrentSteps())
  65. {
  66. std::cerr << "Incorrect widget visibility - the other step's stepArea is showing" << std::endl;
  67. return false;
  68. }
  69. else if (hidden->stepArea()->isVisible() && hidden->stepArea()->isEnabled())
  70. {
  71. std::cerr << "Incorrect widget visibility - the other step's stepArea is enabled" << std::endl;
  72. return false;
  73. }
  74. }
  75. if (hiddenQObject->label())
  76. {
  77. if (hiddenQObject->label()->isVisible() && workflowWidget->hideWidgetsOfNonCurrentSteps())
  78. {
  79. std::cerr << "Incorrect widget visibility - the other step's label is showing" << std::endl;
  80. return false;
  81. }
  82. }
  83. if (hiddenBackButton)
  84. {
  85. if (hiddenBackButton->isVisible() && workflowWidget->hideWidgetsOfNonCurrentSteps())
  86. {
  87. std::cerr << "Incorrect widget visibility - the other step's backButton is showing" << std::endl;
  88. return false;
  89. }
  90. else if (hiddenBackButton->isVisible() && hiddenBackButton->isEnabled())
  91. {
  92. std::cerr << "Incorrect widget visibility - the other step's backButton is enabled" << std::endl;
  93. return false;
  94. }
  95. }
  96. if (hiddenNextButton)
  97. {
  98. if (hiddenNextButton->isVisible() && workflowWidget->hideWidgetsOfNonCurrentSteps())
  99. {
  100. std::cerr << "Incorrect widget visibility - the other step's nextButton is showing" << std::endl;
  101. return false;
  102. }
  103. else if (hiddenNextButton->isVisible() && hiddenNextButton->isEnabled())
  104. {
  105. std::cerr << "Incorrect widget visibility - the other step's nextButton is enabled" << std::endl;
  106. return false;
  107. }
  108. }
  109. if (hiddenQObject->lineEdit())
  110. {
  111. if (hiddenQObject->lineEdit()->isVisible() && workflowWidget->hideWidgetsOfNonCurrentSteps())
  112. {
  113. std::cerr << "Incorrect widget visibility - the other step's lineEdit is showing" << std::endl;
  114. return false;
  115. }
  116. else if (hiddenQObject->lineEdit()->isVisible() && hiddenQObject->lineEdit()->isEnabled())
  117. {
  118. std::cerr << "Incorrect widget visibility - the other step's lineEdit is enabled" << std::endl;
  119. return false;
  120. }
  121. }
  122. if (hiddenFinishButton)
  123. {
  124. if (hiddenFinishButton->isVisible() && workflowWidget->hideWidgetsOfNonCurrentSteps())
  125. {
  126. std::cerr << "Incorrect widget visibility - the other step's finishButton is showing" << std::endl;
  127. return false;
  128. }
  129. else if (hiddenFinishButton->isVisible() && hiddenFinishButton->isEnabled())
  130. {
  131. std::cerr << "Incorrect widget visibility - the other step's finishButton is enabled" << std::endl;
  132. return false;
  133. }
  134. }
  135. if (hiddenFinishButton2)
  136. {
  137. if (hiddenFinishButton2->isVisible() && workflowWidget->hideWidgetsOfNonCurrentSteps())
  138. {
  139. std::cerr << "Incorrect widget visibility - the other step's finishButton is showing" << std::endl;
  140. return false;
  141. }
  142. else if (hiddenFinishButton2->isVisible() && hiddenFinishButton->isEnabled())
  143. {
  144. std::cerr << "Incorrect widget visibility - the other step's finishButton is enabled" << std::endl;
  145. return false;
  146. }
  147. }
  148. return true;
  149. }
  150. //-----------------------------------------------------------------------------
  151. // simulates valid and invalid user interaction for a workflow with
  152. // two steps
  153. int userInteractionSimulator1(QApplication& app, ctkWorkflowWidgetStep* testStep1, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject1, ctkWorkflowWidgetStep* testStep2, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject2, ctkWorkflow* workflow, ctkWorkflowWidget* workflowWidget, int defaultTime)
  154. {
  155. int BACK_BUTTON_INDEX = 0;
  156. int NEXT_BUTTON_INDEX = 1;
  157. // test to ensure we can change the layout of the workflow widget
  158. workflowWidget->setDirection(QBoxLayout::LeftToRight);
  159. // get the buttons
  160. QPushButton* testStep1BackButton = 0;
  161. QPushButton* testStep1NextButton = 0;
  162. QPushButton* testStep2BackButton = 0;
  163. QPushButton* testStep2NextButton = 0;
  164. // get the back/next buttons for the first step
  165. QList<QPushButton*> buttons = testStep1->stepArea()->findChildren<QPushButton*>();
  166. // if (buttons.length() != 1)
  167. // {
  168. // std::cerr << "incorrect number of buttons for testStep1" << std::endl;
  169. // std::cerr << "number of buttons = " << buttons.length() << ", expecting 1" << std::endl;
  170. // return EXIT_FAILURE;
  171. // }
  172. testStep1NextButton = buttons.at(NEXT_BUTTON_INDEX);
  173. if (!testStep1NextButton || testStep1NextButton->text() != "Next")
  174. {
  175. std::cerr << "incorrect button assignment for testStep1" << std::endl;
  176. return EXIT_FAILURE;
  177. }
  178. // we should be in the first step at the start of the workflow
  179. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton)) {return EXIT_FAILURE;}
  180. // tests with good input (lineEdit value = 100, which passes the
  181. // condition that it be >= 10)
  182. // CurrentStep ButtonPress ExpectedStep Shouldn'tDoAnything
  183. // step1 next step2
  184. // step2 back step1
  185. // step1 next step2
  186. // step2 back step1
  187. // normal forwards/backwards transitions
  188. testStep1NextButton->click();
  189. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  190. app.exec();
  191. // get the back/next buttons for the second step
  192. buttons = testStep2->stepArea()->findChildren<QPushButton*>();
  193. // if (buttons.length() != 1)
  194. // {
  195. // std::cerr << "incorrect number of buttons for testStep2" << std::endl;
  196. // std::cerr << "number of buttons = " << buttons.length() << ", expecting 1" << std::endl;
  197. // return EXIT_FAILURE;
  198. // }
  199. testStep2BackButton = buttons.at(BACK_BUTTON_INDEX);
  200. if (!testStep2BackButton || testStep2BackButton->text() != "Back")
  201. {
  202. std::cerr << "incorrect button assignment for testStep2" << std::endl;
  203. return EXIT_FAILURE;
  204. }
  205. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1NextButton)) {return EXIT_FAILURE;}
  206. testStep2BackButton->click();
  207. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton)) {return EXIT_FAILURE;}
  208. testStep1NextButton->click();
  209. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1NextButton)) {return EXIT_FAILURE;}
  210. testStep2BackButton->click();
  211. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton)) {return EXIT_FAILURE;}
  212. // tests with both good and bad input (lineEdit value may be
  213. // invalid)
  214. // CurrentStep ButtonPress Invalid input ExpectedStep
  215. // step1 next * step1
  216. // step1 next step2
  217. // step2 back * step1
  218. // step1 next * (empty) step1
  219. // step1 next step2
  220. std::cout << "HERE" << std::endl;
  221. // ensure transition to the next step fails on bad input
  222. qObject1->lineEdit()->setText("1");
  223. testStep1NextButton->click();
  224. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton)) {return EXIT_FAILURE;}
  225. // now recover, going to the next step using some good input
  226. qObject1->lineEdit()->setText("100");
  227. testStep1NextButton->click();
  228. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1NextButton)) {return EXIT_FAILURE;}
  229. // on bad input, going "Back" should be allowed
  230. testStep2BackButton->click();
  231. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton)) {return EXIT_FAILURE;}
  232. // ensure transition to the next step fails on empty input
  233. qObject1->lineEdit()->setText("");
  234. testStep1NextButton->click();
  235. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton)) {return EXIT_FAILURE;}
  236. // try again with some good input to ensure we can recover
  237. qObject1->lineEdit()->setText("100");
  238. testStep1NextButton->click();
  239. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1NextButton)) {return EXIT_FAILURE;}
  240. // after adding the steps, then the widget's client area should have
  241. // them as a child
  242. if (!workflowWidget->clientArea()->isAncestorOf(testStep1->stepArea()))
  243. {
  244. std::cerr << "testStep1 was incorrectly added to the workflowWidget" << std::endl;
  245. return EXIT_FAILURE;
  246. }
  247. if (!workflowWidget->clientArea()->isAncestorOf(testStep2->stepArea()))
  248. {
  249. std::cerr << "testStep2 was incorrectly added to the workflowWidget" << std::endl;
  250. return EXIT_FAILURE;
  251. }
  252. return EXIT_SUCCESS;
  253. }
  254. //-----------------------------------------------------------------------------
  255. // simulates valid and invalid user interaction for a workflow with
  256. // three steps
  257. int userInteractionSimulator2(QApplication& app, ctkWorkflowWidgetStep* testStep1, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject1, ctkWorkflowWidgetStep* testStep2, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject2, ctkWorkflowWidgetStep* testStep3, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject3, bool hideWidgets, ctkWorkflow* workflow, ctkWorkflowWidget* workflowWidget, int defaultTime)
  258. {
  259. int BACK_BUTTON_INDEX = 0;
  260. int NEXT_BUTTON_INDEX = 1;
  261. int FINISH_BUTTON_INDEX_1 = 2;
  262. // test that the setDirection layout was applied
  263. // properly: the widget should be much wider than it is tall
  264. QSize size = workflowWidget->size();
  265. int height = size.height();
  266. int width = size.width();
  267. if (height >= (width/2))
  268. {
  269. std::cerr << "The workflow widget is too tall - was the direction applied?" << std::endl;
  270. return EXIT_FAILURE;
  271. }
  272. // test that we can change the layout of the stepAreas: it should be
  273. // wider than it was before
  274. testStep1->setStepAreaDirection(QBoxLayout::LeftToRight);
  275. testStep2->setStepAreaDirection(QBoxLayout::LeftToRight);
  276. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  277. app.exec();
  278. size = workflowWidget->size();
  279. if (size.width() <= width)
  280. {
  281. std::cerr << "The workflow widget did not increase in width after setting the step area direction to LeftToRight" << std::endl;
  282. return EXIT_FAILURE;
  283. }
  284. // test to ensure we can change the layout of the workflow widget's
  285. // client area after having added some steps to it
  286. if (ctkWorkflowAbstractPagedWidget* pagedWidget = qobject_cast<ctkWorkflowAbstractPagedWidget*>(workflowWidget))
  287. {
  288. pagedWidget->setClientAreaDirection(QBoxLayout::LeftToRight);
  289. }
  290. else
  291. {
  292. workflowWidget->setClientAreaDirection(QBoxLayout::LeftToRight);
  293. }
  294. // ensure we can get the pages/layouts we may want
  295. if (ctkWorkflowAbstractPagedWidget* pagedWidget = qobject_cast<ctkWorkflowAbstractPagedWidget*>(workflowWidget))
  296. {
  297. if (!pagedWidget->getWidgetFromIndex(1))
  298. {
  299. std::cerr << "could not access widget for page 1" << std::endl;
  300. return EXIT_FAILURE;
  301. }
  302. if (!pagedWidget->getWidgetFromIndex(1)->layout())
  303. {
  304. std::cerr << "could not access client area layout for page 1" << std::endl;
  305. return EXIT_FAILURE;
  306. }
  307. }
  308. else
  309. {
  310. if (!workflowWidget->clientArea()->layout())
  311. {
  312. std::cerr << "could not access client area layout" << std::endl;
  313. return EXIT_FAILURE;
  314. }
  315. }
  316. // get the buttons
  317. QPushButton* testStep1BackButton = 0;
  318. QPushButton* testStep1NextButton = 0;
  319. QPushButton* testStep1FinishButton = 0;
  320. QPushButton* testStep2BackButton = 0;
  321. QPushButton* testStep2NextButton = 0;
  322. QPushButton* testStep2FinishButton = 0;
  323. QPushButton* testStep3BackButton = 0;
  324. QPushButton* testStep3NextButton = 0;
  325. QPushButton* testStep3FinishButton = 0;
  326. // get the back/next buttons for the first step
  327. QList<QPushButton*> buttons = testStep1->stepArea()->findChildren<QPushButton*>();
  328. // if (buttons.length() != 2)
  329. // {
  330. // std::cerr << "incorrect number of buttons for testStep1" << std::endl;
  331. // std::cerr << "number of buttons = " << buttons.length() << ", expecting 2" << std::endl;
  332. // return EXIT_FAILURE;
  333. // }
  334. testStep1NextButton = buttons.at(NEXT_BUTTON_INDEX);
  335. testStep1FinishButton = buttons.at(FINISH_BUTTON_INDEX_1);
  336. if (!testStep1NextButton || !testStep1FinishButton || testStep1NextButton->text() != "Next" || testStep1FinishButton->text() != "Step 3")
  337. {
  338. std::cerr << "incorrect button assignment for testStep1" << std::endl;
  339. return EXIT_FAILURE;
  340. }
  341. // we should be in the first step when we start the workflow
  342. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton, testStep1FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  343. // tests with good input (lineEdit value = 100, which passes the
  344. // condition that it be >= 10)
  345. // CurrentStep ButtonPress ExpectedStep Shouldn'tDoAnything
  346. // step1 next step2
  347. // step2 next step3
  348. // step3 back step2
  349. // step2 back step1
  350. // step1 next step2
  351. // step2 next step3
  352. // step3 back step2
  353. // normal forwards/backwards transitions
  354. testStep1NextButton->click();
  355. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  356. app.exec();
  357. // get the back/next buttons for the second step
  358. buttons = testStep2->stepArea()->findChildren<QPushButton*>();
  359. // if (buttons.length() != 3)
  360. // {
  361. // std::cerr << "incorrect number of buttons for testStep2" << std::endl;
  362. // std::cerr << "number of buttons = " << buttons.length() << ", expecting 3" << std::endl;
  363. // return EXIT_FAILURE;
  364. // }
  365. testStep2BackButton = buttons.at(BACK_BUTTON_INDEX);
  366. testStep2NextButton = buttons.at(NEXT_BUTTON_INDEX);
  367. testStep2FinishButton = buttons.at(FINISH_BUTTON_INDEX_1);
  368. if (!testStep2BackButton || !testStep2NextButton || !testStep2FinishButton || testStep2BackButton->text() != "Back" || testStep2NextButton->text() != "Next" || testStep2FinishButton->text() != "Step 3")
  369. {
  370. std::cerr << "incorrect button assignment for testStep2" << std::endl;
  371. return EXIT_FAILURE;
  372. }
  373. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1NextButton, testStep2FinishButton, testStep1FinishButton)) {return EXIT_FAILURE;}
  374. qObject2->lineEdit()->setText("100");
  375. testStep2NextButton->click();
  376. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  377. app.exec();
  378. // get the back/next buttons for the third step
  379. buttons = testStep3->stepArea()->findChildren<QPushButton*>();
  380. // if (buttons.length() != 2)
  381. // {
  382. // std::cerr << "incorrect number of buttons for testStep3" << std::endl;
  383. // std::cerr << "number of buttons = " << buttons.length() << ", expecting 2" << std::endl;
  384. // return EXIT_FAILURE;
  385. // }
  386. testStep3BackButton = buttons.at(BACK_BUTTON_INDEX);
  387. testStep3FinishButton = buttons.at(FINISH_BUTTON_INDEX_1);
  388. if (!testStep3BackButton || !testStep3FinishButton || testStep3BackButton->text() != "Back" || testStep3FinishButton->text() != "Step 3")
  389. {
  390. std::cerr << "incorrect button assignment for testStep3" << std::endl;
  391. return EXIT_FAILURE;
  392. }
  393. if (!buttonClickTest(app, defaultTime, testStep3, qObject3, testStep2, qObject2, workflow, workflowWidget, testStep3BackButton, testStep3NextButton, testStep2BackButton, testStep2NextButton, testStep3FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  394. // test that the setClientAreaDirection layout was applied properly:
  395. // the widget should be quite a bit wider than it was before
  396. if (!hideWidgets)
  397. {
  398. QSize size = workflowWidget->size();
  399. if (size.width() <= width)
  400. {
  401. std::cerr << "The workflow widget is not wide enough - was the clientAreaDirection applied?" << std::endl;
  402. return EXIT_FAILURE;
  403. }
  404. }
  405. testStep3BackButton->click();
  406. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  407. testStep2BackButton->click();
  408. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton, testStep1FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  409. testStep1NextButton->click();
  410. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1NextButton, testStep2FinishButton, testStep1FinishButton)) {return EXIT_FAILURE;}
  411. testStep2NextButton->click();
  412. if (!buttonClickTest(app, defaultTime, testStep3, qObject3, testStep2, qObject2, workflow, workflowWidget, testStep3BackButton, testStep3NextButton, testStep2BackButton, testStep2NextButton, testStep3FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  413. testStep3BackButton->click();
  414. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  415. // tests with both good and bad input (lineEdit value may be
  416. // invalid)
  417. // CurrentStep ButtonPress Invalid input ExpectedStep
  418. // step2 next * step2
  419. // step2 next step3
  420. // step3 back * step2
  421. // step2 next * (empty) step2
  422. // step2 next step3
  423. // ensure transition to the next step fails on bad input
  424. qObject2->lineEdit()->setText("1");
  425. testStep2NextButton->click();
  426. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  427. // now recover, going to the next step with some good input
  428. qObject2->lineEdit()->setText("100");
  429. testStep2NextButton->click();
  430. if (!buttonClickTest(app, defaultTime, testStep3, qObject3, testStep2, qObject2, workflow, workflowWidget, testStep3BackButton, testStep3NextButton, testStep2BackButton, testStep2NextButton, testStep3FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  431. // on bad input, going "Back" should be allowed
  432. testStep3BackButton->click();
  433. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  434. // ensure transition to the next step fails on empty input
  435. qObject2->lineEdit()->setText("");
  436. testStep2NextButton->click();
  437. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  438. // try again with some good input to ensure we can recover
  439. qObject2->lineEdit()->setText("100");
  440. testStep2NextButton->click();
  441. if (!buttonClickTest(app, defaultTime, testStep3, qObject3, testStep2, qObject2, workflow, workflowWidget, testStep3BackButton, testStep3NextButton, testStep2BackButton, testStep2NextButton, testStep3FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  442. // tests going to the finish step
  443. // CurrentStep ButtonPress Invalid input ExpectedStep
  444. // step1 finish step1
  445. // step1 finish step1
  446. // step1 next step2
  447. // step2 finish step2
  448. // step2 next step3
  449. // step3 finish step3
  450. // step3 back step2
  451. // step2 finish step2
  452. // step2 back step1
  453. // step1 finish step1
  454. // first go back to the beginning
  455. qObject3->lineEdit()->setText("100");
  456. testStep3BackButton->click();
  457. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  458. app.exec();
  459. testStep2BackButton->click();
  460. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton, testStep1FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  461. testStep1FinishButton->click();
  462. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep3, qObject3, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep3BackButton, testStep3NextButton, testStep1FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  463. testStep1FinishButton->click();
  464. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep3, qObject3, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep3BackButton, testStep3NextButton, testStep1FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  465. testStep1NextButton->click();
  466. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1NextButton, testStep2FinishButton, testStep1FinishButton)) {return EXIT_FAILURE;}
  467. testStep2FinishButton->click();
  468. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  469. testStep2NextButton->click();
  470. if (!buttonClickTest(app, defaultTime, testStep3, qObject3, testStep2, qObject2, workflow, workflowWidget, testStep3BackButton, testStep3NextButton, testStep2BackButton, testStep2NextButton, testStep3FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  471. testStep3FinishButton->click();
  472. if (!buttonClickTest(app, defaultTime, testStep3, qObject3, testStep2, qObject2, workflow, workflowWidget, testStep3BackButton, testStep3NextButton, testStep2BackButton, testStep2NextButton, testStep3FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  473. testStep3BackButton->click();
  474. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  475. testStep2FinishButton->click();
  476. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  477. testStep2BackButton->click();
  478. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton, testStep1FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  479. testStep1FinishButton->click();
  480. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep3, qObject3, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep3BackButton, testStep3NextButton, testStep1FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  481. // tests going to the finish step with invalid input
  482. // CurrentStep ButtonPress Invalid input ExpectedStep
  483. // step1 finish * (step2) step2
  484. // step2 next step3
  485. // step3 back step2
  486. // step2 finish * (step2) step2
  487. // step2 back step1
  488. // step1 finish * (step3) step1
  489. qObject2->lineEdit()->setText("0");
  490. testStep1FinishButton->click();
  491. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1NextButton, testStep2FinishButton, testStep1FinishButton)) {return EXIT_FAILURE;}
  492. qObject2->lineEdit()->setText("100");
  493. testStep2NextButton->click();
  494. if (!buttonClickTest(app, defaultTime, testStep3, qObject3, testStep2, qObject2, workflow, workflowWidget, testStep3BackButton, testStep3NextButton, testStep2BackButton, testStep2NextButton, testStep3FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  495. testStep3BackButton->click();
  496. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  497. qObject2->lineEdit()->setText("0");
  498. testStep2FinishButton->click();
  499. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  500. testStep2BackButton->click();
  501. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton, testStep1FinishButton, testStep2FinishButton)) {return EXIT_FAILURE;}
  502. qObject2->lineEdit()->setText("100");
  503. qObject3->lineEdit()->setText("0");
  504. testStep1FinishButton->click();
  505. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep3, qObject3, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep3BackButton, testStep3NextButton, testStep1FinishButton, testStep3FinishButton)) {return EXIT_FAILURE;}
  506. // calling showWidget() with a widget that hasn't been previously
  507. // used with addWidget() would work for ctkWorkflowWidget, but not
  508. // ctkWorkflowAbstractPagedWidget) - make sure it fails
  509. if (ctkWorkflowAbstractPagedWidget* pagedWidget = qobject_cast<ctkWorkflowAbstractPagedWidget*>(workflowWidget))
  510. {
  511. QWidget* test = new QWidget;
  512. pagedWidget->showWidget(test);
  513. if (test->isVisible())
  514. {
  515. std::cerr << "calling ctkWorkflowAbstractPagedWidget::showWidget() using a widget that was not previously added seems to work - and it shouldn't" << std::endl;
  516. return EXIT_FAILURE;
  517. }
  518. }
  519. // after adding the steps, then the widget's client area should have
  520. // them as a child
  521. if (!workflowWidget->clientArea()->isAncestorOf(testStep3->stepArea()))
  522. {
  523. std::cerr << "testStep3 was incorrectly added to the workflowWidget" << std::endl;
  524. return EXIT_FAILURE;
  525. }
  526. return EXIT_SUCCESS;
  527. }
  528. //-----------------------------------------------------------------------------
  529. // simulates valid and invalid user interaction for a workflow with
  530. // three steps and two finish steps
  531. int userInteractionSimulator3(QApplication& app, ctkWorkflowWidgetStep* testStep1, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject1, ctkWorkflowWidgetStep* testStep2, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject2, ctkWorkflowWidgetStep* testStep3, ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject3, ctkWorkflow* workflow, ctkWorkflowWidget* workflowWidget, int defaultTime)
  532. {
  533. int BACK_BUTTON_INDEX = 0;
  534. int NEXT_BUTTON_INDEX = 1;
  535. int FINISH_BUTTON_INDEX_1 = 2;
  536. int FINISH_BUTTON_INDEX_2 = 3;
  537. // get the buttons
  538. QPushButton* testStep1BackButton = 0;
  539. QPushButton* testStep1NextButton = 0;
  540. QPushButton* testStep1FinishButton1 = 0;
  541. QPushButton* testStep1FinishButton2 = 0;
  542. QPushButton* testStep2BackButton = 0;
  543. QPushButton* testStep2NextButton = 0;
  544. QPushButton* testStep2FinishButton1 = 0;
  545. QPushButton* testStep2FinishButton2 = 0;
  546. QPushButton* testStep3BackButton = 0;
  547. QPushButton* testStep3NextButton = 0;
  548. QPushButton* testStep3FinishButton1 = 0;
  549. QPushButton* testStep3FinishButton2 = 0;
  550. // get the back/next buttons for the first step
  551. QList<QPushButton*> buttons = testStep1->stepArea()->findChildren<QPushButton*>();
  552. // if (buttons.length() != 3)
  553. // {
  554. // std::cerr << "incorrect number of buttons for testStep1" << std::endl;
  555. // std::cerr << "number of buttons = " << buttons.length() << ", expecting 3" << std::endl;
  556. // return EXIT_FAILURE;
  557. // }
  558. testStep1NextButton = buttons.at(NEXT_BUTTON_INDEX);
  559. testStep1FinishButton1 = buttons.at(FINISH_BUTTON_INDEX_1);
  560. testStep1FinishButton2 = buttons.at(FINISH_BUTTON_INDEX_2);
  561. if (!testStep1NextButton || !testStep1FinishButton1 || !testStep1FinishButton2 || testStep1NextButton->text() != "Next" || testStep1FinishButton1->text() != "finish" || testStep1FinishButton2->text() != "finish")
  562. {
  563. std::cerr << "incorrect button assignment for testStep1" << std::endl;
  564. return EXIT_FAILURE;
  565. }
  566. // we should be in the first step
  567. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton, testStep1FinishButton1, testStep2FinishButton1, testStep1FinishButton2, testStep2FinishButton2)) {return EXIT_FAILURE;}
  568. // tests with good input, so that we can get all of the buttons
  569. // (lineEdit value = 100, which passes the condition that it be >= 10)
  570. // CurrentStep ButtonPress ExpectedStep Shouldn'tDoAnything
  571. // step1 next step2
  572. // step2 next step3
  573. // normal forwards/backwards transitions
  574. testStep1NextButton->click();
  575. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  576. app.exec();
  577. // get the back/next buttons for the second step
  578. buttons = testStep2->stepArea()->findChildren<QPushButton*>();
  579. // if (buttons.length() != 4)
  580. // {
  581. // std::cerr << "incorrect number of buttons for testStep2" << std::endl;
  582. // std::cerr << "number of buttons = " << buttons.length() << ", expecting 4" << std::endl;
  583. // return EXIT_FAILURE;
  584. // }
  585. testStep2BackButton = buttons.at(BACK_BUTTON_INDEX);
  586. testStep2NextButton = buttons.at(NEXT_BUTTON_INDEX);
  587. testStep2FinishButton1 = buttons.at(FINISH_BUTTON_INDEX_1);
  588. testStep2FinishButton2 = buttons.at(FINISH_BUTTON_INDEX_2);
  589. if (!testStep2BackButton || !testStep2NextButton || !testStep2FinishButton1 || !testStep2FinishButton2 || testStep2BackButton->text() != "Back" || testStep2NextButton->text() != "Next" || testStep2FinishButton1->text() != "finish" || testStep2FinishButton2->text() != "finish")
  590. {
  591. std::cerr << "incorrect button assignment for testStep2" << std::endl;
  592. return EXIT_FAILURE;
  593. }
  594. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1NextButton, testStep2FinishButton1, testStep1FinishButton1, testStep2FinishButton2, testStep1FinishButton2)) {return EXIT_FAILURE;}
  595. testStep2NextButton->click();
  596. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  597. app.exec();
  598. // get the back/next buttons for the third step
  599. buttons = testStep3->stepArea()->findChildren<QPushButton*>();
  600. // if (buttons.length() != 3)
  601. // {
  602. // std::cerr << "incorrect number of buttons for testStep3" << std::endl;
  603. // std::cerr << "number of buttons = " << buttons.length() << ", expecting 3" << std::endl;
  604. // return EXIT_FAILURE;
  605. // }
  606. testStep3BackButton = buttons.at(BACK_BUTTON_INDEX);
  607. testStep3FinishButton1 = buttons.at(FINISH_BUTTON_INDEX_1);
  608. testStep3FinishButton2 = buttons.at(FINISH_BUTTON_INDEX_2);
  609. if (!testStep3BackButton || !testStep3FinishButton1 || !testStep3FinishButton2 || testStep3BackButton->text() != "Back" || testStep3FinishButton1->text() != "finish" || testStep3FinishButton2->text() != "finish")
  610. {
  611. std::cerr << "incorrect button assignment for testStep3" << std::endl;
  612. return EXIT_FAILURE;
  613. }
  614. if (!buttonClickTest(app, defaultTime, testStep3, qObject3, testStep2, qObject2, workflow, workflowWidget, testStep3BackButton, testStep3NextButton, testStep2BackButton, testStep2NextButton, testStep3FinishButton1, testStep2FinishButton1, testStep3FinishButton2, testStep2FinishButton2)) {return EXIT_FAILURE;}
  615. // tests going to the finish step
  616. // CurrentStep ButtonPress Invalid input ExpectedStep
  617. // step3 back step2
  618. // step2 back step1
  619. // step1 finish1 step1
  620. // step1 next step2
  621. // step2 finish1 step2
  622. // step2 finish2 step2
  623. // step2 back step1
  624. // step1 finish2 step1
  625. // step1 next step2
  626. testStep3BackButton->click();
  627. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton1, testStep3FinishButton1, testStep2FinishButton2, testStep3FinishButton2)) {return EXIT_FAILURE;}
  628. testStep2BackButton->click();
  629. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton, testStep1FinishButton1, testStep2FinishButton1, testStep1FinishButton2, testStep2FinishButton2)) {return EXIT_FAILURE;}
  630. testStep1FinishButton1->click();
  631. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep3, qObject3, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep3BackButton, testStep3BackButton, testStep1FinishButton1, testStep3FinishButton1, testStep1FinishButton2, testStep3FinishButton2)) {return EXIT_FAILURE;}
  632. testStep1NextButton->click();
  633. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1BackButton, testStep2FinishButton1, testStep1FinishButton1, testStep2FinishButton2, testStep1FinishButton2)) {return EXIT_FAILURE;}
  634. testStep2FinishButton1->click();
  635. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton1, testStep3FinishButton1, testStep2FinishButton2, testStep3FinishButton2)) {return EXIT_FAILURE;}
  636. testStep2FinishButton2->click();
  637. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep3BackButton, testStep3NextButton, testStep2FinishButton1, testStep3FinishButton1, testStep2FinishButton2, testStep3FinishButton2)) {return EXIT_FAILURE;}
  638. testStep2BackButton->click();
  639. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2NextButton, testStep1FinishButton1, testStep2FinishButton1, testStep1FinishButton2, testStep2FinishButton2)) {return EXIT_FAILURE;}
  640. testStep1FinishButton2->click();
  641. if (!buttonClickTest(app, defaultTime, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, testStep1BackButton, testStep1NextButton, testStep2BackButton, testStep2BackButton, testStep1FinishButton1, testStep2FinishButton1, testStep1FinishButton2, testStep2FinishButton2)) {return EXIT_FAILURE;}
  642. testStep1NextButton->click();
  643. if (!buttonClickTest(app, defaultTime, testStep2, qObject2, testStep1, qObject1, workflow, workflowWidget, testStep2BackButton, testStep2NextButton, testStep1BackButton, testStep1BackButton, testStep2FinishButton1, testStep1FinishButton1, testStep2FinishButton2, testStep1FinishButton2)) {return EXIT_FAILURE;}
  644. return EXIT_SUCCESS;
  645. }
  646. //-----------------------------------------------------------------------------
  647. int ctkWorkflowWidgetTest2(int argc, char * argv [] )
  648. {
  649. QApplication app(argc, argv);
  650. int defaultTime = 100;
  651. bool hideWidgets = false;
  652. ctkWorkflow* workflow = new ctkWorkflow;
  653. ctkWorkflowWidget* workflowWidget = new ctkWorkflowWidget;
  654. workflowWidget->setWorkflow(workflow);
  655. workflowWidget->setPreText("I am some pre-text");
  656. workflowWidget->setPostText("I am some post-text");
  657. workflowWidget->setHideWidgetsOfNonCurrentSteps(hideWidgets);
  658. workflowWidget->setHasButtonBoxWidget(false);
  659. // create and add the first workflow step (depends on workflowWidget
  660. // type)
  661. ctkWorkflowWidgetStep* testStep1 = new ctkWorkflowWidgetStep(workflow, "Step 1");
  662. testStep1->setName("Step 1");
  663. testStep1->setDescription("I am in step 1");
  664. if (ctkWorkflowTabWidget* tabWidget = qobject_cast<ctkWorkflowTabWidget*>(workflowWidget))
  665. {
  666. tabWidget->addStepArea(testStep1, "tab1");
  667. }
  668. testStep1->setHasButtonBoxWidget(true);
  669. // testStep1 is the initial step
  670. workflow->setInitialStep(testStep1);
  671. // create and add the second workflow step (depends on
  672. // workflowWidget type)
  673. ctkWorkflowWidgetStep* testStep2 = new ctkWorkflowWidgetStep(workflow, "Step 2");
  674. testStep2->setName("Step 2");
  675. testStep2->setDescription("I am in step 2");
  676. if (ctkWorkflowTabWidget* tabWidget = qobject_cast<ctkWorkflowTabWidget*>(workflowWidget))
  677. {
  678. tabWidget->addStepArea(testStep2, "tab2");
  679. }
  680. testStep2->setHasButtonBoxWidget(true);
  681. // add the steps to the workflow
  682. workflow->addTransition(testStep1, testStep2);
  683. // create the qObjects that implement the required functions, and
  684. // communicate with the workflow using signals and slots
  685. ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject1 = new ctkExampleWorkflowWidgetStepUsingSignalsAndSlots;
  686. ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject2 = new ctkExampleWorkflowWidgetStepUsingSignalsAndSlots;
  687. // use the qObjects for validation
  688. QObject::connect(testStep1, SIGNAL(invokeValidateCommand(const QString&)), qObject1, SLOT(validate(const QString&)));
  689. QObject::connect(qObject1, SIGNAL(validationComplete(bool, const QString&)), workflow, SLOT(evaluateValidationResults(bool, const QString&)));
  690. QObject::connect(testStep2, SIGNAL(invokeValidateCommand(const QString&)), qObject2, SLOT(validate(const QString&)));
  691. QObject::connect(qObject2, SIGNAL(validationComplete(bool, const QString&)), workflow, SLOT(evaluateValidationResults(bool, const QString&)));
  692. // use the qObjects for entry processing
  693. QObject::connect(testStep1, SIGNAL(invokeOnEntryCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject1, SLOT(onEntry(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
  694. QObject::connect(qObject1, SIGNAL(onEntryComplete()), workflow, SLOT(processingAfterOnEntry()));
  695. QObject::connect(testStep2, SIGNAL(invokeOnEntryCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject2, SLOT(onEntry(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
  696. QObject::connect(qObject2, SIGNAL(onEntryComplete()), workflow, SLOT(processingAfterOnEntry()));
  697. // use the qObjects for exit processing
  698. QObject::connect(testStep1, SIGNAL(invokeOnExitCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject1, SLOT(onExit(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
  699. QObject::connect(qObject1, SIGNAL(onExitComplete()), workflow, SLOT(processingAfterOnExit()));
  700. QObject::connect(testStep2, SIGNAL(invokeOnExitCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject2, SLOT(onExit(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
  701. QObject::connect(qObject2, SIGNAL(onExitComplete()), workflow, SLOT(processingAfterOnExit()));
  702. // use the qObjects for populating the stepWidgetsList
  703. QObject::connect(testStep1, SIGNAL(invokePopulateStepWidgetsListCommand(QList<QWidget*>&)), qObject1, SLOT(populateStepWidgetsList(QList<QWidget*>&)));
  704. QObject::connect(qObject1, SIGNAL(populateStepWidgetsListComplete()), testStep1, SLOT(evaluatePopulateStepWidgetsListResults()));
  705. QObject::connect(testStep2, SIGNAL(invokePopulateStepWidgetsListCommand(QList<QWidget*>&)), qObject2, SLOT(populateStepWidgetsList(QList<QWidget*>&)));
  706. QObject::connect(qObject2, SIGNAL(populateStepWidgetsListComplete()), testStep2, SLOT(evaluatePopulateStepWidgetsListResults()));
  707. testStep1->setHasValidateCommand(1);
  708. testStep2->setHasValidateCommand(1);
  709. testStep1->setHasOnEntryCommand(1);
  710. testStep2->setHasOnEntryCommand(1);
  711. testStep1->setHasOnExitCommand(1);
  712. testStep2->setHasOnExitCommand(1);
  713. testStep1->setHasPopulateStepWidgetsListCommand(1);
  714. testStep2->setHasPopulateStepWidgetsListCommand(1);
  715. // start the workflow
  716. workflow->start();
  717. workflowWidget->show();
  718. // first user interaction test
  719. if (userInteractionSimulator1(app, testStep1, qObject1, testStep2, qObject2, workflow, workflowWidget, defaultTime) == EXIT_FAILURE)
  720. {
  721. return EXIT_FAILURE;
  722. }
  723. // stop the workflow
  724. workflow->stop();
  725. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  726. app.exec();
  727. // create and add a third workflow step (depends on workflowWidget
  728. // type)
  729. ctkWorkflowWidgetStep* testStep3 = new ctkWorkflowWidgetStep(workflow, "Step 3");
  730. testStep3->setName("Step 3");
  731. testStep3->setDescription("I am in step 3");
  732. if (ctkWorkflowStackedWidget* stackedWidget = qobject_cast<ctkWorkflowStackedWidget*>(workflowWidget))
  733. {
  734. stackedWidget->addStepArea(testStep3, 1);
  735. }
  736. else if (ctkWorkflowTabWidget* tabWidget = qobject_cast<ctkWorkflowTabWidget*>(workflowWidget))
  737. {
  738. tabWidget->addStepArea(testStep3, 1, "tab2");
  739. }
  740. testStep3->setHasButtonBoxWidget(true);
  741. // add the step to the workflow
  742. workflow->addTransition(testStep2, testStep3);
  743. // create the qObjects that implement the required functions, and
  744. // communicate with the workflow using signals and slots
  745. ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject3 = new ctkExampleWorkflowWidgetStepUsingSignalsAndSlots;
  746. // use the qObjects for validation
  747. QObject::connect(testStep3, SIGNAL(invokeValidateCommand(const QString&)), qObject3, SLOT(validate(const QString&)));
  748. QObject::connect(qObject3, SIGNAL(validationComplete(bool, const QString&)), workflow, SLOT(evaluateValidationResults(bool, const QString&)));
  749. // use the qObjects for entry processing
  750. QObject::connect(testStep3, SIGNAL(invokeOnEntryCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject3, SLOT(onEntry(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
  751. QObject::connect(qObject3, SIGNAL(onEntryComplete()), workflow, SLOT(processingAfterOnEntry()));
  752. // use the qObjects for exit processing
  753. QObject::connect(testStep3, SIGNAL(invokeOnExitCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject3, SLOT(onExit(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
  754. QObject::connect(qObject3, SIGNAL(onExitComplete()), workflow, SLOT(processingAfterOnExit()));
  755. // use the qObjects for populating the stepWidgetsList
  756. QObject::connect(testStep3, SIGNAL(invokePopulateStepWidgetsListCommand(QList<QWidget*>&)), qObject3, SLOT(populateStepWidgetsList(QList<QWidget*>&)));
  757. QObject::connect(qObject3, SIGNAL(populateStepWidgetsListComplete()), testStep3, SLOT(evaluatePopulateStepWidgetsListResults()));
  758. testStep3->setHasValidateCommand(1);
  759. testStep3->setHasOnEntryCommand(1);
  760. testStep3->setHasOnExitCommand(1);
  761. testStep3->setHasPopulateStepWidgetsListCommand(1);
  762. // restart the workflow
  763. workflow->start();
  764. // second user interaction test
  765. if (userInteractionSimulator2(app, testStep1, qObject1, testStep2, qObject2, testStep3, qObject3, hideWidgets, workflow, workflowWidget, defaultTime) == EXIT_FAILURE)
  766. {
  767. return EXIT_FAILURE;
  768. }
  769. // stop the workflow
  770. workflow->stop();
  771. QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  772. app.exec();
  773. // make the second workflow step a finish step as well
  774. // TODO put this back once we can add multiple finish steps
  775. // finishSteps.push_back(testStep2);
  776. // testStep1->setFinishStepsToHaveButtonsInStepArea(finishSteps);
  777. // testStep2->setFinishStepsToHaveButtonsInStepArea(finishSteps);
  778. // testStep3->setFinishStepsToHaveButtonsInStepArea(finishSteps);
  779. // // workflow->addFinishStep(testStep2);
  780. // // restart the workflow
  781. // workflow->start();
  782. // QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  783. // app.exec();
  784. // // third user interfaction test
  785. // if (userInteractionSimulator3(app, testStep1, qObject1, testStep2, qObject2, testStep3, qObject3, workflow, workflowWidget, defaultTime) == EXIT_FAILURE)
  786. // {
  787. // return EXIT_FAILURE;
  788. // }
  789. // // stop the workflow
  790. // workflow->stop();
  791. // QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  792. // app.exec();
  793. // handles deletion of the workflowWidget, workflow, steps, states
  794. // and transitions
  795. delete workflowWidget;
  796. return EXIT_SUCCESS;
  797. }