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 =
static_cast<Akonadi::ItemFetchJob*
>( job );
77 Akonadi::Item::List items = fjob->items();
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 );
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() ) );
100 uint hash = qHash( message->encodedContent() );
101 kDebug() << idStr << bodyHashes.value( mainId ) << hash;
102 if ( bodyHashes.value( mainId ) == hash ) {
103 duplicates[ mainId ].append( i );
106 messageIds.insert( idStr, i );
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 ) );
121 mParent->emitResult();
125 if ( mJobCount > 0 ) {
128 if ( mDuplicateItems.isEmpty() ) {
129 kDebug() <<
"No duplicates, I'm done here";
130 mParent->emitResult();
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*)) );
140 void slotDeleteDone( KJob *job )
142 kDebug() <<
"Job done";
144 mParent->setError( job->error() );
145 mParent->setErrorText( job->errorText() );
146 mParent->emitResult();
149 Akonadi::Collection::List mFolders;
151 Akonadi::Item::List mDuplicateItems;
153 Akonadi::Job *mCurrentJob;
160 using namespace Akonadi;
164 , d( new Private( this ) )
166 d->mFolders << folder;
171 , d( new Private( this ) )
173 d->mFolders = folders;
174 d->mJobCount = d->mFolders.length();
182 void RemoveDuplicatesJob::doStart()
186 if ( d->mFolders.isEmpty() ) {
187 kWarning() <<
"No collections to process";
195 bool RemoveDuplicatesJob::doKill()
197 kDebug() <<
"Killed!";
200 if ( d->mCurrentJob ) {
201 d->mCurrentJob->kill( EmitResult );
207 #include "removeduplicatesjob.moc"
RemoveDuplicatesJob(const Akonadi::Collection &folder, QObject *parent=0)
Creates a new job that will remove duplicates in folder.
virtual ~RemoveDuplicatesJob()
Destroys the job.
Job that finds and removes duplicate messages in given collection.