From KDE TechBase
    Revision as of 12:47, 31 May 2019 by Jucato (talk | contribs) (Mark for updating)
    (diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

    Attica Introduction
    Tutorial Series   Attica
    Previous   Getting started with KDE development
    What's Next   n/a
    Further Reading   n/a
    This page needs a review and probably holds information that needs to be fixed.

    Parts to be reviewed:

    Port to KF5


    In this tutorial you learn how to use Attica to access the Open Collaboration Services in your application.

    Our goal is to get a list of friends for any user registered on this site.

    With Attica you can easily access services from providers such as It implements the specification for the Open Collaboration Services API.

    The code for this tutorial is also available in the kdeexamples module in kde svn.


    Attica supports multiple Open Collaboration Service (OCS) providers at the same time. Therefor the first thing to do is getting a ProviderManager and either asking it for a default provider (e.g. for KDE) or setting a different provider by hand. Let's create a mainwindow class that loads the provider. Make sure you have the KDE Plugin for Attica built, otherwise will not be in the list of default providers.


    To make setting up the tutorial as easy as possible, here is a complete KDE application. We start with the mainwindow and add things into it.


    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    #include <KMainWindow>
    #include <KLineEdit>
    #include <QLabel>
    #include <attica/providermanager.h>
    #include <attica/provider.h>
    class MainWindow : public KMainWindow
        MainWindow(QWidget *parent=0);
    public Q_SLOTS:
        // Here we will get notified, when the provider is loaded
        void providersChanged();
        // ProviderManager is the class that lets us "create" providers
        Attica::ProviderManager m_manager;
        // A provider that we will ask for data from
        Attica::Provider m_provider;


    #include "mainwindow.h"
    #include <KDebug>
    #include <QVBoxLayout>
    #include <attica/providermanager.h>
    #include "simplepersonrequest.h"
    MainWindow::MainWindow(QWidget *parent) : KMainWindow(parent)
        // connect to get notified, when new Providers are loaded
        connect(&m_manager, SIGNAL(defaultProvidersLoaded()), SLOT(providersChanged()));
        // tell it to get the default Providers
    // called when a provider was loaded
    void MainWindow::providersChanged()
        if (!m_manager.providers().isEmpty()) {
            m_provider = m_manager.providerByUrl(QUrl(""));
            if (!m_provider.isValid()) {
                kDebug() << "Could not find provider.";
            // Use a tab widget here, so we can add more in the next tutorial
            QTabWidget* mainWidget = new QTabWidget(this);
            // Create a widget that will make use of the Provider
            // and supply information about a Person
            SimplePersonRequest* personWidget = new SimplePersonRequest(m_provider, this);
            mainWidget->addTab(personWidget, tr("Person Search"));
    #include "mainwindow.moc"

    Now we have a simple mainwindow with a tab widget. The real contents is still missing though. The first widget we'll add gives some information about a Person.

    Note also that in this case the provider file for the OCS server residing at "" is already loaded calling m_manager.loadDefaultProviders();. If you want to run your custom server you should first load your provider file and then select it using m_manager.providerByUrl() method. Here is a small example quoting only the code that changed:

    // [...]
        connect(&m_manager, SIGNAL(defaultProvidersLoaded()), SLOT(providersChanged()));
        // load your custom provider file to ProviderManager list
    void MainWindow::providersChanged()
        if (!m_manager.providers().isEmpty()) {
            // this will select and return your provider file using the url 
            m_provider = m_manager.providerByUrl(QUrl(""));
    // [...]


    Now that we have a Provider, we can ask it for information. As a first step, let's find out who I am. Entering any user nick into a KLineEdit will look up that Person. Here is a class that subclasses QWidget and simply contains two labels that show the real name and city for a Person. Since the Data has to be fetched from the server using a REST API, it is asynchronous. When the data arrived, we get notified by a signal.


    #include <QtGui/QLabel>
    #include <KLineEdit>
    #include <attica/provider.h>
    class SimplePersonRequest :public QWidget
        SimplePersonRequest(Attica::Provider provider, QWidget* parent = 0);
    public Q_SLOTS:
        // When the user entered a different nick name in the line edit and pressed enter.
        void nickChanged(const QString& nick);
        // The information has been loaded.
        void onPersonJobFinished( Attica::BaseJob *job );
        KLineEdit* mNickNameLineEdit;
        QLabel* mNameLabel;
        QLabel* mLocationLabel;
        QString mNick;
        Attica::Provider m_provider;


    Now to the actual implementation of our Widget that shows information about a person:

    #include "simplepersonrequest.h"
    #include <KDebug>
    #include <QtGui/QBoxLayout>
    #include <QtGui/QSpacerItem>
    #include <attica/person.h>
    #include <attica/itemjob.h>
    SimplePersonRequest::SimplePersonRequest(Attica::Provider provider, QWidget* parent)
        : QWidget(parent)
        , m_provider(provider)
        QVBoxLayout* layout = new QVBoxLayout(this);
        mNickNameLineEdit = new KLineEdit();
        mNameLabel = new QLabel(this);
        mLocationLabel = new QLabel(this);
        mNick = "fregl";
        // watch the LineEdit for changes
        connect(mNickNameLineEdit, SIGNAL(returnPressed(QString)), SLOT(nickChanged(QString)));
        // load the data
    // The user pressed enter, try to get information about the nick name
    void SimplePersonRequest::nickChanged(const QString& nick)
        mNick = nick;
        // ask the provider for a job that loads the person information:
        Attica::ItemJob<Attica::Person>* job = m_provider.requestPerson(mNick);
        // connect that job
        connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(onPersonJobFinished(Attica::BaseJob*)));
        // start the job
    // New information has arrived
    void SimplePersonRequest::onPersonJobFinished( Attica::BaseJob *job )
        kDebug() << "onJobFinished";
        // Get the information about the person: we need to turn the job into its proper sub class
        Attica::ItemJob<Attica::Person> *personJob = static_cast< Attica::ItemJob<Attica::Person> * >( job );
        // check if the request actually worked
        if( personJob->metadata().error() == Attica::Metadata::NoError ) {
            // use the data to fill the labels
            Attica::Person p(personJob->result());
            mNameLabel->setText(p.firstName() + ' ' + p.lastName());
        } else {
            mNameLabel->setText("Could not fetch information.");
    #include "simplepersonrequest.moc"

    Compiling the example

    The last thing missing is a small main.cpp and CMakeLists.txt to complete the example and make it compile:


    #include <KApplication>
    #include <KAboutData>
    #include <KCmdLineArgs>
    #include <KLocale>
    #include "mainwindow.h"
    int main (int argc, char *argv[])
        KAboutData aboutData( "opencollaborationexample", 0,
        ki18n("Open Collaboration Services Demo"), "1.0",
        ki18n("Show how to use libattica to access the Open Collaboration Services"),
        ki18n("Copyright (c) 2009 Frederik Gladhorn") );
        KCmdLineArgs::init( argc, argv, &aboutData );
        KApplication app;
        MainWindow* window = new MainWindow();
        return app.exec();


    project (opencollaborationexample)
    find_package(KDE4 REQUIRED)
    find_package(LibAttica REQUIRED)
    include_directories(${KDE4_INCLUDES}  ${ATTICA_INCLUDE_DIRS}
    kde4_add_executable(opencollaborationexample ${opencollaborationexample_SRCS})
    target_link_libraries(opencollaborationexample  ${LIBATTICA_LIBRARIES}
        ${KDE4_KIO_LIBS}  ${KDE4_KDEUI_LIBS})