• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.14.10 API Reference
  • KDE Home
  • Contact Us
 

akonadi/kmime

  • akonadi
  • kmime
removeduplicatesjob.cpp
1/*
2 Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
3 Copyright (c) 2010 Andras Mantia <andras@kdab.com>
4 Copyright (c) 2012 Dan Vrátil <dvratil@redhat.com>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19*/
20
21#include "removeduplicatesjob.h"
22
23#include <QAbstractItemModel>
24
25#include <akonadi/itemfetchjob.h>
26#include <akonadi/itemdeletejob.h>
27#include <akonadi/itemfetchscope.h>
28#include <kmime/kmime_message.h>
29
30#include <KLocalizedString>
31
32class Akonadi::RemoveDuplicatesJob::Private {
33
34public:
35 Private(RemoveDuplicatesJob *parent)
36 : mJobCount(0)
37 , mKilled(false)
38 , mCurrentJob(0)
39 , mParent(parent)
40 {
41 }
42
43 void fetchItem()
44 {
45 Akonadi::Collection collection = mFolders.value(mJobCount - 1);
46 kDebug() << "Processing collection" << collection.name() << "(" << collection.id() << ")";
47
48 Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob(collection, mParent);
49 job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent);
50 job->fetchScope().fetchFullPayload();
51 mParent->connect(job, SIGNAL(result(KJob*)), mParent, SLOT(slotFetchDone(KJob*)));
52 mCurrentJob = job;
53
54 emit mParent->description(mParent, i18n("Retrieving items..."));
55 }
56
57 void slotFetchDone(KJob *job)
58 {
59 mJobCount--;
60 if (job->error()) {
61 mParent->setError(job->error());
62 mParent->setErrorText(job->errorText());
63 mParent->emitResult();
64 return;
65 }
66
67 if (mKilled) {
68 mParent->emitResult();
69 return;
70 }
71
72 emit mParent->description(mParent, i18n("Searching for duplicates..."));
73
74 Akonadi::ItemFetchJob *fjob = static_cast<Akonadi::ItemFetchJob *>(job);
75 Akonadi::Item::List items = fjob->items();
76
77 //find duplicate mails with the same messageid
78 //if duplicates are found, check the content as well to be sure they are the same
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);
88 //TODO: Maybe do some more check in case of idStr.isEmpty()
89 //like when the first message's body is different from the 2nd,
90 //but the 2nd is the same as the 3rd, etc.
91 //if ( !idStr.isEmpty() )
92 {
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()));
97 }
98 uint hash = qHash(message->encodedContent());
99 kDebug() << idStr << bodyHashes.value(mainId) << hash;
100 if (bodyHashes.value(mainId) == hash) {
101 duplicates[mainId].append(i);
102 }
103 } else {
104 messageIds.insert(idStr, i);
105 }
106 }
107 }
108 }
109
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));
115 }
116 }
117
118 if (mKilled) {
119 mParent->emitResult();
120 return;
121 }
122
123 if (mJobCount > 0) {
124 fetchItem();
125 } else {
126 if (mDuplicateItems.isEmpty()) {
127 kDebug() << "No duplicates, I'm done here";
128 mParent->emitResult();
129 return;
130 } else {
131 emit mParent->description(mParent, i18n("Removing duplicates..."));
132 Akonadi::ItemDeleteJob *delCmd = new Akonadi::ItemDeleteJob(mDuplicateItems, mParent);
133 mParent->connect(delCmd, SIGNAL(result(KJob*)), mParent, SLOT(slotDeleteDone(KJob*)));
134 }
135 }
136 }
137
138 void slotDeleteDone(KJob *job)
139 {
140 kDebug() << "Job done";
141
142 mParent->setError(job->error());
143 mParent->setErrorText(job->errorText());
144 mParent->emitResult();
145 }
146
147 Akonadi::Collection::List mFolders;
148 int mJobCount;
149 Akonadi::Item::List mDuplicateItems;
150 bool mKilled;
151 Akonadi::Job *mCurrentJob;
152
153private:
154 RemoveDuplicatesJob *mParent;
155
156};
157
158using namespace Akonadi;
159
160RemoveDuplicatesJob::RemoveDuplicatesJob(const Akonadi::Collection &folder, QObject *parent)
161 : Job(parent)
162 , d(new Private(this))
163{
164 d->mJobCount = 1;
165 d->mFolders << folder;
166}
167
168RemoveDuplicatesJob::RemoveDuplicatesJob(const Akonadi::Collection::List &folders, QObject *parent)
169 : Job(parent)
170 , d(new Private(this))
171{
172 d->mFolders = folders;
173 d->mJobCount = d->mFolders.length();
174}
175
176RemoveDuplicatesJob::~RemoveDuplicatesJob()
177{
178 delete d;
179}
180
181void RemoveDuplicatesJob::doStart()
182{
183 kDebug();
184
185 if (d->mFolders.isEmpty()) {
186 kWarning() << "No collections to process";
187 emitResult();
188 return;
189 }
190
191 d->fetchItem();
192}
193
194bool RemoveDuplicatesJob::doKill()
195{
196 kDebug() << "Killed!";
197
198 d->mKilled = true;
199 if (d->mCurrentJob) {
200 d->mCurrentJob->kill(EmitResult);
201 }
202
203 return true;
204}
205
206#include "moc_removeduplicatesjob.cpp"
Akonadi::RemoveDuplicatesJob
Job that finds and removes duplicate messages in given collection.
Definition removeduplicatesjob.h:42
Akonadi::RemoveDuplicatesJob::RemoveDuplicatesJob
RemoveDuplicatesJob(const Akonadi::Collection &folder, QObject *parent=0)
Creates a new job that will remove duplicates in folder.
Definition removeduplicatesjob.cpp:160
Akonadi::RemoveDuplicatesJob::~RemoveDuplicatesJob
virtual ~RemoveDuplicatesJob()
Destroys the job.
Definition removeduplicatesjob.cpp:176
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Wed Jan 24 2024 00:00:00 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi/kmime

Skip menu "akonadi/kmime"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal