//-----------------------------------------------------------------------------
int ctkExampleUseOfWorkflowWidgetUsingSignalsAndSlots(int argc, char * argv [] )
{
    QApplication app(argc, argv);

    // this boolean is used in setHideWidgetsOfNonCurrentSteps() below
    // false: when a widget does not belong to the current step, it is
    // hidden
    // true: when a widget does not belong to the current step, it is
    // shown, but disabled
    bool hideWidgets = false;

    // create the workflow
    ctkWorkflow* workflow = new ctkWorkflow;

    // create the workflow's UI component
    ctkWorkflowTabWidget* workflowWidget = new ctkWorkflowTabWidget;
    workflowWidget->setWorkflow(workflow);
    ctkWorkflowGroupBox* groupBox = workflowWidget->workflowGroupBox();
    groupBox->setPreText("I am some pre-text");
    groupBox->setPostText("I am some post-text");
    groupBox->setHideWidgetsOfNonCurrentSteps(hideWidgets);

    // create and add the first workflow step
    ctkWorkflowWidgetStep* testStep1 = new ctkWorkflowWidgetStep(workflow, "Step 1");
    testStep1->setName("Step 1");
    testStep1->setDescription("I am in step 1");
    // can specify the name of the tab
    workflowWidget->associateStepWithLabel(testStep1, "name 1");

    // create and add the second workflow step
    ctkWorkflowWidgetStep* testStep2 = new ctkWorkflowWidgetStep(workflow, "Step 2");
    testStep2->setName("Step 2");
    testStep2->setDescription("I am in step 2");
    // a new tab is automatically created
    workflowWidget->associateStepWithLabel(testStep2, "name 2");

    // create and add a third workflow step
    ctkWorkflowWidgetStep* testStep3 = new ctkWorkflowWidgetStep(workflow, "Step 3");
    testStep3->setName("Step 3");
    testStep3->setDescription("I am in step 3");
    // can place a step on a tab that was previously created by
    // specifying its index
    workflowWidget->associateStepWithPage(testStep3, 1, "name 3");

    // add the steps to the workflow
    workflow->addTransition(testStep1, testStep2);
    workflow->addTransition(testStep2, testStep3);

    // create the qObjects that implement the required functions for
    // each step, and communicate with the workflow using signals and slots
    ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject1 = new ctkExampleWorkflowWidgetStepUsingSignalsAndSlots;
    ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject2 = new ctkExampleWorkflowWidgetStepUsingSignalsAndSlots;
    ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject3 = new ctkExampleWorkflowWidgetStepUsingSignalsAndSlots;

    // set the widget for each qObject
    qObject1->setWidget(testStep1->stepArea());
    qObject2->setWidget(testStep2->stepArea());
    qObject3->setWidget(testStep3->stepArea());

    // use the qObjects for validation
    QObject::connect(testStep1->ctkWorkflowStepQObject(), SIGNAL(invokeValidateCommand(const QString&)), qObject1, SLOT(validate(const QString&)));
    QObject::connect(qObject1, SIGNAL(validationComplete(bool, const QString&)), workflow, SLOT(evaluateValidationResults(bool, const QString&)));
    QObject::connect(testStep2->ctkWorkflowStepQObject(), SIGNAL(invokeValidateCommand(const QString&)), qObject2, SLOT(validate(const QString&)));
    QObject::connect(qObject2, SIGNAL(validationComplete(bool, const QString&)), workflow, SLOT(evaluateValidationResults(bool, const QString&)));
    QObject::connect(testStep3->ctkWorkflowStepQObject(), SIGNAL(invokeValidateCommand(const QString&)), qObject3, SLOT(validate(const QString&)));
    QObject::connect(qObject3, SIGNAL(validationComplete(bool, const QString&)), workflow, SLOT(evaluateValidationResults(bool, const QString&)));

    // use the qObjects for entry processing
    QObject::connect(testStep1->ctkWorkflowStepQObject(), SIGNAL(invokeOnEntryCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject1, SLOT(onEntry(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
    QObject::connect(qObject1, SIGNAL(onEntryComplete()), workflow, SLOT(processingAfterOnEntry()));
    QObject::connect(testStep2->ctkWorkflowStepQObject(), SIGNAL(invokeOnEntryCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject2, SLOT(onEntry(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
    QObject::connect(qObject2, SIGNAL(onEntryComplete()), workflow, SLOT(processingAfterOnEntry()));
    QObject::connect(testStep3->ctkWorkflowStepQObject(), SIGNAL(invokeOnEntryCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject3, SLOT(onEntry(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
    QObject::connect(qObject3, SIGNAL(onEntryComplete()), workflow, SLOT(processingAfterOnEntry()));

    // use the qObjects for exit processing
    QObject::connect(testStep1->ctkWorkflowStepQObject(), SIGNAL(invokeOnExitCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject1, SLOT(onExit(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
    QObject::connect(qObject1, SIGNAL(onExitComplete()), workflow, SLOT(processingAfterOnExit()));
    QObject::connect(testStep2->ctkWorkflowStepQObject(), SIGNAL(invokeOnExitCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject2, SLOT(onExit(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
    QObject::connect(qObject2, SIGNAL(onExitComplete()), workflow, SLOT(processingAfterOnExit()));
    QObject::connect(testStep3->ctkWorkflowStepQObject(), SIGNAL(invokeOnExitCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)), qObject3, SLOT(onExit(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
    QObject::connect(qObject3, SIGNAL(onExitComplete()), workflow, SLOT(processingAfterOnExit()));

    // use the qObjects for populating the stepWidgetsList
    QObject::connect(testStep1->ctkWorkflowAbstractWidgetStepQObject(), SIGNAL(invokeCreateUserInterfaceCommand()), qObject1, SLOT(createUserInterface()));
    QObject::connect(qObject1, SIGNAL(createUserInterfaceComplete()), testStep1->ctkWorkflowAbstractWidgetStepQObject(), SIGNAL(showUserInterfaceComplete()));
    QObject::connect(testStep2->ctkWorkflowAbstractWidgetStepQObject(), SIGNAL(invokeCreateUserInterfaceCommand()), qObject2, SLOT(createUserInterface()));
    QObject::connect(qObject2, SIGNAL(createUserInterfaceComplete()), testStep2->ctkWorkflowAbstractWidgetStepQObject(), SIGNAL(showUserInterfaceComplete()));
    QObject::connect(testStep3->ctkWorkflowAbstractWidgetStepQObject(), SIGNAL(invokeCreateUserInterfaceCommand()), qObject3, SLOT(createUserInterface()));
    QObject::connect(qObject3, SIGNAL(createUserInterfaceComplete()), testStep3->ctkWorkflowAbstractWidgetStepQObject(), SIGNAL(showUserInterfaceComplete()));

    testStep1->setHasValidateCommand(1);
    testStep1->setHasOnEntryCommand(1);
    testStep1->setHasOnExitCommand(1);
    testStep1->setHasCreateUserInterfaceCommand(1);

    testStep2->setHasValidateCommand(1);
    testStep2->setHasOnEntryCommand(1);
    testStep2->setHasOnExitCommand(1);
    testStep2->setHasCreateUserInterfaceCommand(1);

    testStep3->setHasValidateCommand(1);
    testStep3->setHasOnEntryCommand(1);
    testStep3->setHasOnExitCommand(1);
    testStep3->setHasCreateUserInterfaceCommand(1);

    // testStep1 is the initial step
    workflow->setInitialStep(testStep1);

    // testStep3 will be a finish step
    // - will perform the processing associated with entering and
    // leaving each step, using the default values supplied
    // - if successful: brings you back to the step where you requested
    // to go to the finish step, so that you can begin customization
    // using user inputs if desired
    // - if unsuccessful: leaves you in the step of failure, so that you
    // can attempt to recify things from there; prints an error message
    // at the bottom of the widget.  To see this behavior:
    // 1) "Next" to step 2
    // 2) change step 2's value to something invalid (ex. 0)
    // 3) "Back" to step 1
    // 4) "finish" - attempts to go to step 3, but leaves you in step 2

    // start the workflow
    workflow->start();
    workflowWidget->show();
    // change this value (500) to increase the time that the widget is
    // shown
    QTimer::singleShot(500, &app, SLOT(quit()));
    app.exec();

    // stop the workflow
    workflow->stop();
    QTimer::singleShot(100, &app, SLOT(quit()));
    app.exec();

    // handles deletion of the workflowWidget, workflow, steps, states
    // and transitions
    delete workflowWidget;

    return EXIT_SUCCESS;
}
//-----------------------------------------------------------------------------
int ctkWorkflowWidgetTest2(int argc, char * argv [] )
{
  QApplication app(argc, argv);
  int defaultTime = 100;
  bool hideWidgets = false;

  ctkWorkflow* workflow = new ctkWorkflow;
  ctkWorkflowWidget* workflowWidget = new ctkWorkflowWidget;
  workflowWidget->setWorkflow(workflow);

  ctkWorkflowGroupBox* groupBox = workflowWidget->workflowGroupBox();
  groupBox->setPreText("I am some pre-text");
  groupBox->setPostText("I am some post-text");
  groupBox->setHideWidgetsOfNonCurrentSteps(hideWidgets);

  // create and add the first workflow step (depends on workflowWidget
  // type)
  ctkWorkflowWidgetStep* step1 = new ctkWorkflowWidgetStep(workflow, "Step 1");
  step1->setName("Step 1");
  step1->setDescription("I am in step 1");
  if (ctkWorkflowTabWidget* tabWidget = qobject_cast<ctkWorkflowTabWidget*>(workflowWidget))
    {
    tabWidget->associateStepWithLabel(step1, "tab1");
    }
  
  // step1 is the initial step
  workflow->setInitialStep(step1);

  // create and add the second workflow step (depends on
  // workflowWidget type)
  ctkWorkflowWidgetStep* step2 = new ctkWorkflowWidgetStep(workflow, "Step 2");
  step2->setName("Step 2");
  step2->setDescription("I am in step 2");
  if (ctkWorkflowTabWidget* tabWidget = qobject_cast<ctkWorkflowTabWidget*>(workflowWidget))
    {
    tabWidget->associateStepWithLabel(step2, "tab2");
    }

  // add the steps to the workflow
  workflow->addTransition(step1, step2);

  // create the qObjects that implement the required functions, and
  // communicate with the workflow using signals and slots
  ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject1 =
      new ctkExampleWorkflowWidgetStepUsingSignalsAndSlots(step1);
  ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject2 =
      new ctkExampleWorkflowWidgetStepUsingSignalsAndSlots(step2);

  // set the widget for each qObject
  qObject1->setWidget(step1->stepArea());
  qObject2->setWidget(step2->stepArea());

  // use the qObjects for validation
  QObject::connect(step1->ctkWorkflowStepQObject(),
                   SIGNAL(invokeValidateCommand(const QString&)),
                   qObject1, SLOT(validate(const QString&)));
  QObject::connect(step2->ctkWorkflowStepQObject(),
                   SIGNAL(invokeValidateCommand(const QString&)),
                   qObject2, SLOT(validate(const QString&)));

  // use the qObjects for entry processing
  QObject::connect(step1->ctkWorkflowStepQObject(),
                   SIGNAL(invokeOnEntryCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)),
                   qObject1, SLOT(onEntry(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
  QObject::connect(step2->ctkWorkflowStepQObject(),
                   SIGNAL(invokeOnEntryCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)),
                   qObject2, SLOT(onEntry(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));

  // use the qObjects for exit processing
  QObject::connect(step1->ctkWorkflowStepQObject(),
                   SIGNAL(invokeOnExitCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)),
                   qObject1, SLOT(onExit(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));
  QObject::connect(step2->ctkWorkflowStepQObject(),
                   SIGNAL(invokeOnExitCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)),
                   qObject2, SLOT(onExit(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));

  // use the qObjects for populating the stepWidgetsList
  QObject::connect(step1->ctkWorkflowStepQObject(),
                   SIGNAL(invokeCreateUserInterfaceCommand()),
                   qObject1, SLOT(createUserInterface()));
  QObject::connect(step2->ctkWorkflowStepQObject(),
                   SIGNAL(invokeCreateUserInterfaceCommand()),
                   qObject2, SLOT(createUserInterface()));

  step1->setHasValidateCommand(1);
  step2->setHasValidateCommand(1);

  step1->setHasOnEntryCommand(1);
  step2->setHasOnEntryCommand(1);

  step1->setHasOnExitCommand(1);
  step2->setHasOnExitCommand(1);

  step1->setHasCreateUserInterfaceCommand(1);
  step2->setHasCreateUserInterfaceCommand(1);

  // start the workflow
  workflow->start();
  workflowWidget->show();

  // first user interaction test
  if (userInteractionSimulator1(app, step1, qObject1, step2, qObject2, workflow, workflowWidget, defaultTime) == EXIT_FAILURE)
    {
    return EXIT_FAILURE;
    }

  // stop the workflow
  workflow->stop();
  QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  app.exec();

  // create and add a third workflow step (depends on workflowWidget
  // type)
  ctkWorkflowWidgetStep* step3 = new ctkWorkflowWidgetStep(workflow, "Step 3");
  step3->setName("Step 3");
  step3->setDescription("I am in step 3");
  if (ctkWorkflowStackedWidget* stackedWidget = qobject_cast<ctkWorkflowStackedWidget*>(workflowWidget))
    {
    stackedWidget->associateStepWithPage(step3, 1);
    }
  else if (ctkWorkflowTabWidget* tabWidget = qobject_cast<ctkWorkflowTabWidget*>(workflowWidget))
    {
    tabWidget->associateStepWithPage(step3, 1, "tab2");
    }

  // icon test - add an icon to step3, should show up as a icon on the finish button
  step3->setIcon(step3->stepArea()->style()->standardIcon(QStyle::SP_ArrowUp));

  // add the step to the workflow
  workflow->addTransition(step2, step3);

  // create the qObjects that implement the required functions, and
  // communicate with the workflow using signals and slots
  ctkExampleWorkflowWidgetStepUsingSignalsAndSlots* qObject3 =
      new ctkExampleWorkflowWidgetStepUsingSignalsAndSlots(step3);

  qObject3->setWidget(step3->stepArea());

  // use the qObjects for validation
  QObject::connect(step3->ctkWorkflowStepQObject(), SIGNAL(invokeValidateCommand(const QString&)),
                   qObject3, SLOT(validate(const QString&)));

  // use the qObjects for entry processing
  QObject::connect(step3->ctkWorkflowStepQObject(), SIGNAL(invokeOnEntryCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)),
                   qObject3, SLOT(onEntry(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));

  // use the qObjects for exit processing
  QObject::connect(step3->ctkWorkflowStepQObject(), SIGNAL(invokeOnExitCommand(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)),
                   qObject3, SLOT(onExit(const ctkWorkflowStep*, const ctkWorkflowInterstepTransition::InterstepTransitionType)));

  // use the qObjects for populating the stepWidgetsList
  QObject::connect(step3->ctkWorkflowStepQObject(), SIGNAL(invokeCreateUserInterfaceCommand()), qObject3, SLOT(createUserInterface()));
  QObject::connect(qObject3, SIGNAL(createUserInterfaceComplete()), step3->ctkWorkflowStepQObject(), SIGNAL(createUserInterfaceComplete()));

  step3->setHasValidateCommand(1);
  step3->setHasOnEntryCommand(1);
  step3->setHasOnExitCommand(1);
  step3->setHasCreateUserInterfaceCommand(1);

  // restart the workflow
  workflow->start();

  // second user interaction test
  if (userInteractionSimulator2(app, step1, qObject1, step2, qObject2, step3, qObject3, workflow, workflowWidget, defaultTime) == EXIT_FAILURE)
    {
    return EXIT_FAILURE;
    }

  // stop the workflow
  workflow->stop();
  QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  app.exec();

  // make the second workflow step a finish step as well
  // TODO put this back once we can add multiple finish steps
//   finishSteps.push_back(step2);
//   step1->setFinishStepsToHaveButtonsInStepArea(finishSteps);
//   step2->setFinishStepsToHaveButtonsInStepArea(finishSteps);
//   step3->setFinishStepsToHaveButtonsInStepArea(finishSteps);
// //  workflow->addFinishStep(step2);
  
  // // restart the workflow
  // workflow->start();
  // QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  // app.exec();

  // // third user interfaction test
  // if (userInteractionSimulator3(app, step1, qObject1, step2, qObject2, step3, qObject3, workflow, workflowWidget, defaultTime) == EXIT_FAILURE)
  //   {
  //   return EXIT_FAILURE;
  //   }

  // // stop the workflow
  // workflow->stop();
  // QTimer::singleShot(defaultTime, &app, SLOT(quit()));
  // app.exec();
  
  // handles deletion of the workflowWidget, workflow, steps, states
  // and transitions
  delete workflowWidget;

  return EXIT_SUCCESS;
}