• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Plasma

akonadiengine.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2007 Volker Krause <vkrause@kde.org>
00003     Copyright (c) 2009 Sebastian Kügler <sebas@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or modify it
00006     under the terms of the GNU Library General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or (at your
00008     option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful, but WITHOUT
00011     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013     License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to the
00017     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018     02110-1301, USA.
00019 */
00020 
00021 
00022 #include "akonadiengine.h"
00023 
00024 
00025 #include <Akonadi/CollectionFetchJob>
00026 #include <Akonadi/ItemFetchJob>
00027 #include <Akonadi/ItemFetchScope>
00028 #include <Akonadi/Monitor>
00029 #include <akonadi/kmime/messageparts.h>
00030 
00031 #include <kabc/addressee.h>
00032 #include <kabc/phonenumber.h>
00033 #include <kabc/picture.h>
00034 #include <kabc/key.h>
00035 
00036 #include <microblog/statusitem.h>
00037 
00038 using namespace Akonadi;
00039 
00040 AkonadiEngine::AkonadiEngine(QObject* parent, const QVariantList& args)
00041     : Plasma::DataEngine(parent)
00042 {
00043     Q_UNUSED(args);
00044     setMaxSourceCount( 512 ); // Guard against loading thousands of emails
00045     initEmailMonitor();
00046     initMicroBlogMonitor();
00047     initContactMonitor();
00048     // TODO: monitoring for contacts
00049 }
00050 
00051 void AkonadiEngine::initEmailMonitor()
00052 {
00053     m_emailMonitor = new Monitor( this );
00054     m_emailMonitor->setMimeTypeMonitored("message/rfc822");
00055     m_emailMonitor->setCollectionMonitored(Collection::root(), false);
00056     m_emailMonitor->itemFetchScope().fetchPayloadPart( MessagePart::Envelope );
00057     connect(m_emailMonitor, SIGNAL(itemAdded(Akonadi::Item, Akonadi::Collection)),
00058             SLOT(emailItemAdded(Akonadi::Item)) );
00059     connect(m_emailMonitor, SIGNAL(itemChanged(Akonadi::Item, QSet<QByteArray>)),
00060             SLOT(emailItemAdded(Akonadi::Item)) );
00061     // remove the monitor on a source that's not used
00062     connect(this, SIGNAL(sourceRemoved(QString)), SLOT(stopMonitor(QString)));
00063 }
00064 
00065 void AkonadiEngine::initContactMonitor()
00066 {
00067     m_contactMonitor = new Monitor( this );
00068     m_contactMonitor->setMimeTypeMonitored("text/directory");
00069     m_contactMonitor->setCollectionMonitored(Collection::root(), false);
00070     m_contactMonitor->itemFetchScope().fetchFullPayload();
00071     connect(m_contactMonitor, SIGNAL(itemAdded(Akonadi::Item, Akonadi::Collection)),
00072             SLOT(contactItemAdded(Akonadi::Item)) );
00073     connect(m_emailMonitor, SIGNAL(itemChanged(Akonadi::Item, QSet<QByteArray>)),
00074             SLOT(contactItemAdded(Akonadi::Item)) );
00075     // remove the monitor on a source that's not used
00076     connect(this, SIGNAL(sourceRemoved(QString)), SLOT(stopMonitor(QString)));
00077 
00078 
00079 }
00080 
00081 void AkonadiEngine::initMicroBlogMonitor()
00082 {
00083     // TODO: set up monitoring for "application/x-vnd.kde.microblog"
00084     m_microBlogMonitor = new Monitor( this );
00085     m_microBlogMonitor->setMimeTypeMonitored( "application/x-vnd.kde.microblog" );
00086     m_microBlogMonitor->setCollectionMonitored(Collection::root(), false);
00087     m_microBlogMonitor->itemFetchScope().fetchFullPayload();
00088     connect(m_microBlogMonitor, SIGNAL(itemAdded(Akonadi::Item, Akonadi::Collection)),
00089             SLOT(microBlogItemAdded(Akonadi::Item)) );
00090     connect(m_microBlogMonitor, SIGNAL(itemChanged(Akonadi::Item, QSet<QByteArray>)),
00091             SLOT(microBlogItemAdded(Akonadi::Item)) );
00092     // remove the monitor on a source that's not used
00093     connect(this, SIGNAL(sourceRemoved(QString)), SLOT(stopMonitor(QString)));
00094 }
00095 
00096 AkonadiEngine::~AkonadiEngine()
00097 {
00098 }
00099 
00100 QStringList AkonadiEngine::sources() const
00101 {
00102     return QStringList() << "EmailCollections" << "ContactCollections" << "MicroBlogs";
00103 }
00104 
00105 void AkonadiEngine::fetchEmailCollectionsDone(KJob* job)
00106 {
00107     // called when the job fetching email collections from Akonadi emits result()
00108     if ( job->error() ) {
00109         kDebug() << "Job Error:" << job->errorString();
00110     } else {
00111         CollectionFetchJob* cjob = static_cast<CollectionFetchJob*>( job );
00112         int i = 0;
00113         foreach( const Collection &collection, cjob->collections() ) {
00114             if (collection.contentMimeTypes().contains("message/rfc822")) {
00115                 //kDebug() << "EmailCollection setting data:" << collection.name() << collection.url() << collection.contentMimeTypes();
00116                 i++;
00117                 setData("EmailCollections", QString("EmailCollection-%1").arg(collection.id()), collection.name());
00118             }
00119         }
00120         kDebug() << i << "Email collections are in now";
00121         scheduleSourcesUpdated();
00122     }
00123 }
00124 
00125 void AkonadiEngine::fetchContactCollectionsDone(KJob* job)
00126 {
00127     // called when the job fetching contact collections from Akonadi emits result()
00128     if ( job->error() ) {
00129         kDebug() << "Job Error:" << job->errorString();
00130     } else {
00131         CollectionFetchJob* cjob = static_cast<CollectionFetchJob*>( job );
00132         int i = 0;
00133         foreach( const Collection &collection, cjob->collections() ) {
00134             if (collection.contentMimeTypes().contains("text/directory")) {
00135                 //kDebug() << "ContactCollection setting data:" << collection.name() << collection.url() << collection.contentMimeTypes();
00136                 i++;
00137                 setData("ContactCollections", QString("ContactCollection-%1").arg(collection.id()), collection.name());
00138             }
00139         }
00140         kDebug() << i << "Contact collections are in now";
00141         scheduleSourcesUpdated();
00142     }
00143 }
00144 
00145 void AkonadiEngine::fetchMicroBlogCollectionsDone(KJob* job)
00146 {
00147     // called when the job fetching microblog collections from Akonadi emits result()
00148     if ( job->error() ) {
00149         kDebug() << "Job Error:" << job->errorString();
00150     } else {
00151         CollectionFetchJob* cjob = static_cast<CollectionFetchJob*>( job );
00152         int i = 0;
00153         foreach( const Collection &collection, cjob->collections() ) {
00154             if (collection.contentMimeTypes().contains("application/x-vnd.kde.microblog")) {
00155                 kDebug() << "Microblog setting data:" << collection.name() << collection.url() << collection.contentMimeTypes();
00156                 i++;
00157                 setData("MicroblogCollection", QString("MicroBlog-%1").arg(collection.id()), collection.name());
00158             }
00159         }
00160         kDebug() << i << "MicroBlog collections are in now";
00161         scheduleSourcesUpdated();
00162     }
00163 }
00164 
00165 bool AkonadiEngine::sourceRequestEvent(const QString &name)
00166 {
00167     kDebug() << "Source requested:" << name << sources();
00168 
00169     if (name == "EmailCollections") {
00170         Collection emailCollection(Collection::root());
00171         emailCollection.setContentMimeTypes(QStringList() << "message/rfc822");
00172         CollectionFetchJob *fetch = new CollectionFetchJob( emailCollection, CollectionFetchJob::Recursive);
00173         connect( fetch, SIGNAL(result(KJob*)), SLOT(fetchEmailCollectionsDone(KJob*)) );
00174         // For async data fetching, it's mandatory to set the data source to empty before returning true
00175         setData(name, DataEngine::Data());
00176         return true;
00177 
00178     } else if (name.startsWith(QString("EmailCollection-"))) {
00179         qlonglong id = name.split('-')[1].toLongLong();
00180         ItemFetchJob* fetch = new ItemFetchJob( Collection( id ), this );
00181         m_emailMonitor->setCollectionMonitored(Collection( id ), true);
00182         fetch->fetchScope().fetchPayloadPart( MessagePart::Envelope );
00183         connect( fetch, SIGNAL(result(KJob*)), SLOT(fetchEmailCollectionDone(KJob*)) );
00184         connect( fetch, SIGNAL(itemsReceived(const Akonadi::Item::List&)), SLOT(emailItemsReceived(const Akonadi::Item::List&)) );
00185         m_jobCollections[fetch] = name;
00186         setData(name, DataEngine::Data());
00187         return true;
00188 
00189     } else if (name.startsWith(QString("Email-"))) {
00190         qlonglong id = name.split('-')[1].toLongLong();
00191         ItemFetchJob* fetch = new ItemFetchJob( Item( id ), this );
00192         m_emailMonitor->setItemMonitored(Item( id ), true);
00193         fetch->fetchScope().fetchPayloadPart( MessagePart::Envelope );
00194         connect( fetch, SIGNAL(result(KJob*)), SLOT(fetchEmailCollectionDone(KJob*)) );
00195         connect( fetch, SIGNAL(itemsReceived(const Akonadi::Item::List&)), SLOT(emailItemsReceived(const Akonadi::Item::List&)) );
00196         m_jobCollections[fetch] = name;
00197         setData(name, DataEngine::Data());
00198         return true;
00199 
00200     } else if (name == "ContactCollections") {
00201         Collection contactCollection(Collection::root());
00202         contactCollection.setContentMimeTypes(QStringList() << "text/directory");
00203 
00204         CollectionFetchJob* fetch = new CollectionFetchJob( contactCollection, CollectionFetchJob::Recursive);
00205         connect( fetch, SIGNAL(result(KJob*)), SLOT(fetchContactCollectionsDone(KJob*)) );
00206         setData(name, DataEngine::Data());
00207         return true;
00208 
00209     } else if (name.startsWith(QString("ContactCollection-"))) {
00210         qlonglong id = name.split('-')[1].toLongLong();
00211         ItemFetchJob *fetch = new ItemFetchJob( Collection( id ), this );
00212         m_emailMonitor->setCollectionMonitored(Collection( id ), true); // FIXME: should be contacts monitor
00213         fetch->fetchScope().fetchFullPayload();
00214         connect( fetch, SIGNAL(result(KJob*)), SLOT(fetchContactCollectionDone(KJob*)) );
00215         setData(name, DataEngine::Data());
00216         return true;
00217 
00218     } else if (name.startsWith(QString("Contact-"))) {
00219         kDebug() << "Fetching contact" << name;
00220         qlonglong id = name.split('-')[1].toLongLong();
00221         ItemFetchJob *fetch = new ItemFetchJob( Item( id ), this );
00222         m_emailMonitor->setItemMonitored(Item( id ), true); // FIXME: should be contacts monitor
00223         fetch->fetchScope().fetchFullPayload();
00224         connect( fetch, SIGNAL(result(KJob*)), SLOT(fetchContactCollectionDone(KJob*)) );
00225         setData(name, DataEngine::Data());
00226         return true;
00227 
00228     } else if (name == "MicroBlogs") {
00229         Collection microblogCollection(Collection::root());
00230         microblogCollection.setContentMimeTypes(QStringList() << "application/x-vnd.kde.microblog");
00231         CollectionFetchJob *fetch = new CollectionFetchJob( microblogCollection, CollectionFetchJob::Recursive);
00232         connect( fetch, SIGNAL(result(KJob*)), SLOT(fetchMicroBlogCollectionsDone(KJob*)) );
00233         setData(name, DataEngine::Data());
00234         return true;
00235 
00236     } else if (name.startsWith(QString("MicroBlog-"))) {
00237         qlonglong id = name.split('-')[1].toLongLong();
00238         kDebug() << "MicroBlog ID" << id << " requested" << name;
00239         ItemFetchJob *fetch = new ItemFetchJob( Akonadi::Collection( id ));
00240         m_microBlogMonitor->setItemMonitored(Item( id ), true);
00241         fetch->fetchScope().fetchFullPayload();
00242         connect( fetch, SIGNAL(result(KJob*)), SLOT(fetchMicroBlogDone(KJob*)) );
00243         setData(name, DataEngine::Data());
00244         return true;
00245     }
00246     // We don't understand the request.
00247     kDebug() << "Don't know what to do with:" << name;
00248     return false;
00249 }
00250 
00251 void AkonadiEngine::stopMonitor(const QString &name)
00252 {
00253     if (name.startsWith(QString("EmailCollection-"))) {
00254         // Stop monitoring this one
00255         qlonglong id = name.split('-')[1].toLongLong();
00256         m_emailMonitor->setCollectionMonitored( Collection( id ), false);
00257         kDebug() << "Removed monitor from:" << name << id;
00258     }
00259 }
00260 
00261 void AkonadiEngine::emailItemsReceived(const Akonadi::Item::List &items)
00262 {
00263     foreach (const Akonadi::Item &item, items) {
00264         emailItemAdded(item);
00265     }
00266 }
00267 
00268 void AkonadiEngine::emailItemAdded(const Akonadi::Item &item, const QString &collection)
00269 {
00270     if ( !item.hasPayload<MessagePtr>() ) {
00271         return;
00272     }
00273     MessagePtr msg = item.payload<MessagePtr>();
00274     if (msg) {
00275         QString source = QString::number( item.id() );
00276         source = "Email-" + source;
00277         //kDebug() << "new source adding:" << source << item.url() << msg->subject()->asUnicodeString();
00278 
00279         setData( source, "Id", item.id() );
00280         setData( source, "Collection", collection);
00281         setData( source, "Url", item.url().url() );
00282         setData( source, "Subject", msg->subject()->asUnicodeString() );
00283         setData( source, "From", msg->from()->asUnicodeString() );
00284         setData( source, "DateTime", msg->date()->dateTime().date() );
00285         setData( source, "To", msg->to()->asUnicodeString() );
00286         setData( source, "Cc", msg->cc()->asUnicodeString() );
00287         setData( source, "Bcc", msg->bcc()->asUnicodeString() );
00288         setData( source, "Body", msg->mainBodyPart()->body() );
00289         // Flags
00290         //kDebug() << item.flags();
00291         setData( source, "Flag-New", !item.hasFlag("\\Seen") );
00292         setData( source, "Flag-Task", item.hasFlag("\\Task") ); // not in Akonadi!
00293         setData( source, "Flag-Important", item.hasFlag("important") );
00294         setData( source, "Flag-Attachment", item.hasFlag("has_attachment") );
00295         setData( source, "Flag-Spam", item.hasFlag("spam") );
00296         setData( source, "Flag-Draft", item.hasFlag("\\Draft") );
00297         setData( source, "Flag-Answered", item.hasFlag("\\Answered") );
00298         setData( source, "Flag-Deleted", item.hasFlag("\\Deleted") );
00299         setData( source, "Flag-Flagged", item.hasFlag("\\Flagged") );
00300 
00301         //printMessage(msg);
00302         scheduleSourcesUpdated();
00303     }
00304 }
00305 
00306 void AkonadiEngine::printMessage(const MessagePtr msg)
00307 {
00308         kDebug() << "=============== New Item" << msg->from()->asUnicodeString() << msg->subject()->asUnicodeString();
00309         kDebug() << "sub" << msg->subject()->asUnicodeString();
00310         kDebug() << "from" << msg->from()->asUnicodeString();
00311         kDebug() << "date" << msg->date()->dateTime().date();
00312         kDebug() << "to" << msg->to()->asUnicodeString();
00313         kDebug() << "cc" << msg->cc()->asUnicodeString();
00314         kDebug() << "bcc" << msg->bcc()->asUnicodeString();
00315         kDebug() << "body" << msg->mainBodyPart()->body();
00316 }
00317 
00318 void AkonadiEngine::fetchEmailCollectionDone(KJob* job)
00319 {
00320     if ( job->error() ) {
00321         kDebug() << "Job Error:" << job->errorString();
00322         return;
00323     }
00324     const QString col = m_jobCollections[job];
00325     Item::List items = static_cast<ItemFetchJob*>( job )->items();
00326     foreach ( const Item &item, items ) {
00327         emailItemAdded(item, col);
00328     }
00329     m_jobCollections.remove(job);
00330     scheduleSourcesUpdated();
00331 }
00332 
00333 void AkonadiEngine::fetchContactCollectionDone(KJob* job)
00334 {
00335     if ( job->error() ) {
00336         return;
00337     }
00338     Item::List items = static_cast<ItemFetchJob*>( job )->items();
00339     foreach ( const Item &item, items ) {
00340         contactItemAdded( item );
00341     }
00342 }
00343 
00344 void AkonadiEngine::fetchMicroBlogDone(KJob* job)
00345 {
00346     if (job->error()) {
00347         kDebug() << "Microblog job failed:" << job->errorString();
00348     } else {
00349         Item::List items = static_cast<ItemFetchJob*>( job )->items();
00350         kDebug() << "Adding microblogs" << items.count();
00351         foreach (const Item &item, items) {
00352             microBlogItemAdded(item);
00353         }
00354     }
00355 }
00356 
00357 
00358 void AkonadiEngine::microBlogItemAdded(const Akonadi::Item &item)
00359 {
00360     // Get the Akonadi::Item's XML payload and parse that, then
00361     // put it into the DataEngine's Data
00362     kDebug() << "Checking one item";
00363     if (item.hasPayload<Microblog::StatusItem>()) {
00364         Microblog::StatusItem s = item.payload<Microblog::StatusItem>();
00365         const QString source = QString("MicroBlog-%1").arg(s.id());
00366         kDebug() << "Adding" << source << s.keys();
00367         setData(source, "Date", s.date());
00368         setData(source, "Foo", "Bar");
00369         foreach (const QString &key, s.keys()) {
00370             setData(source, key, s.value(key));
00371         }
00372         scheduleSourcesUpdated();
00373     } else {
00374         kDebug() << "Wrong payload (not a StatusItem)";
00375     }
00376 }
00377 
00378 void AkonadiEngine::printContact(const QString &source, const KABC::Addressee &a)
00379 {
00380     kDebug() << "-----------------------------------";
00381     kDebug() << source;
00382     kDebug() << "name" << a.name();
00383     kDebug() << "formattedName" << a.formattedName();
00384     kDebug() << "nameLabel" << a.nameLabel();
00385     kDebug() << "given" << a.givenName();
00386     kDebug() << "familyName" << a.familyName();
00387     kDebug() << "realName" << a.realName();
00388     kDebug() << "organization" << a.organization();
00389     kDebug() << "department" << a.department();
00390     kDebug() << "role" << a.role();
00391     kDebug() << "emails" << a.emails();
00392     kDebug() << "fullEmail" << a.fullEmail();
00393     kDebug() << "photoUrl" << a.photo().url();
00394     kDebug() << "note" << a.note();
00395 
00396     QStringList phoneNumbers;
00397     foreach (const KABC::PhoneNumber &pn, a.phoneNumbers()) {
00398         const QString key = QString("Phone-%1").arg(pn.typeLabel());
00399         kDebug() << key << a.phoneNumber(pn.type()).number();
00400         phoneNumbers << a.phoneNumber(pn.type()).number();
00401     }
00402     kDebug() << "phoneNumbers" << phoneNumbers;
00403 
00404     kDebug() << "additionalName" << a.additionalName();
00405 
00406 }
00407 
00408 void AkonadiEngine::contactItemAdded( const Akonadi::Item &item )
00409 {
00410     if (item.hasPayload<KABC::Addressee>()) {
00411         //kDebug() << item.id() << "item has payload ...";
00412         KABC::Addressee a = item.payload<KABC::Addressee>();
00413         if (!a.isEmpty()) {
00414             const QString source = QString("Contact-%1").arg(item.id());
00415             setData(source, "Id", item.id());
00416             setData(source, "Url", item.url().url());
00417 
00418             // Name and related
00419             setData(source, "Name", a.formattedName());
00420             setData(source, "GivenName", a.givenName());
00421             setData(source, "FamilyName", a.familyName());
00422             setData(source, "NickName", a.nickName());
00423             setData(source, "RealName", a.realName());
00424             setData(source, "AdditionalName", a.additionalName());
00425 
00426             // Organization and related
00427             setData(source, "Organization", a.organization());
00428             setData(source, "Department", a.department());
00429             setData(source, "Role", a.role());
00430 
00431             // EMail and related
00432             setData(source, "Emails", a.emails());
00433             setData(source, "FullEmail", a.fullEmail());
00434 
00435             // Phone and related
00436             QStringList phoneNumbers;
00437             foreach (const KABC::PhoneNumber &pn, a.phoneNumbers()) {
00438                 const QString key = QString("Phone-%1").arg(pn.typeLabel());
00439                 setData(source, key, a.phoneNumber(pn.type()).number());
00440                 phoneNumbers << a.phoneNumber(pn.type()).number();
00441             }
00442             setData(source, "PhoneNumbers", phoneNumbers);
00443 
00444             // Personal
00445             setData(source, "Birthday", a.birthday());
00446             setData(source, "Photo", a.photo().data());
00447             setData(source, "PhotoUrl", a.photo().url());
00448             setData(source, "Latitude", a.geo().latitude());
00449             setData(source, "Longitude", a.geo().longitude());
00450 
00451             // addresses
00452 
00453             // categories
00454 
00455             // note,
00456             setData(source, "Note", a.note());
00457             // prefix
00458 
00459             // ...
00460             //printContact(source, a);
00461 
00462             scheduleSourcesUpdated();
00463         }
00464     }
00465 }
00466 
00467 #include "akonadiengine.moc"

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •     Animators
  •     Applets
  •     Engines
  • Solid Modules
  • System Settings
  •   SystemSettingsView
Generated for API Reference by doxygen 1.5.9-20090814
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