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

akonadi

  • 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 
32 class Akonadi::RemoveDuplicatesJob::Private {
33 
34 public:
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 
153 private:
154  RemoveDuplicatesJob *mParent;
155 
156 };
157 
158 using namespace Akonadi;
159 
160 RemoveDuplicatesJob::RemoveDuplicatesJob(const Akonadi::Collection &folder, QObject *parent)
161  : Job(parent)
162  , d(new Private(this))
163 {
164  d->mFolders << folder;
165 }
166 
167 RemoveDuplicatesJob::RemoveDuplicatesJob(const Akonadi::Collection::List &folders, QObject *parent)
168  : Job(parent)
169  , d(new Private(this))
170 {
171  d->mFolders = folders;
172  d->mJobCount = d->mFolders.length();
173 }
174 
175 RemoveDuplicatesJob::~RemoveDuplicatesJob()
176 {
177  delete d;
178 }
179 
180 void RemoveDuplicatesJob::doStart()
181 {
182  kDebug();
183 
184  if (d->mFolders.isEmpty()) {
185  kWarning() << "No collections to process";
186  emitResult();
187  return;
188  }
189 
190  d->fetchItem();
191 }
192 
193 bool RemoveDuplicatesJob::doKill()
194 {
195  kDebug() << "Killed!";
196 
197  d->mKilled = true;
198  if (d->mCurrentJob) {
199  d->mCurrentJob->kill(EmitResult);
200  }
201 
202  return true;
203 }
204 
205 #include "moc_removeduplicatesjob.cpp"
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::Collection::name
QString name() const
Returns the i18n'ed name of the collection.
Definition: collection.cpp:81
Akonadi::RemoveDuplicatesJob::doStart
virtual void doStart()
This method must be reimplemented in the concrete jobs.
Definition: removeduplicatesjob.cpp:180
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
Akonadi::Job
Base class for all actions in the Akonadi storage.
Definition: job.h:86
Akonadi::ItemFetchScope::fetchFullPayload
void fetchFullPayload(bool fetch=true)
Sets whether the full payload shall be fetched.
Definition: itemfetchscope.cpp:70
Akonadi::ItemFetchJob::items
Item::List items() const
Returns the fetched items.
Definition: itemfetchjob.cpp:233
Akonadi::ItemDeleteJob
Job that deletes items from the Akonadi storage.
Definition: itemdeletejob.h:62
Akonadi::ItemFetchJob::fetchScope
ItemFetchScope & fetchScope()
Returns the item fetch scope.
Definition: itemfetchjob.cpp:261
Akonadi::ItemFetchScope::Parent
Only retrieve the immediate parent collection.
Definition: itemfetchscope.h:78
Akonadi::RemoveDuplicatesJob::doKill
virtual bool doKill()
Kills the execution of the job.
Definition: removeduplicatesjob.cpp:193
Akonadi::Entity::id
Id id() const
Returns the unique identifier of the entity.
Definition: entity.cpp:72
Akonadi::ItemFetchScope::setAncestorRetrieval
void setAncestorRetrieval(AncestorRetrieval ancestorDepth)
Sets how many levels of ancestor collections should be included in the retrieval. ...
Definition: itemfetchscope.cpp:132
Akonadi::RemoveDuplicatesJob::~RemoveDuplicatesJob
virtual ~RemoveDuplicatesJob()
Destroys the job.
Definition: removeduplicatesjob.cpp:175
Akonadi
FreeBusyManager::Singleton.
Definition: actionstatemanager_p.h:28
Akonadi::RemoveDuplicatesJob
Job that finds and removes duplicate messages in given collection.
Definition: removeduplicatesjob.h:41
Akonadi::ItemFetchJob
Job that fetches items from the Akonadi storage.
Definition: itemfetchjob.h:82
Akonadi::Collection::List
QList< Collection > List
Describes a list of collections.
Definition: collection.h:81
This file is part of the KDE documentation.
Documentation copyright © 1996-2015 The KDE developers.
Generated on Tue Nov 24 2015 17:33:50 by doxygen 1.8.8 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs-4.14.3 API Reference

Skip menu "kdepimlibs-4.14.3 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