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

akonadi/kmime

  • sources
  • kde-4.14
  • kdepimlibs
  • 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->mJobCount = 1;
165  d->mFolders << folder;
166 }
167 
168 RemoveDuplicatesJob::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 
176 RemoveDuplicatesJob::~RemoveDuplicatesJob()
177 {
178  delete d;
179 }
180 
181 void 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 
194 bool 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::RemoveDuplicatesJob
RemoveDuplicatesJob(const Akonadi::Collection &folder, QObject *parent=0)
Creates a new job that will remove duplicates in folder.
Definition: removeduplicatesjob.cpp:160
QMap::contains
bool contains(const Key &key) const
QByteArray
QMap::constBegin
const_iterator constBegin() const
QMap
QList::value
T value(int i) const
QList::append
void append(const T &value)
QObject
QMap::constEnd
const_iterator constEnd() const
QList
Akonadi::RemoveDuplicatesJob::~RemoveDuplicatesJob
virtual ~RemoveDuplicatesJob()
Destroys the job.
Definition: removeduplicatesjob.cpp:176
Akonadi::RemoveDuplicatesJob
Job that finds and removes duplicate messages in given collection.
Definition: removeduplicatesjob.h:41
QMap::insert
iterator insert(const Key &key, const T &value)
QMap::value
const T value(const Key &key) const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:38:24 by doxygen 1.8.7 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 Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs API Reference

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

Search



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