• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

collectionsync.cpp

00001 /*
00002     Copyright (c) 2007 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "collectionsync_p.h"
00021 #include "collection.h"
00022 
00023 #include "collectioncreatejob.h"
00024 #include "collectiondeletejob.h"
00025 #include "collectionfetchjob.h"
00026 #include "collectionmodifyjob.h"
00027 
00028 
00029 #include <kdebug.h>
00030 
00031 using namespace Akonadi;
00032 
00036 class CollectionSync::Private
00037 {
00038   public:
00039     Private() :
00040       pendingJobs( 0 ),
00041       incremental( false ),
00042       streaming( false )
00043     {
00044     }
00045 
00046     QString resourceId;
00047 
00048     // local: mapped remote id -> collection, id -> collection
00049     QHash<QString,Collection> localCollections;
00050     QSet<Collection> unprocessedLocalCollections;
00051 
00052     // remote: mapped id -> collection
00053     QHash<Collection::Id, Collection> remoteCollections;
00054 
00055     // remote collections waiting for a parent
00056     QList<Collection> orphanRemoteCollections;
00057 
00058     // removed remote collections
00059     Collection::List removedRemoteCollections;
00060 
00061     // create counter
00062     int pendingJobs;
00063 
00064     bool incremental;
00065     bool streaming;
00066 };
00067 
00068 CollectionSync::CollectionSync( const QString &resourceId, QObject *parent ) :
00069     TransactionSequence( parent ),
00070     d( new Private )
00071 {
00072   d->resourceId = resourceId;
00073 }
00074 
00075 CollectionSync::~CollectionSync()
00076 {
00077   delete d;
00078 }
00079 
00080 void CollectionSync::setRemoteCollections(const Collection::List & remoteCollections)
00081 {
00082   foreach ( const Collection &c, remoteCollections ) {
00083     d->remoteCollections.insert( c.id(), c );
00084   }
00085   if ( !d->streaming )
00086     retrievalDone();
00087 }
00088 
00089 void CollectionSync::setRemoteCollections(const Collection::List & changedCollections, const Collection::List & removedCollections)
00090 {
00091   d->incremental = true;
00092   foreach ( const Collection &c, changedCollections ) {
00093     d->remoteCollections.insert( c.id(), c );
00094   }
00095   d->removedRemoteCollections += removedCollections;
00096   if ( !d->streaming )
00097     retrievalDone();
00098 }
00099 
00100 void CollectionSync::doStart()
00101 {
00102 }
00103 
00104 void CollectionSync::slotLocalListDone(KJob * job)
00105 {
00106   if ( job->error() )
00107     return;
00108 
00109   Collection::List list = static_cast<CollectionFetchJob*>( job )->collections();
00110   foreach ( const Collection &c, list ) {
00111     d->localCollections.insert( c.remoteId(), c );
00112     d->unprocessedLocalCollections.insert( c );
00113   }
00114 
00115 
00116   // added / updated
00117   foreach ( const Collection &c, d->remoteCollections ) {
00118     if ( c.remoteId().isEmpty() ) {
00119       kWarning( 5250 ) << "Collection '" << c.name() <<"' does not have a remote identifier - skipping";
00120       continue;
00121     }
00122 
00123     Collection local = d->localCollections.value( c.remoteId() );
00124     d->unprocessedLocalCollections.remove( local );
00125     // missing locally
00126     if ( !local.isValid() ) {
00127       // determine local parent
00128       Collection localParent;
00129       if ( c.parent() >= 0 )
00130         localParent = Collection( c.parent() );
00131       if ( c.parentRemoteId().isEmpty() )
00132         localParent = Collection::root();
00133       else
00134         localParent = d->localCollections.value( c.parentRemoteId() );
00135 
00136       // no local parent found, create later
00137       if ( !localParent.isValid() ) {
00138         d->orphanRemoteCollections << c;
00139         continue;
00140       }
00141 
00142       createLocalCollection( c, localParent );
00143       continue;
00144     }
00145 
00146     // update local collection
00147     d->pendingJobs++;
00148     Collection upd( c );
00149     upd.setId( local.id() );
00150     CollectionModifyJob *mod = new CollectionModifyJob( upd, this );
00151     connect( mod, SIGNAL(result(KJob*)), SLOT(slotLocalChangeDone(KJob*)) );
00152   }
00153 
00154   // removed
00155   if ( !d->incremental )
00156     d->removedRemoteCollections = d->unprocessedLocalCollections.toList();
00157   foreach ( const Collection &c, d->removedRemoteCollections ) {
00158     d->pendingJobs++;
00159     CollectionDeleteJob *job = new CollectionDeleteJob( c, this );
00160     connect( job, SIGNAL(result(KJob*)), SLOT(slotLocalChangeDone(KJob*)) );
00161   }
00162   d->localCollections.clear();
00163 
00164   checkDone();
00165 }
00166 
00167 void CollectionSync::slotLocalCreateDone(KJob * job)
00168 {
00169   d->pendingJobs--;
00170   if ( job->error() )
00171     return;
00172 
00173   Collection newLocal = static_cast<CollectionCreateJob*>( job )->collection();
00174 //   d->localCollections.insert( newLocal.remoteId(), newLocal );
00175 
00176   // search for children we can create now
00177   Collection::List stillOrphans;
00178   foreach ( const Collection &orphan, d->orphanRemoteCollections ) {
00179     if ( orphan.parentRemoteId() == newLocal.remoteId() ) {
00180       createLocalCollection( orphan, newLocal );
00181     } else {
00182       stillOrphans << orphan;
00183     }
00184   }
00185   d->orphanRemoteCollections = stillOrphans;
00186 
00187   checkDone();
00188 }
00189 
00190 void CollectionSync::createLocalCollection(const Collection & c, const Collection & parent)
00191 {
00192   d->pendingJobs++;
00193   Collection col( c );
00194   col.setParent( parent );
00195   CollectionCreateJob *create = new CollectionCreateJob( col, this );
00196   connect( create, SIGNAL(result(KJob*)), SLOT(slotLocalCreateDone(KJob*)) );
00197 }
00198 
00199 void CollectionSync::checkDone()
00200 {
00201   // still running jobs
00202   if ( d->pendingJobs > 0 )
00203     return;
00204 
00205   // still orphan collections
00206   if ( !d->orphanRemoteCollections.isEmpty() ) {
00207     setError( Unknown );
00208     setErrorText( QLatin1String( "Found unresolved orphan collections" ) );
00209     foreach ( const Collection &col, d->orphanRemoteCollections )
00210       kDebug() << "found orphan collection:" << col.remoteId() << "parent:" << col.parentRemoteId();
00211   }
00212 
00213   commit();
00214 }
00215 
00216 void CollectionSync::slotLocalChangeDone(KJob * job)
00217 {
00218   if ( job->error() )
00219     return;
00220   d->pendingJobs--;
00221   checkDone();
00222 }
00223 
00224 void CollectionSync::setStreamingEnabled( bool streaming )
00225 {
00226   d->streaming = streaming;
00227 }
00228 
00229 void CollectionSync::retrievalDone()
00230 {
00231   CollectionFetchJob *job = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive, this );
00232   job->setResource( d->resourceId );
00233   connect( job, SIGNAL(result(KJob*)), SLOT(slotLocalListDone(KJob*)) );
00234 }
00235 
00236 #include "collectionsync_p.moc"

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal