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>
32 class Akonadi::RemoveDuplicatesJob::Private {
46 Akonadi::Collection collection = mFolders.value( mJobCount - 1);
47 kDebug() <<
"Processing collection" << collection.name() <<
"(" << collection.id() <<
")";
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*)) );
55 emit mParent->description( mParent, i18n(
"Retrieving items..." ) );
58 void slotFetchDone( KJob *job )
62 mParent->setError( job->error() );
63 mParent->setErrorText( job->errorText() );
64 mParent->emitResult();
69 mParent->emitResult();
73 emit mParent->description( mParent, i18n(
"Searching for duplicates..." ) );
75 Akonadi::ItemFetchJob *fjob =
static_cast<Akonadi::ItemFetchJob*
>( job );
76 Akonadi::Item::List items = fjob->items();
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 );
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() ) );
99 uint hash = qHash( message->encodedContent() );
100 kDebug() << idStr << bodyHashes.value( mainId ) << hash;
101 if ( bodyHashes.value( mainId ) == hash ) {
102 duplicates[ mainId ].append( i );
105 messageIds.insert( idStr, i );
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 ) );
120 mParent->emitResult();
124 if ( mJobCount > 0 ) {
127 if ( mDuplicateItems.isEmpty() ) {
128 kDebug() <<
"No duplicates, I'm done here";
129 mParent->emitResult();
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*)) );
139 void slotDeleteDone( KJob *job )
141 kDebug() <<
"Job done";
143 mParent->setError( job->error() );
144 mParent->setErrorText( job->errorText() );
145 mParent->emitResult();
148 Akonadi::Collection::List mFolders;
150 Akonadi::Item::List mDuplicateItems;
152 Akonadi::Job *mCurrentJob;
159 using namespace Akonadi;
163 , d( new Private( this ) )
165 d->mFolders << folder;
170 , d( new Private( this ) )
172 d->mFolders = folders;
173 d->mJobCount = d->mFolders.length();
181 void RemoveDuplicatesJob::doStart()
185 if ( d->mFolders.isEmpty() ) {
186 kWarning() <<
"No collections to process";
194 bool RemoveDuplicatesJob::doKill()
196 kDebug() <<
"Killed!";
199 if ( d->mCurrentJob ) {
200 d->mCurrentJob->kill( EmitResult );
206 #include "moc_removeduplicatesjob.cpp"
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.