20 #include "trashrestorejob.h"
22 #include "collection.h"
23 #include "entitydeletedattribute.h"
26 #include "trashsettings.h"
30 #include <akonadi/itemdeletejob.h>
31 #include <akonadi/collectiondeletejob.h>
32 #include <akonadi/itemmovejob.h>
33 #include <akonadi/collectionmovejob.h>
34 #include <akonadi/itemmodifyjob.h>
35 #include <akonadi/collectionmodifyjob.h>
36 #include <akonadi/collectionfetchjob.h>
37 #include <akonadi/itemfetchjob.h>
38 #include <akonadi/collectionfetchscope.h>
39 #include <akonadi/itemfetchscope.h>
44 using namespace Akonadi;
46 class TrashRestoreJob::TrashRestoreJobPrivate :
public JobPrivate
49 TrashRestoreJobPrivate( TrashRestoreJob *parent )
50 : JobPrivate( parent ) {
53 void selectResult( KJob * );
57 void targetCollectionFetched( KJob * );
59 void removeAttribute(
const Akonadi::Item::List & );
60 void removeAttribute(
const Akonadi::Collection::List & );
63 void itemsReceived(
const Akonadi::Item::List & );
64 void collectionsReceived(
const Akonadi::Collection::List & );
66 Q_DECLARE_PUBLIC( TrashRestoreJob )
69 Collection mCollection;
70 Collection mTargetCollection;
71 QHash<Collection, Item::List> restoreCollections;
75 void TrashRestoreJob::TrashRestoreJobPrivate::selectResult( KJob *job )
77 Q_Q( TrashRestoreJob );
79 kWarning() << job->errorString();
83 if ( !q->hasSubjobs() || ( q->subjobs().contains( static_cast<KJob*>( q->sender() ) ) && q->subjobs().size() == 1 ) ) {
89 void TrashRestoreJob::TrashRestoreJobPrivate::targetCollectionFetched( KJob *job )
91 Q_Q( TrashRestoreJob );
93 CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob*> ( job );
95 const Collection::List &list = fetchJob->collections();
97 if ( list.isEmpty() || !list.first().isValid() || list.first().hasAttribute<Akonadi::EntityDeletedAttribute>() ) {
99 const QString res = fetchJob->property(
"Resource" ).toString();
100 if ( res.isEmpty() ) {
101 q->setError( Job::Unknown );
102 q->setErrorText( i18n(
"Could not find restore collection and restore resource is not available" ) );
105 kWarning() <<
"restore collection not available";
110 CollectionFetchJob *resRootFetch =
new CollectionFetchJob( Collection::root(), CollectionFetchJob::FirstLevel, q );
111 resRootFetch->fetchScope().setResource( res );
112 const QVariant &var = fetchJob->property(
"Items" );
113 if ( var.isValid() ) {
114 resRootFetch->setProperty(
"Items", var.toInt() );
116 q->connect( resRootFetch, SIGNAL(result(KJob*)), SLOT(targetCollectionFetched(KJob*)) );
117 q->connect( resRootFetch, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
120 Q_ASSERT( list.size() == 1 );
123 if ( !mItems.isEmpty() ) {
124 const QVariant &var = fetchJob->property(
"Items" );
125 Q_ASSERT( var.isValid() );
126 const Item::List &items = restoreCollections[Collection( var.toInt() )];
130 removeAttribute( items );
131 if ( items.first().parentCollection() != list.first() ) {
132 ItemMoveJob *job =
new ItemMoveJob( items, list.first(), q );
133 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
136 Q_ASSERT( mCollection.isValid() );
138 removeAttribute( Collection::List() << mCollection );
139 CollectionFetchJob *collectionFetchJob =
new CollectionFetchJob( mCollection, CollectionFetchJob::Recursive, q );
140 q->connect( collectionFetchJob, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
141 q->connect( collectionFetchJob, SIGNAL(collectionsReceived(Akonadi::Collection::List)), SLOT(removeAttribute(Akonadi::Collection::List)) );
143 if ( mCollection.parentCollection() != list.first() ) {
144 CollectionMoveJob *job =
new CollectionMoveJob( mCollection, list.first(), q );
145 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
151 void TrashRestoreJob::TrashRestoreJobPrivate::itemsReceived(
const Akonadi::Item::List &items )
153 Q_Q( TrashRestoreJob );
154 if ( items.isEmpty() ) {
155 q->setError( Job::Unknown );
156 q->setErrorText( i18n(
"Invalid items passed" ) );
163 foreach(
const Item &item, mItems ) {
164 if ( !item.hasAttribute<Akonadi::EntityDeletedAttribute>() ) {
168 restoreCollections[item.attribute<Akonadi::EntityDeletedAttribute>()->restoreCollection()].append( item );
171 foreach(
const Collection &col, restoreCollections.keys() ) {
172 const Item &first = restoreCollections.value( col ).first();
174 Collection targetCollection = col;
175 const QString restoreResource = first.attribute<Akonadi::EntityDeletedAttribute>()->restoreResource();
178 if ( !targetCollection.isValid() ) {
179 removeAttribute( restoreCollections.value( col ) );
184 if ( mTargetCollection.isValid() ) {
185 targetCollection = mTargetCollection;
189 CollectionFetchJob *fetchJob =
new CollectionFetchJob( targetCollection, Akonadi::CollectionFetchJob::Base, q );
190 if ( !mTargetCollection.isValid() ) {
191 fetchJob->setProperty(
"Resource", restoreResource );
193 fetchJob->setProperty(
"Items", col.id() );
194 q->connect( fetchJob, SIGNAL(result(KJob*)), SLOT(targetCollectionFetched(KJob*)) );
199 void TrashRestoreJob::TrashRestoreJobPrivate::collectionsReceived(
const Akonadi::Collection::List &collections )
201 Q_Q( TrashRestoreJob );
202 if ( collections.isEmpty() ) {
203 q->setError( Job::Unknown );
204 q->setErrorText( i18n(
"Invalid collection passed" ) );
208 Q_ASSERT( collections.size() == 1 );
209 mCollection = collections.first();
211 if ( !mCollection.hasAttribute<Akonadi::EntityDeletedAttribute>() ) {
215 const QString restoreResource = mCollection.attribute<Akonadi::EntityDeletedAttribute>()->restoreResource();
216 Collection targetCollection = mCollection.attribute<EntityDeletedAttribute>()->restoreCollection();
219 if ( !targetCollection.isValid() ) {
220 removeAttribute( Collection::List() << mCollection );
221 CollectionFetchJob *collectionFetchJob =
new CollectionFetchJob( mCollection, CollectionFetchJob::Recursive, q );
222 q->connect( collectionFetchJob, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
223 q->connect( collectionFetchJob, SIGNAL(collectionsReceived(Akonadi::Collection::List)), SLOT(removeAttribute(Akonadi::Collection::List)) );
228 if ( mTargetCollection.isValid() ) {
229 targetCollection = mTargetCollection;
233 CollectionFetchJob *fetchJob =
new CollectionFetchJob( targetCollection, CollectionFetchJob::Base, q );
234 if ( !mTargetCollection.isValid() ) {
235 fetchJob->setProperty(
"Resource", restoreResource );
237 q->connect( fetchJob, SIGNAL(result(KJob*)), SLOT(targetCollectionFetched(KJob*)) );
241 void TrashRestoreJob::TrashRestoreJobPrivate::removeAttribute(
const Akonadi::Collection::List &list )
243 Q_Q( TrashRestoreJob );
244 QListIterator<Collection> i( list );
245 while ( i.hasNext() ) {
246 Collection col = i.next();
247 col.removeAttribute<EntityDeletedAttribute>();
249 CollectionModifyJob *job =
new CollectionModifyJob( col, q );
250 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
252 ItemFetchJob *itemFetchJob =
new ItemFetchJob( col, q );
253 itemFetchJob->fetchScope().fetchAttribute<EntityDeletedAttribute> ( true );
254 q->connect( itemFetchJob, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
255 q->connect( itemFetchJob, SIGNAL(itemsReceived(Akonadi::Item::List)), SLOT(removeAttribute(Akonadi::Item::List)) );
259 void TrashRestoreJob::TrashRestoreJobPrivate::removeAttribute(
const Akonadi::Item::List &list )
261 Q_Q( TrashRestoreJob );
262 Item::List items = list;
263 QMutableListIterator<Item> i( items );
264 while ( i.hasNext() ) {
265 Item &item = i.next();
266 item.removeAttribute<EntityDeletedAttribute>();
267 ItemModifyJob *job =
new ItemModifyJob( item, q );
268 job->setIgnorePayload(
true );
269 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
277 TrashRestoreJob::TrashRestoreJob(
const Item & item, QObject * parent )
278 : Job( new TrashRestoreJobPrivate( this ), parent )
280 Q_D( TrashRestoreJob );
284 TrashRestoreJob::TrashRestoreJob(
const Item::List& items, QObject* parent )
285 : Job( new TrashRestoreJobPrivate( this ), parent )
287 Q_D( TrashRestoreJob );
291 TrashRestoreJob::TrashRestoreJob(
const Collection& collection, QObject* parent )
292 : Job( new TrashRestoreJobPrivate( this ), parent )
294 Q_D( TrashRestoreJob );
295 d->mCollection = collection;
298 TrashRestoreJob::~TrashRestoreJob()
302 void TrashRestoreJob::setTargetCollection(
const Akonadi::Collection collection )
304 Q_D( TrashRestoreJob );
305 d->mTargetCollection = collection;
309 Item::List TrashRestoreJob::items()
const
311 Q_D(
const TrashRestoreJob );
315 void TrashRestoreJob::doStart()
317 Q_D( TrashRestoreJob );
320 if ( !d->mItems.isEmpty() ) {
321 ItemFetchJob *job =
new ItemFetchJob( d->mItems,
this );
322 job->fetchScope().setCacheOnly(
true );
323 job->fetchScope().fetchAttribute<EntityDeletedAttribute> ( true );
324 connect( job, SIGNAL(itemsReceived(Akonadi::Item::List)),
this, SLOT(itemsReceived(Akonadi::Item::List)) );
325 }
else if ( d->mCollection.isValid() ) {
326 CollectionFetchJob *job =
new CollectionFetchJob( d->mCollection, CollectionFetchJob::Base,
this );
327 connect( job, SIGNAL(collectionsReceived(Akonadi::Collection::List)),
this, SLOT(collectionsReceived(Akonadi::Collection::List)) );
329 kWarning() <<
"No valid collection or empty itemlist";
330 setError( Job::Unknown );
331 setErrorText( i18n(
"No valid collection or empty itemlist" ) );
337 #include "trashrestorejob.moc"