From 64d0c0a799cad75b202a82261f8e6dd84e9c4cab Mon Sep 17 00:00:00 2001 From: Thomas Kroes Date: Tue, 26 Sep 2023 19:43:56 +0200 Subject: [PATCH] Add some helper fucntions to the abstract tasks model Simplify some code in the abstract tasks tree model Work on modal task handler bug (wip) [skip ci] --- HDPS/src/AbstractTasksModel.cpp | 17 +++++++++ HDPS/src/AbstractTasksModel.h | 6 ++++ HDPS/src/BackgroundTaskTester.cpp | 2 ++ HDPS/src/ModalTaskHandler.cpp | 32 +++++++++-------- HDPS/src/ModalTaskTester.cpp | 18 ++++++++-- HDPS/src/Task.h | 6 ++-- HDPS/src/TasksTreeModel.cpp | 55 ++++++++++++++++++----------- HDPS/src/actions/TaskAction.cpp | 7 ++-- HDPS/src/private/ProjectManager.cpp | 4 +++ 9 files changed, 103 insertions(+), 44 deletions(-) diff --git a/HDPS/src/AbstractTasksModel.cpp b/HDPS/src/AbstractTasksModel.cpp index 2fc84bde5..485889923 100644 --- a/HDPS/src/AbstractTasksModel.cpp +++ b/HDPS/src/AbstractTasksModel.cpp @@ -524,4 +524,21 @@ AbstractTasksModel::AbstractTasksModel(QObject* parent /*= nullptr*/) : setHorizontalHeaderItem(static_cast(column), new HeaderItem(columnInfo[column])); } +QStandardItem* AbstractTasksModel::itemFromTask(Task* task) const +{ + const auto matches = match(index(0, static_cast(Column::ID)), Qt::EditRole, task->getId(), 1, Qt::MatchExactly | Qt::MatchRecursive); + + if (matches.isEmpty()) + throw std::runtime_error(QString("%1 not found").arg(task->getParentTask()->getName()).toStdString()); + + auto item = itemFromIndex(matches.first().siblingAtColumn(static_cast(Column::ExpandCollapse))); + + Q_ASSERT(item != nullptr); + + if (item == nullptr) + throw std::runtime_error("Parent standard item may not be a nullptr"); + + return item; +} + } diff --git a/HDPS/src/AbstractTasksModel.h b/HDPS/src/AbstractTasksModel.h index 005cf12c7..f6294184a 100644 --- a/HDPS/src/AbstractTasksModel.h +++ b/HDPS/src/AbstractTasksModel.h @@ -379,6 +379,12 @@ class AbstractTasksModel : public QStandardItemModel */ AbstractTasksModel(QObject* parent = nullptr); + /** + * Get item from \p task + * @return Pointer to found item, nullptr otherwise + */ + QStandardItem* itemFromTask(Task* task) const; + friend class Item; }; diff --git a/HDPS/src/BackgroundTaskTester.cpp b/HDPS/src/BackgroundTaskTester.cpp index 649c75756..1cb1e3512 100644 --- a/HDPS/src/BackgroundTaskTester.cpp +++ b/HDPS/src/BackgroundTaskTester.cpp @@ -23,6 +23,8 @@ BackgroundTaskTester::BackgroundTaskTester(QObject* parent, const QString& name) const auto addChildTask = [this, &timers](const QString& name, QStringList tasks, int interval) -> Task* { auto childTask = new BackgroundTask(nullptr, name); + //childTask->setParentTask(Application::current()->getTask(Application::TaskType::OverallBackground)); + if (!tasks.isEmpty()) { childTask->setSubtasks(tasks); childTask->setRunning(); diff --git a/HDPS/src/ModalTaskHandler.cpp b/HDPS/src/ModalTaskHandler.cpp index 7b57dca14..154811cf2 100644 --- a/HDPS/src/ModalTaskHandler.cpp +++ b/HDPS/src/ModalTaskHandler.cpp @@ -46,15 +46,18 @@ ModalTaskHandler::ModalTaskHandler(QObject* parent) : connect(&_minimumDurationTimer, &QTimer::timeout, this, &ModalTaskHandler::updateDialogVisibility); - connect(&_tasksFilterModel, &QSortFilterProxyModel::layoutChanged, this, updateVisibilityDeferred); - connect(&_tasksFilterModel, &QSortFilterProxyModel::rowsInserted, this, updateVisibilityDeferred); - connect(&_tasksFilterModel, &QSortFilterProxyModel::rowsRemoved, this, updateVisibilityDeferred); + //connect(&_tasksFilterModel, &QSortFilterProxyModel::layoutChanged, this, [updateVisibilityDeferred]() { qDebug() << " QSortFilterProxyModel::layoutChanged"; }); + //connect(tasks().getTreeModel(), &QStandardItemModel::rowsInserted, this, [this, updateVisibilityDeferred]() { qDebug() << " QStandardItemModel::rowsInserted"; }); + connect(&_tasksFilterModel, &QSortFilterProxyModel::rowsInserted, this, [this, updateVisibilityDeferred]() { qDebug() << " QSortFilterProxyModel::rowsInserted"; updateDialogVisibility(); }); + connect(&_tasksFilterModel, &QSortFilterProxyModel::rowsRemoved, this, [this, updateVisibilityDeferred]() { qDebug() << " QSortFilterProxyModel::rowsRemoved"; updateDialogVisibility(); }); } void ModalTaskHandler::updateDialogVisibility() { const auto numberOfModalTasks = getTasksFilterModel().rowCount(); + qDebug() << " " << __FUNCTION__ << numberOfModalTasks; + for (int rowIndex = 0; rowIndex < numberOfModalTasks; ++rowIndex) { const auto sourceModelIndex = getTasksFilterModel().mapToSource(getTasksFilterModel().index(rowIndex, static_cast(AbstractTasksModel::Column::Progress))); @@ -68,7 +71,7 @@ void ModalTaskHandler::updateDialogVisibility() if (progressItem == nullptr) continue; - qDebug() << " " << __FUNCTION__ << progressItem->getTask()->getName(); + qDebug() << " " << __FUNCTION__ << progressItem->getTask()->getName(); } if (numberOfModalTasks == 0 && _modalTasksDialog.isVisible()) @@ -114,8 +117,7 @@ void ModalTaskHandler::ModalTasksDialog::numberOfModalTasksChanged() const auto numberOfModalTasks = tasksFilterModel.rowCount(); - if (numberOfModalTasks == 0) - return; + qDebug() << __FUNCTION__ << numberOfModalTasks; cleanLayout(); @@ -165,15 +167,15 @@ void ModalTaskHandler::ModalTasksDialog::numberOfModalTasksChanged() const auto clockIcon = Application::getIconFont("FontAwesome").getIcon("clock"); if (numberOfModalTasks == 1) { - const auto sourceModelIndex = tasksFilterModel.mapToSource(tasksFilterModel.index(0, 0)); - const auto item = dynamic_cast(tasks().getTreeModel()->itemFromIndex(sourceModelIndex)); - const auto task = item->getTask(); - const auto taskName = task->getName(); - const auto taskDescription = task->getDescription(); - const auto taskIcon = task->getIcon(); - - setWindowTitle(taskDescription.isEmpty() ? QString("Waiting for %1 to complete...").arg(taskName) : task->getDescription()); - setWindowIcon(taskIcon.isNull() ? clockIcon : taskIcon); + //const auto sourceModelIndex = tasksFilterModel.mapToSource(tasksFilterModel.index(0, 0)); + //const auto item = dynamic_cast(tasks().getTreeModel()->itemFromIndex(sourceModelIndex)); + //const auto task = item->getTask(); + //const auto taskName = task->getName(); + //const auto taskDescription = task->getDescription(); + //const auto taskIcon = task->getIcon(); + + //setWindowTitle(taskDescription.isEmpty() ? QString("Waiting for %1 to complete...").arg(taskName) : task->getDescription()); + //setWindowIcon(taskIcon.isNull() ? clockIcon : taskIcon); } else { setWindowTitle(QString("Waiting for %1 tasks to complete...").arg(QString::number(numberOfModalTasks))); diff --git a/HDPS/src/ModalTaskTester.cpp b/HDPS/src/ModalTaskTester.cpp index 8fb5bbbb2..9802a2b14 100644 --- a/HDPS/src/ModalTaskTester.cpp +++ b/HDPS/src/ModalTaskTester.cpp @@ -5,6 +5,7 @@ #include "ModalTaskTester.h" #include "TaskTesterRunner.h" #include "ModalTask.h" +#include "BackgroundTask.h" #include @@ -14,9 +15,22 @@ namespace hdps ModalTaskTester::ModalTaskTester(QObject* parent, const QString& name) : AbstractTaskTester(parent, name) { - testRunningIndeterminate(); + auto modalTask = new ModalTask(this, "New modal task"); + + + auto childModalTask = new ModalTask(this, "Child modal task"); + + childModalTask->setParentTask(modalTask); + + childModalTask->setRunning(); + childModalTask->setRunning(); + childModalTask->setIdle(); + childModalTask->setRunning(); + childModalTask->setFinished(); + + //testRunningIndeterminate(); //testAggregation(); - testPerformance(); + //testPerformance(); } void ModalTaskTester::testRunningIndeterminate() diff --git a/HDPS/src/Task.h b/HDPS/src/Task.h index 61150af6c..c601a31ef 100644 --- a/HDPS/src/Task.h +++ b/HDPS/src/Task.h @@ -82,10 +82,10 @@ class Task : public QObject, public util::Serializable /** Couples scope enum value to scope name string */ static QMap scopeNames; - using TasksPtrs = QVector; + using TasksPtrs = QVector; using ProgressTextFormatter = std::function; - using Scopes = QVector; - using Statuses = QVector; + using Scopes = QVector; + using Statuses = QVector; private: diff --git a/HDPS/src/TasksTreeModel.cpp b/HDPS/src/TasksTreeModel.cpp index 7d39a5d38..ae65a68d1 100644 --- a/HDPS/src/TasksTreeModel.cpp +++ b/HDPS/src/TasksTreeModel.cpp @@ -10,7 +10,7 @@ #include #ifdef _DEBUG - #define TASKS_MODEL_VERBOSE + #define TASKS_TREE_MODEL_VERBOSE #endif namespace hdps @@ -41,24 +41,38 @@ void TasksTreeModel::taskAddedToTaskManager(Task* task) if (task == nullptr) throw std::runtime_error("Task may not be a nullptr"); - if (task->hasParentTask()) { - const auto matches = match(index(0, static_cast(Column::ID)), Qt::EditRole, task->getParentTask()->getId(), 1, Qt::MatchExactly | Qt::MatchRecursive); - - if (matches.isEmpty()) - throw std::runtime_error(QString("%1 not found").arg(task->getParentTask()->getName()).toStdString()); - - auto parentItem = itemFromIndex(matches.first().siblingAtColumn(static_cast(Column::ExpandCollapse))); + if (task->hasParentTask()) + itemFromTask(task->getParentTask())->appendRow(Row(task)); + else + appendRow(Row(task)); - Q_ASSERT(parentItem != nullptr); + connect(task, &Task::parentTaskChanged, this, [this, task](Task* previousParentTask, Task* currentParentTask) -> void { + try { + auto taskItem = itemFromTask(task); - if (parentItem == nullptr) - throw std::runtime_error("Parent standard item may not be a nullptr"); +#ifdef TASKS_TREE_MODEL_VERBOSE + qDebug() << __FUNCTION__ << task->getName() << currentParentTask->getName(); +#endif - parentItem->appendRow(Row(task)); - } - else { - appendRow(Row(task)); - } + if (previousParentTask) + removeRow(taskItem->row(), itemFromTask(previousParentTask)->index()); + else + removeRow(taskItem->row(), QModelIndex()); + + if (currentParentTask) + itemFromTask(task->getParentTask())->appendRow(Row(task)); + else + appendRow(Row(task)); + } + catch (std::exception& e) + { + exceptionMessageBox("Unable to re-parent task", e); + } + catch (...) + { + exceptionMessageBox("Unable to re-parent task"); + } + }); } catch (std::exception& e) { @@ -81,13 +95,12 @@ void TasksTreeModel::taskAboutToBeRemovedFromTaskManager(Task* task) if (task == nullptr) throw std::runtime_error("Task may not be a nullptr"); - const auto matches = match(index(0, static_cast(Column::ID)), Qt::EditRole, task->getId(), -1, Qt::MatchExactly | Qt::MatchRecursive); - - if (matches.empty()) - throw std::runtime_error(QString("%1 not found").arg(task->getName()).toStdString()); + auto taskItem = itemFromTask(task); - if (!removeRow(matches.first().row())) + if (!removeRow(taskItem->row(), taskItem->parent() ? taskItem->parent()->index() : QModelIndex())) throw std::runtime_error("Remove row failed"); + + disconnect(task, &Task::parentTaskChanged, this, nullptr); } catch (std::exception& e) { diff --git a/HDPS/src/actions/TaskAction.cpp b/HDPS/src/actions/TaskAction.cpp index 69e3d14d2..062c89256 100644 --- a/HDPS/src/actions/TaskAction.cpp +++ b/HDPS/src/actions/TaskAction.cpp @@ -60,7 +60,7 @@ void TaskAction::setTask(Task* task) _task = task; - const auto updateCancelTaskAction = [this]() -> void { + const auto updateKillTaskAction = [this]() -> void { Q_ASSERT(_task != nullptr); if (_task == nullptr) @@ -69,7 +69,7 @@ void TaskAction::setTask(Task* task) _killTaskAction.setToolTip(QString("Cancel %1").arg(_task->getName())); }; - updateCancelTaskAction(); + updateKillTaskAction(); const auto updateProgressAction = [this]() -> void { _progressAction.setProgress(static_cast(_task->getProgress() * 100.f)); @@ -77,7 +77,7 @@ void TaskAction::setTask(Task* task) updateProgressAction(); - connect(_task, &Task::nameChanged, this, updateCancelTaskAction); + connect(_task, &Task::nameChanged, this, updateKillTaskAction); connect(_task, &Task::progressChanged, this, updateProgressAction); connect(_task, &Task::progressTextChanged, this, &TaskAction::updateProgressActionTextFormat); connect(_task, &Task::statusChanged, this, &TaskAction::updateActionsReadOnly); @@ -112,6 +112,7 @@ void TaskAction::updateProgressActionRange() switch (_task->getStatus()) { case Task::Status::Idle: + _progressAction.setRange(0, 100); break; case Task::Status::Running: diff --git a/HDPS/src/private/ProjectManager.cpp b/HDPS/src/private/ProjectManager.cpp index e8bcac77c..1ee32ad97 100644 --- a/HDPS/src/private/ProjectManager.cpp +++ b/HDPS/src/private/ProjectManager.cpp @@ -453,6 +453,10 @@ void ProjectManager::openProject(QString filePath /*= ""*/, bool importDataOnly task.setSubtasks(QStringList() << decompressionTaskNames << "Create data hierarchy" << viewPluginsTaskNames); + connect(&archiver, &Archiver::taskStarted, this, [this](const QString& taskName) -> void { + _project->getTask().setSubtaskStarted(taskName, QString("extracting %1").arg(taskName)); + }); + connect(&archiver, &Archiver::taskFinished, this, [this](const QString& taskName) -> void { _project->getTask().setSubtaskFinished(taskName, QString("%1 extracted").arg(taskName)); });