• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

akonadi

specialcollectionshelperjobs.cpp
00001 /*
00002     Copyright (c) 2009 Constantin Berzan <exit3219@gmail.com>
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 "specialcollectionshelperjobs_p.h"
00021 
00022 #include "dbusconnectionpool.h"
00023 #include "specialcollectionattribute_p.h"
00024 #include "specialcollections.h"
00025 
00026 #include <akonadi/agentinstance.h>
00027 #include <akonadi/agentinstancecreatejob.h>
00028 #include <akonadi/agentmanager.h>
00029 #include <akonadi/collectionfetchjob.h>
00030 #include <akonadi/collectionfetchscope.h>
00031 #include <akonadi/collectionmodifyjob.h>
00032 #include <akonadi/entitydisplayattribute.h>
00033 #include <akonadi/resourcesynchronizationjob.h>
00034 
00035 #include <KDebug>
00036 #include <KLocalizedString>
00037 #include <KStandardDirs>
00038 #include <kcoreconfigskeleton.h>
00039 
00040 #include <QtDBus/QDBusConnectionInterface>
00041 #include <QtDBus/QDBusInterface>
00042 #include <QtDBus/QDBusServiceWatcher>
00043 #include <QtCore/QMetaMethod>
00044 #include <QtCore/QTime>
00045 #include <QtCore/QTimer>
00046 
00047 #define DBUS_SERVICE_NAME QLatin1String( "org.kde.pim.SpecialCollections" )
00048 #define LOCK_WAIT_TIMEOUT_SECONDS 10
00049 
00050 using namespace Akonadi;
00051 
00052 // convenient methods to get/set the default resource id
00053 static void setDefaultResourceId( KCoreConfigSkeleton *settings, const QString &value )
00054 {
00055   KConfigSkeletonItem *item = settings->findItem( QLatin1String( "DefaultResourceId" ) );
00056   Q_ASSERT( item );
00057   item->setProperty( value );
00058 }
00059 
00060 static QString defaultResourceId( KCoreConfigSkeleton *settings )
00061 {
00062   const KConfigSkeletonItem *item = settings->findItem( QLatin1String( "DefaultResourceId" ) );
00063   Q_ASSERT( item );
00064   return item->property().toString();
00065 }
00066 
00067 static QVariant::Type argumentType( const QMetaObject *mo, const QString &method )
00068 {
00069   QMetaMethod m;
00070   for ( int i = 0; i < mo->methodCount(); ++i ) {
00071     const QString signature = QString::fromLatin1( mo->method( i ).signature() );
00072     if ( signature.startsWith( method ) )
00073       m = mo->method( i );
00074   }
00075 
00076   if ( !m.signature() )
00077     return QVariant::Invalid;
00078 
00079   const QList<QByteArray> argTypes = m.parameterTypes();
00080   if ( argTypes.count() != 1 )
00081     return QVariant::Invalid;
00082 
00083   return QVariant::nameToType( argTypes.first() );
00084 }
00085 
00086 // ===================== ResourceScanJob ============================
00087 
00091 class Akonadi::ResourceScanJob::Private
00092 {
00093   public:
00094     Private( KCoreConfigSkeleton *settings, ResourceScanJob *qq );
00095 
00096     void fetchResult( KJob *job ); // slot
00097 
00098     ResourceScanJob *const q;
00099 
00100     // Input:
00101     QString mResourceId;
00102     KCoreConfigSkeleton *mSettings;
00103 
00104     // Output:
00105     Collection mRootCollection;
00106     Collection::List mSpecialCollections;
00107 };
00108 
00109 ResourceScanJob::Private::Private( KCoreConfigSkeleton *settings, ResourceScanJob *qq )
00110   : q( qq ), mSettings( settings )
00111 {
00112 }
00113 
00114 void ResourceScanJob::Private::fetchResult( KJob *job )
00115 {
00116   if ( job->error() ) {
00117     kWarning() << job->errorText();
00118     return;
00119   }
00120 
00121   CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob *>( job );
00122   Q_ASSERT( fetchJob );
00123 
00124   Q_ASSERT( !mRootCollection.isValid() );
00125   Q_ASSERT( mSpecialCollections.isEmpty() );
00126   foreach ( const Collection &collection, fetchJob->collections() ) {
00127     if ( collection.parentCollection() == Collection::root() ) {
00128       if ( mRootCollection.isValid() )
00129         kWarning() << "Resource has more than one root collection. I don't know what to do.";
00130       else
00131         mRootCollection = collection;
00132     }
00133 
00134     if ( collection.hasAttribute<SpecialCollectionAttribute>() )
00135       mSpecialCollections.append( collection );
00136   }
00137 
00138   kDebug() << "Fetched root collection" << mRootCollection.id()
00139            << "and" << mSpecialCollections.count() << "local folders"
00140            << "(total" << fetchJob->collections().count() << "collections).";
00141 
00142   if ( !mRootCollection.isValid() ) {
00143     q->setError( Unknown );
00144     q->setErrorText( i18n( "Could not fetch root collection of resource %1.", mResourceId ) );
00145     q->emitResult();
00146     return;
00147   }
00148 
00149   // We are done!
00150   q->emitResult();
00151 }
00152 
00153 
00154 
00155 ResourceScanJob::ResourceScanJob( const QString &resourceId, KCoreConfigSkeleton *settings, QObject *parent )
00156   : Job( parent ),
00157     d( new Private( settings, this ) )
00158 {
00159   setResourceId( resourceId );
00160 }
00161 
00162 ResourceScanJob::~ResourceScanJob()
00163 {
00164   delete d;
00165 }
00166 
00167 QString ResourceScanJob::resourceId() const
00168 {
00169   return d->mResourceId;
00170 }
00171 
00172 void ResourceScanJob::setResourceId( const QString &resourceId )
00173 {
00174   d->mResourceId = resourceId;
00175 }
00176 
00177 Akonadi::Collection ResourceScanJob::rootResourceCollection() const
00178 {
00179   return d->mRootCollection;
00180 }
00181 
00182 Akonadi::Collection::List ResourceScanJob::specialCollections() const
00183 {
00184   return d->mSpecialCollections;
00185 }
00186 
00187 void ResourceScanJob::doStart()
00188 {
00189   if ( d->mResourceId.isEmpty() ) {
00190     kError() << "No resource ID given.";
00191     setError( Job::Unknown );
00192     setErrorText( i18n( "No resource ID given." ) );
00193     emitResult();
00194     return;
00195   }
00196 
00197   CollectionFetchJob *fetchJob = new CollectionFetchJob( Collection::root(),
00198                                                          CollectionFetchJob::Recursive, this );
00199   fetchJob->fetchScope().setResource( d->mResourceId );
00200   fetchJob->fetchScope().setIncludeStatistics( true );
00201   connect( fetchJob, SIGNAL(result(KJob*)), this, SLOT(fetchResult(KJob*)) );
00202 }
00203 
00204 
00205 // ===================== DefaultResourceJob ============================
00206 
00210 class Akonadi::DefaultResourceJobPrivate
00211 {
00212   public:
00213     DefaultResourceJobPrivate( KCoreConfigSkeleton *settings, DefaultResourceJob *qq );
00214 
00215     void tryFetchResource();
00216     void resourceCreateResult( KJob *job ); // slot
00217     void resourceSyncResult( KJob *job ); // slot
00218     void collectionFetchResult( KJob *job ); // slot
00219     void collectionModifyResult( KJob *job ); // slot
00220 
00221     DefaultResourceJob *const q;
00222     KCoreConfigSkeleton *mSettings;
00223     bool mResourceWasPreexisting;
00224     int mPendingModifyJobs;
00225     QString mDefaultResourceType;
00226     QVariantMap mDefaultResourceOptions;
00227     QList<QByteArray> mKnownTypes;
00228     QMap<QByteArray, QString> mNameForTypeMap;
00229     QMap<QByteArray, QString> mIconForTypeMap;
00230 };
00231 
00232 DefaultResourceJobPrivate::DefaultResourceJobPrivate( KCoreConfigSkeleton *settings, DefaultResourceJob *qq )
00233   : q( qq ),
00234     mSettings( settings ),
00235     mResourceWasPreexisting( true /* for safety, so as not to accidentally delete data */ ),
00236     mPendingModifyJobs( 0 )
00237 {
00238 }
00239 
00240 void DefaultResourceJobPrivate::tryFetchResource()
00241 {
00242   // Get the resourceId from config. Another instance might have changed it in the meantime.
00243   mSettings->readConfig();
00244 
00245   const QString resourceId = defaultResourceId( mSettings );
00246 
00247   kDebug() << "Read defaultResourceId" << resourceId << "from config.";
00248 
00249   const AgentInstance resource = AgentManager::self()->instance( resourceId );
00250   if ( resource.isValid() ) {
00251     // The resource exists; scan it.
00252     mResourceWasPreexisting = true;
00253     kDebug() << "Found resource" << resourceId;
00254     q->setResourceId( resourceId );
00255 
00256     CollectionFetchJob *fetchJob = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive, q );
00257     fetchJob->fetchScope().setResource( resourceId );
00258     fetchJob->fetchScope().setIncludeStatistics( true );
00259     q->connect( fetchJob, SIGNAL(result(KJob*)), q, SLOT(collectionFetchResult(KJob*)) );
00260   } else {
00261     // Try harder: maybe the default resource has been removed and another one added
00262     //             without updating the config file, in this case search for a resource
00263     //             of the same type and the default name
00264     const AgentInstance::List resources = AgentManager::self()->instances();
00265     foreach ( const AgentInstance &resource, resources ) {
00266       if ( resource.type().identifier() == mDefaultResourceType ) {
00267         if ( resource.name() == mDefaultResourceOptions.value( QLatin1String( "Name" ) ).toString() ) {
00268           // found a matching one...
00269           setDefaultResourceId( mSettings, resource.identifier() );
00270           mSettings->writeConfig();
00271           mResourceWasPreexisting = true;
00272           kDebug() << "Found resource" << resource.identifier();
00273           q->setResourceId( resource.identifier() );
00274           q->ResourceScanJob::doStart();
00275           return;
00276         }
00277       }
00278     }
00279 
00280     // Create the resource.
00281     mResourceWasPreexisting = false;
00282     kDebug() << "Creating maildir resource.";
00283     const AgentType type = AgentManager::self()->type( mDefaultResourceType );
00284     AgentInstanceCreateJob *job = new AgentInstanceCreateJob( type, q );
00285     QObject::connect( job, SIGNAL(result(KJob*)), q, SLOT(resourceCreateResult(KJob*)) );
00286     job->start(); // non-Akonadi::Job
00287   }
00288 }
00289 
00290 void DefaultResourceJobPrivate::resourceCreateResult( KJob *job )
00291 {
00292   if ( job->error() ) {
00293     kWarning() << job->errorText();
00294     //fail( i18n( "Failed to create the default resource (%1).", job->errorString() ) );
00295     q->setError( job->error() );
00296     q->setErrorText( job->errorText() );
00297     q->emitResult();
00298     return;
00299   }
00300 
00301   AgentInstance agent;
00302 
00303   // Get the resource instance.
00304   {
00305     AgentInstanceCreateJob *createJob = qobject_cast<AgentInstanceCreateJob*>( job );
00306     Q_ASSERT( createJob );
00307     agent = createJob->instance();
00308     setDefaultResourceId( mSettings, agent.identifier() );
00309     kDebug() << "Created maildir resource with id" << defaultResourceId( mSettings );
00310   }
00311 
00312   const QString defaultId = defaultResourceId( mSettings );
00313 
00314   // Configure the resource.
00315   {
00316     agent.setName( mDefaultResourceOptions.value( QLatin1String( "Name" ) ).toString() );
00317 
00318     QDBusInterface conf( QString::fromLatin1( "org.freedesktop.Akonadi.Resource." ) + defaultId,
00319                          QString::fromLatin1( "/Settings" ), QString() );
00320 
00321     if ( !conf.isValid() ) {
00322       q->setError( -1 );
00323       q->setErrorText( i18n( "Invalid resource identifier '%1'", defaultId ) );
00324       q->emitResult();
00325       return;
00326     }
00327 
00328     QMapIterator<QString, QVariant> it( mDefaultResourceOptions );
00329     while ( it.hasNext() ) {
00330       it.next();
00331 
00332       if ( it.key() == QLatin1String( "Name" ) )
00333         continue;
00334 
00335       const QString methodName = QString::fromLatin1( "set%1" ).arg( it.key() );
00336       const QVariant::Type argType = argumentType( conf.metaObject(), methodName );
00337       if ( argType == QVariant::Invalid ) {
00338         q->setError( Job::Unknown );
00339         q->setErrorText( i18n( "Failed to configure default resource via D-Bus." ) );
00340         q->emitResult();
00341         return;
00342       }
00343 
00344       QDBusReply<void> reply = conf.call( methodName, it.value() );
00345       if ( !reply.isValid() ) {
00346         q->setError( Job::Unknown );
00347         q->setErrorText( i18n( "Failed to configure default resource via D-Bus." ) );
00348         q->emitResult();
00349         return;
00350       }
00351     }
00352 
00353     conf.call( QLatin1String( "writeConfig" ) );
00354 
00355     agent.reconfigure();
00356   }
00357 
00358   // Sync the resource.
00359   {
00360     ResourceSynchronizationJob *syncJob = new ResourceSynchronizationJob( agent, q );
00361     QObject::connect( syncJob, SIGNAL(result(KJob*)), q, SLOT(resourceSyncResult(KJob*)) );
00362     syncJob->start(); // non-Akonadi
00363   }
00364 }
00365 
00366 void DefaultResourceJobPrivate::resourceSyncResult( KJob *job )
00367 {
00368   if ( job->error() ) {
00369     kWarning() << job->errorText();
00370     //fail( i18n( "ResourceSynchronizationJob failed (%1).", job->errorString() ) );
00371     return;
00372   }
00373 
00374   // Fetch the collections of the resource.
00375   kDebug() << "Fetching maildir collections.";
00376   CollectionFetchJob *fetchJob = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive, q );
00377   fetchJob->fetchScope().setResource( defaultResourceId( mSettings ) );
00378   QObject::connect( fetchJob, SIGNAL(result(KJob*)), q, SLOT(collectionFetchResult(KJob*)) );
00379 }
00380 
00381 void DefaultResourceJobPrivate::collectionFetchResult( KJob *job )
00382 {
00383   if ( job->error() ) {
00384     kWarning() << job->errorText();
00385     //fail( i18n( "Failed to fetch the root maildir collection (%1).", job->errorString() ) );
00386     return;
00387   }
00388 
00389   CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob *>( job );
00390   Q_ASSERT( fetchJob );
00391 
00392   const Collection::List collections = fetchJob->collections();
00393   kDebug() << "Fetched" << collections.count() << "collections.";
00394 
00395   // Find the root maildir collection.
00396   Collection::List toRecover;
00397   Collection resourceCollection;
00398   foreach ( const Collection &collection, collections ) {
00399     if ( collection.parentCollection() == Collection::root() ) {
00400       resourceCollection = collection;
00401       toRecover.append( collection );
00402       break;
00403     }
00404   }
00405 
00406   if ( !resourceCollection.isValid() ) {
00407     q->setError( Job::Unknown );
00408     q->setErrorText( i18n( "Failed to fetch the resource collection." ) );
00409     q->emitResult();
00410     return;
00411   }
00412 
00413   // Find all children of the resource collection.
00414   foreach ( const Collection &collection, collections ) {
00415     if ( collection.parentCollection() == resourceCollection ) {
00416       toRecover.append( collection );
00417     }
00418   }
00419 
00420   QHash<QString, QByteArray> typeForName;
00421   foreach ( const QByteArray &type, mKnownTypes ) {
00422     const QString displayName = mNameForTypeMap.value( type );
00423     typeForName[ displayName ] = type;
00424   }
00425 
00426   // These collections have been created by the maildir resource, when it
00427   // found the folders on disk. So give them the necessary attributes now.
00428   Q_ASSERT( mPendingModifyJobs == 0 );
00429   foreach ( Collection collection, toRecover ) {          // krazy:exclude=foreach
00430 
00431     if ( collection.hasAttribute<SpecialCollectionAttribute>() )
00432       continue;
00433 
00434     // Find the type for the collection.
00435     QString name = collection.name();
00436     if ( collection.hasAttribute<EntityDisplayAttribute>() ) {
00437       const QString displayName = collection.attribute<EntityDisplayAttribute>()->displayName();
00438       if (!displayName.isEmpty())
00439         name = displayName;
00440     }
00441     const QByteArray type = typeForName.value( name );
00442 
00443     if ( !type.isEmpty() ) {
00444       kDebug() << "Recovering collection" << name;
00445       setCollectionAttributes( collection, type, mNameForTypeMap, mIconForTypeMap );
00446 
00447       CollectionModifyJob *modifyJob = new CollectionModifyJob( collection, q );
00448       QObject::connect( modifyJob, SIGNAL(result(KJob*)), q, SLOT(collectionModifyResult(KJob*)) );
00449       mPendingModifyJobs++;
00450     } else {
00451       kDebug() << "Searching for names: " << typeForName.keys();
00452       kDebug() << "Unknown collection name" << name << "-- not recovering.";
00453     }
00454   }
00455 
00456   if ( mPendingModifyJobs == 0 ) {
00457     // Scan the resource.
00458     q->setResourceId( defaultResourceId( mSettings ) );
00459     q->ResourceScanJob::doStart();
00460   }
00461 }
00462 
00463 void DefaultResourceJobPrivate::collectionModifyResult( KJob *job )
00464 {
00465   if ( job->error() ) {
00466     kWarning() << job->errorText();
00467     //fail( i18n( "Failed to modify the root maildir collection (%1).", job->errorString() ) );
00468     return;
00469   }
00470 
00471   Q_ASSERT( mPendingModifyJobs > 0 );
00472   mPendingModifyJobs--;
00473   kDebug() << "pendingModifyJobs now" << mPendingModifyJobs;
00474   if ( mPendingModifyJobs == 0 ) {
00475     // Write the updated config.
00476     kDebug() << "Writing defaultResourceId" << defaultResourceId( mSettings ) << "to config.";
00477     mSettings->writeConfig();
00478 
00479     // Scan the resource.
00480     q->setResourceId( defaultResourceId( mSettings ) );
00481     q->ResourceScanJob::doStart();
00482   }
00483 }
00484 
00485 
00486 
00487 DefaultResourceJob::DefaultResourceJob( KCoreConfigSkeleton *settings, QObject *parent )
00488   : ResourceScanJob( QString(), settings, parent ),
00489     d( new DefaultResourceJobPrivate( settings, this ) )
00490 {
00491 }
00492 
00493 DefaultResourceJob::~DefaultResourceJob()
00494 {
00495   delete d;
00496 }
00497 
00498 void DefaultResourceJob::setDefaultResourceType( const QString &type )
00499 {
00500   d->mDefaultResourceType = type;
00501 }
00502 
00503 void DefaultResourceJob::setDefaultResourceOptions( const QVariantMap &options )
00504 {
00505   d->mDefaultResourceOptions = options;
00506 }
00507 
00508 void DefaultResourceJob::setTypes( const QList<QByteArray> &types )
00509 {
00510   d->mKnownTypes = types;
00511 }
00512 
00513 void DefaultResourceJob::setNameForTypeMap( const QMap<QByteArray, QString> &map )
00514 {
00515   d->mNameForTypeMap = map;
00516 }
00517 
00518 void DefaultResourceJob::setIconForTypeMap( const QMap<QByteArray, QString> &map )
00519 {
00520   d->mIconForTypeMap = map;
00521 }
00522 
00523 void DefaultResourceJob::doStart()
00524 {
00525   d->tryFetchResource();
00526 }
00527 
00528 void DefaultResourceJob::slotResult( KJob *job )
00529 {
00530   if ( job->error() ) {
00531     kWarning() << job->errorText();
00532     // Do some cleanup.
00533     if ( !d->mResourceWasPreexisting ) {
00534       // We only removed the resource instance if we have created it.
00535       // Otherwise we might lose the user's data.
00536       const AgentInstance resource = AgentManager::self()->instance( defaultResourceId( d->mSettings ) );
00537       kDebug() << "Removing resource" << resource.identifier();
00538       AgentManager::self()->removeInstance( resource );
00539     }
00540   }
00541 
00542   Job::slotResult( job );
00543 }
00544 
00545 // ===================== GetLockJob ============================
00546 
00547 class Akonadi::GetLockJob::Private
00548 {
00549   public:
00550     Private( GetLockJob *qq );
00551 
00552     void doStart(); // slot
00553     void serviceOwnerChanged( const QString &name, const QString &oldOwner,
00554                               const QString &newOwner ); // slot
00555     void timeout(); // slot
00556 
00557     GetLockJob *const q;
00558     QTimer *mSafetyTimer;
00559 };
00560 
00561 GetLockJob::Private::Private( GetLockJob *qq )
00562   : q( qq ),
00563     mSafetyTimer( 0 )
00564 {
00565 }
00566 
00567 void GetLockJob::Private::doStart()
00568 {
00569   // Just doing registerService() and checking its return value is not sufficient,
00570   // since we may *already* own the name, and then registerService() returns true.
00571 
00572   QDBusConnection bus = DBusConnectionPool::threadConnection();
00573   const bool alreadyLocked = bus.interface()->isServiceRegistered( DBUS_SERVICE_NAME );
00574   const bool gotIt = bus.registerService( DBUS_SERVICE_NAME );
00575 
00576   if ( gotIt && !alreadyLocked ) {
00577     //kDebug() << "Got lock immediately.";
00578     q->emitResult();
00579   } else {
00580     QDBusServiceWatcher *watcher = new QDBusServiceWatcher( DBUS_SERVICE_NAME, DBusConnectionPool::threadConnection(),
00581                                                             QDBusServiceWatcher::WatchForOwnerChange, q );
00582     //kDebug() << "Waiting for lock.";
00583     connect( watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00584              q, SLOT(serviceOwnerChanged(QString,QString,QString)) );
00585 
00586     mSafetyTimer = new QTimer( q );
00587     mSafetyTimer->setSingleShot( true );
00588     mSafetyTimer->setInterval( LOCK_WAIT_TIMEOUT_SECONDS * 1000 );
00589     mSafetyTimer->start();
00590     connect( mSafetyTimer, SIGNAL(timeout()), q, SLOT(timeout()) );
00591   }
00592 }
00593 
00594 void GetLockJob::Private::serviceOwnerChanged( const QString&, const QString&, const QString &newOwner )
00595 {
00596   if ( newOwner.isEmpty() ) {
00597     const bool gotIt = DBusConnectionPool::threadConnection().registerService( DBUS_SERVICE_NAME );
00598     if ( gotIt ) {
00599       mSafetyTimer->stop();
00600       q->emitResult();
00601     }
00602   }
00603 }
00604 
00605 void GetLockJob::Private::timeout()
00606 {
00607   kWarning() << "Timeout trying to get lock. Check who has acquired the name" << DBUS_SERVICE_NAME << "on DBus, using qdbus or qdbusviewer.";
00608   q->setError( Job::Unknown );
00609   q->setErrorText( i18n( "Timeout trying to get lock." ) );
00610   q->emitResult();
00611 }
00612 
00613 
00614 GetLockJob::GetLockJob( QObject *parent )
00615   : KJob( parent ),
00616     d( new Private( this ) )
00617 {
00618 }
00619 
00620 GetLockJob::~GetLockJob()
00621 {
00622   delete d;
00623 }
00624 
00625 void GetLockJob::start()
00626 {
00627   QTimer::singleShot( 0, this, SLOT(doStart()) );
00628 }
00629 
00630 void Akonadi::setCollectionAttributes( Akonadi::Collection &collection, const QByteArray &type,
00631                                        const QMap<QByteArray, QString> &nameForType,
00632                                        const QMap<QByteArray, QString> &iconForType )
00633 {
00634   {
00635     EntityDisplayAttribute *attr = new EntityDisplayAttribute;
00636     attr->setIconName( iconForType.value( type ) );
00637     attr->setDisplayName( nameForType.value( type ) );
00638     collection.addAttribute( attr );
00639   }
00640 
00641   {
00642     SpecialCollectionAttribute *attr = new SpecialCollectionAttribute;
00643     attr->setCollectionType( type );
00644     collection.addAttribute( attr );
00645   }
00646 }
00647 
00648 bool Akonadi::releaseLock()
00649 {
00650   return DBusConnectionPool::threadConnection().unregisterService( DBUS_SERVICE_NAME );
00651 }
00652 
00653 #include "specialcollectionshelperjobs_p.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:25:19 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

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

kdepimlibs-4.8.5 API Reference

Skip menu "kdepimlibs-4.8.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal