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/itemfetchscope.h>
37 #include <akonadi/collectionfetchscope.h>
38 #include <akonadi/itemfetchjob.h>
39 #include <akonadi/collectionfetchjob.h>
43 using namespace Akonadi;
45 class TrashJob::TrashJobPrivate :
public JobPrivate
48 TrashJobPrivate( TrashJob *parent )
49 : JobPrivate( parent ),
50 mKeepTrashInCollection( false ),
51 mSetRestoreCollection( false ),
52 mDeleteIfInTrash( false ) {
55 void selectResult( KJob *job );
58 void setAttribute(
const Akonadi::Collection::List & );
59 void setAttribute(
const Akonadi::Item::List & );
61 void setAttribute( KJob *job );
65 void parentCollectionReceived(
const Akonadi::Collection::List & );
70 void itemsReceived(
const Akonadi::Item::List & );
72 void collectionsReceived(
const Akonadi::Collection::List & );
75 Q_DECLARE_PUBLIC( TrashJob )
78 Collection mCollection;
79 Collection mRestoreCollection;
80 Collection mTrashCollection;
81 bool mKeepTrashInCollection;
82 bool mSetRestoreCollection;
83 bool mDeleteIfInTrash;
84 QHash<Collection, Item::List> mCollectionItems;
85 QHash<Entity::Id, Collection> mParentCollections;
89 void TrashJob::TrashJobPrivate::selectResult( KJob *job )
93 kWarning() << job->objectName();
94 kWarning() << job->errorString();
98 if ( !q->hasSubjobs() || ( q->subjobs().contains( static_cast<KJob*>( q->sender() ) ) && q->subjobs().size() == 1 ) ) {
103 void TrashJob::TrashJobPrivate::setAttribute(
const Akonadi::Collection::List &list )
106 QListIterator<Collection> i( list );
107 while ( i.hasNext() ) {
108 const Collection &col = i.next();
109 EntityDeletedAttribute *eda =
new EntityDeletedAttribute();
110 if ( mSetRestoreCollection ) {
111 Q_ASSERT( mRestoreCollection.isValid() );
112 eda->setRestoreCollection( mRestoreCollection );
115 Collection modCol( col.id() );
116 modCol.addAttribute( eda );
118 CollectionModifyJob *job =
new CollectionModifyJob( modCol, q );
119 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
121 ItemFetchJob *itemFetchJob =
new ItemFetchJob( col, q );
123 q->connect( itemFetchJob, SIGNAL(itemsReceived(Akonadi::Item::List)), SLOT(setAttribute(Akonadi::Item::List)) );
124 q->connect( itemFetchJob, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
128 void TrashJob::TrashJobPrivate::setAttribute(
const Akonadi::Item::List &list )
131 Item::List items = list;
132 QMutableListIterator<Item> i( items );
133 while ( i.hasNext() ) {
134 const Item &item = i.next();
135 EntityDeletedAttribute *eda =
new EntityDeletedAttribute();
136 if ( mSetRestoreCollection ) {
138 if ( mRestoreCollection.isValid() ) {
139 eda->setRestoreCollection( mRestoreCollection );
141 Q_ASSERT( mParentCollections.contains( item.parentCollection().id() ) );
142 eda->setRestoreCollection( mParentCollections.value( item.parentCollection().id() ) );
146 Item modItem( item.id() );
147 modItem.addAttribute( eda );
148 ItemModifyJob *job =
new ItemModifyJob( modItem, q );
149 job->setIgnorePayload(
true );
150 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
158 void TrashJob::TrashJobPrivate::setAttribute( KJob* job )
161 if ( job->error() ) {
162 kWarning() << job->objectName();
163 kWarning() << job->errorString();
164 q->setError( Job::Unknown );
165 q->setErrorText( i18n(
"Move to trash collection failed, aborting trash operation" ) );
170 const QVariant var = job->property(
"MovedItems" );
171 if ( var.isValid() ) {
172 int id = var.toInt();
174 setAttribute( mCollectionItems.value( Collection(
id ) ) );
179 Q_ASSERT( mCollection.isValid() );
180 setAttribute( Collection::List() << mCollection );
182 CollectionFetchJob *colFetchJob =
new CollectionFetchJob( mCollection, CollectionFetchJob::Recursive, q );
183 q->connect( colFetchJob, SIGNAL(collectionsReceived(Akonadi::Collection::List)), SLOT(setAttribute(Akonadi::Collection::List)) );
184 q->connect( colFetchJob, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
187 void TrashJob::TrashJobPrivate::parentCollectionReceived(
const Akonadi::Collection::List &collections )
190 Q_ASSERT( collections.size() == 1 );
191 const Collection &parentCollection = collections.first();
194 Q_ASSERT( !parentCollection.resource().isEmpty() );
195 Collection trashCollection = mTrashCollection;
196 if ( !mTrashCollection.isValid() ) {
199 if ( !mKeepTrashInCollection && trashCollection.isValid() ) {
200 mSetRestoreCollection =
true;
203 mParentCollections.insert( parentCollection.id(), parentCollection );
205 if ( trashCollection.isValid() ) {
206 ItemMoveJob *job =
new ItemMoveJob( mCollectionItems.value( parentCollection ), trashCollection, q );
207 job->setProperty(
"MovedItems", parentCollection.id() );
208 q->connect( job, SIGNAL(result(KJob*)), SLOT(setAttribute(KJob*)) );
209 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
211 setAttribute( mCollectionItems.value( parentCollection ) );
215 void TrashJob::TrashJobPrivate::itemsReceived(
const Akonadi::Item::List &items )
218 if ( items.isEmpty() ) {
219 q->setError( Job::Unknown );
220 q->setErrorText( i18n(
"Invalid items passed" ) );
227 QListIterator<Item> i( items );
228 while ( i.hasNext() ) {
229 const Item &item = i.next();
230 if ( item.hasAttribute<EntityDeletedAttribute>() ) {
231 toDelete.append( item );
234 Q_ASSERT( item.parentCollection().isValid() );
235 mCollectionItems[item.parentCollection()].append( item );
238 foreach(
const Collection &col, mCollectionItems.keys() ) {
239 CollectionFetchJob *job =
new CollectionFetchJob( col, Akonadi::CollectionFetchJob::Base, q );
240 q->connect( job, SIGNAL(collectionsReceived(Akonadi::Collection::List)),
241 SLOT(parentCollectionReceived(Akonadi::Collection::List)) );
244 if ( mDeleteIfInTrash && !toDelete.isEmpty() ) {
245 ItemDeleteJob *job =
new ItemDeleteJob( toDelete, q );
246 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
247 }
else if ( mCollectionItems.isEmpty() ) {
248 kWarning() <<
"Nothing to do";
254 void TrashJob::TrashJobPrivate::collectionsReceived(
const Akonadi::Collection::List &collections )
257 if ( collections.isEmpty() ) {
258 q->setError( Job::Unknown );
259 q->setErrorText( i18n(
"Invalid collection passed" ) );
263 Q_ASSERT( collections.size() == 1 );
264 mCollection = collections.first();
266 if ( mCollection.hasAttribute<EntityDeletedAttribute>() ) {
267 if ( mDeleteIfInTrash ) {
268 CollectionDeleteJob *job =
new CollectionDeleteJob( mCollection, q );
269 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
271 kWarning() <<
"Nothing to do";
277 Collection trashCollection = mTrashCollection;
278 if ( !mTrashCollection.isValid() ) {
281 if ( !mKeepTrashInCollection && trashCollection.isValid() ) {
282 mSetRestoreCollection =
true;
283 Q_ASSERT( mCollection.parentCollection().isValid() );
284 mRestoreCollection = mCollection.parentCollection();
285 mRestoreCollection.setResource( mCollection.resource() );
288 if ( trashCollection.isValid() ) {
289 CollectionMoveJob *job =
new CollectionMoveJob( mCollection, trashCollection, q );
290 q->connect( job, SIGNAL(result(KJob*)), SLOT(setAttribute(KJob*)) );
291 q->connect( job, SIGNAL(result(KJob*)), SLOT(selectResult(KJob*)) );
293 setAttribute( Collection::List() << mCollection );
301 TrashJob::TrashJob(
const Item & item, QObject * parent )
302 : Job( new TrashJobPrivate( this ), parent )
308 TrashJob::TrashJob(
const Item::List& items, QObject* parent )
309 : Job( new TrashJobPrivate( this ), parent )
315 TrashJob::TrashJob(
const Collection& collection, QObject* parent )
316 : Job( new TrashJobPrivate( this ), parent )
319 d->mCollection = collection;
322 TrashJob::~TrashJob()
326 Item::List TrashJob::items()
const
328 Q_D(
const TrashJob );
332 void TrashJob::setTrashCollection(
const Akonadi::Collection &collection )
335 d->mTrashCollection = collection;
338 void TrashJob::keepTrashInCollection(
bool enable )
341 d->mKeepTrashInCollection = enable;
344 void TrashJob::deleteIfInTrash(
bool enable )
347 d->mDeleteIfInTrash = enable;
350 void TrashJob::doStart()
355 if ( !d->mItems.isEmpty() ) {
356 ItemFetchJob *job =
new ItemFetchJob( d->mItems,
this );
357 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
359 job->fetchScope().fetchAttribute<EntityDeletedAttribute>( true );
360 connect( job, SIGNAL(itemsReceived(Akonadi::Item::List)),
this, SLOT(itemsReceived(Akonadi::Item::List)) );
362 }
else if ( d->mCollection.isValid() ) {
363 CollectionFetchJob *job =
new CollectionFetchJob( d->mCollection, CollectionFetchJob::Base,
this );
364 job->fetchScope().setAncestorRetrieval( Akonadi::CollectionFetchScope::Parent );
365 connect( job, SIGNAL(collectionsReceived(Akonadi::Collection::List)),
this, SLOT(collectionsReceived(Akonadi::Collection::List)) );
368 kWarning() <<
"No valid collection or empty itemlist";
369 setError( Job::Unknown );
370 setErrorText( i18n(
"No valid collection or empty itemlist" ) );
375 #include "trashjob.moc"