00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "removeduplicatescommand_p.h"
00022 #include "movetotrashcommand_p.h"
00023 #include "util_p.h"
00024
00025 #include "akonadi/itemfetchjob.h"
00026 #include "akonadi/itemfetchscope.h"
00027 #include "kmime/kmime_message.h"
00028
00029 RemoveDuplicatesCommand::RemoveDuplicatesCommand( const QAbstractItemModel* model, const Akonadi::Collection::List& folders, QObject* parent ) :
00030 CommandBase( parent )
00031 {
00032 mModel = model;
00033 mFolders = folders;
00034 mJobCount = mFolders.size();
00035 }
00036
00037 void RemoveDuplicatesCommand::execute()
00038 {
00039 if ( mJobCount <= 0 ) {
00040 emitResult( OK );
00041 return;
00042 }
00043 Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( mFolders[ mJobCount - 1] , parent() );
00044 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
00045 job->fetchScope().fetchFullPayload();
00046 connect( job, SIGNAL( result( KJob* ) ), this, SLOT( slotFetchDone( KJob* ) ) );
00047 }
00048
00049 void RemoveDuplicatesCommand::slotFetchDone( KJob* job )
00050 {
00051 mJobCount--;
00052 if ( job->error() ) {
00053
00054 Util::showJobError(job);
00055 emitResult( Failed );
00056 return;
00057 }
00058 Akonadi::ItemFetchJob *fjob = dynamic_cast<Akonadi::ItemFetchJob*>( job );
00059 Q_ASSERT( fjob );
00060 Akonadi::Item::List items = fjob->items();
00061
00062
00063
00064 QMap<QByteArray, uint> messageIds;
00065 QMap<uint, QList<uint> > duplicates;
00066 QMap<uint, uint> bodyHashes;
00067 for ( int i = 0; i < items.size(); ++i ) {
00068 Akonadi::Item item = items[i];
00069 if ( item.hasPayload<KMime::Message::Ptr>() ) {
00070 KMime::Message::Ptr message = item.payload<KMime::Message::Ptr>();
00071 QByteArray idStr = message->messageID()->as7BitString( false );
00072
00073
00074
00075
00076 {
00077 if ( messageIds.contains( idStr ) ) {
00078 uint mainId = messageIds.value( idStr );
00079 if ( !bodyHashes.contains( mainId ) )
00080 bodyHashes[ mainId ] = qHash( items[mainId].payload<KMime::Message::Ptr>()->encodedContent() );
00081 uint hash = qHash( message->encodedContent() );
00082 qDebug() << idStr << bodyHashes[ mainId ] << hash;
00083 if ( bodyHashes[ mainId ] == hash )
00084 duplicates[ mainId ].append( i );
00085 } else {
00086 messageIds[ idStr ] = i;
00087 }
00088 }
00089 }
00090 }
00091
00092 for( QMap<uint, QList<uint> >::iterator it = duplicates.begin(); it != duplicates.end(); ++it ) {
00093 for (QList<uint>::iterator dupIt = it.value().begin(); dupIt != it.value().end(); ++dupIt ) {
00094 mDuplicateItems.append( items[*dupIt] );
00095 }
00096 }
00097
00098 if ( mJobCount > 0 ) {
00099 Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( mFolders[ mJobCount - 1 ] , parent() );
00100 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
00101 job->fetchScope().fetchFullPayload();
00102 connect( job, SIGNAL( result( KJob* ) ), this, SLOT( slotFetchDone( KJob* ) ) );
00103 } else {
00104 MoveToTrashCommand *trashCmd = new MoveToTrashCommand( mModel, mDuplicateItems, parent() );
00105 connect( trashCmd, SIGNAL(result(Result)), this, SLOT(emitResult(Result)) );
00106 trashCmd->execute();
00107 }
00108 }
00109