00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 );
00045 initEmailMonitor();
00046 initMicroBlogMonitor();
00047 initContactMonitor();
00048
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
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
00076 connect(this, SIGNAL(sourceRemoved(QString)), SLOT(stopMonitor(QString)));
00077
00078
00079 }
00080
00081 void AkonadiEngine::initMicroBlogMonitor()
00082 {
00083
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
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
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
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
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
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
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
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);
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);
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
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
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
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
00290
00291 setData( source, "Flag-New", !item.hasFlag("\\Seen") );
00292 setData( source, "Flag-Task", item.hasFlag("\\Task") );
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
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
00361
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
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
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
00427 setData(source, "Organization", a.organization());
00428 setData(source, "Department", a.department());
00429 setData(source, "Role", a.role());
00430
00431
00432 setData(source, "Emails", a.emails());
00433 setData(source, "FullEmail", a.fullEmail());
00434
00435
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
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
00452
00453
00454
00455
00456 setData(source, "Note", a.note());
00457
00458
00459
00460
00461
00462 scheduleSourcesUpdated();
00463 }
00464 }
00465 }
00466
00467 #include "akonadiengine.moc"