Files
qt-creator/tests/manual/tasking/demo/main.cpp
Jarek Kobus 37b6cb7f90 TaskTree: Get rid of onGroupError element
Make it possible to setup onGroupDone element with additional
OnDone argument.
The onGroupDone handler may accept extra DoneResult argument.
The onGroupDone handler may also tweak the success bit of a group.

All above features conform to the behavior of the task done handler.

Task-number: QTCREATORBUG-29834
Change-Id: I125bdfe155e585678fb33410632246401cbc9390
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
2023-11-07 14:08:04 +00:00

279 lines
8.8 KiB
C++

// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "taskwidget.h"
#include <tasking/tasktree.h>
#include <QApplication>
#include <QBoxLayout>
#include <QGroupBox>
#include <QProgressBar>
#include <QScrollArea>
#include <QTimer>
#include <QToolButton>
using namespace Tasking;
using namespace std::chrono;
static QWidget *hr()
{
auto frame = new QFrame;
frame->setFrameShape(QFrame::HLine);
frame->setFrameShadow(QFrame::Sunken);
return frame;
}
static QWidget *taskGroup(QWidget *groupWidget, const QList<QWidget *> &widgets)
{
QWidget *widget = new QWidget;
QBoxLayout *layout = new QHBoxLayout(widget);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(groupWidget);
QGroupBox *groupBox = new QGroupBox;
QBoxLayout *subLayout = new QVBoxLayout(groupBox);
for (int i = 0; i < widgets.size(); ++i) {
if (i > 0)
subLayout->addWidget(hr());
subLayout->addWidget(widgets.at(i));
}
layout->addWidget(groupBox);
return widget;
}
static State resultToState(DoneWith result)
{
return result == DoneWith::Success ? State::Done : State::Error;
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget mainWidget;
mainWidget.setWindowTitle("Task Tree Demo");
// Non-task GUI
QToolButton *startButton = new QToolButton;
startButton->setText("Start");
QToolButton *stopButton = new QToolButton;
stopButton->setText("Stop");
QToolButton *resetButton = new QToolButton;
resetButton->setText("Reset");
QProgressBar *progressBar = new QProgressBar;
QScrollArea *scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(true);
QWidget *scrollAreaWidget = new QWidget;
// Task GUI
QList<StateWidget *> allStateWidgets;
auto createGroupWidget = [&allStateWidgets] {
auto *widget = new GroupWidget();
allStateWidgets.append(widget);
return widget;
};
auto createTaskWidget = [&allStateWidgets] {
auto *widget = new TaskWidget();
allStateWidgets.append(widget);
return widget;
};
GroupWidget *rootGroup = createGroupWidget();
GroupWidget *groupTask_1 = createGroupWidget();
TaskWidget *task_1_1 = createTaskWidget();
TaskWidget *task_1_2 = createTaskWidget();
TaskWidget *task_1_3 = createTaskWidget();
TaskWidget *task_2 = createTaskWidget();
TaskWidget *task_3 = createTaskWidget();
GroupWidget *groupTask_4 = createGroupWidget();
TaskWidget *task_4_1 = createTaskWidget();
TaskWidget *task_4_2 = createTaskWidget();
GroupWidget *groupTask_4_3 = createGroupWidget();
TaskWidget *task_4_3_1 = createTaskWidget();
TaskWidget *task_4_3_2 = createTaskWidget();
TaskWidget *task_4_3_3 = createTaskWidget();
TaskWidget *task_4_3_4 = createTaskWidget();
TaskWidget *task_4_4 = createTaskWidget();
TaskWidget *task_4_5 = createTaskWidget();
TaskWidget *task_5 = createTaskWidget();
// Task initial configuration
task_1_2->setBusyTime(2);
task_1_2->setSuccess(false);
task_1_3->setBusyTime(3);
task_4_3_1->setBusyTime(4);
task_4_3_2->setBusyTime(2);
task_4_3_3->setBusyTime(1);
task_4_3_4->setBusyTime(3);
task_4_3_4->setSuccess(false);
task_4_4->setBusyTime(6);
task_4_4->setBusyTime(3);
groupTask_1->setWorkflowPolicy(WorkflowPolicy::ContinueOnDone);
groupTask_4->setWorkflowPolicy(WorkflowPolicy::FinishAllAndDone);
groupTask_4_3->setExecuteMode(ExecuteMode::Parallel);
groupTask_4_3->setWorkflowPolicy(WorkflowPolicy::StopOnError);
// Task layout
{
QWidget *taskTree = taskGroup(rootGroup, {
taskGroup(groupTask_1, {
task_1_1,
task_1_2,
task_1_3
}),
task_2,
task_3,
taskGroup(groupTask_4, {
task_4_1,
task_4_2,
taskGroup(groupTask_4_3, {
task_4_3_1,
task_4_3_2,
task_4_3_3,
task_4_3_4,
}),
task_4_4,
task_4_5
}),
task_5
});
QBoxLayout *scrollLayout = new QVBoxLayout(scrollAreaWidget);
scrollLayout->addWidget(taskTree);
scrollLayout->addStretch();
scrollArea->setWidget(scrollAreaWidget);
QBoxLayout *mainLayout = new QVBoxLayout(&mainWidget);
QBoxLayout *subLayout = new QHBoxLayout;
subLayout->addWidget(startButton);
subLayout->addWidget(stopButton);
subLayout->addWidget(resetButton);
subLayout->addWidget(progressBar);
mainLayout->addLayout(subLayout);
mainLayout->addWidget(hr());
mainLayout->addWidget(scrollArea);
}
// Task tree (takes initial configuation from GUI)
std::unique_ptr<TaskTree> taskTree;
const auto createTask = [](TaskWidget *widget) {
const milliseconds timeout{widget->busyTime() * 1000};
const auto setupTask = [widget, timeout](milliseconds &taskObject) {
taskObject = timeout;
widget->setState(State::Running);
};
const Group root {
widget->isSuccess() ? stopOnError : finishAllAndError,
TimeoutTask(setupTask),
onGroupDone([widget](DoneWith result) { widget->setState(resultToState(result)); })
};
return root;
};
const auto recipe = [&] {
const Group root {
rootGroup->executeMode(),
rootGroup->workflowPolicy(),
onGroupSetup([rootGroup] { rootGroup->setState(State::Running); }),
onGroupDone([rootGroup](DoneWith result) { rootGroup->setState(resultToState(result)); }),
Group {
groupTask_1->executeMode(),
groupTask_1->workflowPolicy(),
onGroupSetup([groupTask_1] { groupTask_1->setState(State::Running); }),
onGroupDone([groupTask_1](DoneWith result) { groupTask_1->setState(resultToState(result)); }),
createTask(task_1_1),
createTask(task_1_2),
createTask(task_1_3)
},
createTask(task_2),
createTask(task_3),
Group {
groupTask_4->executeMode(),
groupTask_4->workflowPolicy(),
onGroupSetup([groupTask_4] { groupTask_4->setState(State::Running); }),
onGroupDone([groupTask_4](DoneWith result) { groupTask_4->setState(resultToState(result)); }),
createTask(task_4_1),
createTask(task_4_2),
Group {
groupTask_4_3->executeMode(),
groupTask_4_3->workflowPolicy(),
onGroupSetup([groupTask_4_3] { groupTask_4_3->setState(State::Running); }),
onGroupDone([groupTask_4_3](DoneWith result) { groupTask_4_3->setState(resultToState(result)); }),
createTask(task_4_3_1),
createTask(task_4_3_2),
createTask(task_4_3_3),
createTask(task_4_3_4)
},
createTask(task_4_4),
createTask(task_4_5)
},
createTask(task_5)
};
return root;
};
// Non-task GUI handling
const auto createTaskTree = [&] {
TaskTree *taskTree = new TaskTree(recipe());
progressBar->setMaximum(taskTree->progressMaximum());
QObject::connect(taskTree, &TaskTree::progressValueChanged,
progressBar, &QProgressBar::setValue);
return taskTree;
};
const auto stopTaskTree = [&] {
if (taskTree)
taskTree->stop();
// TODO: unlock GUI controls?
};
const auto resetTaskTree = [&] {
if (!taskTree)
return;
stopTaskTree();
taskTree.reset();
for (StateWidget *widget : allStateWidgets)
widget->setState(State::Initial);
progressBar->setValue(0);
};
auto startTaskTree = [&] {
resetTaskTree();
taskTree.reset(createTaskTree());
taskTree->start();
// TODO: lock GUI controls?
};
QObject::connect(startButton, &QAbstractButton::clicked, startTaskTree);
QObject::connect(stopButton, &QAbstractButton::clicked, stopTaskTree);
QObject::connect(resetButton, &QAbstractButton::clicked, resetTaskTree);
// Hack in order to show initial size minimal, but without scrollbars.
// Apparently setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow) doesn't work.
const int margin = 4;
scrollArea->setMinimumSize(scrollAreaWidget->minimumSizeHint().grownBy({0, 0, margin, margin}));
QTimer::singleShot(0, scrollArea, [&] { scrollArea->setMinimumSize({0, 0}); });
mainWidget.show();
return app.exec();
}