• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.11.3 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 
32 
33 class Akonadi::RemoveDuplicatesJob::Private {
34 
35  public:
36  Private( RemoveDuplicatesJob *parent )
37  : mJobCount( 0 )
38  , mKilled( false )
39  , mCurrentJob( 0 )
40  , mParent( parent )
41  {
42 
43  }
44 
45  void fetchItem()
46  {
47  Akonadi::Collection collection = mFolders.value( mJobCount - 1);
48  kDebug() << "Processing collection" << collection.name() << "(" << collection.id() << ")";
49 
50  Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( collection, mParent );
51  job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
52  job->fetchScope().fetchFullPayload();
53  mParent->connect( job, SIGNAL(result(KJob*)), mParent, SLOT(slotFetchDone(KJob*)) );
54  mCurrentJob = job;
55 
56  emit mParent->description( mParent, i18n( "Retrieving items..." ) );
57  }
58 
59  void slotFetchDone( KJob *job )
60  {
61  mJobCount--;
62  if ( job->error() ) {
63  mParent->setError( job->error() );
64  mParent->setErrorText( job->errorText() );
65  mParent->emitResult();
66  return;
67  }
68 
69  if ( mKilled ) {
70  mParent->emitResult();
71  return;
72  }
73 
74  emit mParent->description( mParent, i18n( "Searching for duplicates..." ) );
75 
76  Akonadi::ItemFetchJob *fjob = static_cast<Akonadi::ItemFetchJob*>( job );
77  Akonadi::Item::List items = fjob->items();
78 
79  //find duplicate mails with the same messageid
80  //if duplicates are found, check the content as well to be sure they are the same
81  QMap<QByteArray, uint> messageIds;
82  QMap<uint, QList<uint> > duplicates;
83  QMap<uint, uint> bodyHashes;
84  const int numberOfItems( items.size() );
85  for ( int i = 0; i < numberOfItems; ++i ) {
86  Akonadi::Item item = items.at( i );
87  if ( item.hasPayload<KMime::Message::Ptr>() ) {
88  KMime::Message::Ptr message = item.payload<KMime::Message::Ptr>();
89  QByteArray idStr = message->messageID()->as7BitString( false );
90  //TODO: Maybe do some more check in case of idStr.isEmpty()
91  //like when the first message's body is different from the 2nd,
92  //but the 2nd is the same as the 3rd, etc.
93  //if ( !idStr.isEmpty() )
94  {
95  if ( messageIds.contains( idStr ) ) {
96  uint mainId = messageIds.value( idStr );
97  if ( !bodyHashes.contains( mainId ) ) {
98  bodyHashes.insert( mainId, qHash( items.value( mainId ).payload<KMime::Message::Ptr>()->encodedContent() ) );
99  }
100  uint hash = qHash( message->encodedContent() );
101  kDebug() << idStr << bodyHashes.value( mainId ) << hash;
102  if ( bodyHashes.value( mainId ) == hash ) {
103  duplicates[ mainId ].append( i );
104  }
105  } else {
106  messageIds.insert( idStr, i );
107  }
108  }
109  }
110  }
111 
112  QMap<uint, QList<uint> >::ConstIterator end( duplicates.constEnd() );
113  for( QMap<uint, QList<uint> >::ConstIterator it = duplicates.constBegin(); it != end; ++it ) {
114  QList<uint>::ConstIterator dupEnd( it.value().constEnd() );
115  for ( QList<uint>::ConstIterator dupIt = it.value().constBegin(); dupIt != dupEnd; ++dupIt ) {
116  mDuplicateItems.append( items.value( *dupIt ) );
117  }
118  }
119 
120  if ( mKilled ) {
121  mParent->emitResult();
122  return;
123  }
124 
125  if ( mJobCount > 0 ) {
126  fetchItem();
127  } else {
128  if ( mDuplicateItems.isEmpty() ) {
129  kDebug() << "No duplicates, I'm done here";
130  mParent->emitResult();
131  return;
132  } else {
133  emit mParent->description( mParent, i18n( "Removing duplicates..." ) );
134  Akonadi::ItemDeleteJob *delCmd = new Akonadi::ItemDeleteJob( mDuplicateItems, mParent );
135  mParent->connect( delCmd, SIGNAL(result(KJob*)), mParent, SLOT(slotDeleteDone(KJob*)) );
136  }
137  }
138  }
139 
140  void slotDeleteDone( KJob *job )
141  {
142  kDebug() << "Job done";
143 
144  mParent->setError( job->error() );
145  mParent->setErrorText( job->errorText() );
146  mParent->emitResult();
147  }
148 
149  Akonadi::Collection::List mFolders;
150  int mJobCount;
151  Akonadi::Item::List mDuplicateItems;
152  bool mKilled;
153  Akonadi::Job *mCurrentJob;
154 
155  private:
156  RemoveDuplicatesJob *mParent;
157 
158 };
159 
160 using namespace Akonadi;
161 
162 RemoveDuplicatesJob::RemoveDuplicatesJob( const Akonadi::Collection &folder, QObject* parent )
163  : Job( parent )
164  , d( new Private( this ) )
165 {
166  d->mFolders << folder;
167 }
168 
169 RemoveDuplicatesJob::RemoveDuplicatesJob( const Akonadi::Collection::List &folders, QObject* parent)
170  : Job(parent)
171  , d( new Private( this ) )
172 {
173  d->mFolders = folders;
174  d->mJobCount = d->mFolders.length();
175 }
176 
177 RemoveDuplicatesJob::~RemoveDuplicatesJob()
178 {
179  delete d;
180 }
181 
182 void RemoveDuplicatesJob::doStart()
183 {
184  kDebug();
185 
186  if ( d->mFolders.isEmpty() ) {
187  kWarning() << "No collections to process";
188  emitResult();
189  return;
190  }
191 
192  d->fetchItem();
193 }
194 
195 bool RemoveDuplicatesJob::doKill()
196 {
197  kDebug() << "Killed!";
198 
199  d->mKilled = true;
200  if ( d->mCurrentJob ) {
201  d->mCurrentJob->kill( EmitResult );
202  }
203 
204  return true;
205 }
206 
207 #include "removeduplicatesjob.moc"
Akonadi::RemoveDuplicatesJob::RemoveDuplicatesJob
RemoveDuplicatesJob(const Akonadi::Collection &folder, QObject *parent=0)
Creates a new job that will remove duplicates in folder.
Definition: removeduplicatesjob.cpp:162
Akonadi::RemoveDuplicatesJob::~RemoveDuplicatesJob
virtual ~RemoveDuplicatesJob()
Destroys the job.
Definition: removeduplicatesjob.cpp:177
Akonadi::RemoveDuplicatesJob
Job that finds and removes duplicate messages in given collection.
Definition: removeduplicatesjob.h:41
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Tue Nov 26 2013 09:03:54 by doxygen 1.8.5 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.11.3 API Reference

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