forked from qt-creator/qt-creator
TaskTree: De-utils-ize manual test, rename it to demo
Change-Id: I80a2522f7ba12ee9b63c19d66e514d7047951733 Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -17,5 +17,5 @@ add_subdirectory(proparser)
|
|||||||
# add_subdirectory(search)
|
# add_subdirectory(search)
|
||||||
add_subdirectory(shootout)
|
add_subdirectory(shootout)
|
||||||
add_subdirectory(subdirfileiterator)
|
add_subdirectory(subdirfileiterator)
|
||||||
add_subdirectory(tasktree)
|
add_subdirectory(tasking)
|
||||||
add_subdirectory(widgets)
|
add_subdirectory(widgets)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Project {
|
|||||||
"proparser/testreader.qbs",
|
"proparser/testreader.qbs",
|
||||||
"shootout/shootout.qbs",
|
"shootout/shootout.qbs",
|
||||||
"subdirfileiterator/subdirfileiterator.qbs",
|
"subdirfileiterator/subdirfileiterator.qbs",
|
||||||
"tasktree/tasktree.qbs",
|
"tasking/demo/demo.qbs",
|
||||||
"widgets/widgets.qbs",
|
"widgets/widgets.qbs",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
1
tests/manual/tasking/CMakeLists.txt
Normal file
1
tests/manual/tasking/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
add_subdirectory(demo)
|
||||||
11
tests/manual/tasking/demo/CMakeLists.txt
Normal file
11
tests/manual/tasking/demo/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
add_qtc_test(tst_tasking_demo
|
||||||
|
MANUALTEST
|
||||||
|
DEPENDS Tasking Qt::Widgets
|
||||||
|
SOURCES
|
||||||
|
demo.qrc
|
||||||
|
main.cpp
|
||||||
|
progressindicator.h
|
||||||
|
progressindicator.cpp
|
||||||
|
taskwidget.h
|
||||||
|
taskwidget.cpp
|
||||||
|
)
|
||||||
18
tests/manual/tasking/demo/demo.qbs
Normal file
18
tests/manual/tasking/demo/demo.qbs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import qbs.FileInfo
|
||||||
|
|
||||||
|
QtcManualtest {
|
||||||
|
name: "Tasking demo"
|
||||||
|
type: ["application"]
|
||||||
|
|
||||||
|
Depends { name: "Qt"; submodules: ["widgets"] }
|
||||||
|
Depends { name: "Tasking" }
|
||||||
|
|
||||||
|
files: [
|
||||||
|
"demo.qrc",
|
||||||
|
"main.cpp",
|
||||||
|
"progressindicator.h",
|
||||||
|
"progressindicator.cpp",
|
||||||
|
"taskwidget.h",
|
||||||
|
"taskwidget.cpp",
|
||||||
|
]
|
||||||
|
}
|
||||||
6
tests/manual/tasking/demo/demo.qrc
Normal file
6
tests/manual/tasking/demo/demo.qrc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/" >
|
||||||
|
<file>icons/progressindicator.png</file>
|
||||||
|
<file>icons/progressindicator@2x.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
BIN
tests/manual/tasking/demo/icons/progressindicator.png
Normal file
BIN
tests/manual/tasking/demo/icons/progressindicator.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 336 B |
BIN
tests/manual/tasking/demo/icons/progressindicator@2x.png
Normal file
BIN
tests/manual/tasking/demo/icons/progressindicator@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 302 B |
@@ -1,53 +1,66 @@
|
|||||||
// Copyright (C) 2022 The Qt Company Ltd.
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
#include "taskwidget.h"
|
#include "taskwidget.h"
|
||||||
|
|
||||||
#include <utils/async.h>
|
#include <tasking/tasktree.h>
|
||||||
#include <utils/futuresynchronizer.h>
|
|
||||||
#include <utils/layoutbuilder.h>
|
|
||||||
#include <utils/theme/theme_p.h>
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCheckBox>
|
#include <QBoxLayout>
|
||||||
|
#include <QGroupBox>
|
||||||
#include <QProgressBar>
|
#include <QProgressBar>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Tasking;
|
||||||
|
|
||||||
// TODO: make tasks cancellable
|
using namespace std::chrono;
|
||||||
static void sleepInThread(QPromise<void> &promise, int seconds, bool reportSuccess)
|
|
||||||
|
static QWidget *hr()
|
||||||
{
|
{
|
||||||
QThread::sleep(seconds);
|
auto frame = new QFrame;
|
||||||
if (!reportSuccess)
|
frame->setFrameShape(QFrame::HLine);
|
||||||
promise.future().cancel();
|
frame->setFrameShadow(QFrame::Sunken);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
setCreatorTheme(new Theme("default", &app));
|
|
||||||
|
|
||||||
QWidget mainWidget;
|
QWidget mainWidget;
|
||||||
mainWidget.setWindowTitle("Task Tree Demo");
|
mainWidget.setWindowTitle("Task Tree Demo");
|
||||||
|
|
||||||
// Non-task GUI
|
// Non-task GUI
|
||||||
|
|
||||||
QToolButton *startButton = new QToolButton();
|
QToolButton *startButton = new QToolButton;
|
||||||
startButton->setText("Start");
|
startButton->setText("Start");
|
||||||
QToolButton *stopButton = new QToolButton();
|
QToolButton *stopButton = new QToolButton;
|
||||||
stopButton->setText("Stop");
|
stopButton->setText("Stop");
|
||||||
QToolButton *resetButton = new QToolButton();
|
QToolButton *resetButton = new QToolButton;
|
||||||
resetButton->setText("Reset");
|
resetButton->setText("Reset");
|
||||||
QProgressBar *progressBar = new QProgressBar();
|
QProgressBar *progressBar = new QProgressBar;
|
||||||
QCheckBox *synchronizerCheckBox = new QCheckBox("Use Future Synchronizer");
|
QScrollArea *scrollArea = new QScrollArea;
|
||||||
synchronizerCheckBox->setChecked(true);
|
|
||||||
QScrollArea *scrollArea = new QScrollArea();
|
|
||||||
scrollArea->setWidgetResizable(true);
|
scrollArea->setWidgetResizable(true);
|
||||||
QWidget *scrollAreaWidget = new QWidget();
|
QWidget *scrollAreaWidget = new QWidget;
|
||||||
|
|
||||||
// Task GUI
|
// Task GUI
|
||||||
|
|
||||||
@@ -100,120 +113,124 @@ int main(int argc, char *argv[])
|
|||||||
task_4_4->setBusyTime(6);
|
task_4_4->setBusyTime(6);
|
||||||
task_4_4->setBusyTime(3);
|
task_4_4->setBusyTime(3);
|
||||||
|
|
||||||
groupTask_1->setWorkflowPolicy(Tasking::WorkflowPolicy::ContinueOnDone);
|
groupTask_1->setWorkflowPolicy(WorkflowPolicy::ContinueOnDone);
|
||||||
groupTask_4->setWorkflowPolicy(Tasking::WorkflowPolicy::FinishAllAndDone);
|
groupTask_4->setWorkflowPolicy(WorkflowPolicy::FinishAllAndDone);
|
||||||
groupTask_4_3->setExecuteMode(ExecuteMode::Parallel);
|
groupTask_4_3->setExecuteMode(ExecuteMode::Parallel);
|
||||||
groupTask_4_3->setWorkflowPolicy(Tasking::WorkflowPolicy::StopOnError);
|
groupTask_4_3->setWorkflowPolicy(WorkflowPolicy::StopOnError);
|
||||||
|
|
||||||
// Task layout
|
// Task layout
|
||||||
|
|
||||||
{
|
{
|
||||||
using namespace Layouting;
|
QWidget *taskTree = taskGroup(rootGroup, {
|
||||||
|
taskGroup(groupTask_1, {
|
||||||
Column {
|
task_1_1,
|
||||||
TaskGroup { rootGroup, {
|
task_1_2,
|
||||||
TaskGroup { groupTask_1, {
|
task_1_3
|
||||||
task_1_1, hr,
|
}),
|
||||||
task_1_2, hr,
|
task_2,
|
||||||
task_1_3,
|
task_3,
|
||||||
}}, hr,
|
taskGroup(groupTask_4, {
|
||||||
task_2, hr,
|
task_4_1,
|
||||||
task_3, hr,
|
task_4_2,
|
||||||
TaskGroup { groupTask_4, {
|
taskGroup(groupTask_4_3, {
|
||||||
task_4_1, hr,
|
task_4_3_1,
|
||||||
task_4_2, hr,
|
task_4_3_2,
|
||||||
TaskGroup { groupTask_4_3, {
|
task_4_3_3,
|
||||||
task_4_3_1, hr,
|
task_4_3_4,
|
||||||
task_4_3_2, hr,
|
}),
|
||||||
task_4_3_3, hr,
|
task_4_4,
|
||||||
task_4_3_4,
|
task_4_5
|
||||||
}}, hr,
|
}),
|
||||||
task_4_4, hr,
|
task_5
|
||||||
task_4_5,
|
});
|
||||||
}}, hr,
|
QBoxLayout *scrollLayout = new QVBoxLayout(scrollAreaWidget);
|
||||||
task_5
|
scrollLayout->addWidget(taskTree);
|
||||||
}}, st
|
scrollLayout->addStretch();
|
||||||
}.attachTo(scrollAreaWidget);
|
|
||||||
|
|
||||||
scrollArea->setWidget(scrollAreaWidget);
|
scrollArea->setWidget(scrollAreaWidget);
|
||||||
|
|
||||||
Column {
|
QBoxLayout *mainLayout = new QVBoxLayout(&mainWidget);
|
||||||
Row { startButton, stopButton, resetButton, synchronizerCheckBox, progressBar },
|
QBoxLayout *subLayout = new QHBoxLayout;
|
||||||
hr,
|
subLayout->addWidget(startButton);
|
||||||
scrollArea
|
subLayout->addWidget(stopButton);
|
||||||
}.attachTo(&mainWidget);
|
subLayout->addWidget(resetButton);
|
||||||
|
subLayout->addWidget(progressBar);
|
||||||
|
mainLayout->addLayout(subLayout);
|
||||||
|
mainLayout->addWidget(hr());
|
||||||
|
mainLayout->addWidget(scrollArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Task tree creator (takes configuation from GUI)
|
// Task tree (takes initial configuation from GUI)
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
|
|
||||||
std::unique_ptr<TaskTree> taskTree;
|
std::unique_ptr<TaskTree> taskTree;
|
||||||
FutureSynchronizer synchronizer;
|
|
||||||
|
const auto createTask = [](TaskWidget *widget) -> TaskItem {
|
||||||
|
const auto setupTask = [](TaskWidget *widget) {
|
||||||
|
return [widget](milliseconds &taskObject) {
|
||||||
|
taskObject = milliseconds{widget->busyTime() * 1000};
|
||||||
|
widget->setState(State::Running);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (widget->isSuccess()) {
|
||||||
|
return TimeoutTask(setupTask(widget),
|
||||||
|
[widget](const milliseconds &) { widget->setState(State::Done); },
|
||||||
|
[widget](const milliseconds &) { widget->setState(State::Error); });
|
||||||
|
}
|
||||||
|
const Group root {
|
||||||
|
finishAllAndError,
|
||||||
|
TimeoutTask(setupTask(widget)),
|
||||||
|
onGroupDone([widget] { widget->setState(State::Done); }),
|
||||||
|
onGroupError([widget] { widget->setState(State::Error); })
|
||||||
|
};
|
||||||
|
return root;
|
||||||
|
};
|
||||||
|
|
||||||
auto treeRoot = [&] {
|
auto treeRoot = [&] {
|
||||||
|
|
||||||
auto taskItem = [sync = &synchronizer, synchronizerCheckBox](TaskWidget *widget) {
|
|
||||||
const auto setupHandler = [=](Async<void> &task) {
|
|
||||||
task.setConcurrentCallData(sleepInThread, widget->busyTime(), widget->isSuccess());
|
|
||||||
if (synchronizerCheckBox->isChecked())
|
|
||||||
task.setFutureSynchronizer(sync);
|
|
||||||
widget->setState(State::Running);
|
|
||||||
};
|
|
||||||
const auto doneHandler = [widget](const Async<void> &) {
|
|
||||||
widget->setState(State::Done);
|
|
||||||
};
|
|
||||||
const auto errorHandler = [widget](const Async<void> &) {
|
|
||||||
widget->setState(State::Error);
|
|
||||||
};
|
|
||||||
return AsyncTask<void>(setupHandler, doneHandler, errorHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
const Group root {
|
const Group root {
|
||||||
rootGroup->executeMode(),
|
rootGroup->executeMode(),
|
||||||
workflowPolicy(rootGroup->workflowPolicy()),
|
rootGroup->workflowPolicy(),
|
||||||
onGroupSetup([rootGroup] { rootGroup->setState(State::Running); }),
|
onGroupSetup([rootGroup] { rootGroup->setState(State::Running); }),
|
||||||
onGroupDone([rootGroup] { rootGroup->setState(State::Done); }),
|
onGroupDone([rootGroup] { rootGroup->setState(State::Done); }),
|
||||||
onGroupError([rootGroup] { rootGroup->setState(State::Error); }),
|
onGroupError([rootGroup] { rootGroup->setState(State::Error); }),
|
||||||
|
|
||||||
Group {
|
Group {
|
||||||
groupTask_1->executeMode(),
|
groupTask_1->executeMode(),
|
||||||
workflowPolicy(groupTask_1->workflowPolicy()),
|
groupTask_1->workflowPolicy(),
|
||||||
onGroupSetup([groupTask_1] { groupTask_1->setState(State::Running); }),
|
onGroupSetup([groupTask_1] { groupTask_1->setState(State::Running); }),
|
||||||
onGroupDone([groupTask_1] { groupTask_1->setState(State::Done); }),
|
onGroupDone([groupTask_1] { groupTask_1->setState(State::Done); }),
|
||||||
onGroupError([groupTask_1] { groupTask_1->setState(State::Error); }),
|
onGroupError([groupTask_1] { groupTask_1->setState(State::Error); }),
|
||||||
|
|
||||||
taskItem(task_1_1),
|
createTask(task_1_1),
|
||||||
taskItem(task_1_2),
|
createTask(task_1_2),
|
||||||
taskItem(task_1_3)
|
createTask(task_1_3)
|
||||||
},
|
},
|
||||||
taskItem(task_2),
|
createTask(task_2),
|
||||||
taskItem(task_3),
|
createTask(task_3),
|
||||||
Group {
|
Group {
|
||||||
groupTask_4->executeMode(),
|
groupTask_4->executeMode(),
|
||||||
workflowPolicy(groupTask_4->workflowPolicy()),
|
groupTask_4->workflowPolicy(),
|
||||||
onGroupSetup([groupTask_4] { groupTask_4->setState(State::Running); }),
|
onGroupSetup([groupTask_4] { groupTask_4->setState(State::Running); }),
|
||||||
onGroupDone([groupTask_4] { groupTask_4->setState(State::Done); }),
|
onGroupDone([groupTask_4] { groupTask_4->setState(State::Done); }),
|
||||||
onGroupError([groupTask_4] { groupTask_4->setState(State::Error); }),
|
onGroupError([groupTask_4] { groupTask_4->setState(State::Error); }),
|
||||||
|
|
||||||
taskItem(task_4_1),
|
createTask(task_4_1),
|
||||||
taskItem(task_4_2),
|
createTask(task_4_2),
|
||||||
Group {
|
Group {
|
||||||
groupTask_4_3->executeMode(),
|
groupTask_4_3->executeMode(),
|
||||||
workflowPolicy(groupTask_4_3->workflowPolicy()),
|
groupTask_4_3->workflowPolicy(),
|
||||||
onGroupSetup([groupTask_4_3] { groupTask_4_3->setState(State::Running); }),
|
onGroupSetup([groupTask_4_3] { groupTask_4_3->setState(State::Running); }),
|
||||||
onGroupDone([groupTask_4_3] { groupTask_4_3->setState(State::Done); }),
|
onGroupDone([groupTask_4_3] { groupTask_4_3->setState(State::Done); }),
|
||||||
onGroupError([groupTask_4_3] { groupTask_4_3->setState(State::Error); }),
|
onGroupError([groupTask_4_3] { groupTask_4_3->setState(State::Error); }),
|
||||||
|
|
||||||
taskItem(task_4_3_1),
|
createTask(task_4_3_1),
|
||||||
taskItem(task_4_3_2),
|
createTask(task_4_3_2),
|
||||||
taskItem(task_4_3_3),
|
createTask(task_4_3_3),
|
||||||
taskItem(task_4_3_4)
|
createTask(task_4_3_4)
|
||||||
},
|
},
|
||||||
taskItem(task_4_4),
|
createTask(task_4_4),
|
||||||
taskItem(task_4_5)
|
createTask(task_4_5)
|
||||||
},
|
},
|
||||||
taskItem(task_5)
|
createTask(task_5)
|
||||||
};
|
};
|
||||||
return root;
|
return root;
|
||||||
};
|
};
|
||||||
@@ -258,7 +275,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// Hack in order to show initial size minimal, but without scrollbars.
|
// Hack in order to show initial size minimal, but without scrollbars.
|
||||||
// Apparently setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow) doesn't work.
|
// Apparently setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow) doesn't work.
|
||||||
const int margin = 2;
|
const int margin = 4;
|
||||||
scrollArea->setMinimumSize(scrollAreaWidget->minimumSizeHint().grownBy({0, 0, margin, margin}));
|
scrollArea->setMinimumSize(scrollAreaWidget->minimumSizeHint().grownBy({0, 0, margin, margin}));
|
||||||
QTimer::singleShot(0, scrollArea, [&] { scrollArea->setMinimumSize({0, 0}); });
|
QTimer::singleShot(0, scrollArea, [&] { scrollArea->setMinimumSize({0, 0}); });
|
||||||
|
|
||||||
149
tests/manual/tasking/demo/progressindicator.cpp
Normal file
149
tests/manual/tasking/demo/progressindicator.cpp
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "progressindicator.h"
|
||||||
|
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class OverlayWidget : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using PaintFunction = std::function<void(QWidget *, QPainter &, QPaintEvent *)>;
|
||||||
|
|
||||||
|
explicit OverlayWidget(QWidget *parent = nullptr)
|
||||||
|
{
|
||||||
|
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
if (parent)
|
||||||
|
attachToWidget(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void attachToWidget(QWidget *parent)
|
||||||
|
{
|
||||||
|
if (parentWidget())
|
||||||
|
parentWidget()->removeEventFilter(this);
|
||||||
|
setParent(parent);
|
||||||
|
if (parent) {
|
||||||
|
parent->installEventFilter(this);
|
||||||
|
resizeToParent();
|
||||||
|
raise();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setPaintFunction(const PaintFunction &paint) { m_paint = paint; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *ev) override
|
||||||
|
{
|
||||||
|
if (obj == parent() && ev->type() == QEvent::Resize)
|
||||||
|
resizeToParent();
|
||||||
|
return QWidget::eventFilter(obj, ev);
|
||||||
|
}
|
||||||
|
void paintEvent(QPaintEvent *ev) override
|
||||||
|
{
|
||||||
|
if (m_paint) {
|
||||||
|
QPainter p(this);
|
||||||
|
m_paint(this, p, ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void resizeToParent() { setGeometry(QRect(QPoint(0, 0), parentWidget()->size())); }
|
||||||
|
|
||||||
|
PaintFunction m_paint;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ProgressIndicatorPainter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using UpdateCallback = std::function<void()>;
|
||||||
|
|
||||||
|
ProgressIndicatorPainter();
|
||||||
|
virtual ~ProgressIndicatorPainter() = default;
|
||||||
|
|
||||||
|
void setUpdateCallback(const UpdateCallback &cb) { m_callback = cb; }
|
||||||
|
|
||||||
|
QSize size() const { return m_pixmap.size() / m_pixmap.devicePixelRatio(); }
|
||||||
|
|
||||||
|
void paint(QPainter &painter, const QRect &rect) const;
|
||||||
|
void startAnimation() { m_timer.start(); }
|
||||||
|
void stopAnimation() { m_timer.stop(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void nextAnimationStep() { m_rotation = (m_rotation + m_rotationStep + 360) % 360; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int m_rotationStep = 45;
|
||||||
|
int m_rotation = 0;
|
||||||
|
QTimer m_timer;
|
||||||
|
QPixmap m_pixmap;
|
||||||
|
UpdateCallback m_callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
ProgressIndicatorPainter::ProgressIndicatorPainter()
|
||||||
|
{
|
||||||
|
m_timer.setSingleShot(false);
|
||||||
|
QObject::connect(&m_timer, &QTimer::timeout, &m_timer, [this] {
|
||||||
|
nextAnimationStep();
|
||||||
|
if (m_callback)
|
||||||
|
m_callback();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_timer.setInterval(100);
|
||||||
|
m_pixmap = QPixmap(":/icons/progressindicator.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressIndicatorPainter::paint(QPainter &painter, const QRect &rect) const
|
||||||
|
{
|
||||||
|
painter.save();
|
||||||
|
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||||
|
QPoint translate(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2);
|
||||||
|
QTransform t;
|
||||||
|
t.translate(translate.x(), translate.y());
|
||||||
|
t.rotate(m_rotation);
|
||||||
|
t.translate(-translate.x(), -translate.y());
|
||||||
|
painter.setTransform(t);
|
||||||
|
QSize pixmapUserSize(m_pixmap.size() / m_pixmap.devicePixelRatio());
|
||||||
|
painter.drawPixmap(QPoint(rect.x() + ((rect.width() - pixmapUserSize.width()) / 2),
|
||||||
|
rect.y() + ((rect.height() - pixmapUserSize.height()) / 2)),
|
||||||
|
m_pixmap);
|
||||||
|
painter.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProgressIndicatorWidget : public OverlayWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ProgressIndicatorWidget(QWidget *parent = nullptr)
|
||||||
|
: OverlayWidget(parent)
|
||||||
|
{
|
||||||
|
setPaintFunction(
|
||||||
|
[this](QWidget *w, QPainter &p, QPaintEvent *) { m_paint.paint(p, w->rect()); });
|
||||||
|
m_paint.setUpdateCallback([this] { update(); });
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize sizeHint() const final { return m_paint.size(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent *) final { m_paint.startAnimation(); }
|
||||||
|
void hideEvent(QHideEvent *) final { m_paint.stopAnimation(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ProgressIndicatorPainter m_paint;
|
||||||
|
};
|
||||||
|
|
||||||
|
ProgressIndicator::ProgressIndicator(QWidget *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_widget(new ProgressIndicatorWidget(parent)) {}
|
||||||
|
|
||||||
|
|
||||||
|
void ProgressIndicator::show()
|
||||||
|
{
|
||||||
|
m_widget->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgressIndicator::hide()
|
||||||
|
{
|
||||||
|
m_widget->hide();
|
||||||
|
}
|
||||||
21
tests/manual/tasking/demo/progressindicator.h
Normal file
21
tests/manual/tasking/demo/progressindicator.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#ifndef PROGRESSINDICATOR_H
|
||||||
|
#define PROGRESSINDICATOR_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class ProgressIndicator : public QObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProgressIndicator(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void show();
|
||||||
|
void hide();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ProgressIndicatorWidget *m_widget = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PROGRESSINDICATOR_H
|
||||||
@@ -1,20 +1,18 @@
|
|||||||
// Copyright (C) 2022 The Qt Company Ltd.
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
|
#include "progressindicator.h"
|
||||||
#include "taskwidget.h"
|
#include "taskwidget.h"
|
||||||
|
|
||||||
#include <utils/layoutbuilder.h>
|
#include <QBoxLayout>
|
||||||
#include <utils/progressindicator.h>
|
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QMetaEnum>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Tasking;
|
||||||
using namespace Layouting;
|
|
||||||
|
|
||||||
static QString colorButtonStyleSheet(const QColor &bgColor)
|
static QString colorButtonStyleSheet(const QColor &bgColor)
|
||||||
{
|
{
|
||||||
@@ -37,10 +35,10 @@ static QColor stateToColor(State state) {
|
|||||||
class StateIndicator : public QLabel
|
class StateIndicator : public QLabel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StateIndicator()
|
StateIndicator(QWidget *parent = nullptr)
|
||||||
|
: QLabel(parent)
|
||||||
{
|
{
|
||||||
m_progressIndicator = new ProgressIndicator(ProgressIndicatorSize::Small);
|
m_progressIndicator = new ProgressIndicator(this);
|
||||||
m_progressIndicator->attachToWidget(this);
|
|
||||||
m_progressIndicator->hide();
|
m_progressIndicator->hide();
|
||||||
updateState();
|
updateState();
|
||||||
}
|
}
|
||||||
@@ -67,9 +65,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
StateWidget::StateWidget()
|
StateWidget::StateWidget()
|
||||||
: m_stateIndicator(new StateIndicator)
|
: m_stateIndicator(new StateIndicator(this)) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void StateWidget::setState(State state)
|
void StateWidget::setState(State state)
|
||||||
{
|
{
|
||||||
@@ -86,14 +82,13 @@ TaskWidget::TaskWidget()
|
|||||||
setBusyTime(1);
|
setBusyTime(1);
|
||||||
setSuccess(true);
|
setSuccess(true);
|
||||||
|
|
||||||
Row {
|
QBoxLayout *layout = new QHBoxLayout(this);
|
||||||
m_stateIndicator,
|
layout->addWidget(m_stateIndicator);
|
||||||
m_infoLabel,
|
layout->addWidget(m_infoLabel);
|
||||||
m_spinBox,
|
layout->addWidget(m_spinBox);
|
||||||
m_checkBox,
|
layout->addWidget(m_checkBox);
|
||||||
st,
|
layout->addStretch();
|
||||||
noMargin,
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
}.attachTo(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskWidget::setBusyTime(int seconds)
|
void TaskWidget::setBusyTime(int seconds)
|
||||||
@@ -122,34 +117,32 @@ GroupWidget::GroupWidget()
|
|||||||
{
|
{
|
||||||
m_stateIndicator->setFixedWidth(30);
|
m_stateIndicator->setFixedWidth(30);
|
||||||
|
|
||||||
m_executeCombo->addItem("Sequential", (int)ExecuteMode::Sequential);
|
m_executeCombo->addItem("Sequential", int(ExecuteMode::Sequential));
|
||||||
m_executeCombo->addItem("Parallel", (int)ExecuteMode::Parallel);
|
m_executeCombo->addItem("Parallel", int(ExecuteMode::Parallel));
|
||||||
updateExecuteMode();
|
updateExecuteMode();
|
||||||
connect(m_executeCombo, &QComboBox::currentIndexChanged, this, [this](int index) {
|
connect(m_executeCombo, &QComboBox::currentIndexChanged, this, [this](int index) {
|
||||||
m_executeMode = (ExecuteMode)m_executeCombo->itemData(index).toInt();
|
m_executeMode = (ExecuteMode)m_executeCombo->itemData(index).toInt();
|
||||||
});
|
});
|
||||||
|
|
||||||
m_workflowCombo->addItem("Stop On Error", (int)Tasking::WorkflowPolicy::StopOnError);
|
const QMetaEnum workflow = QMetaEnum::fromType<WorkflowPolicy>();
|
||||||
m_workflowCombo->addItem("Cont On Error", (int)Tasking::WorkflowPolicy::ContinueOnError);
|
for (int i = 0; i < workflow.keyCount(); ++i)
|
||||||
m_workflowCombo->addItem("Stop On Done", (int)Tasking::WorkflowPolicy::StopOnDone);
|
m_workflowCombo->addItem(workflow.key(i), workflow.value(i));
|
||||||
m_workflowCombo->addItem("Cont On Done", (int)Tasking::WorkflowPolicy::ContinueOnDone);
|
|
||||||
m_workflowCombo->addItem("Optional", (int)Tasking::WorkflowPolicy::FinishAllAndDone);
|
|
||||||
updateWorkflowPolicy();
|
updateWorkflowPolicy();
|
||||||
connect(m_workflowCombo, &QComboBox::currentIndexChanged, this, [this](int index) {
|
connect(m_workflowCombo, &QComboBox::currentIndexChanged, this, [this](int index) {
|
||||||
m_workflowPolicy = (Tasking::WorkflowPolicy)m_workflowCombo->itemData(index).toInt();
|
m_workflowPolicy = (WorkflowPolicy)m_workflowCombo->itemData(index).toInt();
|
||||||
});
|
});
|
||||||
|
|
||||||
Row {
|
QBoxLayout *layout = new QHBoxLayout(this);
|
||||||
m_stateIndicator,
|
layout->addWidget(m_stateIndicator);
|
||||||
Column {
|
QBoxLayout *subLayout = new QVBoxLayout;
|
||||||
new QLabel("Execute:"),
|
subLayout->addWidget(new QLabel("Execute Mode:"));
|
||||||
m_executeCombo,
|
subLayout->addWidget(m_executeCombo);
|
||||||
new QLabel("Workflow:"),
|
subLayout->addWidget(new QLabel("Workflow Policy:"));
|
||||||
m_workflowCombo,
|
subLayout->addWidget(m_workflowCombo);
|
||||||
st,
|
subLayout->addStretch();
|
||||||
noMargin
|
layout->addLayout(subLayout);
|
||||||
}
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
}.attachTo(this);
|
|
||||||
|
|
||||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||||
}
|
}
|
||||||
@@ -165,12 +158,12 @@ void GroupWidget::updateExecuteMode()
|
|||||||
m_executeCombo->setCurrentIndex(m_executeCombo->findData((int)m_executeMode));
|
m_executeCombo->setCurrentIndex(m_executeCombo->findData((int)m_executeMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
Tasking::TaskItem GroupWidget::executeMode() const
|
TaskItem GroupWidget::executeMode() const
|
||||||
{
|
{
|
||||||
return m_executeMode == ExecuteMode::Sequential ? Tasking::sequential : Tasking::parallel;
|
return m_executeMode == ExecuteMode::Sequential ? sequential : parallel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupWidget::setWorkflowPolicy(Tasking::WorkflowPolicy policy)
|
void GroupWidget::setWorkflowPolicy(WorkflowPolicy policy)
|
||||||
{
|
{
|
||||||
m_workflowPolicy = policy;
|
m_workflowPolicy = policy;
|
||||||
updateWorkflowPolicy();
|
updateWorkflowPolicy();
|
||||||
@@ -181,13 +174,7 @@ void GroupWidget::updateWorkflowPolicy()
|
|||||||
m_workflowCombo->setCurrentIndex(m_workflowCombo->findData((int)m_workflowPolicy));
|
m_workflowCombo->setCurrentIndex(m_workflowCombo->findData((int)m_workflowPolicy));
|
||||||
}
|
}
|
||||||
|
|
||||||
Tasking::WorkflowPolicy GroupWidget::workflowPolicy() const
|
TaskItem GroupWidget::workflowPolicy() const
|
||||||
{
|
{
|
||||||
return m_workflowPolicy;
|
return Tasking::workflowPolicy(m_workflowPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createItem(Layouting::LayoutItem *item, const TaskGroup &taskGroup)
|
|
||||||
{
|
|
||||||
item->addItems({taskGroup.group, Group { taskGroup.items }, br});
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
// Copyright (C) 2022 The Qt Company Ltd.
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
#include <solutions/tasking/tasktree.h>
|
#ifndef TASKWIDGET_H
|
||||||
|
#define TASKWIDGET_H
|
||||||
|
|
||||||
#include <utils/layoutbuilder.h>
|
#include <tasking/tasktree.h>
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ public:
|
|||||||
Tasking::TaskItem executeMode() const;
|
Tasking::TaskItem executeMode() const;
|
||||||
|
|
||||||
void setWorkflowPolicy(Tasking::WorkflowPolicy policy);
|
void setWorkflowPolicy(Tasking::WorkflowPolicy policy);
|
||||||
Tasking::WorkflowPolicy workflowPolicy() const;
|
Tasking::TaskItem workflowPolicy() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateExecuteMode();
|
void updateExecuteMode();
|
||||||
@@ -77,11 +78,4 @@ private:
|
|||||||
Tasking::WorkflowPolicy m_workflowPolicy = Tasking::WorkflowPolicy::StopOnError;
|
Tasking::WorkflowPolicy m_workflowPolicy = Tasking::WorkflowPolicy::StopOnError;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TaskGroup
|
#endif // TASKWIDGET_H
|
||||||
{
|
|
||||||
public:
|
|
||||||
QWidget *group;
|
|
||||||
Layouting::Column items;
|
|
||||||
};
|
|
||||||
|
|
||||||
void createItem(Layouting::LayoutItem *item, const TaskGroup &taskGroup);
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
add_qtc_test(tst_manual_tasktree
|
|
||||||
MANUALTEST
|
|
||||||
DEPENDS Utils
|
|
||||||
SOURCES
|
|
||||||
main.cpp taskwidget.h taskwidget.cpp
|
|
||||||
)
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import qbs.FileInfo
|
|
||||||
|
|
||||||
QtcManualtest {
|
|
||||||
name: "Manual TaskTree test"
|
|
||||||
type: ["application"]
|
|
||||||
|
|
||||||
Depends { name: "Utils" }
|
|
||||||
|
|
||||||
files: [
|
|
||||||
"main.cpp",
|
|
||||||
"taskwidget.h",
|
|
||||||
"taskwidget.cpp",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user