diff --git a/src/akonadi/akonaditaskqueries.cpp b/src/akonadi/akonaditaskqueries.cpp --- a/src/akonadi/akonaditaskqueries.cpp +++ b/src/akonadi/akonaditaskqueries.cpp @@ -111,7 +111,7 @@ } auto fetch = m_helpers->fetchItems(StorageInterface::Tasks); - auto predicate = [this] (const Akonadi::Item &item) { + auto isWorkdayItem = [this] (const Akonadi::Item &item) { if (!m_serializer->isTaskItem(item)) return false; @@ -131,6 +131,30 @@ else return pastStartDate || pastDueDate; }; + auto predicate = [this, isWorkdayItem] (const Akonadi::Item &item) { + if (!isWorkdayItem(item)) + return false; + + const auto items = m_cache->items(item.parentCollection()); + auto currentItem = item; + auto parentUid = m_serializer->relatedUidFromItem(currentItem); + 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; + + if (isWorkdayItem(*parent)) + return false; + + currentItem = *parent; + parentUid = m_serializer->relatedUidFromItem(currentItem); + } + + return true; + }; m_integrator->bind("TaskQueries::findWorkdayTopLevel", m_findWorkdayTopLevel, fetch, predicate); return m_findWorkdayTopLevel->result(); } 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 @@ -1571,6 +1571,51 @@ QCOMPARE(result->data().at(0)->title(), QStringLiteral("42")); QCOMPARE(result->data().at(1)->title(), QStringLiteral("43")); } + + void shouldNotListWorkdayTasksTwiceIfTheyHaveAParentInWorkday() + { + // GIVEN + const auto today = Utils::DateTime::currentDateTime(); + AkonadiFakeData data; + + // One top level collection + data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); + + // One context tag + data.createTag(GenTag().withId(42).withName(QStringLiteral("42")).asContext()); + + // Five tasks in the collection, two start today, three not, all forming an ancestry line + data.createItem(GenTodo().withParent(42).withId(42).withTitle(QStringLiteral("42")).withUid("42")); + data.createItem(GenTodo().withParent(42).withId(43).withTitle(QStringLiteral("43")).withUid("43").withParentUid("42").withStartDate(today.addSecs(300))); + data.createItem(GenTodo().withParent(42).withId(44).withTitle(QStringLiteral("44")).withUid("44").withParentUid("43")); + data.createItem(GenTodo().withParent(42).withId(45).withTitle(QStringLiteral("45")).withUid("45").withParentUid("44").withStartDate(today.addSecs(300))); + data.createItem(GenTodo().withParent(42).withId(46).withTitle(QStringLiteral("46")).withUid("46").withParentUid("45")); + + // WHEN + auto serializer = Akonadi::Serializer::Ptr(new Akonadi::Serializer); + auto cache = Akonadi::Cache::Ptr::create(serializer, Akonadi::MonitorInterface::Ptr(data.createMonitor())); + QScopedPointer queries(new Akonadi::TaskQueries(createCachingStorage(data, cache), + Akonadi::Serializer::Ptr(new Akonadi::Serializer), + Akonadi::MonitorInterface::Ptr(data.createMonitor()), + cache)); + auto result = queries->findWorkdayTopLevel(); + result->data(); + result = queries->findWorkdayTopLevel(); // Should not cause any problem or wrong data + + // THEN + QVERIFY(result->data().isEmpty()); + TestHelpers::waitForEmptyJobQueue(); + + QCOMPARE(result->data().size(), 1); + QCOMPARE(result->data().at(0)->title(), QStringLiteral("43")); + + // Should not change anything + result = queries->findWorkdayTopLevel(); + TestHelpers::waitForEmptyJobQueue(); + + QCOMPARE(result->data().size(), 1); + QCOMPARE(result->data().at(0)->title(), QStringLiteral("43")); + } }; ZANSHIN_TEST_MAIN(AkonadiTaskQueriesTest)