• Skip to content
  • Skip to link menu
KDE 4.8 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • 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     agent.reconfigure();
00354   }
00355 
00356   // Sync the resource.
00357   {
00358     ResourceSynchronizationJob *syncJob = new ResourceSynchronizationJob( agent, q );
00359     QObject::connect( syncJob, SIGNAL(result(KJob*)), q, SLOT(resourceSyncResult(KJob*)) );
00360     syncJob->start(); // non-Akonadi
00361   }
00362 }
00363 
00364 void DefaultResourceJobPrivate::resourceSyncResult( KJob *job )
00365 {
00366   if ( job->error() ) {
00367     kWarning() << job->errorText();
00368     //fail( i18n( "ResourceSynchronizationJob failed (%1).", job->errorString() ) );
00369     return;
00370   }
00371 
00372   // Fetch the collections of the resource.
00373   kDebug() << "Fetching maildir collections.";
00374   CollectionFetchJob *fetchJob = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive, q );
00375   fetchJob->fetchScope().setResource( defaultResourceId( mSettings ) );
00376   QObject::connect( fetchJob, SIGNAL(result(KJob*)), q, SLOT(collectionFetchResult(KJob*)) );
00377 }
00378 
00379 void DefaultResourceJobPrivate::collectionFetchResult( KJob *job )
00380 {
00381   if ( job->error() ) {
00382     kWarning() << job->errorText();
00383     //fail( i18n( "Failed to fetch the root maildir collection (%1).", job->errorString() ) );
00384     return;
00385   }
00386 
00387   CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob *>( job );
00388   Q_ASSERT( fetchJob );
00389 
00390   const Collection::List collections = fetchJob->collections();
00391   kDebug() << "Fetched" << collections.count() << "collections.";
00392 
00393   // Find the root maildir collection.
00394   Collection::List toRecover;
00395   Collection resourceCollection;
00396   foreach ( const Collection &collection, collections ) {
00397     if ( collection.parentCollection() == Collection::root() ) {
00398       resourceCollection = collection;
00399       toRecover.append( collection );
00400       break;
00401     }
00402   }
00403 
00404   if ( !resourceCollection.isValid() ) {
00405     q->setError( Job::Unknown );
00406     q->setErrorText( i18n( "Failed to fetch the resource collection." ) );
00407     q->emitResult();
00408     return;
00409   }
00410 
00411   // Find all children of the resource collection.
00412   foreach ( const Collection &collection, collections ) {
00413     if ( collection.parentCollection() == resourceCollection ) {
00414       toRecover.append( collection );
00415     }
00416   }
00417 
00418   QHash<QString, QByteArray> typeForName;
00419   foreach ( const QByteArray &type, mKnownTypes ) {
00420     const QString displayName = mNameForTypeMap.value( type );
00421     typeForName[ displayName ] = type;
00422   }
00423 
00424   // These collections have been created by the maildir resource, when it
00425   // found the folders on disk. So give them the necessary attributes now.
00426   Q_ASSERT( mPendingModifyJobs == 0 );
00427   foreach ( Collection collection, toRecover ) {          // krazy:exclude=foreach
00428 
00429     if ( collection.hasAttribute<SpecialCollectionAttribute>() )
00430       continue;
00431 
00432     // Find the type for the collection.
00433     QString name = collection.name();
00434     if ( collection.hasAttribute<EntityDisplayAttribute>() ) {
00435       const QString displayName = collection.attribute<EntityDisplayAttribute>()->displayName();
00436       if (!displayName.isEmpty())
00437         name = displayName;
00438     }
00439     const QByteArray type = typeForName.value( name );
00440 
00441     if ( !type.isEmpty() ) {
00442       kDebug() << "Recovering collection" << name;
00443       setCollectionAttributes( collection, type, mNameForTypeMap, mIconForTypeMap );
00444 
00445       CollectionModifyJob *modifyJob = new CollectionModifyJob( collection, q );
00446       QObject::connect( modifyJob, SIGNAL(result(KJob*)), q, SLOT(collectionModifyResult(KJob*)) );
00447       mPendingModifyJobs++;
00448     } else {
00449       kDebug() << "Searching for names: " << typeForName.keys();
00450       kDebug() << "Unknown collection name" << name << "-- not recovering.";
00451     }
00452   }
00453 
00454   if ( mPendingModifyJobs == 0 ) {
00455     // Scan the resource.
00456     q->setResourceId( defaultResourceId( mSettings ) );
00457     q->ResourceScanJob::doStart();
00458   }
00459 }
00460 
00461 void DefaultResourceJobPrivate::collectionModifyResult( KJob *job )
00462 {
00463   if ( job->error() ) {
00464     kWarning() << job->errorText();
00465     //fail( i18n( "Failed to modify the root maildir collection (%1).", job->errorString() ) );
00466     return;
00467   }
00468 
00469   Q_ASSERT( mPendingModifyJobs > 0 );
00470   mPendingModifyJobs--;
00471   kDebug() << "pendingModifyJobs now" << mPendingModifyJobs;
00472   if ( mPendingModifyJobs == 0 ) {
00473     // Write the updated config.
00474     kDebug() << "Writing defaultResourceId" << defaultResourceId( mSettings ) << "to config.";
00475     mSettings->writeConfig();
00476 
00477     // Scan the resource.
00478     q->setResourceId( defaultResourceId( mSettings ) );
00479     q->ResourceScanJob::doStart();
00480   }
00481 }
00482 
00483 
00484 
00485 DefaultResourceJob::DefaultResourceJob( KCoreConfigSkeleton *settings, QObject *parent )
00486   : ResourceScanJob( QString(), settings, parent ),
00487     d( new DefaultResourceJobPrivate( settings, this ) )
00488 {
00489 }
00490 
00491 DefaultResourceJob::~DefaultResourceJob()
00492 {
00493   delete d;
00494 }
00495 
00496 void DefaultResourceJob::setDefaultResourceType( const QString &type )
00497 {
00498   d->mDefaultResourceType = type;
00499 }
00500 
00501 void DefaultResourceJob::setDefaultResourceOptions( const QVariantMap &options )
00502 {
00503   d->mDefaultResourceOptions = options;
00504 }
00505 
00506 void DefaultResourceJob::setTypes( const QList<QByteArray> &types )
00507 {
00508   d->mKnownTypes = types;
00509 }
00510 
00511 void DefaultResourceJob::setNameForTypeMap( const QMap<QByteArray, QString> &map )
00512 {
00513   d->mNameForTypeMap = map;
00514 }
00515 
00516 void DefaultResourceJob::setIconForTypeMap( const QMap<QByteArray, QString> &map )
00517 {
00518   d->mIconForTypeMap = map;
00519 }
00520 
00521 void DefaultResourceJob::doStart()
00522 {
00523   d->tryFetchResource();
00524 }
00525 
00526 void DefaultResourceJob::slotResult( KJob *job )
00527 {
00528   if ( job->error() ) {
00529     kWarning() << job->errorText();
00530     // Do some cleanup.
00531     if ( !d->mResourceWasPreexisting ) {
00532       // We only removed the resource instance if we have created it.
00533       // Otherwise we might lose the user's data.
00534       const AgentInstance resource = AgentManager::self()->instance( defaultResourceId( d->mSettings ) );
00535       kDebug() << "Removing resource" << resource.identifier();
00536       AgentManager::self()->removeInstance( resource );
00537     }
00538   }
00539 
00540   Job::slotResult( job );
00541 }
00542 
00543 // ===================== GetLockJob ============================
00544 
00545 class Akonadi::GetLockJob::Private
00546 {
00547   public:
00548     Private( GetLockJob *qq );
00549 
00550     void doStart(); // slot
00551     void serviceOwnerChanged( const QString &name, const QString &oldOwner,
00552                               const QString &newOwner ); // slot
00553     void timeout(); // slot
00554 
00555     GetLockJob *const q;
00556     QTimer *mSafetyTimer;
00557 };
00558 
00559 GetLockJob::Private::Private( GetLockJob *qq )
00560   : q( qq ),
00561     mSafetyTimer( 0 )
00562 {
00563 }
00564 
00565 void GetLockJob::Private::doStart()
00566 {
00567   // Just doing registerService() and checking its return value is not sufficient,
00568   // since we may *already* own the name, and then registerService() returns true.
00569 
00570   QDBusConnection bus = DBusConnectionPool::threadConnection();
00571   const bool alreadyLocked = bus.interface()->isServiceRegistered( DBUS_SERVICE_NAME );
00572   const bool gotIt = bus.registerService( DBUS_SERVICE_NAME );
00573 
00574   if ( gotIt && !alreadyLocked ) {
00575     //kDebug() << "Got lock immediately.";
00576     q->emitResult();
00577   } else {
00578     QDBusServiceWatcher *watcher = new QDBusServiceWatcher( DBUS_SERVICE_NAME, DBusConnectionPool::threadConnection(),
00579                                                             QDBusServiceWatcher::WatchForOwnerChange, q );
00580     //kDebug() << "Waiting for lock.";
00581     connect( watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
00582              q, SLOT(serviceOwnerChanged(QString,QString,QString)) );
00583 
00584     mSafetyTimer = new QTimer( q );
00585     mSafetyTimer->setSingleShot( true );
00586     mSafetyTimer->setInterval( LOCK_WAIT_TIMEOUT_SECONDS * 1000 );
00587     mSafetyTimer->start();
00588     connect( mSafetyTimer, SIGNAL(timeout()), q, SLOT(timeout()) );
00589   }
00590 }
00591 
00592 void GetLockJob::Private::serviceOwnerChanged( const QString&, const QString&, const QString &newOwner )
00593 {
00594   if ( newOwner.isEmpty() ) {
00595     const bool gotIt = DBusConnectionPool::threadConnection().registerService( DBUS_SERVICE_NAME );
00596     if ( gotIt ) {
00597       mSafetyTimer->stop();
00598       q->emitResult();
00599     }
00600   }
00601 }
00602 
00603 void GetLockJob::Private::timeout()
00604 {
00605   kWarning() << "Timeout trying to get lock. Check who has acquired the name" << DBUS_SERVICE_NAME << "on DBus, using qdbus or qdbusviewer.";
00606   q->setError( Job::Unknown );
00607   q->setErrorText( i18n( "Timeout trying to get lock." ) );
00608   q->emitResult();
00609 }
00610 
00611 
00612 GetLockJob::GetLockJob( QObject *parent )
00613   : KJob( parent ),
00614     d( new Private( this ) )
00615 {
00616 }
00617 
00618 GetLockJob::~GetLockJob()
00619 {
00620   delete d;
00621 }
00622 
00623 void GetLockJob::start()
00624 {
00625   QTimer::singleShot( 0, this, SLOT(doStart()) );
00626 }
00627 
00628 void Akonadi::setCollectionAttributes( Akonadi::Collection &collection, const QByteArray &type,
00629                                        const QMap<QByteArray, QString> &nameForType,
00630                                        const QMap<QByteArray, QString> &iconForType )
00631 {
00632   {
00633     EntityDisplayAttribute *attr = new EntityDisplayAttribute;
00634     attr->setIconName( iconForType.value( type ) );
00635     attr->setDisplayName( nameForType.value( type ) );
00636     collection.addAttribute( attr );
00637   }
00638 
00639   {
00640     SpecialCollectionAttribute *attr = new SpecialCollectionAttribute;
00641     attr->setCollectionType( type );
00642     collection.addAttribute( attr );
00643   }
00644 }
00645 
00646 bool Akonadi::releaseLock()
00647 {
00648   return DBusConnectionPool::threadConnection().unregisterService( DBUS_SERVICE_NAME );
00649 }
00650 
00651 #include "specialcollectionshelperjobs_p.moc"

akonadi

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

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • 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
Generated for KDE-PIM Libraries by doxygen 1.7.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