diff --git a/src/akonadi/akonadinotequeries.h b/src/akonadi/akonadinotequeries.h --- a/src/akonadi/akonadinotequeries.h +++ b/src/akonadi/akonadinotequeries.h @@ -47,6 +47,7 @@ const MonitorInterface::Ptr &monitor); NoteResult::Ptr findAll() const Q_DECL_OVERRIDE; + NoteResult::Ptr findInbox() const Q_DECL_OVERRIDE; private: SerializerInterface::Ptr m_serializer; diff --git a/src/akonadi/akonadinotequeries.cpp b/src/akonadi/akonadinotequeries.cpp --- a/src/akonadi/akonadinotequeries.cpp +++ b/src/akonadi/akonadinotequeries.cpp @@ -44,3 +44,14 @@ m_integrator->bind(m_findAll, fetch, predicate); return m_findAll->result(); } + +NoteQueries::NoteResult::Ptr NoteQueries::findInbox() const +{ + auto fetch = m_helpers->fetchItems(StorageInterface::Notes); + auto predicate = [this] (const Item &item) { + return m_serializer->isNoteItem(item) + && !m_serializer->hasAkonadiTags(item); + }; + m_integrator->bind(m_findAll, fetch, predicate); + return m_findAll->result(); +} diff --git a/src/domain/notequeries.h b/src/domain/notequeries.h --- a/src/domain/notequeries.h +++ b/src/domain/notequeries.h @@ -39,6 +39,7 @@ virtual ~NoteQueries(); virtual QueryResult::Ptr findAll() const = 0; + virtual QueryResult::Ptr findInbox() const = 0; }; } diff --git a/tests/units/akonadi/akonadinotequeriestest.cpp b/tests/units/akonadi/akonadinotequeriestest.cpp --- a/tests/units/akonadi/akonadinotequeriestest.cpp +++ b/tests/units/akonadi/akonadinotequeriestest.cpp @@ -30,6 +30,8 @@ #include "testlib/akonadifakedata.h" #include "testlib/gencollection.h" #include "testlib/gennote.h" +#include "testlib/gentag.h" +#include "testlib/gentodo.h" #include "testlib/testhelpers.h" using namespace Testlib; @@ -193,6 +195,291 @@ QCOMPARE(result->data().at(2)->title(), QString("44")); QVERIFY(replaceHandlerCalled); } + + void shouldLookInAllSelectedCollectionsForInboxNotes() + { + // GIVEN + AkonadiFakeData data; + + // Three top level collections + data.createCollection(GenCollection().withId(42).withRootAsParent().withNoteContent()); + data.createCollection(GenCollection().withId(43).withRootAsParent().withNoteContent()); + data.createCollection(GenCollection().withId(44).withRootAsParent().withNoteContent().enabled(false)); + + // One note in the first collection + data.createItem(GenNote().withId(42).withParent(42).withTitle("42")); + + // Two notes in the second collection + data.createItem(GenNote().withId(43).withParent(43).withTitle("43")); + data.createItem(GenNote().withId(44).withParent(43).withTitle("44")); + + // One note in the third collection + data.createItem(GenNote().withId(45).withParent(44).withTitle("45")); + + // WHEN + QScopedPointer queries(new Akonadi::NoteQueries(Akonadi::StorageInterface::Ptr(data.createStorage()), + Akonadi::Serializer::Ptr(new Akonadi::Serializer), + Akonadi::MonitorInterface::Ptr(data.createMonitor()))); + auto result = queries->findInbox(); + result->data(); + result = queries->findInbox(); // Should not cause any problem or wrong data + + // THEN + QVERIFY(result->data().isEmpty()); + TestHelpers::waitForEmptyJobQueue(); + + QCOMPARE(result->data().size(), 3); + QCOMPARE(result->data().at(0)->title(), QString("42")); + QCOMPARE(result->data().at(1)->title(), QString("43")); + QCOMPARE(result->data().at(2)->title(), QString("44")); + } + + void shouldIgnoreItemsWhichAreNotNotesInInbox() + { + // GIVEN + AkonadiFakeData data; + + // One top level collection + data.createCollection(GenCollection().withId(42).withRootAsParent().withNoteContent()); + + // Three items in the collection + data.createItem(GenNote().withId(42).withParent(42).withTitle("42")); + // One of them is a task + data.createItem(GenTodo().withId(43).withParent(42).withTitle("43")); + // One of them is not a task or a note + auto item = Akonadi::Item(44); + item.setPayloadFromData("FooBar"); + item.setParentCollection(Akonadi::Collection(42)); + data.createItem(item); + + // WHEN + QScopedPointer queries(new Akonadi::NoteQueries(Akonadi::StorageInterface::Ptr(data.createStorage()), + Akonadi::Serializer::Ptr(new Akonadi::Serializer), + Akonadi::MonitorInterface::Ptr(data.createMonitor()))); + auto result = queries->findInbox(); + + // THEN + QVERIFY(result->data().isEmpty()); + TestHelpers::waitForEmptyJobQueue(); + + QCOMPARE(result->data().size(), 1); + QCOMPARE(result->data().at(0)->title(), QString("42")); + } + + void shouldNotHaveNotesWithTagsInInbox_data() + { + QTest::addColumn("hasTags"); + QTest::addColumn("isExpectedInInbox"); + + QTest::newRow("note with no tags") << false << true; + QTest::newRow("note with tags") << true << false; + } + + void shouldNotHaveNotesWithTagsInInbox() + { + // GIVEN + AkonadiFakeData data; + + // One top level collection + data.createCollection(GenCollection().withId(42).withRootAsParent().withNoteContent()); + + // One plain tag + data.createTag(GenTag().withId(42).withName("tag-42").asPlain()); + + // One item in the collection + QFETCH(bool, hasTags); + auto tagIds = QList(); + if (hasTags) tagIds << 42; + data.createItem(GenNote().withId(42).withParent(42).withTitle("42").withTags(tagIds)); + + // WHEN + QScopedPointer queries(new Akonadi::NoteQueries(Akonadi::StorageInterface::Ptr(data.createStorage()), + Akonadi::Serializer::Ptr(new Akonadi::Serializer), + Akonadi::MonitorInterface::Ptr(data.createMonitor()))); + auto result = queries->findInbox(); + + // THEN + QVERIFY(result->data().isEmpty()); + TestHelpers::waitForEmptyJobQueue(); + + QFETCH(bool, isExpectedInInbox); + if (isExpectedInInbox) { + QCOMPARE(result->data().size(), 1); + QCOMPARE(result->data().at(0)->title(), QString("42")); + } else { + QVERIFY(result->data().isEmpty()); + } + } + + void shouldReactToItemAddsForInbox_data() + { + QTest::addColumn("reactionExpected"); + QTest::addColumn("isTodo"); + QTest::addColumn("hasTags"); + + QTest::newRow("task with no tag") << false << true << false; + QTest::newRow("task with tag") << false << true << true; + + QTest::newRow("note which should be in inbox") << true << false << false; + QTest::newRow("note with tag") << false << false << true; + } + + void shouldReactToItemAddsForInbox() + { + // GIVEN + AkonadiFakeData data; + + // One top level collection + data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent().withNoteContent()); + + // One plain tag + data.createTag(GenTag().withId(42).withName("tag-42").asPlain()); + + QScopedPointer queries(new Akonadi::NoteQueries(Akonadi::StorageInterface::Ptr(data.createStorage()), + Akonadi::Serializer::Ptr(new Akonadi::Serializer), + Akonadi::MonitorInterface::Ptr(data.createMonitor()))); + auto result = queries->findInbox(); + TestHelpers::waitForEmptyJobQueue(); + QVERIFY(result->data().isEmpty()); + + // WHEN + QFETCH(bool, hasTags); + auto tagIds = QList(); + if (hasTags) tagIds << 42; + + QFETCH(bool, isTodo); + if (isTodo) { + data.createItem(GenTodo().withId(42).withParent(42).withTitle("42").withTags(tagIds)); + } else { + data.createItem(GenNote().withId(42).withParent(42).withTitle("42").withTags(tagIds)); + } + + // THEN + QFETCH(bool, reactionExpected); + if (reactionExpected) { + QCOMPARE(result->data().size(), 1); + QCOMPARE(result->data().at(0)->title(), QString("42")); + } else { + QVERIFY(result->data().isEmpty()); + } + } + + void shouldReactToItemRemovesForInbox() + { + // GIVEN + AkonadiFakeData data; + + // One top level collection + data.createCollection(GenCollection().withId(42).withRootAsParent().withNoteContent()); + + // One item in the collection + data.createItem(GenNote().withId(42).withParent(42).withTitle("42")); + + // WHEN + QScopedPointer queries(new Akonadi::NoteQueries(Akonadi::StorageInterface::Ptr(data.createStorage()), + Akonadi::Serializer::Ptr(new Akonadi::Serializer), + Akonadi::MonitorInterface::Ptr(data.createMonitor()))); + auto result = queries->findInbox(); + TestHelpers::waitForEmptyJobQueue(); + QCOMPARE(result->data().size(), 1); + QCOMPARE(result->data().first()->title(), QString("42")); + + // WHEN + data.removeItem(Akonadi::Item(42)); + + // THEN + QVERIFY(result->data().isEmpty()); + } + + void shouldReactToItemChangesForInbox_data() + { + QTest::addColumn("hasTagsBefore"); + QTest::addColumn("hasTagsAfter"); + QTest::addColumn("inListAfterChange"); + + QTest::newRow("note appears in inbox") << true << false << true; + QTest::newRow("note disappears from inbox") << false << true << false; + } + + void shouldReactToItemChangesForInbox() + { + // GIVEN + AkonadiFakeData data; + + // One top level collection + data.createCollection(GenCollection().withId(42).withRootAsParent().withNoteContent()); + + // One plain tag + data.createTag(GenTag().withId(42).withName("tag-42").asPlain()); + + // Note data + QFETCH(bool, hasTagsBefore); + + auto tagIds = QList(); + if (hasTagsBefore) tagIds << 42; + data.createItem(GenNote().withId(42).withParent(42).withTitle("42").withTags(tagIds)); + + QScopedPointer queries(new Akonadi::NoteQueries(Akonadi::StorageInterface::Ptr(data.createStorage()), + Akonadi::Serializer::Ptr(new Akonadi::Serializer), + Akonadi::MonitorInterface::Ptr(data.createMonitor()))); + auto result = queries->findInbox(); + TestHelpers::waitForEmptyJobQueue(); + + QFETCH(bool, inListAfterChange); + + if (inListAfterChange) { + QVERIFY(result->data().isEmpty()); + } else { + QCOMPARE(result->data().size(), 1); + QCOMPARE(result->data().at(0)->title(), QString("42")); + } + + // WHEN + QFETCH(bool, hasTagsAfter); + + tagIds.clear(); + if (hasTagsAfter) tagIds << 42; + data.modifyItem(GenNote(data.item(42)).withTags(tagIds)); + + // THEN + if (inListAfterChange) { + QCOMPARE(result->data().size(), 1); + QCOMPARE(result->data().at(0)->title(), QString("42")); + } else { + QVERIFY(result->data().isEmpty()); + } + } + + void shouldReactToCollectionSelectionChangesForInbox() + { + // GIVEN + AkonadiFakeData data; + + // Two top level collections + data.createCollection(GenCollection().withId(42).withRootAsParent().withNoteContent()); + data.createCollection(GenCollection().withId(43).withRootAsParent().withNoteContent()); + + // One note in each collection + data.createItem(GenNote().withId(42).withParent(42).withTitle("42")); + data.createItem(GenNote().withId(43).withParent(43).withTitle("43")); + + QScopedPointer queries(new Akonadi::NoteQueries(Akonadi::StorageInterface::Ptr(data.createStorage()), + Akonadi::Serializer::Ptr(new Akonadi::Serializer), + Akonadi::MonitorInterface::Ptr(data.createMonitor()))); + auto result = queries->findInbox(); + TestHelpers::waitForEmptyJobQueue(); + QCOMPARE(result->data().size(), 2); + QCOMPARE(result->data().at(0)->title(), QString("42")); + QCOMPARE(result->data().at(1)->title(), QString("43")); + + // WHEN + data.modifyCollection(GenCollection(data.collection(43)).selected(false)); + TestHelpers::waitForEmptyJobQueue(); + + // THEN + QCOMPARE(result->data().size(), 1); + QCOMPARE(result->data().at(0)->title(), QString("42")); + } }; QTEST_MAIN(AkonadiNoteQueriesTest)