diff --git a/src/akonadi/akonadiserializer.cpp b/src/akonadi/akonadiserializer.cpp --- a/src/akonadi/akonadiserializer.cpp +++ b/src/akonadi/akonadiserializer.cpp @@ -67,7 +67,7 @@ QString Serializer::itemUid(const Item &item) { - if (isTaskItem(item)) { + if (item.hasPayload()) { const auto todo = item.payload(); return todo->uid(); } else { diff --git a/src/akonadi/akonaditaskqueries.h b/src/akonadi/akonaditaskqueries.h --- a/src/akonadi/akonaditaskqueries.h +++ b/src/akonadi/akonaditaskqueries.h @@ -62,6 +62,7 @@ TaskResult::Ptr findInboxTopLevel() const Q_DECL_OVERRIDE; TaskResult::Ptr findWorkdayTopLevel() const Q_DECL_OVERRIDE; ContextResult::Ptr findContexts(Domain::Task::Ptr task) const Q_DECL_OVERRIDE; + Domain::Project::Ptr findProjectForTask(Domain::Task::Ptr task) const Q_DECL_OVERRIDE; private slots: void onWorkdayPollTimeout(); diff --git a/src/akonadi/akonaditaskqueries.cpp b/src/akonadi/akonaditaskqueries.cpp --- a/src/akonadi/akonaditaskqueries.cpp +++ b/src/akonadi/akonaditaskqueries.cpp @@ -73,13 +73,38 @@ Akonadi::Item item = m_serializer->createItemFromTask(task); auto &query = m_findChildren[item.id()]; auto fetch = m_helpers->fetchSiblings(item); - auto predicate = [this, task] (const Akonadi::Item &item) { - return m_serializer->isTaskChild(task, item); + auto predicate = [this, task] (const Akonadi::Item &childItem) { + return m_serializer->isTaskChild(task, childItem); }; m_integrator->bind("TaskQueries::findChildren", query, fetch, predicate); return query->result(); } +Domain::Project::Ptr TaskQueries::findProjectForTask(Domain::Task::Ptr task) const +{ + Akonadi::Item childItem = m_serializer->createItemFromTask(task); + + const auto items = m_cache->items(childItem.parentCollection()); + auto parentUid = m_serializer->relatedUidFromItem(childItem); + while (!parentUid.isEmpty()) { + const auto parent = std::find_if(items.cbegin(), items.cend(), + [this, parentUid] (const Akonadi::Item &item) { + return m_serializer->itemUid(item) == parentUid; + }); + if (parent == items.cend()) { + break; + } + + auto project = m_serializer->createProjectFromItem(*parent); + if (m_serializer->isProjectItem(*parent)) { + return project; + } + + parentUid = m_serializer->relatedUidFromItem(*parent); + } + return nullptr; +} + TaskQueries::TaskResult::Ptr TaskQueries::findTopLevel() const { auto fetch = m_helpers->fetchItems(StorageInterface::Tasks); diff --git a/src/domain/taskqueries.h b/src/domain/taskqueries.h --- a/src/domain/taskqueries.h +++ b/src/domain/taskqueries.h @@ -27,6 +27,7 @@ #include "context.h" #include "queryresult.h" #include "task.h" +#include "project.h" namespace Domain { @@ -49,6 +50,8 @@ virtual QueryResult::Ptr findWorkdayTopLevel() const = 0; virtual QueryResult::Ptr findContexts(Task::Ptr task) const = 0; + + virtual Project::Ptr findProjectForTask(Task::Ptr task) const = 0; }; } diff --git a/src/presentation/workdaypagemodel.cpp b/src/presentation/workdaypagemodel.cpp --- a/src/presentation/workdaypagemodel.cpp +++ b/src/presentation/workdaypagemodel.cpp @@ -105,20 +105,28 @@ return artifact.dynamicCast() ? (defaultFlags | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled) : defaultFlags; }; - auto data = [](const Domain::Artifact::Ptr &artifact, int role) -> QVariant { - if (role != Qt::DisplayRole - && role != Qt::EditRole - && role != Qt::CheckStateRole) { - return QVariant(); - } - - if (role == Qt::DisplayRole || role == Qt::EditRole) { - return artifact->title(); - } else if (auto task = artifact.dynamicCast()) { - return task->isDone() ? Qt::Checked : Qt::Unchecked; - } else { - return QVariant(); + auto data = [this](const Domain::Artifact::Ptr &artifact, int role) -> QVariant { + switch (role) { + case Qt::DisplayRole: + case Qt::EditRole: + return artifact->title(); + case Qt::CheckStateRole: + if (auto task = artifact.dynamicCast()) { + return task->isDone() ? Qt::Checked : Qt::Unchecked; + } + break; + case Qt::ToolTipRole: + if (auto task = artifact.dynamicCast()) { + auto project = m_taskQueries->findProjectForTask(task); + if (project) { + return project->name(); + } + } + break; + default: + break; } + return QVariant(); }; auto setData = [this](const Domain::Artifact::Ptr &artifact, const QVariant &value, int role) { diff --git a/tests/units/akonadi/akonaditaskqueriestest.cpp b/tests/units/akonadi/akonaditaskqueriestest.cpp --- a/tests/units/akonadi/akonaditaskqueriestest.cpp +++ b/tests/units/akonadi/akonaditaskqueriestest.cpp @@ -26,6 +26,7 @@ #include "akonadi/akonadicachingstorage.h" #include "akonadi/akonaditaskqueries.h" #include "akonadi/akonadiserializer.h" +#include "akonadi/akonadiitemfetchjobinterface.h" #include "testlib/akonadifakedata.h" #include "testlib/gencollection.h" @@ -256,6 +257,52 @@ QCOMPARE(result->data().at(1)->title(), QStringLiteral("44")); } + void shouldLookInCollectionToFindProjectForTask() + { + // GIVEN + AkonadiFakeData data; + + // One top level collection + auto collection = GenCollection().withId(42).withRootAsParent().withTaskContent(); + data.createCollection(collection); + + // Three tasks in the collection (two being children of the first one) + data.createItem(GenTodo().withId(42).asProject().withParent(42) + .withTitle(QStringLiteral("42")).withUid(QStringLiteral("uid-42"))); + data.createItem(GenTodo().withId(43).withParent(42) + .withTitle(QStringLiteral("43")).withUid(QStringLiteral("uid-43")) + .withParentUid(QStringLiteral("uid-42"))); + data.createItem(GenTodo().withId(44).withParent(42) + .withTitle(QStringLiteral("44")).withUid(QStringLiteral("uid-44")) + .withParentUid(QStringLiteral("uid-42"))); + + // WHEN + auto serializer = Akonadi::Serializer::Ptr(new Akonadi::Serializer); + + auto cache = Akonadi::Cache::Ptr::create(serializer, Akonadi::MonitorInterface::Ptr(data.createMonitor())); + auto storage = createCachingStorage(data, cache); + QScopedPointer queries(new Akonadi::TaskQueries(storage, + serializer, + Akonadi::MonitorInterface::Ptr(data.createMonitor()), + cache)); + auto task = serializer->createTaskFromItem(data.item(44)); + // populate cache for collection + auto *fetchJob = storage->fetchItems(collection); + QVERIFY2(fetchJob->kjob()->exec(), qPrintable(fetchJob->kjob()->errorString())); + + auto parentTask = queries->findProjectForTask(task); + + // THEN + QVERIFY(parentTask); + + QCOMPARE(parentTask->name(), QStringLiteral("42")); + + // Should not change anything + parentTask = queries->findProjectForTask(task); + + QCOMPARE(parentTask->name(), QStringLiteral("42")); + } + void shouldNotCrashWhenWeAskAgainTheSameChildrenList() { // GIVEN