21 #include "removeduplicatesjob.h"
23 #include <QAbstractItemModel>
25 #include <akonadi/itemfetchjob.h>
26 #include <akonadi/itemdeletejob.h>
27 #include <akonadi/itemfetchscope.h>
28 #include <kmime/kmime_message.h>
30 #include <KLocalizedString>
33 class Akonadi::RemoveDuplicatesJob::Private {
47 Akonadi::Collection collection = mFolders.value( mJobCount - 1);
48 kDebug() <<
"Processing collection" << collection.name() <<
"(" << collection.id() <<
")";
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*)) );
56 emit mParent->description( mParent, i18n(
"Retrieving items..." ) );
59 void slotFetchDone( KJob *job )
63 mParent->setError( job->error() );
64 mParent->setErrorText( job->errorText() );
65 mParent->emitResult();
70 mParent->emitResult();
74 emit mParent->description( mParent, i18n(
"Searching for duplicates..." ) );
76 Akonadi::ItemFetchJob *fjob =
dynamic_cast<Akonadi::ItemFetchJob*
>( job );
78 Akonadi::Item::List items = fjob->items();
82 QMap<QByteArray, uint> messageIds;
83 QMap<uint, QList<uint> > duplicates;
84 QMap<uint, uint> bodyHashes;
85 const int numberOfItems( items.size() );
86 for (
int i = 0; i < numberOfItems; ++i ) {
87 Akonadi::Item item = items.at( i );
88 if ( item.hasPayload<KMime::Message::Ptr>() ) {
89 KMime::Message::Ptr message = item.payload<KMime::Message::Ptr>();
90 QByteArray idStr = message->messageID()->as7BitString(
false );
96 if ( messageIds.contains( idStr ) ) {
97 uint mainId = messageIds.value( idStr );
98 if ( !bodyHashes.contains( mainId ) ) {
99 bodyHashes.insert( mainId, qHash( items.value( mainId ).payload<KMime::Message::Ptr>()->encodedContent() ) );
101 uint hash = qHash( message->encodedContent() );
102 kDebug() << idStr << bodyHashes.value( mainId ) << hash;
103 if ( bodyHashes.value( mainId ) == hash ) {
104 duplicates[ mainId ].append( i );
107 messageIds.insert( idStr, i );
113 QMap<uint, QList<uint> >::ConstIterator end( duplicates.constEnd() );
114 for( QMap<uint, QList<uint> >::ConstIterator it = duplicates.constBegin(); it != end; ++it ) {
115 QList<uint>::ConstIterator dupEnd( it.value().constEnd() );
116 for ( QList<uint>::ConstIterator dupIt = it.value().constBegin(); dupIt != dupEnd; ++dupIt ) {
117 mDuplicateItems.append( items.value( *dupIt ) );
122 mParent->emitResult();
126 if ( mJobCount > 0 ) {
129 if ( mDuplicateItems.isEmpty() ) {
130 kDebug() <<
"No duplicates, I'm done here";
131 mParent->emitResult();
134 emit mParent->description( mParent, i18n(
"Removing duplicates..." ) );
135 Akonadi::ItemDeleteJob *delCmd =
new Akonadi::ItemDeleteJob( mDuplicateItems, mParent );
136 mParent->connect( delCmd, SIGNAL(result(KJob*)), mParent, SLOT(slotDeleteDone(KJob*)) );
141 void slotDeleteDone( KJob *job )
143 kDebug() <<
"Job done";
145 mParent->setError( job->error() );
146 mParent->setErrorText( job->errorText() );
147 mParent->emitResult();
150 Akonadi::Collection::List mFolders;
152 Akonadi::Item::List mDuplicateItems;
154 Akonadi::Job *mCurrentJob;
161 using namespace Akonadi;
165 , d( new Private( this ) )
167 d->mFolders << folder;
172 , d( new Private( this ) )
174 d->mFolders = folders;
175 d->mJobCount = d->mFolders.length();
183 void RemoveDuplicatesJob::doStart()
187 if ( d->mFolders.isEmpty() ) {
188 kWarning() <<
"No collections to process";
196 bool RemoveDuplicatesJob::doKill()
198 kDebug() <<
"Killed!";
201 if ( d->mCurrentJob ) {
202 d->mCurrentJob->kill( EmitResult );
208 #include "removeduplicatesjob.moc"