00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "specialcollections.h"
00021
00022 #include "specialcollections_p.h"
00023 #include "specialcollectionattribute_p.h"
00024
00025 #include "akonadi/agentinstance.h"
00026 #include "akonadi/agentmanager.h"
00027 #include "akonadi/collectionmodifyjob.h"
00028 #include "akonadi/collectionfetchjob.h"
00029 #include "akonadi/monitor.h"
00030
00031 #include <KDebug>
00032 #include <kcoreconfigskeleton.h>
00033
00034 #include <QtCore/QHash>
00035 #include <QtCore/QObject>
00036 #include <QtCore/QSet>
00037 #include <akonadi/collectionfetchscope.h>
00038
00039 using namespace Akonadi;
00040
00041 SpecialCollectionsPrivate::SpecialCollectionsPrivate( KCoreConfigSkeleton *settings, SpecialCollections *qq )
00042 : q( qq ),
00043 mSettings( settings ),
00044 mBatchMode( false )
00045 {
00046 mMonitor = new Monitor( q );
00047 mMonitor->fetchCollectionStatistics( true );
00048
00053 QObject::connect( mMonitor, SIGNAL( collectionRemoved( const Akonadi::Collection& ) ),
00054 q, SLOT( collectionRemoved( const Akonadi::Collection& ) ) );
00055 QObject::connect( mMonitor, SIGNAL( collectionStatisticsChanged( Akonadi::Collection::Id, const Akonadi::CollectionStatistics& ) ),
00056 q, SLOT( collectionStatisticsChanged( Akonadi::Collection::Id, const Akonadi::CollectionStatistics& ) ) );
00057 }
00058
00059 SpecialCollectionsPrivate::~SpecialCollectionsPrivate()
00060 {
00061 }
00062
00063 QString SpecialCollectionsPrivate::defaultResourceId() const
00064 {
00065 mSettings->readConfig();
00066 const KConfigSkeletonItem *item = mSettings->findItem( QLatin1String( "DefaultResourceId" ) );
00067 Q_ASSERT( item );
00068
00069 mDefaultResourceId = item->property().toString();
00070 return mDefaultResourceId;
00071 }
00072
00073 void SpecialCollectionsPrivate::emitChanged( const QString &resourceId )
00074 {
00075 if ( mBatchMode ) {
00076 mToEmitChangedFor.insert( resourceId );
00077 } else {
00078 kDebug() << "Emitting changed for" << resourceId;
00079 const AgentInstance agentInstance = AgentManager::self()->instance( resourceId );
00080 emit q->collectionsChanged( agentInstance );
00081
00082 if ( resourceId == mDefaultResourceId || resourceId == defaultResourceId() ) {
00083 kDebug() << "Emitting defaultFoldersChanged.";
00084 emit q->defaultCollectionsChanged();
00085 }
00086 }
00087 }
00088
00089 void SpecialCollectionsPrivate::collectionRemoved( const Collection &collection )
00090 {
00091 kDebug() << "Collection" << collection.id() << "resource" << collection.resource();
00092 if ( mFoldersForResource.contains( collection.resource() ) ) {
00093
00094
00095 QHash<QByteArray, Collection> &folders = mFoldersForResource[ collection.resource() ];
00096 {
00097 QMutableHashIterator<QByteArray, Collection> it( folders );
00098 while ( it.hasNext() ) {
00099 it.next();
00100 if ( it.value() == collection ) {
00101
00102 it.remove();
00103 emitChanged( collection.resource() );
00104 }
00105 }
00106 }
00107
00108 if ( folders.isEmpty() ) {
00109
00110 mFoldersForResource.remove( collection.resource() );
00111 }
00112 }
00113 }
00114
00115 void SpecialCollectionsPrivate::collectionStatisticsChanged( Akonadi::Collection::Id collectionId, const Akonadi::CollectionStatistics &statistics )
00116 {
00117
00118
00119 Akonadi::CollectionFetchJob* fetchJob = new Akonadi::CollectionFetchJob( Collection( collectionId ), Akonadi::CollectionFetchJob::Base );
00120 fetchJob->fetchScope().setAncestorRetrieval( Akonadi::CollectionFetchScope::None );
00121 fetchJob->setProperty( "statistics", QVariant::fromValue( statistics ) );
00122
00123 q->connect( fetchJob, SIGNAL( result( KJob* ) ), q, SLOT( collectionFetchJobFinished( KJob* ) ) );
00124 }
00125
00126
00127 void SpecialCollectionsPrivate::collectionFetchJobFinished( KJob* job )
00128 {
00129 if ( job->error() ) {
00130 kWarning() << "Error fetching collection to get name from id for statistics updating in specialcollections!";
00131 return;
00132 }
00133
00134 const Akonadi::CollectionFetchJob *fetchJob = qobject_cast<Akonadi::CollectionFetchJob*>( job );
00135
00136 Q_ASSERT( fetchJob->collections().size() > 0 );
00137 const Akonadi::Collection collection = fetchJob->collections().first();
00138 const Akonadi::CollectionStatistics statistics = fetchJob->property( "statistics" ).value<Akonadi::CollectionStatistics>();
00139
00140 mFoldersForResource[ collection.resource() ][ collection.name().toUtf8() ].setStatistics( statistics );
00141 }
00142
00143 void SpecialCollectionsPrivate::beginBatchRegister()
00144 {
00145 Q_ASSERT( !mBatchMode );
00146 mBatchMode = true;
00147 Q_ASSERT( mToEmitChangedFor.isEmpty() );
00148 }
00149
00150 void SpecialCollectionsPrivate::endBatchRegister()
00151 {
00152 Q_ASSERT( mBatchMode );
00153 mBatchMode = false;
00154
00155 foreach ( const QString &resourceId, mToEmitChangedFor ) {
00156 emitChanged( resourceId );
00157 }
00158
00159 mToEmitChangedFor.clear();
00160 }
00161
00162 void SpecialCollectionsPrivate::forgetFoldersForResource( const QString &resourceId )
00163 {
00164 if ( mFoldersForResource.contains( resourceId ) ) {
00165 const Collection::List folders = mFoldersForResource[ resourceId ].values();
00166
00167 foreach ( const Collection &collection, folders ) {
00168 mMonitor->setCollectionMonitored( collection, false );
00169 }
00170
00171 mFoldersForResource.remove( resourceId );
00172 emitChanged( resourceId );
00173 }
00174 }
00175
00176 AgentInstance SpecialCollectionsPrivate::defaultResource() const
00177 {
00178 const QString identifier = defaultResourceId();
00179 return AgentManager::self()->instance( identifier );
00180 }
00181
00182
00183 SpecialCollections::SpecialCollections( KCoreConfigSkeleton *settings, QObject *parent )
00184 : QObject( parent ),
00185 d( new SpecialCollectionsPrivate( settings, this ) )
00186 {
00187 }
00188
00189 SpecialCollections::~SpecialCollections()
00190 {
00191 delete d;
00192 }
00193
00194 bool SpecialCollections::hasCollection( const QByteArray &type, const AgentInstance &instance ) const
00195 {
00196 kDebug() << "Type" << type << "resourceId" << instance.identifier();
00197
00198 if ( !d->mFoldersForResource.contains( instance.identifier() ) ) {
00199
00200 return false;
00201 }
00202
00203 return d->mFoldersForResource[ instance.identifier() ].contains( type );
00204 }
00205
00206 Akonadi::Collection SpecialCollections::collection( const QByteArray &type, const AgentInstance &instance ) const
00207 {
00208 if ( !d->mFoldersForResource.contains( instance.identifier() ) ) {
00209
00210 return Collection( -1 );
00211 }
00212 return d->mFoldersForResource[ instance.identifier() ][ type ];
00213 }
00214
00215 bool SpecialCollections::registerCollection( const QByteArray &type, const Collection &collection )
00216 {
00217 if ( !collection.isValid() ) {
00218 kWarning() << "Invalid collection.";
00219 return false;
00220 }
00221
00222 const QString &resourceId = collection.resource();
00223 if ( resourceId.isEmpty() ) {
00224 kWarning() << "Collection has empty resourceId.";
00225 return false;
00226 }
00227
00228 if ( !collection.hasAttribute<SpecialCollectionAttribute>() || collection.attribute<SpecialCollectionAttribute>()->collectionType() != type ) {
00229 Collection attributeCollection( collection );
00230 SpecialCollectionAttribute *attribute = attributeCollection.attribute<SpecialCollectionAttribute>( Collection::AddIfMissing );
00231 attribute->setCollectionType( type );
00232
00233 new CollectionModifyJob( attributeCollection );
00234 }
00235
00236 if ( !d->mFoldersForResource.contains( resourceId ) ) {
00237
00238 d->mFoldersForResource.insert( resourceId, QHash<QByteArray, Collection>() );
00239 }
00240
00241 if ( !d->mFoldersForResource[ resourceId ].contains( type ) )
00242 d->mFoldersForResource[ resourceId ].insert( type, Collection() );
00243
00244 if ( d->mFoldersForResource[ resourceId ][ type ] != collection ) {
00245 d->mMonitor->setCollectionMonitored( d->mFoldersForResource[ resourceId ][ type ], false );
00246 d->mMonitor->setCollectionMonitored( collection, true );
00247 d->mFoldersForResource[ resourceId ].insert( type, collection );
00248 d->emitChanged( resourceId );
00249 }
00250
00251 kDebug() << "Registered collection" << collection.id() << "as folder of type" << type
00252 << "in resource" << resourceId;
00253 return true;
00254 }
00255
00256 bool SpecialCollections::hasDefaultCollection( const QByteArray &type ) const
00257 {
00258 return hasCollection( type, d->defaultResource() );
00259 }
00260
00261 Akonadi::Collection SpecialCollections::defaultCollection( const QByteArray &type ) const
00262 {
00263 return collection( type, d->defaultResource() );
00264 }
00265
00266 #include "specialcollections.moc"