diff options
-rw-r--r-- | examples/maildirresource/maildirresource.cpp | 170 | ||||
-rw-r--r-- | examples/maildirresource/maildirresource.h | 28 | ||||
-rw-r--r-- | tests/maildirresourcetest.cpp | 43 |
3 files changed, 155 insertions, 86 deletions
diff --git a/examples/maildirresource/maildirresource.cpp b/examples/maildirresource/maildirresource.cpp index 10e9046..90b4e55 100644 --- a/examples/maildirresource/maildirresource.cpp +++ b/examples/maildirresource/maildirresource.cpp | |||
@@ -114,7 +114,7 @@ QStringList MaildirResource::listAvailableFolders() | |||
114 | return folderList; | 114 | return folderList; |
115 | } | 115 | } |
116 | 116 | ||
117 | static void createEntity(const QByteArray &akonadiId, const QByteArray &bufferType, Akonadi2::ApplicationDomain::ApplicationDomainType &domainObject, DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback) | 117 | static void createEntity(const QByteArray &akonadiId, const QByteArray &bufferType, const Akonadi2::ApplicationDomain::ApplicationDomainType &domainObject, DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback) |
118 | { | 118 | { |
119 | flatbuffers::FlatBufferBuilder entityFbb; | 119 | flatbuffers::FlatBufferBuilder entityFbb; |
120 | adaptorFactory.createBuffer(domainObject, entityFbb); | 120 | adaptorFactory.createBuffer(domainObject, entityFbb); |
@@ -128,7 +128,7 @@ static void createEntity(const QByteArray &akonadiId, const QByteArray &bufferTy | |||
128 | callback(QByteArray::fromRawData(reinterpret_cast<char const *>(fbb.GetBufferPointer()), fbb.GetSize())); | 128 | callback(QByteArray::fromRawData(reinterpret_cast<char const *>(fbb.GetBufferPointer()), fbb.GetSize())); |
129 | } | 129 | } |
130 | 130 | ||
131 | static void modifyEntity(const QByteArray &akonadiId, qint64 revision, const QByteArray &bufferType, Akonadi2::ApplicationDomain::ApplicationDomainType &domainObject, DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback) | 131 | static void modifyEntity(const QByteArray &akonadiId, qint64 revision, const QByteArray &bufferType, const Akonadi2::ApplicationDomain::ApplicationDomainType &domainObject, DomainTypeAdaptorFactoryInterface &adaptorFactory, std::function<void(const QByteArray &)> callback) |
132 | { | 132 | { |
133 | flatbuffers::FlatBufferBuilder entityFbb; | 133 | flatbuffers::FlatBufferBuilder entityFbb; |
134 | adaptorFactory.createBuffer(domainObject, entityFbb); | 134 | adaptorFactory.createBuffer(domainObject, entityFbb); |
@@ -172,40 +172,79 @@ static QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor> getLatest(cons | |||
172 | return current; | 172 | return current; |
173 | } | 173 | } |
174 | 174 | ||
175 | void MaildirResource::synchronizeFolders(Akonadi2::Storage::Transaction &transaction) | 175 | void MaildirResource::scanForRemovals(Akonadi2::Storage::Transaction &transaction, Akonadi2::Storage::Transaction &synchronizationTransaction, const QByteArray &bufferType, std::function<bool(const QByteArray &remoteId)> exists) |
176 | { | 176 | { |
177 | const QByteArray bufferType = ENTITY_TYPE_FOLDER; | ||
178 | QStringList folderList = listAvailableFolders(); | ||
179 | Trace() << "Found folders " << folderList; | ||
180 | |||
181 | Akonadi2::Storage store(Akonadi2::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Akonadi2::Storage::ReadWrite); | ||
182 | auto synchronizationTransaction = store.createTransaction(Akonadi2::Storage::ReadWrite); | ||
183 | auto mainDatabase = transaction.openDatabase(bufferType + ".main"); | 177 | auto mainDatabase = transaction.openDatabase(bufferType + ".main"); |
184 | |||
185 | //TODO Instead of iterating over all entries in the database, which can also pick up the same item multiple times, | 178 | //TODO Instead of iterating over all entries in the database, which can also pick up the same item multiple times, |
186 | //we should rather iterate over an index that contains every uid exactly once. The remoteId index would be such an index, | 179 | //we should rather iterate over an index that contains every uid exactly once. The remoteId index would be such an index, |
187 | //but we currently fail to iterate over all entries in an index it seems. | 180 | //but we currently fail to iterate over all entries in an index it seems. |
188 | // auto remoteIds = synchronizationTransaction.openDatabase("rid.mapping." + bufferType, std::function<void(const Akonadi2::Storage::Error &)>(), true); | 181 | // auto remoteIds = synchronizationTransaction.openDatabase("rid.mapping." + bufferType, std::function<void(const Akonadi2::Storage::Error &)>(), true); |
189 | mainDatabase.scan("", [&folderList, this, &transaction, bufferType, &synchronizationTransaction](const QByteArray &key, const QByteArray &) { | 182 | mainDatabase.scan("", [this, &transaction, bufferType, &synchronizationTransaction, &exists](const QByteArray &key, const QByteArray &) { |
190 | auto akonadiId = Akonadi2::Storage::uidFromKey(key); | 183 | auto akonadiId = Akonadi2::Storage::uidFromKey(key); |
184 | Trace() << "Checking for removal " << key; | ||
191 | const auto remoteId = resolveLocalId(bufferType, akonadiId, synchronizationTransaction); | 185 | const auto remoteId = resolveLocalId(bufferType, akonadiId, synchronizationTransaction); |
192 | if (!folderList.contains(remoteId)) { | 186 | if (!remoteId.isEmpty()) { |
193 | Trace() << "Found a removed entity: " << akonadiId; | 187 | if (!exists(remoteId.toLatin1())) { |
194 | deleteEntity(akonadiId, Akonadi2::Storage::maxRevision(transaction), bufferType, [this](const QByteArray &buffer) { | 188 | Trace() << "Found a removed entity: " << akonadiId; |
195 | enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::DeleteEntityCommand, buffer); | 189 | deleteEntity(akonadiId, Akonadi2::Storage::maxRevision(transaction), bufferType, [this](const QByteArray &buffer) { |
196 | }); | 190 | enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::DeleteEntityCommand, buffer); |
191 | }); | ||
192 | } | ||
197 | } | 193 | } |
198 | return true; | 194 | return true; |
199 | }, | 195 | }, |
200 | [](const Akonadi2::Storage::Error &error) { | 196 | [](const Akonadi2::Storage::Error &error) { |
201 | }); | 197 | }); |
202 | 198 | ||
199 | } | ||
200 | |||
201 | void MaildirResource::createOrModify(Akonadi2::Storage::Transaction &transaction, Akonadi2::Storage::Transaction &synchronizationTransaction, DomainTypeAdaptorFactoryInterface &adaptorFactory, const QByteArray &bufferType, const QByteArray &remoteId, const Akonadi2::ApplicationDomain::ApplicationDomainType &entity) | ||
202 | { | ||
203 | auto mainDatabase = transaction.openDatabase(bufferType + ".main"); | ||
204 | const auto akonadiId = resolveRemoteId(bufferType, remoteId, synchronizationTransaction).toLatin1(); | ||
205 | const auto found = mainDatabase.contains(akonadiId); | ||
206 | if (!found) { | ||
207 | Trace() << "Found a new entity: " << remoteId; | ||
208 | createEntity(akonadiId, bufferType, entity, adaptorFactory, [this](const QByteArray &buffer) { | ||
209 | enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::CreateEntityCommand, buffer); | ||
210 | }); | ||
211 | } else { //modification | ||
212 | if (auto current = getLatest(mainDatabase, akonadiId, adaptorFactory)) { | ||
213 | bool changed = false; | ||
214 | for (const auto &property : entity.changedProperties()) { | ||
215 | if (entity.getProperty(property) != current->getProperty(property)) { | ||
216 | Trace() << "Property changed " << akonadiId << property; | ||
217 | changed = true; | ||
218 | } | ||
219 | } | ||
220 | if (changed) { | ||
221 | Trace() << "Found a modified entity: " << remoteId; | ||
222 | modifyEntity(akonadiId, Akonadi2::Storage::maxRevision(transaction), bufferType, entity, adaptorFactory, [this](const QByteArray &buffer) { | ||
223 | enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::ModifyEntityCommand, buffer); | ||
224 | }); | ||
225 | } | ||
226 | } else { | ||
227 | Warning() << "Failed to get current entity"; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | void MaildirResource::synchronizeFolders(Akonadi2::Storage::Transaction &transaction) | ||
233 | { | ||
234 | const QByteArray bufferType = ENTITY_TYPE_FOLDER; | ||
235 | QStringList folderList = listAvailableFolders(); | ||
236 | Trace() << "Found folders " << folderList; | ||
237 | |||
238 | Akonadi2::Storage store(Akonadi2::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Akonadi2::Storage::ReadWrite); | ||
239 | auto synchronizationTransaction = store.createTransaction(Akonadi2::Storage::ReadWrite); | ||
240 | auto mainDatabase = transaction.openDatabase(bufferType + ".main"); | ||
241 | scanForRemovals(transaction, synchronizationTransaction, bufferType, [&folderList](const QByteArray &remoteId) -> bool { | ||
242 | return folderList.contains(remoteId); | ||
243 | }); | ||
244 | |||
203 | for (const auto folderPath : folderList) { | 245 | for (const auto folderPath : folderList) { |
204 | const auto remoteId = folderPath.toUtf8(); | 246 | const auto remoteId = folderPath.toUtf8(); |
205 | Trace() << "Processing folder " << remoteId; | 247 | Trace() << "Processing folder " << remoteId; |
206 | const auto akonadiId = resolveRemoteId(bufferType, remoteId, synchronizationTransaction).toLatin1(); | ||
207 | const auto found = mainDatabase.contains(akonadiId); | ||
208 | |||
209 | KPIM::Maildir md(folderPath, folderPath == mMaildirPath); | 248 | KPIM::Maildir md(folderPath, folderPath == mMaildirPath); |
210 | 249 | ||
211 | Akonadi2::ApplicationDomain::Folder folder; | 250 | Akonadi2::ApplicationDomain::Folder folder; |
@@ -214,31 +253,7 @@ void MaildirResource::synchronizeFolders(Akonadi2::Storage::Transaction &transac | |||
214 | if (!md.isRoot()) { | 253 | if (!md.isRoot()) { |
215 | folder.setProperty("parent", resolveRemoteId(ENTITY_TYPE_FOLDER, md.parent().path(), synchronizationTransaction).toLatin1()); | 254 | folder.setProperty("parent", resolveRemoteId(ENTITY_TYPE_FOLDER, md.parent().path(), synchronizationTransaction).toLatin1()); |
216 | } | 255 | } |
217 | 256 | createOrModify(transaction, synchronizationTransaction, *mFolderAdaptorFactory, bufferType, remoteId, folder); | |
218 | if (!found) { | ||
219 | Trace() << "Found a new entity: " << remoteId; | ||
220 | createEntity(akonadiId, bufferType, folder, *mFolderAdaptorFactory, [this](const QByteArray &buffer) { | ||
221 | enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::CreateEntityCommand, buffer); | ||
222 | }); | ||
223 | } else { //modification | ||
224 | if (auto current = getLatest(mainDatabase, akonadiId, *mFolderAdaptorFactory)) { | ||
225 | bool changed = false; | ||
226 | for (const auto &property : folder.changedProperties()) { | ||
227 | if (folder.getProperty(property) != current->getProperty(property)) { | ||
228 | Trace() << "Property changed " << akonadiId << property; | ||
229 | changed = true; | ||
230 | } | ||
231 | } | ||
232 | if (changed) { | ||
233 | Trace() << "Found a modified entity: " << remoteId; | ||
234 | modifyEntity(akonadiId, Akonadi2::Storage::maxRevision(transaction), bufferType, folder, *mFolderAdaptorFactory, [this](const QByteArray &buffer) { | ||
235 | enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::ModifyEntityCommand, buffer); | ||
236 | }); | ||
237 | } | ||
238 | } else { | ||
239 | Warning() << "Failed to get current entity"; | ||
240 | } | ||
241 | } | ||
242 | } | 257 | } |
243 | } | 258 | } |
244 | 259 | ||
@@ -262,53 +277,36 @@ void MaildirResource::synchronizeMails(Akonadi2::Storage::Transaction &transacti | |||
262 | Akonadi2::Storage store(Akonadi2::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Akonadi2::Storage::ReadWrite); | 277 | Akonadi2::Storage store(Akonadi2::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Akonadi2::Storage::ReadWrite); |
263 | auto synchronizationTransaction = store.createTransaction(Akonadi2::Storage::ReadWrite); | 278 | auto synchronizationTransaction = store.createTransaction(Akonadi2::Storage::ReadWrite); |
264 | 279 | ||
280 | scanForRemovals(transaction, synchronizationTransaction, bufferType, [&listingPath](const QByteArray &remoteId) -> bool { | ||
281 | return QFile(listingPath + QDir::separator() + remoteId).exists(); | ||
282 | }); | ||
283 | |||
265 | while (entryIterator->hasNext()) { | 284 | while (entryIterator->hasNext()) { |
266 | QString filePath = entryIterator->next(); | 285 | QString filePath = entryIterator->next(); |
267 | QString fileName = entryIterator->fileName(); | 286 | QString fileName = entryIterator->fileName(); |
268 | |||
269 | const auto remoteId = fileName.toUtf8(); | 287 | const auto remoteId = fileName.toUtf8(); |
270 | auto akonadiId = resolveRemoteId(bufferType, remoteId, synchronizationTransaction); | 288 | |
271 | 289 | KMime::Message *msg = new KMime::Message; | |
272 | bool found = false; | 290 | auto filepath = listingPath + QDir::separator() + fileName; |
273 | transaction.openDatabase(bufferType + ".main").scan(akonadiId.toUtf8(), [&found](const QByteArray &, const QByteArray &) -> bool { | 291 | msg->setHead(KMime::CRLFtoLF(maildir.readEntryHeadersFromFile(filepath))); |
274 | found = true; | 292 | msg->parse(); |
275 | return false; | 293 | |
276 | }, [this](const Akonadi2::Storage::Error &error) { | 294 | const auto flags = maildir.readEntryFlags(fileName); |
277 | }, true); | 295 | |
278 | 296 | Trace() << "Found a mail " << filePath << fileName << msg->subject(true)->asUnicodeString(); | |
279 | if (!found) { //A new entity | 297 | |
280 | KMime::Message *msg = new KMime::Message; | 298 | Akonadi2::ApplicationDomain::Mail mail; |
281 | auto filepath = listingPath + QDir::separator() + fileName; | 299 | mail.setProperty("subject", msg->subject(true)->asUnicodeString()); |
282 | msg->setHead(KMime::CRLFtoLF(maildir.readEntryHeadersFromFile(filepath))); | 300 | mail.setProperty("sender", msg->from(true)->asUnicodeString()); |
283 | msg->parse(); | 301 | mail.setProperty("senderName", msg->from(true)->asUnicodeString()); |
284 | 302 | mail.setProperty("date", msg->date(true)->dateTime().toString()); | |
285 | const auto flags = maildir.readEntryFlags(fileName); | 303 | mail.setProperty("folder", resolveRemoteId(ENTITY_TYPE_FOLDER, path, synchronizationTransaction)); |
286 | 304 | mail.setProperty("mimeMessage", filepath); | |
287 | Trace() << "Found a mail " << filePath << fileName << msg->subject(true)->asUnicodeString(); | 305 | mail.setProperty("unread", !flags.testFlag(KPIM::Maildir::Seen)); |
288 | 306 | mail.setProperty("important", flags.testFlag(KPIM::Maildir::Flagged)); | |
289 | Akonadi2::ApplicationDomain::Mail mail; | 307 | |
290 | mail.setProperty("subject", msg->subject(true)->asUnicodeString()); | 308 | createOrModify(transaction, synchronizationTransaction, *mMailAdaptorFactory, bufferType, remoteId, mail); |
291 | mail.setProperty("sender", msg->from(true)->asUnicodeString()); | ||
292 | mail.setProperty("senderName", msg->from(true)->asUnicodeString()); | ||
293 | mail.setProperty("date", msg->date(true)->dateTime().toString()); | ||
294 | mail.setProperty("folder", resolveRemoteId(ENTITY_TYPE_FOLDER, path, synchronizationTransaction)); | ||
295 | mail.setProperty("mimeMessage", filepath); | ||
296 | mail.setProperty("unread", !flags.testFlag(KPIM::Maildir::Seen)); | ||
297 | mail.setProperty("important", flags.testFlag(KPIM::Maildir::Flagged)); | ||
298 | |||
299 | flatbuffers::FlatBufferBuilder entityFbb; | ||
300 | mMailAdaptorFactory->createBuffer(mail, entityFbb); | ||
301 | |||
302 | Trace() << "Found a new entity: " << remoteId; | ||
303 | createEntity(akonadiId.toLatin1(), bufferType, mail, *mMailAdaptorFactory, [this](const QByteArray &buffer) { | ||
304 | enqueueCommand(mSynchronizerQueue, Akonadi2::Commands::CreateEntityCommand, buffer); | ||
305 | }); | ||
306 | } else { //modification | ||
307 | Trace() << "Found a modified entity: " << remoteId; | ||
308 | //TODO diff and create modification if necessary | ||
309 | } | ||
310 | } | 309 | } |
311 | //TODO find items to remove | ||
312 | } | 310 | } |
313 | 311 | ||
314 | KAsync::Job<void> MaildirResource::synchronizeWithSource() | 312 | KAsync::Job<void> MaildirResource::synchronizeWithSource() |
diff --git a/examples/maildirresource/maildirresource.h b/examples/maildirresource/maildirresource.h index e1eecc1..eec1e97 100644 --- a/examples/maildirresource/maildirresource.h +++ b/examples/maildirresource/maildirresource.h | |||
@@ -39,8 +39,36 @@ public: | |||
39 | static void removeFromDisk(const QByteArray &instanceIdentifier); | 39 | static void removeFromDisk(const QByteArray &instanceIdentifier); |
40 | private: | 40 | private: |
41 | KAsync::Job<void> replay(const QByteArray &type, const QByteArray &key, const QByteArray &value) Q_DECL_OVERRIDE; | 41 | KAsync::Job<void> replay(const QByteArray &type, const QByteArray &key, const QByteArray &value) Q_DECL_OVERRIDE; |
42 | |||
43 | /** | ||
44 | * Tries to find a local id for the remote id, and creates a new local id otherwise. | ||
45 | * | ||
46 | * The new local id is recorded in the local to remote id mapping. | ||
47 | */ | ||
42 | QString resolveRemoteId(const QByteArray &type, const QString &remoteId, Akonadi2::Storage::Transaction &transaction); | 48 | QString resolveRemoteId(const QByteArray &type, const QString &remoteId, Akonadi2::Storage::Transaction &transaction); |
49 | |||
50 | /** | ||
51 | * Tries to find a remote id for a local id. | ||
52 | * | ||
53 | * This can fail if the entity hasn't been written back to the server yet. | ||
54 | */ | ||
43 | QString resolveLocalId(const QByteArray &bufferType, const QByteArray &localId, Akonadi2::Storage::Transaction &transaction); | 55 | QString resolveLocalId(const QByteArray &bufferType, const QByteArray &localId, Akonadi2::Storage::Transaction &transaction); |
56 | |||
57 | /** | ||
58 | * An algorithm to remove entities that are no longer existing. | ||
59 | * | ||
60 | * This algorithm calls @param exists for every entity of type @param type, with its remoteId. For every entity where @param exists returns false, | ||
61 | * an entity delete command is enqueued. | ||
62 | */ | ||
63 | void scanForRemovals(Akonadi2::Storage::Transaction &transaction, Akonadi2::Storage::Transaction &synchronizationTransaction, const QByteArray &bufferType, std::function<bool(const QByteArray &remoteId)> exists); | ||
64 | |||
65 | /** | ||
66 | * An algorithm to create or modify the entity. | ||
67 | * | ||
68 | * Depending on whether the entity is locally available, or has changed. | ||
69 | */ | ||
70 | void createOrModify(Akonadi2::Storage::Transaction &transaction, Akonadi2::Storage::Transaction &synchronizationTransaction, DomainTypeAdaptorFactoryInterface &adaptorFactory, const QByteArray &bufferType, const QByteArray &remoteId, const Akonadi2::ApplicationDomain::ApplicationDomainType &entity); | ||
71 | |||
44 | void synchronizeFolders(Akonadi2::Storage::Transaction &transaction); | 72 | void synchronizeFolders(Akonadi2::Storage::Transaction &transaction); |
45 | void synchronizeMails(Akonadi2::Storage::Transaction &transaction, const QString &folder); | 73 | void synchronizeMails(Akonadi2::Storage::Transaction &transaction, const QString &folder); |
46 | QStringList listAvailableFolders(); | 74 | QStringList listAvailableFolders(); |
diff --git a/tests/maildirresourcetest.cpp b/tests/maildirresourcetest.cpp index e6b6849..a4856ce 100644 --- a/tests/maildirresourcetest.cpp +++ b/tests/maildirresourcetest.cpp | |||
@@ -149,6 +149,26 @@ private Q_SLOTS: | |||
149 | QVERIFY(mailModel->rowCount(QModelIndex()) >= 1); | 149 | QVERIFY(mailModel->rowCount(QModelIndex()) >= 1); |
150 | } | 150 | } |
151 | 151 | ||
152 | void testMailContent() | ||
153 | { | ||
154 | Akonadi2::Query query; | ||
155 | query.resources << "org.kde.maildir.instance1"; | ||
156 | query.requestedProperties << "folder" << "subject" << "mimeMessage"; | ||
157 | query.syncOnDemand = true; | ||
158 | query.processAll = true; | ||
159 | |||
160 | //Ensure all local data is processed | ||
161 | Akonadi2::Store::synchronize(query).exec().waitForFinished(); | ||
162 | |||
163 | auto mailModel = Akonadi2::Store::loadModel<Akonadi2::ApplicationDomain::Mail>(query); | ||
164 | QTRY_VERIFY(mailModel->data(QModelIndex(), Akonadi2::Store::ChildrenFetchedRole).toBool()); | ||
165 | QVERIFY(mailModel->rowCount(QModelIndex()) >= 1); | ||
166 | auto mail = mailModel->index(0, 0, QModelIndex()).data(Akonadi2::Store::DomainObjectRole).value<Akonadi2::ApplicationDomain::Mail::Ptr>(); | ||
167 | QVERIFY(!mail->getProperty("subject").toString().isEmpty()); | ||
168 | QVERIFY(!mail->getProperty("mimeMessage").toString().isEmpty()); | ||
169 | } | ||
170 | |||
171 | |||
152 | void testSyncFolderMove() | 172 | void testSyncFolderMove() |
153 | { | 173 | { |
154 | Akonadi2::Query query; | 174 | Akonadi2::Query query; |
@@ -173,6 +193,29 @@ private Q_SLOTS: | |||
173 | QCOMPARE(model->match(model->index(0, 0, QModelIndex()), Qt::DisplayRole, QStringLiteral("newbox"), 1).size(), 1); | 193 | QCOMPARE(model->match(model->index(0, 0, QModelIndex()), Qt::DisplayRole, QStringLiteral("newbox"), 1).size(), 1); |
174 | } | 194 | } |
175 | 195 | ||
196 | void testSyncMailMove() | ||
197 | { | ||
198 | Akonadi2::Query query; | ||
199 | query.resources << "org.kde.maildir.instance1"; | ||
200 | query.syncOnDemand = true; | ||
201 | query.processAll = true; | ||
202 | query.requestedProperties << "folder" << "summary"; | ||
203 | |||
204 | //Ensure all local data is processed | ||
205 | Akonadi2::Store::synchronize(query).exec().waitForFinished(); | ||
206 | |||
207 | auto targetPath = tempDir.path() + QDir::separator() + "maildir1/cur/1365777830.R28.localhost.localdomain:2,S"; | ||
208 | QFile file(targetPath); | ||
209 | QVERIFY(file.remove()); | ||
210 | |||
211 | //Ensure all local data is processed | ||
212 | Akonadi2::Store::synchronize(query).exec().waitForFinished(); | ||
213 | |||
214 | auto mailModel = Akonadi2::Store::loadModel<Akonadi2::ApplicationDomain::Mail>(query); | ||
215 | QTRY_VERIFY(mailModel->data(QModelIndex(), Akonadi2::Store::ChildrenFetchedRole).toBool()); | ||
216 | QCOMPARE(mailModel->rowCount(QModelIndex()), 1); | ||
217 | } | ||
218 | |||
176 | }; | 219 | }; |
177 | 220 | ||
178 | QTEST_MAIN(MaildirResourceTest) | 221 | QTEST_MAIN(MaildirResourceTest) |