TaskTree: Implement simple progress reporting

The progressMaximum is the number of tasks in tree.
The progressValueChanged signal is emitted whenever task is done
(advance by one) or when some number of tasks were skipped or stopped
due to workflow policy or dynamic setup group handler.

Change-Id: I403059a6466ae0534ef647c3c1c61c0318f10325
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2022-11-10 15:59:54 +01:00
parent e38db06203
commit a4b7e10861
3 changed files with 93 additions and 9 deletions

View File

@@ -84,12 +84,12 @@ public:
const TaskItem &task);
~TaskContainer();
void start();
void selectChildren();
int selectChildren(); // returns the skipped child count
void stop();
bool isRunning() const;
int taskCount() const;
void childDone(bool success);
void invokeEndHandler(bool success);
void invokeEndHandler(bool success, bool propagateToParent = true);
void resetSuccessBit();
void updateSuccessBit(bool success);
@@ -135,11 +135,46 @@ public:
: q(taskTree)
, m_root(this, nullptr, root) {}
void start() {
m_progressValue = 0;
emitStartedAndProgress();
m_root.start();
}
void stop() {
if (!m_root.isRunning())
return;
// TODO: should we have canceled flag (passed to handler)?
// Just one done handler with result flag:
// FinishedWithSuccess, FinishedWithError, Canceled, TimedOut.
// Canceled either directly by user, or by workflow policy - doesn't matter, in both
// cases canceled from outside.
m_root.stop();
emitError();
}
void advanceProgress(int byValue) {
if (byValue == 0)
return;
QTC_CHECK(byValue > 0);
QTC_CHECK(m_progressValue + byValue <= m_root.taskCount());
m_progressValue += byValue;
emitProgress();
}
void emitStartedAndProgress() {
GuardLocker locker(m_guard);
emit q->started();
emit q->progressValueChanged(m_progressValue);
}
void emitProgress() {
GuardLocker locker(m_guard);
emit q->progressValueChanged(m_progressValue);
}
void emitDone() {
QTC_CHECK(m_progressValue == m_root.taskCount());
GuardLocker locker(m_guard);
emit q->done();
}
void emitError() {
QTC_CHECK(m_progressValue == m_root.taskCount());
GuardLocker locker(m_guard);
emit q->errorOccurred();
}
@@ -147,6 +182,7 @@ public:
TaskTree *q = nullptr;
TaskNode m_root;
Guard m_guard;
int m_progressValue = 0;
};
TaskContainer::TaskContainer(TaskTreePrivate *taskTreePrivate, TaskContainer *parentContainer,
@@ -172,6 +208,7 @@ TaskContainer::~TaskContainer()
void TaskContainer::start()
{
m_currentIndex = 0;
m_groupConfig = {};
m_selectedChildren.clear();
@@ -187,11 +224,14 @@ void TaskContainer::start()
if (m_groupConfig.action == GroupAction::StopWithDone || m_groupConfig.action == GroupAction::StopWithError) {
const bool success = m_groupConfig.action == GroupAction::StopWithDone;
const int skippedTaskCount = taskCount();
m_taskTreePrivate->advanceProgress(skippedTaskCount);
invokeEndHandler(success);
return;
}
selectChildren();
const int skippedTaskCount = selectChildren();
m_taskTreePrivate->advanceProgress(skippedTaskCount);
if (m_selectedChildren.isEmpty()) {
invokeEndHandler(true);
@@ -213,21 +253,35 @@ void TaskContainer::start()
}
}
void TaskContainer::selectChildren()
int TaskContainer::selectChildren()
{
if (m_groupConfig.action != GroupAction::ContinueSelected) {
m_selectedChildren = m_children;
return;
return 0;
}
m_selectedChildren.clear();
int skippedTaskCount = 0;
for (int i = 0; i < m_children.size(); ++i) {
if (m_groupConfig.childrenToRun.contains(i))
m_selectedChildren.append(m_children.at(i));
else
skippedTaskCount += m_children.at(i)->taskCount();
}
return skippedTaskCount;
}
void TaskContainer::stop()
{
if (!isRunning())
return;
if (m_executeMode == TaskItem::ExecuteMode::Sequential) {
int skippedTaskCount = 0;
for (int i = m_currentIndex + 1; i < m_selectedChildren.size(); ++i)
skippedTaskCount += m_selectedChildren.at(i)->taskCount();
m_taskTreePrivate->advanceProgress(skippedTaskCount);
}
m_currentIndex = -1;
for (TaskNode *child : std::as_const(m_selectedChildren))
child->stop();
@@ -264,7 +318,7 @@ void TaskContainer::childDone(bool success)
m_selectedChildren.at(m_currentIndex)->start();
}
void TaskContainer::invokeEndHandler(bool success)
void TaskContainer::invokeEndHandler(bool success, bool propagateToParent)
{
m_currentIndex = -1;
m_successBit = success;
@@ -275,6 +329,10 @@ void TaskContainer::invokeEndHandler(bool success)
GuardLocker locker(m_taskTreePrivate->m_guard);
m_groupHandler.m_errorHandler();
}
if (!propagateToParent)
return;
if (m_parentContainer) {
m_parentContainer->childDone(success);
return;
@@ -329,6 +387,7 @@ bool TaskNode::start()
GuardLocker locker(m_container.m_taskTreePrivate->m_guard);
m_taskHandler.m_errorHandler(*m_task.get());
}
m_container.m_taskTreePrivate->advanceProgress(1);
m_task.release()->deleteLater();
@@ -342,8 +401,23 @@ bool TaskNode::start()
void TaskNode::stop()
{
if (!isRunning())
return;
if (!m_task) {
m_container.stop();
m_container.invokeEndHandler(false, false);
return;
}
// TODO: cancelHandler?
// TODO: call TaskInterface::stop() ?
if (m_taskHandler.m_errorHandler) {
GuardLocker locker(m_container.m_taskTreePrivate->m_guard);
m_taskHandler.m_errorHandler(*m_task.get());
}
m_container.m_taskTreePrivate->advanceProgress(1);
m_task.reset();
m_container.stop();
}
bool TaskNode::isRunning() const
@@ -422,14 +496,14 @@ void TaskTree::start()
QTC_ASSERT(!isRunning(), qWarning("The TaskTree is already running, ignoring..."); return);
QTC_ASSERT(!d->m_guard.isLocked(), qWarning("The start() is called from one of the"
"TaskTree handlers, ingoring..."); return);
d->m_root.start();
d->start();
}
void TaskTree::stop()
{
QTC_ASSERT(!d->m_guard.isLocked(), qWarning("The stop() is called from one of the"
"TaskTree handlers, ingoring..."); return);
d->m_root.stop();
d->stop();
}
bool TaskTree::isRunning() const
@@ -442,4 +516,9 @@ int TaskTree::taskCount() const
return d->m_root.taskCount();
}
int TaskTree::progressValue() const
{
return d->m_progressValue;
}
} // namespace Utils