21#include "removeduplicatesjob.h"
23#include <QAbstractItemModel>
25#include <akonadi/itemfetchjob.h>
26#include <akonadi/itemdeletejob.h>
27#include <akonadi/itemfetchscope.h>
28#include <kmime/kmime_message.h>
30#include <KLocalizedString>
32class Akonadi::RemoveDuplicatesJob::Private {
46 kDebug() <<
"Processing collection" << collection.name() <<
"(" << collection.id() <<
")";
51 mParent->connect(job, SIGNAL(result(KJob*)), mParent, SLOT(slotFetchDone(KJob*)));
54 emit mParent->description(mParent, i18n(
"Retrieving items..."));
57 void slotFetchDone(KJob *job)
61 mParent->setError(job->error());
62 mParent->setErrorText(job->errorText());
63 mParent->emitResult();
68 mParent->emitResult();
72 emit mParent->description(mParent, i18n(
"Searching for duplicates..."));
75 Akonadi::Item::List items = fjob->
items();
79 QMap<QByteArray, uint> messageIds;
80 QMap<uint, QList<uint> > duplicates;
81 QMap<uint, uint> bodyHashes;
82 const int numberOfItems(items.size());
83 for (
int i = 0; i < numberOfItems; ++i) {
84 Akonadi::Item item = items.at(i);
85 if (item.hasPayload<KMime::Message::Ptr>()) {
86 KMime::Message::Ptr message = item.payload<KMime::Message::Ptr>();
87 QByteArray idStr = message->messageID()->as7BitString(
false);
93 if (messageIds.contains(idStr)) {
94 uint mainId = messageIds.value(idStr);
95 if (!bodyHashes.contains(mainId)) {
96 bodyHashes.insert(mainId, qHash(items.value(mainId).payload<KMime::Message::Ptr>()->encodedContent()));
98 uint hash = qHash(message->encodedContent());
99 kDebug() << idStr << bodyHashes.value(mainId) << hash;
100 if (bodyHashes.value(mainId) == hash) {
101 duplicates[mainId].append(i);
104 messageIds.insert(idStr, i);
110 QMap<uint, QList<uint> >::ConstIterator end(duplicates.constEnd());
111 for (QMap<uint, QList<uint> >::ConstIterator it = duplicates.constBegin(); it != end; ++it) {
112 QList<uint>::ConstIterator dupEnd(it.value().constEnd());
113 for (QList<uint>::ConstIterator dupIt = it.value().constBegin(); dupIt != dupEnd; ++dupIt) {
114 mDuplicateItems.append(items.value(*dupIt));
119 mParent->emitResult();
126 if (mDuplicateItems.isEmpty()) {
127 kDebug() <<
"No duplicates, I'm done here";
128 mParent->emitResult();
131 emit mParent->description(mParent, i18n(
"Removing duplicates..."));
133 mParent->connect(delCmd, SIGNAL(result(KJob*)), mParent, SLOT(slotDeleteDone(KJob*)));
138 void slotDeleteDone(KJob *job)
140 kDebug() <<
"Job done";
142 mParent->setError(job->error());
143 mParent->setErrorText(job->errorText());
144 mParent->emitResult();
149 Akonadi::Item::List mDuplicateItems;
162 , d(new Private(this))
165 d->mFolders << folder;
170 , d(new Private(this))
172 d->mFolders = folders;
173 d->mJobCount = d->mFolders.length();
185 if (d->mFolders.isEmpty()) {
186 kWarning() <<
"No collections to process";
196 kDebug() <<
"Killed!";
199 if (d->mCurrentJob) {
200 d->mCurrentJob->kill(EmitResult);
206#include "moc_removeduplicatesjob.cpp"
Represents a collection of PIM items.
QList< Collection > List
Describes a list of collections.
Job that deletes items from the Akonadi storage.
Job that fetches items from the Akonadi storage.
ItemFetchScope & fetchScope()
Returns the item fetch scope.
Item::List items() const
Returns the fetched items.
void setAncestorRetrieval(AncestorRetrieval ancestorDepth)
Sets how many levels of ancestor collections should be included in the retrieval.
void fetchFullPayload(bool fetch=true)
Sets whether the full payload shall be fetched.
@ Parent
Only retrieve the immediate parent collection.
Base class for all actions in the Akonadi storage.
Job that finds and removes duplicate messages in given collection.
virtual bool doKill()
Kills the execution of the job.
virtual void doStart()
This method must be reimplemented in the concrete jobs.
RemoveDuplicatesJob(const Akonadi::Collection &folder, QObject *parent=0)
Creates a new job that will remove duplicates in folder.
virtual ~RemoveDuplicatesJob()
Destroys the job.
FreeBusyManager::Singleton.