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

akonadi

  • sources
  • kde-4.12
  • 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 
44  void fetchItem()
45  {
46  Akonadi::Collection collection = mFolders.value( mJobCount - 1);
47  kDebug() << "Processing collection" << collection.name() << "(" << collection.id() << ")";
48 
49  Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( collection, mParent );
50  job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
51  job->fetchScope().fetchFullPayload();
52  mParent->connect( job, SIGNAL(result(KJob*)), mParent, SLOT(slotFetchDone(KJob*)) );
53  mCurrentJob = job;
54 
55  emit mParent->description( mParent, i18n( "Retrieving items..." ) );
56  }
57 
58  void slotFetchDone( KJob *job )
59  {
60  mJobCount--;
61  if ( job->error() ) {
62  mParent->setError( job->error() );
63  mParent->setErrorText( job->errorText() );
64  mParent->emitResult();
65  return;
66  }
67 
68  if ( mKilled ) {
69  mParent->emitResult();
70  return;
71  }
72 
73  emit mParent->description( mParent, i18n( "Searching for duplicates..." ) );
74 
75  Akonadi::ItemFetchJob *fjob = static_cast<Akonadi::ItemFetchJob*>( job );
76  Akonadi::Item::List items = fjob->items();
77 
78  //find duplicate mails with the same messageid
79  //if duplicates are found, check the content as well to be sure they are the same
80  QMap<QByteArray, uint> messageIds;
81  QMap<uint, QList<uint> > duplicates;
82  QMap<uint, uint> bodyHashes;
83  const int numberOfItems( items.size() );
84  for ( int i = 0; i < numberOfItems; ++i ) {
85  Akonadi::Item item = items.at( i );
86  if ( item.hasPayload<KMime::Message::Ptr>() ) {
87  KMime::Message::Ptr message = item.payload<KMime::Message::Ptr>();
88  QByteArray idStr = message->messageID()->as7BitString( false );
89  //TODO: Maybe do some more check in case of idStr.isEmpty()
90  //like when the first message's body is different from the 2nd,
91  //but the 2nd is the same as the 3rd, etc.
92  //if ( !idStr.isEmpty() )
93  {
94  if ( messageIds.contains( idStr ) ) {
95  uint mainId = messageIds.value( idStr );
96  if ( !bodyHashes.contains( mainId ) ) {
97  bodyHashes.insert( mainId, qHash( items.value( mainId ).payload<KMime::Message::Ptr>()->encodedContent() ) );
98  }
99  uint hash = qHash( message->encodedContent() );
100  kDebug() << idStr << bodyHashes.value( mainId ) << hash;
101  if ( bodyHashes.value( mainId ) == hash ) {
102  duplicates[ mainId ].append( i );
103  }
104  } else {
105  messageIds.insert( idStr, i );
106  }
107  }
108  }
109  }
110 
111  QMap<uint, QList<uint> >::ConstIterator end( duplicates.constEnd() );
112  for ( QMap<uint, QList<uint> >::ConstIterator it = duplicates.constBegin(); it != end; ++it ) {
113  QList<uint>::ConstIterator dupEnd( it.value().constEnd() );
114  for ( QList<uint>::ConstIterator dupIt = it.value().constBegin(); dupIt != dupEnd; ++dupIt ) {
115  mDuplicateItems.append( items.value( *dupIt ) );
116  }
117  }
118 
119  if ( mKilled ) {
120  mParent->emitResult();
121  return;
122  }
123 
124  if ( mJobCount > 0 ) {
125  fetchItem();
126  } else {
127  if ( mDuplicateItems.isEmpty() ) {
128  kDebug() << "No duplicates, I'm done here";
129  mParent->emitResult();
130  return;
131  } else {
132  emit mParent->description( mParent, i18n( "Removing duplicates..." ) );
133  Akonadi::ItemDeleteJob *delCmd = new Akonadi::ItemDeleteJob( mDuplicateItems, mParent );
134  mParent->connect( delCmd, SIGNAL(result(KJob*)), mParent, SLOT(slotDeleteDone(KJob*)) );
135  }
136  }
137  }
138 
139  void slotDeleteDone( KJob *job )
140  {
141  kDebug() << "Job done";
142 
143  mParent->setError( job->error() );
144  mParent->setErrorText( job->errorText() );
145  mParent->emitResult();
146  }
147 
148  Akonadi::Collection::List mFolders;
149  int mJobCount;
150  Akonadi::Item::List mDuplicateItems;
151  bool mKilled;
152  Akonadi::Job *mCurrentJob;
153 
154  private:
155  RemoveDuplicatesJob *mParent;
156 
157 };
158 
159 using namespace Akonadi;
160 
161 RemoveDuplicatesJob::RemoveDuplicatesJob( const Akonadi::Collection &folder, QObject* parent )
162  : Job( parent )
163  , d( new Private( this ) )
164 {
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:161
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:181
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:68
Akonadi::ItemFetchJob::items
Item::List items() const
Returns the fetched items.
Definition: itemfetchjob.cpp:228
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:256
Akonadi::ItemFetchScope::Parent
Only retrieve the immediate parent collection.
Definition: itemfetchscope.h:77
Akonadi::RemoveDuplicatesJob::doKill
virtual bool doKill()
Kills the execution of the job.
Definition: removeduplicatesjob.cpp:194
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:128
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
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-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:00:27 by doxygen 1.8.7 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 API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

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