[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [Amarok]  Made ExtendedAboutDialog provider-independent. Thi
From:       Teo Mrnjavac <teo () getamarok ! com>
Date:       2009-09-10 14:54:30
Message-ID: 200909101454.n8AEsUNm016706 () Wurst ! kollide ! net
[Download RAW message or body]

commit ec09f498cc595b321ebfa48c45a3177713b92e32
Author:     Teo Mrnjavac <teo@getamarok.com>
AuthorDate: Thu Sep 10 16:20:36 2009 +0200
Commit:     Teo Mrnjavac <teo@getamarok.com>
CommitDate: Thu Sep 10 16:49:38 2009 +0200

    Made ExtendedAboutDialog provider-independent.
    This means that contributors' data can now be fetched from any host that \
implements the OCS API.  Imported new libAttica snapshot and made the dialog work \
with the recent libAttica API changes.  Removed frame with "anonymous" picture for \
users who don't have an avatar on oD.o.  Also thanks Eckhart Wörner for his recent \
work on libAttica, without it none of this would have been possible.

diff --git a/src/App.cpp b/src/App.cpp
index 824dc2d..d3ce70f 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -115,7 +115,7 @@ AMAROK_EXPORT KAboutData aboutData( "amarok", 0,
     ki18n( "IRC:\nirc.freenode.net - #amarok, #amarok.de, #amarok.es, \
#amarok.fr\n\nFeedback:\namarok@kde.org\n\n(Build Date: %1)" ).subs( __DATE__ ),  ( \
"http://amarok.kde.org" ) );  
-AMAROK_EXPORT OcsData ocsData;
+AMAROK_EXPORT OcsData ocsData( "opendesktop" );
 
 App::App()
         : KUniqueApplication()
diff --git a/src/aboutdialog/ExtendedAboutDialog.cpp \
b/src/aboutdialog/ExtendedAboutDialog.cpp index 7d7bd2f..5597743 100644
--- a/src/aboutdialog/ExtendedAboutDialog.cpp
+++ b/src/aboutdialog/ExtendedAboutDialog.cpp
@@ -23,9 +23,8 @@
 
 #include "Amarok.h"
 #include "Debug.h"
-#include "libattica-ocsclient/ocsapi.h"
-#include "libattica-ocsclient/personjob.h"
 #include "OcsPersonItem.h"
+#include "libattica-ocsclient/providerinitjob.h"
 
 #include <QLabel>
 #include <QLayout>
@@ -61,8 +60,8 @@ public:
 };
 
 ExtendedAboutDialog::ExtendedAboutDialog(const KAboutData *aboutData, const OcsData \
                *ocsData, QWidget *parent)
-  : KDialog(parent),
-    d(new Private(this))
+  : KDialog(parent)
+  , d(new Private(this))
 {
     DEBUG_BLOCK
     if (aboutData == 0)
@@ -343,19 +342,22 @@ ExtendedAboutDialog::switchToOcsWidgets()
 
     m_showOcsAuthorButton->animate();
     m_showOcsCreditButton->animate();
-    //TODO: Ask Solid if the network is available.
-    if( sender() == m_showOcsAuthorButton )
-    {
-        m_authorListWidget->switchToOcs();
-        m_creditListWidget->switchToOcs();
-    }
-    else if( sender() == m_showOcsCreditButton )
+    Attica::ProviderInitJob *providerJob = Attica::Provider::byId( \
m_ocsData.providerId() ); +    connect( providerJob, SIGNAL( result( KJob * ) ), \
this, SLOT( onProviderFetched( KJob * ) ) ); +}
+void
+ExtendedAboutDialog::onProviderFetched( KJob *job )
+{
+    Attica::ProviderInitJob *providerJob = qobject_cast< Attica::ProviderInitJob * \
>( job ); +    if( providerJob->error() == 0 )
     {
-        m_creditListWidget->switchToOcs();
-        m_authorListWidget->switchToOcs();
+        debug()<<"Successfully fetched OCS provider"<< \
providerJob->provider().name(); +        debug()<<"About to request OCS data";
+        m_authorListWidget->switchToOcs( providerJob->provider() );
+        m_creditListWidget->switchToOcs( providerJob->provider() );
     }
     else
-        warning() << "Invalid sender for ExtendedAboutDialog::switchToOcsWidgets()";
+        warning() << "OCS provider fetch failed";
 }
 
 #include "ExtendedAboutDialog.moc"
diff --git a/src/aboutdialog/ExtendedAboutDialog.h \
b/src/aboutdialog/ExtendedAboutDialog.h index 094fca7..1cc433f 100644
--- a/src/aboutdialog/ExtendedAboutDialog.h
+++ b/src/aboutdialog/ExtendedAboutDialog.h
@@ -40,6 +40,7 @@ public:
 
 private slots:
     void switchToOcsWidgets();
+    void onProviderFetched( KJob *job );
 
 private:
     class Private;
diff --git a/src/aboutdialog/OcsData.cpp b/src/aboutdialog/OcsData.cpp
index a4cb818..4df32fe 100644
--- a/src/aboutdialog/OcsData.cpp
+++ b/src/aboutdialog/OcsData.cpp
@@ -16,8 +16,10 @@
 
 #include "OcsData.h"
 
-OcsData::OcsData()
-{}
+OcsData::OcsData( const QByteArray &providerId )
+{
+    m_providerId = QString::fromUtf8( providerId );
+}
 
 OcsData::~OcsData()
 {}
diff --git a/src/aboutdialog/OcsData.h b/src/aboutdialog/OcsData.h
index 038fd9b..786abc7 100644
--- a/src/aboutdialog/OcsData.h
+++ b/src/aboutdialog/OcsData.h
@@ -31,17 +31,19 @@ class AMAROK_EXPORT OcsData
 public:
     typedef QList< QPair< QString, KAboutPerson > > OcsPersonList;
 
-    OcsData();
+    OcsData( const QByteArray &providerId = "opendesktop" );
     virtual ~OcsData();
     void addAuthor( const QString &username, const KAboutPerson &person );
     void addCredit( const QString &username, const KAboutPerson &person );
 
     const OcsPersonList * authors() const { return &m_authors; }
     const OcsPersonList * credits() const { return &m_credits; }
+    const QString providerId() const { return m_providerId; }
 
 private:
     QList< QPair< QString, KAboutPerson > > m_authors;
     QList< QPair< QString, KAboutPerson > > m_credits;
+    QString m_providerId;
 };
 
 #endif //AMAROK_OCSDATA_H
diff --git a/src/aboutdialog/OcsPersonItem.cpp b/src/aboutdialog/OcsPersonItem.cpp
index 6393491..4c34d7a 100644
--- a/src/aboutdialog/OcsPersonItem.cpp
+++ b/src/aboutdialog/OcsPersonItem.cpp
@@ -17,6 +17,9 @@
 #include "OcsPersonItem.h"
 
 #include "Debug.h"
+#include "libattica-ocsclient/provider.h"
+#include "libattica-ocsclient/providerinitjob.h"
+#include "libattica-ocsclient/personjob.h"
 
 #include <KAction>
 #include <KRun>
@@ -118,7 +121,7 @@ OcsPersonItem::launchUrl( QAction *action ) //SLOT
 }
 
 void
-OcsPersonItem::switchToOcs()
+OcsPersonItem::switchToOcs( const Attica::Provider &provider )
 {
     if( m_state == Online )
         return;
@@ -132,7 +135,8 @@ OcsPersonItem::switchToOcs()
         Attica::PersonJob *personJob;
         if( m_ocsUsername == QString( "%%category%%" ) )   //TODO: handle grouping
             return;
-        personJob = Attica::OcsApi::requestPerson( m_ocsUsername );
+
+        personJob = provider.requestPerson( m_ocsUsername );
         connect( personJob, SIGNAL( result( KJob * ) ), this, SLOT( onJobFinished( \
KJob * ) ) );  emit ocsFetchStarted();
         m_state = Online;
@@ -153,11 +157,13 @@ OcsPersonItem::onJobFinished( KJob *job )
 void
 OcsPersonItem::fillOcsData( const Attica::Person &ocsPerson )
 {
-    m_avatar->setFixedSize( 56, 56 );
-    m_avatar->setFrameShape( QFrame::StyledPanel ); //this is a FramedLabel, \
                otherwise oxygen wouldn't paint the frame
-    m_avatar->setPixmap( ocsPerson.avatar() );
-    m_avatar->setAlignment( Qt::AlignCenter );
-
+    if( !( ocsPerson.avatar().isNull() ) )
+    {
+        m_avatar->setFixedSize( 56, 56 );
+        m_avatar->setFrameShape( QFrame::StyledPanel ); //this is a FramedLabel, \
otherwise oxygen wouldn't paint the frame +        m_avatar->setPixmap( \
ocsPerson.avatar() ); +        m_avatar->setAlignment( Qt::AlignCenter );
+    }
     if( !( ocsPerson.city().isEmpty() && ocsPerson.country().isEmpty() ) )
         m_aboutText.append( "<br/>" + ( ocsPerson.city().isEmpty() ? "" : ( \
ocsPerson.city() + ", " ) ) + ocsPerson.country() );  
diff --git a/src/aboutdialog/OcsPersonItem.h b/src/aboutdialog/OcsPersonItem.h
index 3373d56..d87cbad 100644
--- a/src/aboutdialog/OcsPersonItem.h
+++ b/src/aboutdialog/OcsPersonItem.h
@@ -19,7 +19,8 @@
 
 #include "ui_OcsPersonItem.h"
 
-#include "libattica-ocsclient/ocsapi.h"
+#include "libattica-ocsclient/person.h"
+#include "libattica-ocsclient/provider.h"
 #include "OcsData.h"
 
 #include <KAboutPerson>
@@ -49,7 +50,7 @@ public:
 
     QString name();
 
-    void switchToOcs();
+    void switchToOcs( const Attica::Provider &provider );
 
 signals:
     void ocsFetchStarted();
diff --git a/src/aboutdialog/OcsPersonListWidget.cpp \
b/src/aboutdialog/OcsPersonListWidget.cpp index c6deb12..8a7d87e 100644
--- a/src/aboutdialog/OcsPersonListWidget.cpp
+++ b/src/aboutdialog/OcsPersonListWidget.cpp
@@ -21,7 +21,10 @@
 #include <QScrollArea>
 
 
-OcsPersonListWidget::OcsPersonListWidget( const QList< KAboutPerson > &persons, \
const OcsData::OcsPersonList *ocsPersons, OcsPersonItem::PersonStatus status, QWidget \
*parent ) +OcsPersonListWidget::OcsPersonListWidget( const QList< KAboutPerson > \
&persons, +                                          const OcsData::OcsPersonList \
*ocsPersons, +                                          OcsPersonItem::PersonStatus \
status, +                                          QWidget *parent )
     : QWidget( parent )
     , m_status( status )
     , m_fetchCount( 0 )
@@ -55,12 +58,12 @@ OcsPersonListWidget::OcsPersonListWidget( const QList< \
KAboutPerson > &persons,  }
 
 void
-OcsPersonListWidget::switchToOcs()
+OcsPersonListWidget::switchToOcs( const Attica::Provider &provider )
 {
     for( int i = 0; i < m_areaLayout->count(); ++i )
     {
         OcsPersonItem *item = qobject_cast< OcsPersonItem * >( m_areaLayout->itemAt( \
                i )->widget() );
-        item->switchToOcs();
+        item->switchToOcs( provider );
     }
 }
 
diff --git a/src/aboutdialog/OcsPersonListWidget.h \
b/src/aboutdialog/OcsPersonListWidget.h index e376405..8651880 100644
--- a/src/aboutdialog/OcsPersonListWidget.h
+++ b/src/aboutdialog/OcsPersonListWidget.h
@@ -19,17 +19,20 @@
 
 #include "OcsPersonItem.h"
 #include "OcsData.h"
+#include "libattica-ocsclient/provider.h"
 
 class OcsPersonListWidget : public QWidget
 {
     Q_OBJECT
 
 public:
-    OcsPersonListWidget( const QList< KAboutPerson > &persons, const \
                OcsData::OcsPersonList *ocsPersons,
-                         OcsPersonItem::PersonStatus status = OcsPersonItem::Author, \
QWidget *parent = 0 ); +    OcsPersonListWidget( const QList< KAboutPerson > \
&persons, +                         const OcsData::OcsPersonList *ocsPersons,
+                         OcsPersonItem::PersonStatus status = OcsPersonItem::Author,
+                         QWidget *parent = 0 );
 
 public slots:
-    void switchToOcs();
+    void switchToOcs( const Attica::Provider &provider );
     void onOcsFetchStarted();
     void onOcsDataFetched( int err );
 
diff --git a/src/aboutdialog/libattica-ocsclient/CMakeLists.txt \
b/src/aboutdialog/libattica-ocsclient/CMakeLists.txt index 4f275bd..aadfb1a 100644
--- a/src/aboutdialog/libattica-ocsclient/CMakeLists.txt
+++ b/src/aboutdialog/libattica-ocsclient/CMakeLists.txt
@@ -1,4 +1,9 @@
 set(ocsclient_SRCS
+   providerinitjob.cpp
+   eventjob.cpp
+   eventlistjob.cpp
+   eventparser.cpp
+   event.cpp
    activity.cpp
    activityparser.cpp
    activitylistjob.cpp
@@ -6,7 +11,7 @@ set(ocsclient_SRCS
    personparser.cpp
    personjob.cpp
    personlistjob.cpp
-   ocsapi.cpp
+   provider.cpp
    postjob.cpp
    folder.cpp
    folderlistjob.cpp
diff --git a/src/aboutdialog/libattica-ocsclient/activity.cpp \
b/src/aboutdialog/libattica-ocsclient/activity.cpp index a31bf4d..fe94840 100644
--- a/src/aboutdialog/libattica-ocsclient/activity.cpp
+++ b/src/aboutdialog/libattica-ocsclient/activity.cpp
@@ -21,60 +21,86 @@
 
 #include "activity.h"
 
-#include "activitylistjob.h"
+#include <QDateTime>
+
 
 using namespace Attica;
 
-Activity::Activity()
+class Activity::Private : public QSharedData {
+    public:
+        QString m_id;
+        QString m_user;
+        QDateTime m_timestamp;
+        QString m_message;
+        QString m_link;
+};
+
+Activity::Activity() : d(new Private)
+{
+}
+
+Activity::Activity(const Attica::Activity& other)
+    : d(other.d)
+{
+}
+
+Activity& Activity::operator=(const Attica::Activity & other)
+{
+    d = other.d;
+    return *this;
+}
+
+Activity::~Activity()
 {
 }
 
+
 void Activity::setId( const QString &id )
 {
-    m_id = id;
+    d->m_id = id;
 }
 
 QString Activity::id() const
 {
-    return m_id;
+    return d->m_id;
 }
 
 void Activity::setUser( const QString &u )
 {
-  m_user = u;
+  d->m_user = u;
 }
 
 QString Activity::user() const
 {
-  return m_user;
+  return d->m_user;
 }
 
-void Activity::setTimestamp( const QDateTime &d )
+void Activity::setTimestamp( const QDateTime &date )
 {
-  m_timestamp = d;
+  d->m_timestamp = date;
 }
 
 QDateTime Activity::timestamp() const
 {
-  return m_timestamp;
+  return d->m_timestamp;
 }
 
 void Activity::setMessage( const QString &c )
 {
-  m_message = c;
+  d->m_message = c;
 }
 
 QString Activity::message() const
 {
-  return m_message;
+  return d->m_message;
 }
 
 void Activity::setLink( const QString &v )
 {
-  m_link = v;
+  d->m_link = v;
 }
 
 QString Activity::link() const
 {
-  return m_link;
+  return d->m_link;
 }
diff --git a/src/aboutdialog/libattica-ocsclient/activity.h \
b/src/aboutdialog/libattica-ocsclient/activity.h index fcd94a7..1961f86 100644
--- a/src/aboutdialog/libattica-ocsclient/activity.h
+++ b/src/aboutdialog/libattica-ocsclient/activity.h
@@ -21,11 +21,13 @@
 #ifndef ATTICA_ACTIVITY_H
 #define ATTICA_ACTIVITY_H
 
+#include <QtCore/QList>
+#include <QtCore/QSharedDataPointer>
+
 #include "atticaclient_export.h"
 
-#include <kurl.h>
 
-#include <QtCore>
+class QDateTime;
 
 namespace Attica {
 
@@ -36,6 +38,9 @@ class ATTICA_EXPORT Activity
     typedef QList<Activity> List;
 
     Activity();
+    Activity(const Activity& other);
+    Activity& operator=(const Activity& other);
+    ~Activity();
 
     void setId( const QString & );
     QString id() const;
@@ -53,11 +58,8 @@ class ATTICA_EXPORT Activity
     QString link() const;
 
   private:
-    QString m_id;
-    QString m_user;
-    QDateTime m_timestamp;
-    QString m_message;
-    QString m_link;
+    class Private;
+    QSharedDataPointer<Private> d;
 };
 
 }
diff --git a/src/aboutdialog/libattica-ocsclient/activitylistjob.cpp \
b/src/aboutdialog/libattica-ocsclient/activitylistjob.cpp index 445059a..15a622a \
                100644
--- a/src/aboutdialog/libattica-ocsclient/activitylistjob.cpp
+++ b/src/aboutdialog/libattica-ocsclient/activitylistjob.cpp
@@ -23,6 +23,9 @@
 
 #include "activityparser.h"
 
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
 #include <kio/job.h>
 #include <klocale.h>
 
@@ -70,7 +73,7 @@ void ActivityListJob::slotJobResult( KJob *job )
   
     emitResult();
   } else {
-    qDebug() << m_data;
+    // qDebug() << m_data;
     m_activityList = ActivityParser().parseList(
       QString::fromUtf8( m_data.data() ) );
 
diff --git a/src/aboutdialog/libattica-ocsclient/activitylistjob.h \
b/src/aboutdialog/libattica-ocsclient/activitylistjob.h index a12664b..bbe5030 100644
--- a/src/aboutdialog/libattica-ocsclient/activitylistjob.h
+++ b/src/aboutdialog/libattica-ocsclient/activitylistjob.h
@@ -21,9 +21,11 @@
 #ifndef ATTICA_ACTIVITYLISTJOB_H
 #define ATTICA_ACTIVITYLISTJOB_H
 
+#include <KJob>
+#include <KUrl>
+
 #include "activity.h"
 
-#include <kjob.h>
 
 namespace KIO {
 class Job;
diff --git a/src/aboutdialog/libattica-ocsclient/activityparser.cpp \
b/src/aboutdialog/libattica-ocsclient/activityparser.cpp index 945882a..7fd7aac \
                100644
--- a/src/aboutdialog/libattica-ocsclient/activityparser.cpp
+++ b/src/aboutdialog/libattica-ocsclient/activityparser.cpp
@@ -21,8 +21,11 @@
 
 #include "activityparser.h"
 
+#include <QtCore/QDateTime>
+#include <QRegExp>
 #include <QXmlStreamReader>
 
+
 using namespace Attica;
 
 ActivityParser::ActivityParser()
diff --git a/src/aboutdialog/libattica-ocsclient/category.cpp \
b/src/aboutdialog/libattica-ocsclient/category.cpp index 5ca182d..4a9c930 100644
--- a/src/aboutdialog/libattica-ocsclient/category.cpp
+++ b/src/aboutdialog/libattica-ocsclient/category.cpp
@@ -21,28 +21,54 @@
 
 #include "category.h"
 
+#include <QtCore/QString>
+
+
 using namespace Attica;
 
-Category::Category()
+class Category::Private : public QSharedData {
+    public:
+        QString m_id;
+        QString m_name;
+};
+
+
+Category::Category() : d(new Private)
+{
+}
+
+Category::Category(const Attica::Category& other)
+    : d(other.d)
 {
 }
 
+Category& Category::operator=(const Attica::Category & other)
+{
+    d = other.d;
+    return *this;
+}
+
+Category::~Category()
+{
+}
+
+
 void Category::setId( const QString &u )
 {
-  m_id = u;
+  d->m_id = u;
 }
 
 QString Category::id() const
 {
-  return m_id;
+  return d->m_id;
 }
 
-void Category::setName( const QString &d )
+void Category::setName( const QString &name )
 {
-  m_name = d;
+  d->m_name = name;
 }
 
 QString Category::name() const
 {
-  return m_name;
+  return d->m_name;
 }
diff --git a/src/aboutdialog/libattica-ocsclient/category.h \
b/src/aboutdialog/libattica-ocsclient/category.h index 9a953a7..36f4427 100644
--- a/src/aboutdialog/libattica-ocsclient/category.h
+++ b/src/aboutdialog/libattica-ocsclient/category.h
@@ -21,9 +21,11 @@
 #ifndef ATTICA_CATEGORY_H
 #define ATTICA_CATEGORY_H
 
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QList>
+
 #include "atticaclient_export.h"
 
-#include <QtCore>
 
 namespace Attica {
 
@@ -34,6 +36,9 @@ class ATTICA_EXPORT Category
     typedef QList<Category> List;
   
     Category();
+    Category(const Category& other);
+    Category& operator=(const Category& other);
+    ~Category();
 
     void setId( const QString & );
     QString id() const;
@@ -42,8 +47,8 @@ class ATTICA_EXPORT Category
     QString name() const;
 
   private:
-    QString m_id;  
-    QString m_name;
+    class Private;
+    QSharedDataPointer<Private> d;
 };
 
 }
diff --git a/src/aboutdialog/libattica-ocsclient/categorylistjob.cpp \
b/src/aboutdialog/libattica-ocsclient/categorylistjob.cpp index 84e34aa..6d9312f \
                100644
--- a/src/aboutdialog/libattica-ocsclient/categorylistjob.cpp
+++ b/src/aboutdialog/libattica-ocsclient/categorylistjob.cpp
@@ -23,6 +23,9 @@
 
 #include "categoryparser.h"
 
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
 #include <kio/job.h>
 #include <klocale.h>
 
diff --git a/src/aboutdialog/libattica-ocsclient/content.cpp \
b/src/aboutdialog/libattica-ocsclient/content.cpp index 9effdd4..1fc0b18 100644
--- a/src/aboutdialog/libattica-ocsclient/content.cpp
+++ b/src/aboutdialog/libattica-ocsclient/content.cpp
@@ -21,84 +21,122 @@
 
 #include "content.h"
 
+#include <QtCore/QDateTime>
+
+
 using namespace Attica;
 
+class Content::Private : public QSharedData {
+    public:
+        QDateTime m_created;
+        int m_downloads;
+        QString m_id;  
+        QString m_name;
+        int m_rating;
+        QDateTime m_updated;
+
+        QMap<QString,QString> m_extendedAttributes;
+
+        Private()
+            : m_downloads(0),
+              m_rating(0)
+        {
+        }
+};
+
+
 Content::Content()
-  : m_rating( 0 ), m_downloads( 0 )
+  : d(new Private)
+{
+}
+
+Content::Content(const Attica::Content& other)
+    : d(other.d)
+{
+}
+
+Content& Content::operator=(const Attica::Content & other)
 {
+    d = other.d;
+    return *this;
 }
 
+Content::~Content()
+{
+}
+
+
 void Content::setId( const QString &u )
 {
-  m_id = u;
+  d->m_id = u;
 }
 
 QString Content::id() const
 {
-  return m_id;
+  return d->m_id;
 }
 
 void Content::setName( const QString &name )
 {
-  m_name = name;
+  d->m_name = name;
 }
 
 QString Content::name() const
 {
-  return m_name;
+  return d->m_name;
 }
   
 void Content::setRating( int v )
 {
-  m_rating = v;
+  d->m_rating = v;
 }
 
 int Content::rating() const
 {
-  return m_rating;
+  return d->m_rating;
 }
     
 void Content::setDownloads( int v )
 {
-  m_downloads = v;
+  d->m_downloads = v;
 }
 
 int Content::downloads() const
 {
-  return m_downloads;
+  return d->m_downloads;
 }
     
-void Content::setCreated( const QDateTime &d )
+void Content::setCreated( const QDateTime &date )
 {
-  m_created = d;
+  d->m_created = date;
 }
 
 QDateTime Content::created() const
 {
-  return m_created;
+  return d->m_created;
 }
 
-void Content::setUpdated( const QDateTime &d )
+void Content::setUpdated( const QDateTime &date )
 {
-  m_updated = d;
+  d->m_updated = date;
 }
 
 QDateTime Content::updated() const
 {
-  return m_updated;
+  return d->m_updated;
 }
 
 void Content::addExtendedAttribute( const QString &key, const QString &value )
 {
-  m_extendedAttributes.insert( key, value );
+  d->m_extendedAttributes.insert( key, value );
 }
 
 QString Content::extendedAttribute( const QString &key ) const
 {
-  return m_extendedAttributes.value( key );
+  return d->m_extendedAttributes.value( key );
 }
 
 QMap<QString,QString> Content::extendedAttributes() const
 {
-  return m_extendedAttributes;
+  return d->m_extendedAttributes;
 }
diff --git a/src/aboutdialog/libattica-ocsclient/content.h \
b/src/aboutdialog/libattica-ocsclient/content.h index 6c22543..f0b5173 100644
--- a/src/aboutdialog/libattica-ocsclient/content.h
+++ b/src/aboutdialog/libattica-ocsclient/content.h
@@ -21,9 +21,14 @@
 #ifndef ATTICA_CONTENT_H
 #define ATTICA_CONTENT_H
 
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QSharedDataPointer>
+
 #include "atticaclient_export.h"
 
-#include <QtCore>
+
+class QDateTime;
 
 namespace Attica {
 
@@ -33,6 +38,9 @@ class ATTICA_EXPORT Content
     typedef QList<Content> List;
   
     Content();
+    Content(const Content& other);
+    Content& operator=(const Content& other);
+    ~Content();
 
     void setId( const QString & );
     QString id() const;
@@ -58,14 +66,8 @@ class ATTICA_EXPORT Content
     QMap<QString,QString> extendedAttributes() const;
 
   private:
-    QString m_id;  
-    QString m_name;
-    int m_rating;
-    int m_downloads;
-    QDateTime m_created;
-    QDateTime m_updated;
-
-    QMap<QString,QString> m_extendedAttributes;
+    class Private;
+    QSharedDataPointer<Private> d;
 };
 
 }
diff --git a/src/aboutdialog/libattica-ocsclient/contentjob.cpp \
b/src/aboutdialog/libattica-ocsclient/contentjob.cpp index 8ee8459..96002cd 100644
--- a/src/aboutdialog/libattica-ocsclient/contentjob.cpp
+++ b/src/aboutdialog/libattica-ocsclient/contentjob.cpp
@@ -23,6 +23,9 @@
 
 #include "contentparser.h"
 
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
 #include <kio/job.h>
 #include <klocale.h>
 
diff --git a/src/aboutdialog/libattica-ocsclient/contentlistjob.cpp \
b/src/aboutdialog/libattica-ocsclient/contentlistjob.cpp index 24fcb32..3fad954 \
                100644
--- a/src/aboutdialog/libattica-ocsclient/contentlistjob.cpp
+++ b/src/aboutdialog/libattica-ocsclient/contentlistjob.cpp
@@ -23,6 +23,9 @@
 
 #include "contentparser.h"
 
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
 #include <kio/job.h>
 #include <klocale.h>
 
diff --git a/src/aboutdialog/libattica-ocsclient/contentparser.cpp \
b/src/aboutdialog/libattica-ocsclient/contentparser.cpp index ce45feb..18237d1 100644
--- a/src/aboutdialog/libattica-ocsclient/contentparser.cpp
+++ b/src/aboutdialog/libattica-ocsclient/contentparser.cpp
@@ -21,6 +21,7 @@
 
 #include "contentparser.h"
 
+#include <QtCore/QDateTime>
 #include <QXmlStreamReader>
 
 using namespace Attica;
diff --git a/src/aboutdialog/libattica-ocsclient/event.cpp \
b/src/aboutdialog/libattica-ocsclient/event.cpp new file mode 100644
index 0000000..8a79c47
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/event.cpp
@@ -0,0 +1,168 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#include "event.h"
+
+
+using namespace Attica;
+
+
+Event::Event()
+    : m_latitude(0), m_longitude(0)
+{
+}
+
+
+void Event::setId(const QString& id)
+{
+    m_id = id;
+}
+
+QString Event::id() const
+{
+    return m_id;
+}
+
+
+void Event::setName(const QString& name)
+{
+    m_name = name;
+}
+
+QString Event::name() const
+{
+    return m_name;
+}
+
+
+void Event::setDescription(const QString& text)
+{
+    m_description = text;
+}
+
+QString Event::description() const
+{
+    return m_description;
+}
+
+
+void Event::setUser(const QString& id)
+{
+    m_user = id;
+}
+
+QString Event::user() const
+{
+    return m_user;
+}
+
+
+void Event::setStartDate(const QDate& date)
+{
+    m_startDate = date;
+}
+
+QDate Event::startDate() const
+{
+    return m_startDate;
+}
+
+
+void Event::setEndDate(const QDate& date)
+{
+    m_endDate = date;
+}
+
+QDate Event::endDate() const
+{
+    return m_endDate;
+}
+
+
+void Event::setLatitude(qreal lat)
+{
+    m_latitude = lat;
+}
+
+qreal Event::latitude() const
+{
+    return m_latitude;
+}
+
+
+void Event::setLongitude(qreal lon)
+{
+    m_longitude = lon;
+}
+
+qreal Event::longitude() const
+{
+    return m_longitude;
+}
+
+
+void Event::setHomepage(const QString& url)
+{
+    m_homepage = url;
+}
+
+QString Event::homepage() const
+{
+    return m_homepage;
+}
+
+
+void Event::setCountry(const QString& country)
+{
+    m_country = country;
+}
+
+QString Event::country() const
+{
+    return m_country;
+}
+
+
+void Event::setCity(const QString& city)
+{
+    m_city = city;
+}
+
+QString Event::city() const
+{
+    return m_city;
+}
+
+
+void Event::addExtendedAttribute(const QString& key, const QString& value)
+{
+    m_extendedAttributes.insert(key, value);
+}
+
+QString Event::extendedAttribute(const QString& key) const
+{
+    return m_extendedAttributes.value(key);
+}
+
+QMap<QString, QString> Event::extendedAttributes() const
+{
+    return m_extendedAttributes;
+}
diff --git a/src/aboutdialog/libattica-ocsclient/event.h \
b/src/aboutdialog/libattica-ocsclient/event.h new file mode 100644
index 0000000..4c32b19
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/event.h
@@ -0,0 +1,96 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#ifndef ATTICA_EVENT_H
+#define ATTICA_EVENT_H
+
+#include "atticaclient_export.h"
+
+#include <QtCore/QDate>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+
+
+namespace Attica {
+
+class ATTICA_EXPORT Event
+{
+    public:
+        typedef QList<Event> List;
+
+        Event();
+
+        void setId(const QString& id);
+        QString id() const;
+
+        void setName(const QString& name);
+        QString name() const;
+
+        void setDescription(const QString& text);
+        QString description() const;
+
+        void setUser(const QString& id);
+        QString user() const;
+
+        void setStartDate(const QDate& date);
+        QDate startDate() const;
+
+        void setEndDate(const QDate& date);
+        QDate endDate() const;
+
+        void setLatitude(qreal lat);
+        qreal latitude() const;
+
+        void setLongitude(qreal lon);
+        qreal longitude() const;
+
+        void setHomepage(const QString& url);
+        QString homepage() const;
+
+        void setCountry(const QString& country);
+        QString country() const;
+
+        void setCity(const QString& city);
+        QString city() const;
+
+        void addExtendedAttribute(const QString& key, const QString& value);
+        QString extendedAttribute(const QString& key) const;
+        QMap<QString,QString> extendedAttributes() const;
+
+    private:
+        QString m_id;
+        QString m_name;
+        QString m_description;
+        QString m_user;
+        QDate m_startDate;
+        QDate m_endDate;
+        qreal m_latitude;
+        qreal m_longitude;
+        QString m_homepage;
+        QString m_country;
+        QString m_city;
+        QMap<QString, QString> m_extendedAttributes;
+};
+
+}
+
+
+#endif
diff --git a/src/aboutdialog/libattica-ocsclient/eventjob.cpp \
b/src/aboutdialog/libattica-ocsclient/eventjob.cpp new file mode 100644
index 0000000..6d9550a
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/eventjob.cpp
@@ -0,0 +1,92 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#include "eventjob.h"
+
+#include <QtCore/QTimer>
+
+#include <KIO/Job>
+
+#include "eventparser.h"
+
+
+using namespace Attica;
+
+
+EventJob::EventJob()
+    : m_job(0)
+{
+}
+
+
+void EventJob::setUrl(const KUrl& url)
+{
+    m_url = url;
+}
+
+
+void EventJob::start()
+{
+    QTimer::singleShot(0, this, SLOT(doWork()));
+}
+
+
+Event EventJob::event() const
+{
+    return m_event;
+}
+
+
+void EventJob::doWork()
+{
+    m_job = KIO::get(m_url, KIO::NoReload, KIO::HideProgressInfo);
+    connect(m_job, SIGNAL(result(KJob*)), SLOT(slotJobResult(KJob*)));
+    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+        SLOT(slotJobData(KIO::Job*, const QByteArray&)));
+}
+
+
+void EventJob::slotJobResult(KJob* job)
+{
+    m_job = 0;
+
+    if (job->error()) {
+        setError(job->error());
+        setErrorText(job->errorText());
+    
+        emitResult();
+    } else {
+        m_event = EventParser().parse(QString::fromUtf8(m_data.data()));
+
+        emitResult();
+    }
+}
+
+
+void EventJob::slotJobData(KIO::Job* job, const QByteArray& data)
+{
+    Q_UNUSED(job);
+
+    m_data.append(data);
+}
+
+
+#include "eventjob.moc"
diff --git a/src/aboutdialog/libattica-ocsclient/eventjob.h \
b/src/aboutdialog/libattica-ocsclient/eventjob.h new file mode 100644
index 0000000..efde7c1
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/eventjob.h
@@ -0,0 +1,69 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#ifndef ATTICA_EVENTJOB_H
+#define ATTICA_EVENTJOB_H
+
+#include <KJob>
+#include <KUrl>
+
+#include "atticaclient_export.h"
+#include "event.h"
+
+
+namespace KIO {
+    class Job;
+}
+
+namespace Attica {
+
+class ATTICA_EXPORT EventJob : public KJob
+{
+    Q_OBJECT
+
+    public:
+        EventJob();
+
+        void setUrl(const KUrl& url);
+
+        void start();
+
+        Event event() const;
+        using QObject::event; // Unhide QObject's event()
+        
+    protected slots:
+        void doWork();
+
+        void slotJobResult(KJob* job);
+        void slotJobData(KIO::Job* job, const QByteArray& data);
+        
+    private:
+        KUrl m_url;
+        KIO::Job* m_job;
+        QByteArray m_data;
+    
+        Event m_event;
+};
+
+}
+
+
+#endif
diff --git a/src/aboutdialog/libattica-ocsclient/eventlistjob.cpp \
b/src/aboutdialog/libattica-ocsclient/eventlistjob.cpp new file mode 100644
index 0000000..fd4d532
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/eventlistjob.cpp
@@ -0,0 +1,92 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#include "eventlistjob.h"
+
+#include <QtCore/QTimer>
+
+#include <KIO/Job>
+
+#include "eventparser.h"
+
+
+using namespace Attica;
+
+
+EventListJob::EventListJob()
+    : m_job(0)
+{
+}
+
+
+void EventListJob::setUrl(const KUrl& url)
+{
+    m_url = url;
+}
+
+
+void EventListJob::start()
+{
+    QTimer::singleShot(0, this, SLOT(doWork()));
+}
+
+
+Event::List EventListJob::eventList() const
+{
+    return m_eventList;
+}
+
+
+void EventListJob::doWork()
+{
+    m_job = KIO::get(m_url, KIO::NoReload, KIO::HideProgressInfo);
+    connect(m_job, SIGNAL(result(KJob*)), SLOT(slotJobResult(KJob*)));
+    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+        SLOT(slotJobData(KIO::Job*, const QByteArray&)));
+}
+
+
+void EventListJob::slotJobResult(KJob* job)
+{
+    m_job = 0;
+
+    if (job->error()) {
+        setError(job->error());
+        setErrorText(job->errorText());
+    
+        emitResult();
+    } else {
+        m_eventList = EventParser().parseList(QString::fromUtf8(m_data.data()));
+
+        emitResult();
+    }
+}
+
+
+void EventListJob::slotJobData(KIO::Job* job, const QByteArray& data)
+{
+    Q_UNUSED(job);
+
+    m_data.append(data);
+}
+
+
+#include "eventlistjob.moc"
diff --git a/src/aboutdialog/libattica-ocsclient/eventlistjob.h \
b/src/aboutdialog/libattica-ocsclient/eventlistjob.h new file mode 100644
index 0000000..a218b6d
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/eventlistjob.h
@@ -0,0 +1,68 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#ifndef ATTICA_EVENTLISTJOB_H
+#define ATTICA_EVENTLISTJOB_H
+
+#include <KJob>
+#include <KUrl>
+
+#include "atticaclient_export.h"
+#include "event.h"
+
+
+namespace KIO {
+    class Job;
+}
+
+namespace Attica {
+
+class ATTICA_EXPORT EventListJob : public KJob
+{
+    Q_OBJECT
+
+    public:
+        EventListJob();
+
+        void setUrl(const KUrl& url);
+
+        void start();
+
+        Event::List eventList() const;
+        
+    protected slots:
+        void doWork();
+
+        void slotJobResult(KJob* job);
+        void slotJobData(KIO::Job* job, const QByteArray& data);
+        
+    private:
+        KUrl m_url;
+        KIO::Job* m_job;
+        QByteArray m_data;
+    
+        Event::List m_eventList;
+};
+
+}
+
+
+#endif
diff --git a/src/aboutdialog/libattica-ocsclient/eventparser.cpp \
b/src/aboutdialog/libattica-ocsclient/eventparser.cpp new file mode 100644
index 0000000..fb5d929
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/eventparser.cpp
@@ -0,0 +1,112 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#include "eventparser.h"
+
+#include <QtCore/QRegExp>
+#include <QtXml/QXmlStreamReader>
+
+
+using namespace Attica;
+
+EventParser::EventParser()
+{
+}
+
+
+Event EventParser::parse(const QString& xmlString)
+{
+    Event event;
+
+    QXmlStreamReader xml(xmlString);
+
+    while (!xml.atEnd()) {
+        xml.readNext();
+        
+        if (xml.isStartElement() && xml.name() == "event") {
+            event = parseEvent(xml);
+        }
+    }
+    
+    return event;
+}
+
+
+Event::List Attica::EventParser::parseList(const QString& xmlString)
+{
+    Event::List eventList;
+    
+    QXmlStreamReader xml(xmlString);
+    
+    while (!xml.atEnd()) {
+        xml.readNext();
+        
+        if (xml.isStartElement() && xml.name() == "event") {
+            eventList.append(parseEvent(xml));
+        }
+    }
+    
+    return eventList;
+}
+
+
+Event EventParser::parseEvent(QXmlStreamReader& xml)
+{
+    Event event;
+
+    while (!xml.atEnd()) {
+        xml.readNext();
+
+        if (xml.isStartElement()) {
+            if (xml.name() == "id") {
+                event.setId(xml.readElementText());
+            } else if (xml.name() == "name") {
+                event.setName(xml.readElementText());
+            } else if (xml.name() == "description") {
+                event.setDescription(xml.readElementText());
+            } else if (xml.name() == "user") {
+                event.setUser(xml.readElementText());
+            } else if (xml.name() == "startdate") {
+                QString date = xml.readElementText().remove(QRegExp("\\+.*$"));
+                event.setStartDate(QDate::fromString(date, Qt::ISODate));
+            } else if (xml.name() == "enddate") {
+                QString date = xml.readElementText().remove(QRegExp("\\+.*$"));
+                event.setEndDate(QDate::fromString(date, Qt::ISODate));
+            } else if (xml.name() == "latitude") {
+                event.setLatitude(xml.readElementText().toFloat());
+            } else if (xml.name() == "longitude") {
+                event.setLongitude(xml.readElementText().toFloat());
+            } else if (xml.name() == "homepage") {
+                event.setHomepage(xml.readElementText());
+            } else if (xml.name() == "country") {
+                event.setCountry(xml.readElementText());
+            } else if (xml.name() == "city") {
+                event.setCity(xml.readElementText());
+            } else {
+                event.addExtendedAttribute(xml.name().toString(), \
xml.readElementText()); +            }
+        }
+        else if (xml.isEndElement() && xml.name() == "event") {
+            break;
+        }
+    }
+    return event;
+}
diff --git a/src/aboutdialog/libattica-ocsclient/eventparser.h \
b/src/aboutdialog/libattica-ocsclient/eventparser.h new file mode 100644
index 0000000..8f9a2be
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/eventparser.h
@@ -0,0 +1,47 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#ifndef ATTICA_EVENTPARSER_H
+#define ATTICA_EVENTPARSER_H
+
+#include "event.h"
+
+
+class QXmlStreamReader;
+
+namespace Attica {
+
+class EventParser
+{
+    public:
+        EventParser();
+
+        Event parse(const QString& xml);
+        Event::List parseList(const QString& xml);
+
+    private:
+        Event parseEvent(QXmlStreamReader& xml);
+};
+
+}
+
+
+#endif
diff --git a/src/aboutdialog/libattica-ocsclient/knowledgebaseparser.h \
b/src/aboutdialog/libattica-ocsclient/knowledgebaseparser.h index e791c32..667ddea \
                100644
--- a/src/aboutdialog/libattica-ocsclient/knowledgebaseparser.h
+++ b/src/aboutdialog/libattica-ocsclient/knowledgebaseparser.h
@@ -24,7 +24,7 @@
 
 #include "knowledgebase.h"
 
-#include <QXmlStreamReader>
+class QXmlStreamReader;
 
 namespace Attica {
 
diff --git a/src/aboutdialog/libattica-ocsclient/message.h \
b/src/aboutdialog/libattica-ocsclient/message.h index 03f02ba..b1742e7 100644
--- a/src/aboutdialog/libattica-ocsclient/message.h
+++ b/src/aboutdialog/libattica-ocsclient/message.h
@@ -21,9 +21,11 @@
 #ifndef ATTICA_MESSAGE_H
 #define ATTICA_MESSAGE_H
 
+#include <QtCore/QDateTime>
+#include <QtCore/QList>
+
 #include "atticaclient_export.h"
 
-#include <QtCore>
 
 namespace Attica {
 
diff --git a/src/aboutdialog/libattica-ocsclient/messagelistjob.cpp \
b/src/aboutdialog/libattica-ocsclient/messagelistjob.cpp index aa6bdaf..5b4c82d \
                100644
--- a/src/aboutdialog/libattica-ocsclient/messagelistjob.cpp
+++ b/src/aboutdialog/libattica-ocsclient/messagelistjob.cpp
@@ -23,6 +23,9 @@
 
 #include "messageparser.h"
 
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
 #include <kio/job.h>
 #include <klocale.h>
 
diff --git a/src/aboutdialog/libattica-ocsclient/ocsapi.cpp \
b/src/aboutdialog/libattica-ocsclient/ocsapi.cpp deleted file mode 100644
index 6de70ab..0000000
--- a/src/aboutdialog/libattica-ocsclient/ocsapi.cpp
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
-    This file is part of KDE.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-    USA.
-*/
-
-#include "ocsapi.h"
-
-#include <KDebug>
-
-using namespace Attica;
-
-OcsApi::OcsApi()
-{
-}
-
-PersonJob *OcsApi::requestPerson( const QString &id )
-{
-  KUrl url = createUrl( "person/data/" + id );
-  return doRequestPerson( url );
-}
-
-PersonJob *OcsApi::requestPersonSelf()
-{
-  KUrl url = createUrl( "person/self" );
-  return doRequestPerson( url );
-}
-
-PersonListJob *OcsApi::requestPersonSearchByName( const QString &name )
-{
-  KUrl url = createUrl( "person/data");
-  url.addQueryItem("name", name);
-  return doRequestPersonList( url );
-}
-
-PersonListJob *OcsApi::requestPersonSearchByLocation( qreal latitude, qreal \
                longitude, qreal distance, const int page, const int pageSize)
-{
-  KUrl url = createUrl( "person/data" );
-  url.addQueryItem("latitude", QString::number(latitude));
-  url.addQueryItem("longitude", QString::number(longitude));
-  url.addQueryItem("distance", QString::number(distance));
-  url.addQueryItem("page", QString::number(page));
-  url.addQueryItem("pagesize", QString::number(pageSize));
-  
-  qDebug() << "Location-based search:" << latitude << longitude << distance;
-  qDebug() << "URL:" << url;
-  return doRequestPersonList( url );
-}
-
-PersonListJob *OcsApi::requestFriend( const QString &id, const int page, const int \
                pageSize )
-{
-  KUrl url = createUrl( "friend/data/" + id );
-  url.addQueryItem("page", QString::number(page));
-  url.addQueryItem("pagesize", QString::number(pageSize));
-  kDebug() << "URL:" << url;
-  return doRequestPersonList( url );
-}
-
-ActivityListJob *OcsApi::requestActivity()
-{
-  KUrl url = createUrl( "activity" );
-  return doRequestActivityList( url );
-}
-
-PostJob *OcsApi::postActivity( const QString &message )
-{
-  PostJob *job = new PostJob();
-
-  KUrl url = createUrl( "activity" );
-  job->setUrl( url );
-  job->setData( "message", message );
-  
-  job->start();
-  return job;
-}
-
-PostJob *OcsApi::postInvitation( const QString &to, const QString &message )
-{
-  PostJob *job = new PostJob();
-
-  KUrl url = createUrl( "friend/outbox/" + to );
-  job->setUrl( url );
-  job->setData( "message", message );
-
-  job->start();
-  return job;  
-}
-
-PostJob *OcsApi::postLocation( qreal latitude, qreal longitude, const QString &city, \
                const QString &country )
-{
-  PostJob *job = new PostJob();
-  
-  KUrl url = createUrl( "person/self" );
-  
-  job->setUrl( url ); 
-
-  job->setData( "latitude", QString("%1").arg(latitude) );
-  job->setData( "longitude", QString("%1").arg(longitude) );
-  job->setData( "city", city );
-  job->setData( "country", country );
-  
-  job->start();
-  return job;
-}
-
-
-FolderListJob *OcsApi::requestFolders()
-{
-  return doRequestFolderList( createUrl( "message" ) );
-}
-
-MessageListJob *OcsApi::requestMessages( const QString &folderId )
-{
-  return doRequestMessageList( createUrl( "message/" + folderId ) );
-}
-
-PostJob *OcsApi::postMessage( const Message &message )
-{
-  PostJob *job = new PostJob();
-  
-  KUrl url = createUrl( "message/2" );
-  job->setUrl( url );
-  job->setData( "message", message.body() );
-  job->setData( "subject", message.subject() );
-  job->setData( "to", message.to() );
-  
-  job->start();
-  return job;
-}
-
-CategoryListJob *OcsApi::requestCategories()
-{
-  CategoryListJob *job = new CategoryListJob();
-  
-  KUrl url = createUrl( "content/categories" );
-  job->setUrl( url );
-  
-  job->start();
-  return job;
-}
-
-ContentListJob *OcsApi::requestContent( const Category::List &categories,
-  const QString &search, SortMode sortMode )
-{
-  ContentListJob *job = new ContentListJob();
-  
-  KUrl url = createUrl( "content/data" );
-
-  QStringList categoryIds;
-  foreach( const Category &category, categories ) {
-    categoryIds.append( category.id() );
-  }
-  url.addQueryItem( "categories", categoryIds.join( "x" ) );
-  
-  url.addQueryItem( "search", search );
-  QString sortModeString;
-  switch ( sortMode ) {
-    case Newest:
-      sortModeString = "new";
-      break;
-    case Alphabetical:
-      sortModeString = "alpha";
-      break;
-    case Rating:
-      sortModeString = "high";
-      break;
-    case Downloads:
-      sortModeString = "down";
-      break;
-  }
-  if ( !sortModeString.isEmpty() ) {
-    url.addQueryItem( "sortmode", sortModeString );
-  }
-
-  job->setUrl( url );
-  
-  job->start();
-  return job;
-}
-
-ContentJob *OcsApi::requestContent( const QString &id )
-{
-  ContentJob *job = new ContentJob();
-  
-  KUrl url = createUrl( "content/data/" + id );
-  job->setUrl( url );
-  
-  job->start();
-  return job;
-}
-
-KnowledgeBaseJob *OcsApi::requestKnowledgeBase( const QString &id )
-{
-  KnowledgeBaseJob *job = new KnowledgeBaseJob();
-
-  KUrl url = createUrl( "knowledgebase/data/" + id );
-  job->setUrl( url );
-
-  job->start();
-  return job;
-}
-
-KnowledgeBaseListJob *OcsApi::requestKnowledgeBase( const int content, const QString \
                &search, SortMode sortMode, const int page, const int pageSize )
-{
-  KnowledgeBaseListJob *job = new KnowledgeBaseListJob();
-
-  KUrl url = createUrl( "knowledgebase/data" );
-
-  if (content) {
-      url.addQueryItem("content", QString::number(content));
-  }
-
-  url.addQueryItem( "search", search );
-  QString sortModeString;
-  switch ( sortMode ) {
-    case Newest:
-      sortModeString = "new";
-      break;
-    case Alphabetical:
-      sortModeString = "alpha";
-      break;
-    case Rating:
-      sortModeString = "high";
-      break;
-    //FIXME: knowledge base doesn't have downloads
-    case Downloads:
-      sortModeString = "new";
-      break;
-  }
-  if ( !sortModeString.isEmpty() ) {
-    url.addQueryItem( "sortmode", sortModeString );
-  }
-
-  url.addQueryItem( "page", QString::number(page) );
-  url.addQueryItem( "pagesize", QString::number(pageSize) );
-
-  job->setUrl( url );
-
-  job->start();
-  return job;
-}
-
-KUrl OcsApi::createUrl( const QString &path )
-{
-  KUrl url( "https://api.opendesktop.org/v1/" );
-  url.addPath( path );
-  return url;
-}
-
-PersonJob *OcsApi::doRequestPerson( const KUrl &url )
-{
-  PersonJob *job = new PersonJob();
-
-  job->setUrl( url );
-
-  job->start();
-  return job;
-}
-
-PersonListJob *OcsApi::doRequestPersonList( const KUrl &url )
-{
-  PersonListJob *job = new PersonListJob();
-
-  job->setUrl( url );
-
-  job->start();
-  return job;
-}
-
-ActivityListJob *OcsApi::doRequestActivityList( const KUrl &url )
-{
-  ActivityListJob *job = new ActivityListJob();
-
-  job->setUrl( url );
-
-  job->start();
-  return job;
-}
-
-FolderListJob *OcsApi::doRequestFolderList( const KUrl &url )
-{
-  FolderListJob *job = new FolderListJob();
-  
-  job->setUrl( url );
-  job->start();
-  return job;
-}
-
-MessageListJob *OcsApi::doRequestMessageList( const KUrl &url )
-{
-  MessageListJob *job = new MessageListJob();
-  
-  job->setUrl( url );
-  job->start();
-  return job;
-}
diff --git a/src/aboutdialog/libattica-ocsclient/ocsapi.h \
b/src/aboutdialog/libattica-ocsclient/ocsapi.h deleted file mode 100644
index 61bab3c..0000000
--- a/src/aboutdialog/libattica-ocsclient/ocsapi.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-    This file is part of KDE.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-    USA.
-*/
-#ifndef ATTICA_OCSAPI_H
-#define ATTICA_OCSAPI_H
-
-#include "atticaclient_export.h"
-
-#include "personjob.h"
-#include "personlistjob.h"
-#include "activitylistjob.h"
-#include "postjob.h"
-#include "folderlistjob.h"
-#include "messagelistjob.h"
-#include "categorylistjob.h"
-#include "contentjob.h"
-#include "contentlistjob.h"
-#include "knowledgebasejob.h"
-#include "knowledgebaselistjob.h"
-
-namespace Attica {
-
-/**
-  Open Collaboration Services API.
-*/
-class ATTICA_EXPORT OcsApi
-{
-  public:
-    OcsApi();
-
-    static PersonJob *requestPerson( const QString &id );
-    static PersonJob *requestPersonSelf();
-    static PersonListJob *requestPersonSearchByName( const QString &name );
-    static PersonListJob *requestPersonSearchByLocation( qreal latitude, qreal \
                longitude, qreal distance, const int page = 0, const int pageSize = \
                100);
-
-    static PersonListJob *requestFriend( const QString &id, const int page = 0, \
                const int pageSize = 100 );
-
-    static ActivityListJob *requestActivity();
-    static PostJob *postActivity( const QString &message );
-
-    static PostJob *postInvitation( const QString &to, const QString &message );
-    static PostJob *postLocation( qreal latitude, qreal longitude, const QString \
                &city = QString(), const QString &country = QString());
-
-    static FolderListJob *requestFolders();
-    static MessageListJob *requestMessages( const QString &folderId );
-    static PostJob *postMessage( const Message &message );
-
-    enum SortMode { Newest, Alphabetical, Rating, Downloads };
-    static CategoryListJob *requestCategories();
-    static ContentListJob *requestContent( const Category::List &categories,
-      const QString &search, SortMode );
-    static ContentJob *requestContent( const QString &id );
-    static KnowledgeBaseJob *requestKnowledgeBase(const QString &id);
-    static KnowledgeBaseListJob *requestKnowledgeBase(const int content, const \
                QString &search, SortMode, const int page, const int pageSize);
-
-  protected:
-    static KUrl createUrl( const QString &path );
-  
-    static PersonJob *doRequestPerson( const KUrl & );
-    static PersonListJob *doRequestPersonList( const KUrl & );
-    static ActivityListJob *doRequestActivityList( const KUrl & );
-    static FolderListJob *doRequestFolderList( const KUrl &url );
-    static MessageListJob * doRequestMessageList( const KUrl &url );
-};
-
-}
-
-#endif
diff --git a/src/aboutdialog/libattica-ocsclient/person.h \
b/src/aboutdialog/libattica-ocsclient/person.h index b1b15cd..e14ce79 100644
--- a/src/aboutdialog/libattica-ocsclient/person.h
+++ b/src/aboutdialog/libattica-ocsclient/person.h
@@ -21,12 +21,14 @@
 #ifndef ATTICA_PERSON_H
 #define ATTICA_PERSON_H
 
-#include "atticaclient_export.h"
+#include <QtCore/QDate>
+#include <QtCore/QList>
+#include <QtGui/QPixmap>
+
+#include <KUrl>
 
-#include <kurl.h>
+#include "atticaclient_export.h"
 
-#include <QtCore>
-#include <QPixmap>
 
 namespace Attica {
 
diff --git a/src/aboutdialog/libattica-ocsclient/personjob.cpp \
b/src/aboutdialog/libattica-ocsclient/personjob.cpp index 6884688..2ccf89a 100644
--- a/src/aboutdialog/libattica-ocsclient/personjob.cpp
+++ b/src/aboutdialog/libattica-ocsclient/personjob.cpp
@@ -23,6 +23,9 @@
 
 #include "personparser.h"
 
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
 #include <kio/job.h>
 #include <klocale.h>
 
@@ -70,17 +73,21 @@ void PersonJob::slotUserJobResult( KJob *job )
   
     emitResult();
   } else {
-    qDebug() << m_userData;
+    // qDebug() << m_userData;
     m_person = PersonParser().parse( m_userData );
   
-    qDebug() << "Getting avatar from" << m_person.avatarUrl();
-  
-    m_job = KIO::get( m_person.avatarUrl(), KIO::NoReload,
-      KIO::HideProgressInfo );
-    connect( m_job, SIGNAL( result( KJob * ) ),
-      SLOT( slotAvatarJobResult( KJob * ) ) );
-    connect( m_job, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
-      SLOT( slotAvatarJobData( KIO::Job *, const QByteArray & ) ) );    
+    if (!m_person.avatarUrl().isEmpty()) {
+      qDebug() << "Getting avatar from" << m_person.avatarUrl();
+
+      m_job = KIO::get( m_person.avatarUrl(), KIO::NoReload,
+        KIO::HideProgressInfo );
+      connect( m_job, SIGNAL( result( KJob * ) ),
+        SLOT( slotAvatarJobResult( KJob * ) ) );
+      connect( m_job, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
+        SLOT( slotAvatarJobData( KIO::Job *, const QByteArray & ) ) );
+    } else {
+      emitResult();
+    }
   }
 }
 
@@ -97,10 +104,7 @@ void PersonJob::slotAvatarJobResult( KJob *job )
     qWarning() << "Error retrieving Avatar:" << job->errorText();
   } else {
     QPixmap pic;
-    if ( !pic.loadFromData( m_avatarData ) ) {
-      setError( UserDefinedError );
-      setErrorText( i18n("Unable to parse avatar image data.") );
-    } else {
+    if ( pic.loadFromData( m_avatarData ) ) {
       m_person.setAvatar( pic );
     }
   }
diff --git a/src/aboutdialog/libattica-ocsclient/personlistjob.cpp \
b/src/aboutdialog/libattica-ocsclient/personlistjob.cpp index 2b531db..c24a9ea 100644
--- a/src/aboutdialog/libattica-ocsclient/personlistjob.cpp
+++ b/src/aboutdialog/libattica-ocsclient/personlistjob.cpp
@@ -23,6 +23,9 @@
 
 #include "personparser.h"
 
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
 #include <kio/job.h>
 #include <klocale.h>
 
@@ -70,7 +73,7 @@ void PersonListJob::slotUserJobResult( KJob *job )
   
     emitResult();
   } else {
-    qDebug() << m_userData;
+    // qDebug() << m_userData;
     m_personList = PersonParser().parseList( m_userData );
 
 #if 0
diff --git a/src/aboutdialog/libattica-ocsclient/personparser.cpp \
b/src/aboutdialog/libattica-ocsclient/personparser.cpp index 66d7d3c..e0233fc 100644
--- a/src/aboutdialog/libattica-ocsclient/personparser.cpp
+++ b/src/aboutdialog/libattica-ocsclient/personparser.cpp
@@ -68,6 +68,7 @@ Person PersonParser::parse( const QString &xmlString )
 Person PersonParser::parsePerson( QXmlStreamReader &xml )
 {
   Person person;
+  bool hasAvatarPic = false;
   
   while ( !xml.atEnd() ) {
     xml.readNext();
@@ -83,6 +84,11 @@ Person PersonParser::parsePerson( QXmlStreamReader &xml )
         person.setHomepage( xml.readElementText() );
       } else if ( xml.name() == "avatarpic" ) {
         person.setAvatarUrl( xml.readElementText() );
+      } else if ( xml.name() == "avatarpicfound" ) {
+        QString value = xml.readElementText();
+        if (value.toInt()) {
+          hasAvatarPic = true;
+        }
       } else if ( xml.name() == "birthday" ) {
         person.setBirthday( QDate::fromString( xml.readElementText(),
           Qt::ISODate ) );
@@ -104,5 +110,9 @@ Person PersonParser::parsePerson( QXmlStreamReader &xml )
          ( xml.name() == "person" || xml.name() == "user" ) ) break;
   }
 
+  if (!hasAvatarPic) {
+    person.setAvatarUrl(QString());
+  }
+
   return person;
 }
diff --git a/src/aboutdialog/libattica-ocsclient/provider.cpp \
b/src/aboutdialog/libattica-ocsclient/provider.cpp new file mode 100644
index 0000000..a5e7d19
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/provider.cpp
@@ -0,0 +1,437 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2008 Cornelius Schumacher <schumacher@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#include "provider.h"
+
+#include <KDebug>
+#include <KUrl>
+
+#include "activitylistjob.h"
+#include "categorylistjob.h"
+#include "contentjob.h"
+#include "contentlistjob.h"
+#include "eventjob.h"
+#include "eventlistjob.h"
+#include "folderlistjob.h"
+#include "knowledgebasejob.h"
+#include "knowledgebaselistjob.h"
+#include "messagelistjob.h"
+#include "personjob.h"
+#include "personlistjob.h"
+#include "postjob.h"
+#include "providerinitjob.h"
+
+
+using namespace Attica;
+
+
+class Provider::Private : public QSharedData {
+  public:
+    KUrl m_baseUrl;
+    QString m_id;
+    QString m_name;
+    Private(const Private& other)
+      : QSharedData(other), m_baseUrl(other.m_baseUrl), m_id(other.m_id), \
m_name(other.m_name) +    {
+    }
+    Private(const QString& id, const KUrl& baseUrl, const QString name)
+      : m_baseUrl(baseUrl), m_id(id), m_name(name)
+    {
+    }
+};
+
+
+ProviderInitJob* Provider::byId(const QString& id)
+{
+  ProviderInitJob* job = new ProviderInitJob(id);
+  job->start();
+  return job;
+}
+
+
+Provider::Provider()
+  : d(new Private(QString(), KUrl(), QString()))
+{
+}
+
+Provider::Provider(const Provider& other)
+  : d(other.d)
+{
+}
+
+Provider::Provider(const QString& id, const KUrl& baseUrl, const QString& name)
+  : d(new Private(id, baseUrl, name))
+{
+}
+
+Provider& Provider::operator=(const Attica::Provider & other)
+{
+    d = other.d;
+    return *this;
+}
+
+Provider::~Provider()
+{
+}
+
+
+QString Provider::id() const
+{
+    return d->m_id;
+}
+
+
+QString Provider::name() const
+{
+    return d->m_name;
+}
+
+
+PersonJob* Provider::requestPerson(const QString& id) const
+{
+  KUrl url = createUrl( "person/data/" + id );
+  return doRequestPerson( url );
+}
+
+PersonJob* Provider::requestPersonSelf()
+{
+  KUrl url = createUrl( "person/self" );
+  return doRequestPerson( url );
+}
+
+PersonListJob* Provider::requestPersonSearchByName(const QString& name)
+{
+  KUrl url = createUrl( "person/data");
+  url.addQueryItem("name", name);
+  return doRequestPersonList( url );
+}
+
+PersonListJob* Provider::requestPersonSearchByLocation(qreal latitude, qreal \
longitude, qreal distance, int page, int pageSize) +{
+  KUrl url = createUrl( "person/data" );
+  url.addQueryItem("latitude", QString::number(latitude));
+  url.addQueryItem("longitude", QString::number(longitude));
+  url.addQueryItem("distance", QString::number(distance));
+  url.addQueryItem("page", QString::number(page));
+  url.addQueryItem("pagesize", QString::number(pageSize));
+  
+  qDebug() << "Location-based search:" << latitude << longitude << distance;
+  qDebug() << "URL:" << url;
+  return doRequestPersonList( url );
+}
+
+PersonListJob* Provider::requestFriend(const QString& id, int page, int pageSize)
+{
+  KUrl url = createUrl( "friend/data/" + id );
+  url.addQueryItem("page", QString::number(page));
+  url.addQueryItem("pagesize", QString::number(pageSize));
+  kDebug() << "URL:" << url;
+  return doRequestPersonList( url );
+}
+
+ActivityListJob* Provider::requestActivity()
+{
+  KUrl url = createUrl( "activity" );
+  return doRequestActivityList( url );
+}
+
+PostJob* Provider::postActivity(const QString& message)
+{
+  PostJob *job = new PostJob();
+
+  KUrl url = createUrl( "activity" );
+  job->setUrl( url );
+  job->setData( "message", message );
+  
+  job->start();
+  return job;
+}
+
+PostJob* Provider::postInvitation(const QString& to, const QString& message)
+{
+  PostJob *job = new PostJob();
+
+  KUrl url = createUrl( "friend/outbox/" + to );
+  job->setUrl( url );
+  job->setData( "message", message );
+
+  job->start();
+  return job;  
+}
+
+PostJob* Provider::postLocation(qreal latitude, qreal longitude, const QString& \
city, const QString& country) +{
+  PostJob *job = new PostJob();
+  
+  KUrl url = createUrl( "person/self" );
+  
+  job->setUrl( url ); 
+
+  job->setData( "latitude", QString("%1").arg(latitude) );
+  job->setData( "longitude", QString("%1").arg(longitude) );
+  job->setData( "city", city );
+  job->setData( "country", country );
+  
+  job->start();
+  return job;
+}
+
+
+FolderListJob* Provider::requestFolders()
+{
+  return doRequestFolderList( createUrl( "message" ) );
+}
+
+MessageListJob* Provider::requestMessages(const QString& folderId)
+{
+  return doRequestMessageList( createUrl( "message/" + folderId ) );
+}
+
+PostJob* Provider::postMessage( const Message &message )
+{
+  PostJob *job = new PostJob();
+  
+  KUrl url = createUrl( "message/2" );
+  job->setUrl( url );
+  job->setData( "message", message.body() );
+  job->setData( "subject", message.subject() );
+  job->setData( "to", message.to() );
+  
+  job->start();
+  return job;
+}
+
+CategoryListJob* Provider::requestCategories()
+{
+  CategoryListJob *job = new CategoryListJob();
+  
+  KUrl url = createUrl( "content/categories" );
+  job->setUrl( url );
+  
+  job->start();
+  return job;
+}
+
+ContentListJob* Provider::requestContent(const Category::List& categories, const \
QString& search, SortMode sortMode) +{
+  ContentListJob *job = new ContentListJob();
+  
+  KUrl url = createUrl( "content/data" );
+
+  QStringList categoryIds;
+  foreach( const Category &category, categories ) {
+    categoryIds.append( category.id() );
+  }
+  url.addQueryItem( "categories", categoryIds.join( "x" ) );
+  
+  url.addQueryItem( "search", search );
+  QString sortModeString;
+  switch ( sortMode ) {
+    case Newest:
+      sortModeString = "new";
+      break;
+    case Alphabetical:
+      sortModeString = "alpha";
+      break;
+    case Rating:
+      sortModeString = "high";
+      break;
+    case Downloads:
+      sortModeString = "down";
+      break;
+  }
+  if ( !sortModeString.isEmpty() ) {
+    url.addQueryItem( "sortmode", sortModeString );
+  }
+
+  job->setUrl( url );
+  
+  job->start();
+  return job;
+}
+
+ContentJob* Provider::requestContent(const QString& id)
+{
+  ContentJob *job = new ContentJob();
+  
+  KUrl url = createUrl( "content/data/" + id );
+  job->setUrl( url );
+  
+  job->start();
+  return job;
+}
+
+KnowledgeBaseJob* Provider::requestKnowledgeBase(const QString& id)
+{
+  KnowledgeBaseJob *job = new KnowledgeBaseJob();
+
+  KUrl url = createUrl( "knowledgebase/data/" + id );
+  job->setUrl( url );
+
+  job->start();
+  return job;
+}
+
+KnowledgeBaseListJob* Provider::requestKnowledgeBase(int content, const QString& \
search, Provider::SortMode sortMode, int page, int pageSize) +{
+  KnowledgeBaseListJob *job = new KnowledgeBaseListJob();
+
+  KUrl url = createUrl( "knowledgebase/data" );
+
+  if (content) {
+      url.addQueryItem("content", QString::number(content));
+  }
+
+  url.addQueryItem( "search", search );
+  QString sortModeString;
+  switch ( sortMode ) {
+    case Newest:
+      sortModeString = "new";
+      break;
+    case Alphabetical:
+      sortModeString = "alpha";
+      break;
+    case Rating:
+      sortModeString = "high";
+      break;
+    //FIXME: knowledge base doesn't have downloads
+    case Downloads:
+      sortModeString = "new";
+      break;
+  }
+  if ( !sortModeString.isEmpty() ) {
+    url.addQueryItem( "sortmode", sortModeString );
+  }
+
+  url.addQueryItem( "page", QString::number(page) );
+  url.addQueryItem( "pagesize", QString::number(pageSize) );
+
+  job->setUrl( url );
+
+  job->start();
+  return job;
+}
+
+EventJob* Provider::requestEvent(const QString& id)
+{
+  EventJob* job = new EventJob();
+
+  job->setUrl(createUrl("event/data/" + id));
+
+  job->start();
+  return job;
+}
+
+EventListJob* Provider::requestEvent(const QString& country, const QString& search, \
const QDate& startAt, Provider::SortMode mode, int page, int pageSize) +{
+  EventListJob* job = new EventListJob();
+
+  KUrl url = createUrl("event/data");
+
+  if (!search.isEmpty()) {
+      url.addQueryItem("search", search);
+  }
+
+  QString sortModeString;
+  switch (mode) {
+    case Newest:
+      sortModeString = "new";
+      break;
+    case Alphabetical:
+      sortModeString = "alpha";
+      break;
+    default:
+        break;
+  }
+  if (!sortModeString.isEmpty()) {
+    url.addQueryItem("sortmode", sortModeString);
+  }
+  
+  if (!country.isEmpty()) {
+    url.addQueryItem("country", country);
+  }
+  
+  url.addQueryItem("startat", startAt.toString(Qt::ISODate));
+
+  url.addQueryItem("page", QString::number(page));
+  url.addQueryItem("pagesize", QString::number(pageSize));
+
+  job->setUrl(url);
+
+  job->start();
+  return job;
+
+}
+
+KUrl Provider::createUrl(const QString& path) const
+{
+  KUrl url(d->m_baseUrl);
+  url.addPath( path );
+  return url;
+}
+
+PersonJob* Provider::doRequestPerson(const KUrl& url) const
+{
+  PersonJob *job = new PersonJob();
+
+  job->setUrl( url );
+
+  job->start();
+  return job;
+}
+
+PersonListJob* Provider::doRequestPersonList(const KUrl& url)
+{
+  PersonListJob *job = new PersonListJob();
+
+  job->setUrl( url );
+
+  job->start();
+  return job;
+}
+
+ActivityListJob* Provider::doRequestActivityList(const KUrl& url)
+{
+  ActivityListJob *job = new ActivityListJob();
+
+  job->setUrl( url );
+
+  job->start();
+  return job;
+}
+
+FolderListJob* Provider::doRequestFolderList(const KUrl& url)
+{
+  FolderListJob *job = new FolderListJob();
+  
+  job->setUrl( url );
+  job->start();
+  return job;
+}
+
+MessageListJob* Provider::doRequestMessageList(const KUrl& url)
+{
+  MessageListJob *job = new MessageListJob();
+  
+  job->setUrl( url );
+  job->start();
+  return job;
+}
diff --git a/src/aboutdialog/libattica-ocsclient/provider.h \
b/src/aboutdialog/libattica-ocsclient/provider.h new file mode 100644
index 0000000..197b08e
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/provider.h
@@ -0,0 +1,132 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2008 Cornelius Schumacher <schumacher@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#ifndef ATTICA_PROVIDER_H
+#define ATTICA_PROVIDER_H
+
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QString>
+
+#include "atticaclient_export.h"
+#include "category.h"
+
+class KUrl;
+class QDate;
+
+namespace Attica {
+
+class ActivityListJob;
+class CategoryListJob;
+class ContentJob;
+class ContentListJob;
+class EventJob;
+class EventListJob;
+class FolderListJob;
+class KnowledgeBaseJob;
+class KnowledgeBaseListJob;
+class Message;
+class MessageListJob;
+class PersonJob;
+class PersonListJob;
+class PostJob;
+class ProviderInitJob;
+
+/**
+  Open Collaboration Services API.
+*/
+class ATTICA_EXPORT Provider
+{
+  public:
+    Provider();
+    Provider(const Provider& other);
+    Provider(const QString& id, const KUrl& baseUrl, const QString& name);
+    Provider& operator=(const Provider& other);
+    ~Provider();
+    
+    QString name() const;
+    QString id() const;
+
+    enum SortMode {
+        Newest,
+        Alphabetical,
+        Rating,
+        Downloads
+    };
+
+    static ProviderInitJob* byId(const QString& id);
+
+    // Person part of OCS
+
+    PersonJob* requestPerson(const QString& id) const;
+    PersonJob* requestPersonSelf();
+    PersonListJob* requestPersonSearchByName(const QString& name);
+    PersonListJob* requestPersonSearchByLocation(qreal latitude, qreal longitude, \
qreal distance, int page = 0, int pageSize = 100); +    PostJob* postLocation(qreal \
latitude, qreal longitude, const QString& city = QString(), const QString& country = \
QString()); +
+    // Friend part of OCS
+
+    PersonListJob* requestFriend(const QString& id, int page = 0, int pageSize = \
100); +    PostJob* postInvitation(const QString& to, const QString& message);
+
+    // Message part of OCS
+
+    FolderListJob* requestFolders();
+    MessageListJob* requestMessages(const QString& folderId);
+    PostJob* postMessage(const Message& message);
+
+    // Activity part of OCS
+
+    ActivityListJob* requestActivity();
+    PostJob* postActivity(const QString& message);
+
+    // Content part of OCS
+
+    CategoryListJob* requestCategories();
+    ContentListJob* requestContent(const Category::List& categories, const QString& \
search, SortMode mode); +    ContentJob* requestContent(const QString& id);
+
+    // KnowledgeBase part of OCS
+
+    KnowledgeBaseJob* requestKnowledgeBase(const QString& id);
+    KnowledgeBaseListJob* requestKnowledgeBase(int content, const QString& search, \
SortMode, int page, int pageSize); +
+    // Event part of OCS
+
+    EventJob* requestEvent(const QString& id);
+    EventListJob* requestEvent(const QString& country, const QString& search, const \
QDate& startAt, SortMode mode, int page, int pageSize); +
+  protected:
+    KUrl createUrl(const QString& path) const;
+  
+    PersonJob* doRequestPerson(const KUrl& url) const;
+    PersonListJob* doRequestPersonList(const KUrl& url);
+    ActivityListJob* doRequestActivityList(const KUrl& url);
+    FolderListJob* doRequestFolderList(const KUrl& url);
+    MessageListJob* doRequestMessageList(const KUrl& url);
+
+  private:
+    class Private;
+    QExplicitlySharedDataPointer<Private> d;
+};
+
+}
+
+#endif
diff --git a/src/aboutdialog/libattica-ocsclient/providerinitjob.cpp \
b/src/aboutdialog/libattica-ocsclient/providerinitjob.cpp new file mode 100644
index 0000000..9e33fa2
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/providerinitjob.cpp
@@ -0,0 +1,38 @@
+#include "providerinitjob.h"
+
+#include <QTimer>
+
+#include <KUrl>
+
+
+using namespace Attica;
+
+
+ProviderInitJob::ProviderInitJob(const QString& id, QObject* parent)
+    : KJob(parent), m_id(id)
+{
+}
+
+
+void ProviderInitJob::start()
+{
+    QTimer::singleShot(0, this, SLOT(doWork()));
+}
+
+
+void ProviderInitJob::doWork()
+{
+    if (m_id == "opendesktop") {
+        m_provider = Provider(m_id, KUrl("https://api.opendesktop.org/v1/"), \
"OpenDesktop.org"); +    }
+    emitResult();
+}
+
+
+Provider ProviderInitJob::provider() const
+{
+    return m_provider;
+}
+
+
+#include "providerinitjob.moc"
diff --git a/src/aboutdialog/libattica-ocsclient/providerinitjob.h \
b/src/aboutdialog/libattica-ocsclient/providerinitjob.h new file mode 100644
index 0000000..a67a45f
--- /dev/null
+++ b/src/aboutdialog/libattica-ocsclient/providerinitjob.h
@@ -0,0 +1,54 @@
+/*
+    This file is part of KDE.
+
+    Copyright (c) 2009 Eckhart Wörner <ewoerner@kde.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+    USA.
+*/
+
+#ifndef PROVIDERINITJOB_H
+#define PROVIDERINITJOB_H
+
+#include <KJob>
+
+#include "atticaclient_export.h"
+#include "provider.h"
+
+namespace Attica {
+
+class ATTICA_EXPORT ProviderInitJob : public KJob
+{
+    Q_OBJECT
+
+    public:
+        ProviderInitJob(const QString& id, QObject* parent = 0);
+
+        void start();
+
+        Provider provider() const;
+
+    private slots:
+        void doWork();
+
+    private:
+        const QString m_id;
+        Provider m_provider;
+};
+
+}
+
+
+#endif


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic