Files
qt-creator/tests/manual/tasking/demo/main.cpp
Jarek Kobus 1da7f18fb7 TaskTree: Introduce List element
The List element of GroupItem type is a helper for
constructing Group content with an initializer lists.
Since there is no easy way of mixing items and lists of items
inside the initializer list, the List element encloses
the list of children in a single GroupItem element making it
possible to mix the lists of GroupItems with individual
GroupItem elements on a single initializer list.

This addresses the 25th point in the master task below.

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

289 lines
8.9 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 <QLabel>
#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)
{
switch (result) {
case DoneWith::Success : return State::Success;
case DoneWith::Error : return State::Error;
case DoneWith::Cancel : return State::Canceled;
}
return State::Initial;
}
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<GroupWidget *> allGroupWidgets;
QList<TaskWidget *> allTaskWidgets;
auto createGroupWidget = [&allGroupWidgets] {
auto *widget = new GroupWidget;
allGroupWidgets.append(widget);
return widget;
};
auto createTaskWidget = [&allTaskWidgets] {
auto *widget = new TaskWidget;
allTaskWidgets.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);
mainLayout->addWidget(hr());
QBoxLayout *footerLayout = new QHBoxLayout;
footerLayout->addWidget(new StateLabel(State::Initial));
footerLayout->addWidget(new StateLabel(State::Running));
footerLayout->addWidget(new StateLabel(State::Success));
footerLayout->addWidget(new StateLabel(State::Error));
footerLayout->addWidget(new StateLabel(State::Canceled));
mainLayout->addLayout(footerLayout);
}
// Task tree (takes initial configuation from GUI)
std::unique_ptr<TaskTree> taskTree;
const auto createGroup = [](GroupWidget *widget) {
return List {
widget->executeMode(),
widget->workflowPolicy(),
onGroupSetup([widget] { widget->setState(State::Running); }),
onGroupDone([widget](DoneWith result) { widget->setState(resultToState(result)); }),
};
};
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 {
createGroup(rootGroup),
Group {
createGroup(groupTask_1),
createTask(task_1_1),
createTask(task_1_2),
createTask(task_1_3)
},
createTask(task_2),
createTask(task_3),
Group {
createGroup(groupTask_4),
createTask(task_4_1),
createTask(task_4_2),
Group {
createGroup(groupTask_4_3),
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 (GroupWidget *widget : allGroupWidgets)
widget->setState(State::Initial);
for (TaskWidget *widget : allTaskWidgets)
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();
}