[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdepim/akonadi/libakonadi
From:       Volker Krause <vkrause () kde ! org>
Date:       2008-03-09 13:50:39
Message-ID: 1205070639.085028.5223.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 783746 by vkrause:

- fix TransactionSequence hanging before rollback
- use a single transaction for pasting multiple entries
- use the paste code for drops on the models as well


 M  +7 -75     collectionmodel.cpp  
 M  +2 -2      collectionmodel.h  
 M  +10 -0     itemmodel.cpp  
 M  +4 -1      itemmodel.h  
 M  +11 -1     job.cpp  
 M  +1 -0      job.h  
 M  +12 -15    pastehelper.cpp  
 M  +2 -2      pastehelper.h  
 M  +2 -3      standardactionmanager.cpp  
 M  +12 -1     transactionjobs.cpp  
 M  +4 -0      transactionjobs.h  


--- trunk/KDE/kdepim/akonadi/libakonadi/collectionmodel.cpp #783745:783746
@@ -26,6 +26,7 @@
 #include "itemstorejob.h"
 #include "itemappendjob.h"
 #include "monitor.h"
+#include "pastehelper.h"
 #include "session.h"
 
 #include <kdebug.h>
@@ -68,7 +69,7 @@
     void collectionStatusChanged( int, const Akonadi::CollectionStatus& );
     void listDone( KJob* );
     void editDone( KJob* );
-    void appendDone( KJob* );
+    void dropResult( KJob* );
     void collectionsChanged( const Akonadi::Collection::List &cols );
 
     void updateSupportedMimeTypes( Collection col )
@@ -183,10 +184,10 @@
   }
 }
 
-void CollectionModel::Private::appendDone(KJob * job)
+void CollectionModel::Private::dropResult(KJob * job)
 {
   if ( job->error() ) {
-    kWarning( 5250 ) << "Append failed:" << job->errorString();
+    kWarning( 5250 ) << "Paste failed:" << job->errorString();
     // TODO: error handling
   }
 }
@@ -551,78 +552,9 @@
   if (!parentCol.isValid())
     return false;
 
-  // we try to drop data not coming with the akonadi:// url
-  // find a type the target collection supports
-  foreach ( QString type, data->formats() ) {
-    if ( !supportsContentType( idx, QStringList( type ) ) )
-      continue;
-
-    QByteArray item = data->data( type );
-    // HACK for some unknown reason the data is sometimes 0-terminated...
-    if ( !item.isEmpty() && item.at( item.size() - 1 ) == 0 )
-      item.resize( item.size() - 1 );
-
-    Item it;
-    it.setMimeType( type );
-    it.addPart( Item::PartBody, item );
-
-    ItemAppendJob *job = new ItemAppendJob( it, parentCol, d->session );
-    connect( job, SIGNAL(result(KJob*)), SLOT(appendDone(KJob*)) );
-    return job->exec();
-  }
-
-  if ( !KUrl::List::canDecode( data ) )
-    return false;
-
-  // data contains an url list
-  bool success = false;
-  KUrl::List urls = KUrl::List::fromMimeData( data );
-  foreach( KUrl url, urls ) {
-    if ( Collection::urlIsValid( url ) )
-    {
-      Collection col = Collection::fromUrl( url );
-      if (action == Qt::MoveAction) {
-        CollectionModifyJob *job = new CollectionModifyJob( col, d->session );
-        job->setParent( parentCol );
-        connect( job, SIGNAL(result(KJob*)), SLOT(appendDone(KJob*)) );
-        job->exec();
-        if ( !job->exec() ) {
-          success = false;
-          break;
-        } else {
-          success = true; // continue, there might be other urls
-        }
-      }
-      else { // TODO A Copy Collection Job
-        return false;
-      }
-    }
-    else if ( Item::urlIsValid( url ) )
-    {
-      // TODO Extract mimetype from url and check if collection accepts it
-      DataReference ref = Item::fromUrl( url );
-      if (action == Qt::MoveAction) {
-        ItemStoreJob *job = new ItemStoreJob( Item( ref ), d->session );
-        job->setCollection( parentCol );
-        job->noRevCheck();
-        connect( job, SIGNAL(result(KJob*)), SLOT(appendDone(KJob*)) );
-        if ( !job->exec() ) {
-          success = false;
-          break;
-        } else {
-          success = true; // continue, there might be other urls
-        }
-      }
-      else if ( action == Qt::CopyAction ) {
-      // TODO Wait for a job allowing to copy on server side.
-      }
-      else {
-        return false;
-      }
-    }
-  }
-
-  return success;
+  KJob *job = PasteHelper::paste( data, parentCol, action != Qt::MoveAction );
+  connect( job, SIGNAL(result(KJob*)), SLOT(dropResult(KJob*)) );
+  return true;
 }
 
 Collection CollectionModel::collectionForId(int id) const
--- trunk/KDE/kdepim/akonadi/libakonadi/collectionmodel.h #783745:783746
@@ -121,7 +121,7 @@
     /**
       Reimplemented.
     */
-    virtual bool dropMimeData( const QMimeData *data, Qt::DropAction action, int \
row, int column, const QModelIndex &parent ); +   virtual bool dropMimeData( const \
QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex \
&parent );  
   Q_SIGNALS:
     /**
@@ -184,7 +184,7 @@
     Q_PRIVATE_SLOT( d, void collectionStatusChanged( int, const \
Akonadi::CollectionStatus& ) )  Q_PRIVATE_SLOT( d, void listDone( KJob* ) )
     Q_PRIVATE_SLOT( d, void editDone( KJob* ) )
-    Q_PRIVATE_SLOT( d, void appendDone( KJob* ) )
+    Q_PRIVATE_SLOT( d, void dropResult( KJob* ) )
     Q_PRIVATE_SLOT( d, void collectionsChanged( const Akonadi::Collection::List& ) )
 
 };
--- trunk/KDE/kdepim/akonadi/libakonadi/itemmodel.cpp #783745:783746
@@ -21,6 +21,7 @@
 
 #include "itemfetchjob.h"
 #include "monitor.h"
+#include "pastehelper.h"
 #include "session.h"
 
 #include <kmime/kmime_message.h>
@@ -380,4 +381,13 @@
   return index( d->rowForItem( ref ), column );
 }
 
+bool ItemModel::dropMimeData(const QMimeData * data, Qt::DropAction action, int row, \
int column, const QModelIndex & parent) +{
+  Q_UNUSED( row );
+  Q_UNUSED( column );
+  Q_UNUSED( parent );
+  KJob* job = PasteHelper::paste( data, d->collection, action != Qt::MoveAction );
+  // TODO: error handling
+}
+
 #include "itemmodel.moc"
--- trunk/KDE/kdepim/akonadi/libakonadi/itemmodel.h #783745:783746
@@ -118,13 +118,16 @@
     */
     Item itemForIndex( const QModelIndex &index ) const;
 
-    /*
+    /**
       Returns the model index for the given reference, with the given column
       @param ref The reference to find
       @param column The column for the returned index
     */
     QModelIndex indexForItem( const Akonadi::DataReference& ref, const int column ) \
const;  
+    /* reimpl */
+    bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int \
column, const QModelIndex &parent ); +
   public Q_SLOTS:
     /**
       Sets the collection the model should display. If the collection has
--- trunk/KDE/kdepim/akonadi/libakonadi/job.cpp #783745:783746
@@ -186,6 +186,16 @@
   return rv;
 }
 
+bool Job::removeSubjob(KJob * job)
+{
+  bool rv = KCompositeJob::removeSubjob( job );
+  if ( job == d->mCurrentSubJob ) {
+    d->mCurrentSubJob = 0;
+    QTimer::singleShot( 0, this, SLOT(startNext()) );
+  }
+  return rv;
+}
+
 void Job::doHandleResponse(const QByteArray & tag, const QByteArray & data)
 {
   kDebug( 5250 ) << "Unhandled response: " << tag << data;
@@ -201,8 +211,8 @@
 void Job::slotResult(KJob * job)
 {
   Q_ASSERT( job == d->mCurrentSubJob );
+  d->mCurrentSubJob = 0;
   KCompositeJob::slotResult( job );
-  d->mCurrentSubJob = 0;
   if ( !job->error() )
     QTimer::singleShot( 0, this, SLOT(startNext()) );
 }
--- trunk/KDE/kdepim/akonadi/libakonadi/job.h #783745:783746
@@ -195,6 +195,7 @@
     */
     virtual bool addSubjob( KJob* job );
 
+    virtual bool removeSubjob( KJob* job );
     virtual bool doKill();
 
     /**
--- trunk/KDE/kdepim/akonadi/libakonadi/pastehelper.cpp #783745:783746
@@ -25,6 +25,7 @@
 #include "itemappendjob.h"
 #include "itemcopyjob.h"
 #include "itemstorejob.h"
+#include "transactionjobs.h"
 
 #include <KDebug>
 #include <KUrl>
@@ -49,11 +50,10 @@
   return false;
 }
 
-QList<KJob*> PasteHelper::paste(const QMimeData * mimeData, const Collection & \
collection, bool copy) +KJob* PasteHelper::paste(const QMimeData * mimeData, const \
Collection & collection, bool copy)  {
-  QList<KJob*> rv;
   if ( !canPaste( mimeData, collection ) )
-    return rv;
+    return 0;
 
   // we try to drop data not coming with the akonadi:// url
   // find a type the target collection supports
@@ -71,43 +71,40 @@
     it.addPart( Item::PartBody, item );
 
     ItemAppendJob *job = new ItemAppendJob( it, collection );
-    rv.append( job );
-    return rv;
+    return job;
   }
 
   if ( !KUrl::List::canDecode( mimeData ) )
-    return rv;
+    return 0;
 
   // data contains an url list
+  TransactionSequence *transaction = new TransactionSequence();
   KUrl::List urls = KUrl::List::fromMimeData( mimeData );
   foreach ( const KUrl url, urls ) {
     if ( Collection::urlIsValid( url ) ) {
       Collection col = Collection::fromUrl( url );
       if ( !copy ) {
-        CollectionModifyJob *job = new CollectionModifyJob( col );
+        CollectionModifyJob *job = new CollectionModifyJob( col, transaction );
         job->setParent( collection );
-        rv.append( job );
       } else {
-        CollectionCopyJob *job = new CollectionCopyJob( col, collection );
-        rv.append( job );
+        new CollectionCopyJob( col, collection, transaction );
       }
     } else if ( Item::urlIsValid( url ) ) {
       // TODO Extract mimetype from url and check if collection accepts it
       DataReference ref = Item::fromUrl( url );
       if ( !copy ) {
-        ItemStoreJob *job = new ItemStoreJob( Item( ref ) );
+        ItemStoreJob *job = new ItemStoreJob( Item( ref ), transaction );
         job->setCollection( collection );
         job->noRevCheck();
-        rv.append( job );
       } else  {
-        ItemCopyJob *job = new ItemCopyJob( Item( ref ), collection );
-        rv.append( job );
+        new ItemCopyJob( Item( ref ), collection, transaction );
       }
     } else {
       // non-akonadi URL
       // TODO
+      kDebug() << "Implement me!";
     }
   }
-  return rv;
+  return transaction;
 }
 
--- trunk/KDE/kdepim/akonadi/libakonadi/pastehelper.h #783745:783746
@@ -50,9 +50,9 @@
     @param mimeData The pasted/dropped data.
     @param collection The target collection.
     @param copy Indicate wether this is a copy or a move.
-    @returns A list of started jobs.
+    @returns The job performing the paste, 0 if there is nothing to paste.
   */
-  QList<KJob*> paste( const QMimeData* mimeData, const Collection &collection, bool \
copy = true ); +  KJob* paste( const QMimeData* mimeData, const Collection \
&collection, bool copy = true );  }
 
 
--- trunk/KDE/kdepim/akonadi/libakonadi/standardactionmanager.cpp #783745:783746
@@ -234,9 +234,8 @@
       if ( !index.isValid() )
         return;
       const Collection col = index.data( CollectionModel::CollectionRole \
                ).value<Collection>();
-      QList<KJob*> jobs = PasteHelper::paste( QApplication::clipboard()->mimeData(), \
                col );
-      foreach ( KJob* job, jobs )
-        q->connect( job, SIGNAL(result(KJob*)), q, SLOT(pasteResult(KJob*)) );
+      KJob *job = PasteHelper::paste( QApplication::clipboard()->mimeData(), col );
+      q->connect( job, SIGNAL(result(KJob*)), q, SLOT(pasteResult(KJob*)) );
     }
 
     void slotDeleteItems()
--- trunk/KDE/kdepim/akonadi/libakonadi/transactionjobs.cpp #783745:783746
@@ -19,6 +19,8 @@
 
 #include "transactionjobs.h"
 
+#include <kdebug.h>
+
 using namespace Akonadi;
 
 TransactionBeginJob::TransactionBeginJob(QObject * parent) :
@@ -141,8 +143,9 @@
   } else {
     setError( job->error() );
     setErrorText( job->errorText() );
+    removeSubjob( job );
     clearSubjobs();
-    if ( d->state == Private::Running ) {
+    if ( d->state == Private::Running || d->state == Private::WaitingForSubjobs ) {
       d->state = Private::RollingBack;
       TransactionRollbackJob *job = new TransactionRollbackJob( this );
       connect( job, SIGNAL(result(KJob*)), SLOT(rollbackResult(KJob*)) );
@@ -170,4 +173,12 @@
   }
 }
 
+void TransactionSequence::doStart()
+{
+  if ( d->state == Private::Idle )
+    emitResult();
+  else
+    commit();
+}
+
 #include "transactionjobs.moc"
--- trunk/KDE/kdepim/akonadi/libakonadi/transactionjobs.h #783745:783746
@@ -104,6 +104,9 @@
   As soon as the first subjob is added, the transaction is started.
   As soon as the last subjob has successfully finished, the transaction is \
committed.  If any subjob fails, the transaction is rolled back.
+
+  Alternatively, a TransactionSequence object can be used as a parent object for a \
set +  of jobs to achive the same behaviour without subclassing.
 */
 class AKONADI_EXPORT TransactionSequence : public Job
 {
@@ -127,6 +130,7 @@
     void commit();
 
     bool addSubjob( KJob* job );
+    void doStart();
 
   protected Q_SLOTS:
     void slotResult( KJob *job );


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic