📜 ⬆️ ⬇️

Application Development with Akonadi on KDE4

On Habré, it was already written about what Akonadi is and what it is eaten with , here I want to write about how to write applications that use it.

As an example, I will consider a simple console application that allows you to add tasks to the calendar. Why the console application? In order not to be distracted by aspects that are not directly related to Akonadi.

Requirements


I use Ubuntu 9.10 Karmic, it requires the following packages to work:

Respectively:
sudo aptitude install kdelibs5-dev kdepimlibs5-dev libboost-dev

Application framework


So, let's start creating such an application. Let's call it, for example, addtodo. To begin with, in the directory of the future application, create files for sources:
')
CMakeLists.txt , file for configuration and build:
PROJECT(add-todo)

find_package(KDE4 REQUIRED) # KDE4
find_package(KdepimLibs REQUIRED) # KDE PIM

include(KDE4Defaults)

add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDEPIMLIBS_INCLUDE_DIR} ${KDE4_INCLUDES})

set (CMAKE_CXX_FLAGS "-fexceptions" )

kde4_add_executable(add-todo add_todo.cpp) #

target_link_libraries(add-todo ${KDE4_PLASMA_LIBS} ${KDE4_KDEUI_LIBS} ${KDE4_AKONADI_LIBS} ${KDEPIMLIBS_KCAL_LIBS}) #


* This source code was highlighted with Source Code Highlighter .

add_todo_app.h , header file:
#ifndef ADD_TODO_H
#define ADD_TODO_H

#include <QCoreApplication>

#include <KJob>

class AddTodo : public QCoreApplication {
Q_OBJECT
public :
AddTodo( int argc, char ** argv );
public slots:
void collectionsFetched( KJob * job ); // ,
void todoCreated( KJob * job ); // ,
};

#endif // ADD_TODO_H


* This source code was highlighted with Source Code Highlighter .

add_todo_app.cpp , this will contain the main code:
#include "add_todo.h"

#include <QTextStream>

static QTextStream out ( stdout ); //

AddTodo::AddTodo( int argc, char ** argv ) : QCoreApplication( argc, argv ) {
out << "Application started" << endl;
}

void AddTodo::collectionsFetched( KJob * job ) {
}

void AddTodo::todoCreated( KJob * job ) {
}

int main( int argc, char ** argv ) {
AddTodo app( argc, argv ); //

return app.exec(); //
}

Now you can check that our application, which is still not doing anything, is correctly assembled:
mkdir build
cd build
cmake ..
make

If we start the application, it will write “Application started” and go into an infinite loop to wait for signals. Let, now we will add useful work.

Retrieving a list of collections via Akonadi



In order to create a task through Akonadi, you must first get a link to the collection ( Akonadi :: Collection ), in which we will create it. For this we will get all the collections and choose the one that supports the appropriate type of elements. Getting a collection in Akonadi is done by creating an Akonadi :: CollectionFetchJob task.

In the beginning add_todo.cpp we add inclusions, import the Akonadi namespace and declare one constant in which the MIME type for the task will be written. We need it in order to select the appropriate task.
#include <QStringList>

#include <Akonadi/Collection>
#include <Akonadi/CollectionFetchJob>

using namespace Akonadi;

static QString todoMimeType( "text/calendar" ); // MIME-


* This source code was highlighted with Source Code Highlighter .

Add to the application designer:
CollectionFetchJob *job = new CollectionFetchJob( Collection::root(), CollectionFetchJob::FirstLevel, this ); //

connect( job, SIGNAL(result(KJob*)), this , SLOT(collectionsFetched(KJob*)) ); //

In the first line, the arguments mean that we get subcollections of the root collection, and only the first level.

In the collectionsFetched method, add the processing and selection code for the collection we need:
out << "Collections fetched" << endl;

if ( job->error() ) {
out << "Error occurred: " << job->errorText() << endl;
exit( -1 );
return ;
}

const CollectionFetchJob * fetchJob = qobject_cast<CollectionFetchJob*>( job ); //

const Collection * selectedCollection = 0; //

foreach ( const Collection & collection, fetchJob->collections() ) {
out << "Name: " << collection.name(); //

if ( collection.contentMimeTypes().contains( todoMimeType ) ) { // ,
selectedCollection = &collection;
break ;
}
}

if ( !selectedCollection ) { // ,
out << "Error occurred: no valid collection found" << endl;
exit( -1 );
return ;
}

//


* This source code was highlighted with Source Code Highlighter .

Task creation



Now we have a collection to which we can finally add a task. For this, you need to do three things:

So let's get started. First, connect the header files:
#include <Akonadi/Item>
#include <Akonadi/ItemCreateJob>

#include <kcal/todo.h>

#include <boost/shared_ptr.hpp>

Now we will write the code for the first three items at the end of the collectionsFetched method:
KDateTime dueDate = KDateTime::fromString( arguments()[2], "%d.%m.%Y" ); //

if ( !dueDate.isValid() ) { // ,
out << "Error occured: invalid date '" << arguments()[2] << "'" << endl;
exit( -2 );
}

KCal::Todo::Ptr todo( new KCal::Todo() );
todo->setSummary( arguments()[1] ); //
todo->setDtDue( dueDate ); //
todo->setPercentComplete( 0 ); //
todo->setHasStartDate( false ); //
todo->setHasDueDate( true ); //

Item item( todoMimeType );
item.setPayload<KCal::Todo::Ptr>( todo );

ItemCreateJob * itemCreateJob = new ItemCreateJob( item, *selectedCollection, this ); //

connect( itemCreateJob, SIGNAL(result(KJob*)), this , SLOT(todoCreated(KJob*)) ); //


* This source code was highlighted with Source Code Highlighter .

And in the todoCreated method we add a check:
if ( job->error() ) {
out << "Error occurred: " << job->errorText() << endl;
exit( -1 );
return ;
}

out << "TODO created" << endl;
quit();


* This source code was highlighted with Source Code Highlighter .

Also, it's nice to add a check of the number of arguments to the beginning of main :
if ( argc < 3 ) { //
out << "Usage: add-todo [text] [date]" << endl;
return -2;
}


* This source code was highlighted with Source Code Highlighter .

Everything, now the program is complete, you can compile it and run as follows:

./add-todo "Something" 21.01.2010

After completing, a new task should appear in your calendar. Now you can improve something, for example, add the ability to recognize links to dates like “today”, “tomorrow”, support for time, categories and many interesting things ...

The full code can be viewed at the link .

The example code is based on a plugin for Plasma Runner, which I created a few days ago based on an idea from the KDE Brainstorm, which can be found here and here .

Source: https://habr.com/ru/post/81336/


All Articles