Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Add templates for Akonadi resource and serializer plugins

Summary:
Overhauled versions of the templates from kapptemplate.

Keeping the template with the sources they are based on
helps both discovery and also maintenance.

Reviewers: mlaurent, dvratil

Reviewed By: mlaurent

Subscribers: #kde_pim

Tags: #kde_pim

Differential Revision: https://phabricator.kde.org/D8537
parent 4381eafb
......@@ -24,6 +24,7 @@ include(CheckIncludeFiles)
include(ECMQtDeclareLoggingCategory)
include(CheckSymbolExists)
include(ECMCoverageOption)
include(KDEPackageAppTemplates)
include(AkonadiMacros)
......@@ -257,6 +258,8 @@ include_directories(
add_subdirectory(src)
add_subdirectory(icons)
add_subdirectory(templates)
if(BUILD_TOOLS)
# add testrunner (application for managing a self-contained
# test environment)
......
#! /usr/bin/env bash
#This file outputs in a separate line each file with a .desktop syntax
#that needs to be translated but has a non .desktop extension
find -name \*.kdevtemplate -print
set(apptemplate_DIRS
akonadiresource
akonadiserializer
)
kde_package_app_templates(TEMPLATES ${apptemplate_DIRS} INSTALL_DIR ${KDE_INSTALL_KTEMPLATESDIR})
cmake_minimum_required(VERSION 3.1)
project(%{APPNAMELC})
set(ECM_MIN_VERSION "5.22.0")
find_package(ECM ${ECM_MIN_VERSION} CONFIG REQUIRED)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH})
include(FeatureSummary)
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
include(ECMQtDeclareLoggingCategory)
set(QT_MIN_VERSION "5.6.0")
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED Core DBus Gui)
set(KF5_MIN_VERSION "5.22.0")
find_package(KF5Config ${KF5_MIN_VERSION} CONFIG REQUIRED)
set(AKONADI_MIN_VERSION "5.2")
find_package(KF5Akonadi ${AKONADI_MIN_VERSION} CONFIG REQUIRED)
find_package(Xsltproc REQUIRED)
set_package_properties(Xsltproc PROPERTIES
DESCRIPTION "XSLT processor from libxslt"
TYPE REQUIRED
PURPOSE "Required to generate a D-Bus interface for the resource."
)
add_subdirectory(src)
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
How To Build This Template
-=-=-=-=-=-=-=-=-=-=-=-=-=
--- On Linux & similar:
cd <project_name_path>
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$MY_PREFIX -DCMAKE_BUILD_TYPE=Debug
make
make install or su -c 'make install'
(MY_PREFIX is where you install your Akonadi setup, replace it accordingly)
to uninstall the project:
make uninstall or su -c 'make uninstall'
Note: you can use another build path. Then cd in your build dir and:
export MY_SRC=path_to_your_src
cmake $MY_SRC -DCMAKE_INSTALL_PREFIX=$MY_PREFIX -DCMAKE_BUILD_TYPE=Debug
--- On Windows:
cd <project_name_path>
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=%MY_PREFIX% -DCMAKE_BUILD_TYPE=Debug
[n]make
[n]make install
(MY_PREFIX is where you install your Akonadi setup, replace it accordingly)
to uninstall the project:
[n]make uninstall
Note: use nmake if you're building with the Visual Studio compiler, or make
if you're using the minGW compiler
Implementation hints
-=-=-=-=-=-=-=-=-=-=
The code generated by the template can be compiled without any further
changes, so you can start with your own code right away.
However, there are a couple of things you will need to change outside the
resource's code, i.e. in the resource's .desktop file:
- Name field: the name of the resource with which it will be displayed in
system settings and applications which can add resources on their own.
E.g. MyBackend Resource
- Comment field: short description of the resource, also used to be
displayed, e.g. For calendars and contacts stored in MyBackend
- Icon field: if you are not writing a contact (addressbook) resource, you have
to change this to either an icon for the respective MIME type you are going
to provide or use a resource specific icon which you provide yourself
- X-Akonadi-MimeTypes field: if you are not writing a contact (addressbook)
resource, you have to change this to either a known MIME type or one you
install together with the resource.
If your resource can provide data of more than one MIME type, you can
specific all possible ones as a comma separate list.
Common MIME types are:
* text/directory: for contact data
* text/calendar: for calendar data (there are Akonadi defined subtypes
available, e.g. application/x-vnd.akonadi.calendar.event)
* message/rfc822: for e-mails and usenet news
The template comes with an input file for KDE's KConfigXT framework
for improved configuration file handling. The generated class is called
"Settings", so access to its data is provided through its singleton
instance method Settings::self().
See https://techbase.kde.org/Development/Tutorials/Using_KConfig_XT
Documentation
-=-=-=-=-=-=-
The Akonadi-KDE API documentation can be found here:
https://api.kde.org/kdepim/akonadi/html/index.html
General developer information, e.g. tutorials can be found here:
https://techbase.kde.org/KDE_PIM/Akonadi
The contact site can be found here:
https://community.kde.org/KDE_PIM/Contact
[General]
Name=C++
Comment=Akonadi Resource Template. A template for an Akonadi PIM data resource
Category=Akonadi/Resource
Icon=akonadiresource.png
ShowFilesAfterGeneration=src/akonadi_serializer_%{APPNAMELC}.cpp
# Find xsltproc executable and provide a macro to generate D-Bus interfaces.
#
# The following variables are defined :
# XSLTPROC_EXECUTABLE - path to the xsltproc executable
# Xsltproc_FOUND - true if the program was found
find_program(XSLTPROC_EXECUTABLE xsltproc DOC "Path to the xsltproc executable")
mark_as_advanced(XSLTPROC_EXECUTABLE)
if(XSLTPROC_EXECUTABLE)
set(Xsltproc_FOUND TRUE)
# We depend on Akonadi, make sure it's found
if(NOT DEFINED KF5Akonadi_DATA_DIR)
find_package(KF5Akonadi REQUIRED)
endif()
# Macro to generate a D-Bus interface description from a KConfigXT file
macro(kcfg_generate_dbus_interface _kcfg _name)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_name}.xml
COMMAND ${XSLTPROC_EXECUTABLE}
--stringparam interfaceName ${_name}
${KF5Akonadi_DATA_DIR}/kcfg2dbus.xsl
${_kcfg}
> ${CMAKE_CURRENT_BINARY_DIR}/${_name}.xml
DEPENDS
${KF5Akonadi_DATA_DIR}/kcfg2dbus.xsl
${_kcfg}
)
endmacro()
endif()
/*
* Copyright (C) %{CURRENT_YEAR} by %{AUTHOR} <%{EMAIL}>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "%{APPNAMELC}resource.h"
#include "settings.h"
#include "settingsadaptor.h"
#include "debug.h"
#include <QDBusConnection>
using namespace Akonadi;
%{APPNAME}Resource::%{APPNAME}Resource(const QString &id)
: ResourceBase(id)
{
new SettingsAdaptor(Settings::self());
QDBusConnection::sessionBus().registerObject(QStringLiteral("/Settings"),
Settings::self(),
QDBusConnection::ExportAdaptors);
// TODO: you can put any resource specific initialization code here.
qCDebug(log_%{APPNAMELC}resource) << "Resource started";
}
%{APPNAME}Resource::~%{APPNAME}Resource()
{
}
void %{APPNAME}Resource::retrieveCollections()
{
// TODO: this method is called when Akonadi wants to have all the
// collections your resource provides.
// Be sure to set the remote ID and the content MIME types
}
void %{APPNAME}Resource::retrieveItems(const Akonadi::Collection &collection)
{
// TODO: this method is called when Akonadi wants to know about all the
// items in the given collection. You can but don't have to provide all the
// data for each item, remote ID and MIME type are enough at this stage.
// Depending on how your resource accesses the data, there are several
// different ways to tell Akonadi when you are done.
}
bool %{APPNAME}Resource::retrieveItem(const Akonadi::Item &item, const QSet<QByteArray> &parts)
{
// TODO: this method is called when Akonadi wants more data for a given item.
// You can only provide the parts that have been requested but you are allowed
// to provide all in one go
return true;
}
void %{APPNAME}Resource::aboutToQuit()
{
// TODO: any cleanup you need to do while there is still an active
// event loop. The resource will terminate after this method returns
}
void %{APPNAME}Resource::configure(WId windowId)
{
// TODO: this method is usually called when a new resource is being
// added to the Akonadi setup. You can do any kind of user interaction here,
// e.g. showing dialogs.
// The given window ID is usually useful to get the correct
// "on top of parent" behavior if the running window manager applies any kind
// of focus stealing prevention technique
//
// If the configuration dialog has been accepted by the user by clicking Ok,
// the signal configurationDialogAccepted() has to be emitted, otherwise, if
// the user canceled the dialog, configurationDialogRejected() has to be emitted.
}
void %{APPNAME}Resource::itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection)
{
// TODO: this method is called when somebody else, e.g. a client application,
// has created an item in a collection managed by your resource.
// NOTE: There is an equivalent method for collections, but it isn't part
// of this template code to keep it simple
}
void %{APPNAME}Resource::itemChanged(const Akonadi::Item &item, const QSet<QByteArray> &parts)
{
// TODO: this method is called when somebody else, e.g. a client application,
// has changed an item managed by your resource.
// NOTE: There is an equivalent method for collections, but it isn't part
// of this template code to keep it simple
}
void %{APPNAME}Resource::itemRemoved(const Akonadi::Item &item)
{
// TODO: this method is called when somebody else, e.g. a client application,
// has deleted an item managed by your resource.
// NOTE: There is an equivalent method for collections, but it isn't part
// of this template code to keep it simple
}
AKONADI_RESOURCE_MAIN(%{APPNAME}Resource)
[Desktop Entry]
Name=%{APPNAME} Resource
Comment=An Akonadi resource plugin for %{APPNAME}
Type=AkonadiResource
Exec=akonadi_%{APPNAMELC}_resource
Icon=text-directory
X-Akonadi-MimeTypes=text/directory
X-Akonadi-Capabilities=Resource
X-Akonadi-Identifier=akonadi_%{APPNAMELC}_resource
/*
* Copyright (C) %{CURRENT_YEAR} by %{AUTHOR} <%{EMAIL}>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef %{APPNAMEUC}RESOURCE_H
#define %{APPNAMEUC}RESOURCE_H
#include <AkonadiAgentBase/ResourceBase>
class %{APPNAME}Resource : public Akonadi::ResourceBase,
public Akonadi::AgentBase::Observer
{
Q_OBJECT
public:
explicit %{APPNAME}Resource(const QString &id);
~%{APPNAME}Resource() override;
public Q_SLOTS:
void configure(WId windowId) override;
protected Q_SLOTS:
void retrieveCollections() override;
void retrieveItems(const Akonadi::Collection &col) override;
bool retrieveItem(const Akonadi::Item &item, const QSet<QByteArray> &parts) override;
protected:
void aboutToQuit() override;
void itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection) override;
void itemChanged(const Akonadi::Item &item, const QSet<QByteArray> &parts) override;
void itemRemoved(const Akonadi::Item &item) override;
};
#endif
set(%{APPNAMELC}resource_SRCS
%{APPNAMELC}resource.cpp
)
ecm_qt_declare_logging_category(%{APPNAMELC}resource_SRCS
HEADER debug.h
IDENTIFIER log_%{APPNAMELC}resource
CATEGORY_NAME log_%{APPNAMELC}resource
)
kconfig_add_kcfg_files(%{APPNAMELC}resource_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/settings.kcfgc
)
kcfg_generate_dbus_interface(
${CMAKE_CURRENT_SOURCE_DIR}/settings.kcfg
org.kde.Akonadi.%{APPNAME}.Settings
)
qt5_add_dbus_adaptor(%{APPNAMELC}resource_SRCS
${CMAKE_CURRENT_BINARY_DIR}/org.kde.Akonadi.%{APPNAME}.Settings.xml
${CMAKE_CURRENT_BINARY_DIR}/settings.h
Settings
)
add_executable(akonadi_%{APPNAMELC}_resource ${%{APPNAMELC}resource_SRCS})
target_link_libraries(akonadi_%{APPNAMELC}_resource
Qt5::DBus
KF5::AkonadiAgentBase
KF5::ConfigCore
)
install(TARGETS akonadi_%{APPNAMELC}_resource ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES %{APPNAMELC}resource.desktop
DESTINATION ${KDE_INSTALL_DATAROOTDIR}/akonadi/agents
)
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:kcfg="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile/>
<group name="General">
<entry name="ReadOnly" type="Bool">
<label>Do not change the actual backend data.</label>
<default>false</default>
</entry>
</group>
</kcfg>
File=settings.kcfg
ClassName=Settings
Mutators=true
ItemAccessors=true
SetUserTexts=true
Singleton=true
#IncludeFiles=
GlobalEnums=true
cmake_minimum_required(VERSION 3.1)
project(%{APPNAMELC})
set(ECM_MIN_VERSION "5.22.0")
find_package(ECM ${ECM_MIN_VERSION} CONFIG REQUIRED)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH})
include(FeatureSummary)
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
set(QT_MIN_VERSION "5.6.0")
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED Core Network Gui)
set(KF5_MIN_VERSION "5.22.0")
find_package(KF5Config ${KF5_MIN_VERSION} CONFIG REQUIRED)
set(AKONADI_MIN_VERSION "5.2")
find_package(KF5Akonadi ${AKONADI_MIN_VERSION} CONFIG REQUIRED)
add_subdirectory(src)
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
How To Build This Template
-=-=-=-=-=-=-=-=-=-=-=-=-=
--- On Linux & similar:
cd <project_name_path>
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$MY_PREFIX -DCMAKE_BUILD_TYPE=Debug
make
make install or su -c 'make install'
(MY_PREFIX is where you install your Akonadi setup, replace it accordingly)
to uninstall the project:
make uninstall or su -c 'make uninstall'
Note: you can use another build path. Then cd in your build dir and:
export MY_SRC=path_to_your_src
cmake $MY_SRC -DCMAKE_INSTALL_PREFIX=$MY_PREFIX -DCMAKE_BUILD_TYPE=Debug
--- On Windows:
cd <project_name_path>
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=%MY_PREFIX% -DCMAKE_BUILD_TYPE=Debug
[n]make
[n]make install
(MY_PREFIX is where you install your Akonadi setup, replace it accordingly)
to uninstall the project:
[n]make uninstall
Note: use nmake if you're building with the Visual Studio compiler, or make
if you're using the minGW compiler
Implementation hints
-=-=-=-=-=-=-=-=-=-=
The code generated by the template can be compiled without any further
changes, so you can start with your own code right away.
However, there are a couple of things you will need to change outside the
serialzer's code, i.e. in the serializer's .desktop file:
- Name field
- Comment field
- Type field: MIME type of your data type
Documentation
-=-=-=-=-=-=-
The Akonadi-KDE API documentation can be found here:
https://api.kde.org/kdepim/akonadi/html/index.html
General developer information, e.g. tutorials can be found here:
https://techbase.kde.org/KDE_PIM/Akonadi
The contact site can be found here:
https://community.kde.org/KDE_PIM/Contact
[General]
Name=C++
Comment=Akonadi Serializer Template. A template for an Akonadi data serializer plugin
Category=Akonadi/Serializer
Icon=akonadiserializer.png
ShowFilesAfterGeneration=src/%{APPNAMELC}resource.cpp
set(akonadi_serializer_%{APPNAMELC}_SRCS
akonadi_serializer_%{APPNAMELC}.cpp
)
add_library(akonadi_serializer_%{APPNAMELC} MODULE ${akonadi_serializer_%{APPNAMELC}_SRCS})
target_link_libraries(akonadi_serializer_%{APPNAMELC}
KF5::AkonadiCore
)
install(TARGETS akonadi_serializer_%{APPNAMELC}
DESTINATION ${KDE_INSTALL_PLUGINDIR})
install(FILES akonadi_serializer_%{APPNAMELC}.desktop
DESTINATION ${KDE_INSTALL_DATADIR}/akonadi/plugins/serializer
)
/*
* Copyright (C) %{CURRENT_YEAR} by %{AUTHOR} <%{EMAIL}>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "akonadi_serializer_%{APPNAMELC}.h"
#include <AkonadiCore/Item>
using namespace Akonadi;
bool SerializerPlugin%{APPNAME}::deserialize(Item &item, const QByteArray &label, QIODevice &data, int version)
{
Q_UNUSED(item);
Q_UNUSED(label);
Q_UNUSED(data);
Q_UNUSED(version);
// TODO Implement this
return false;
}
void SerializerPlugin%{APPNAME}::serialize(const Item &item, const QByteArray &label, QIODevice &data, int &version)
{
Q_UNUSED(item);
Q_UNUSED(label);
Q_UNUSED(data);
Q_UNUSED(version);
// TODO Implement this
}
QSet<QByteArray> SerializerPlugin%{APPNAME}::parts(const Item &item) const
{
// only need to reimplement this when implementing partial serialization
// i.e. when using the "label" parameter of the other two methods
return ItemSerializerPlugin::parts(item);
}
[Misc]
Name=%{APPNAME} Serializer
Comment=An Akonadi serializer plugin for %{APPNAMELC}
[Plugin]
Type=application/x-vnd.kde.%{APPNAMELC}
X-KDE-Library=akonadi_serializer_%{APPNAMELC}
/*
* Copyright (C) %{CURRENT_YEAR} by %{AUTHOR} <%{EMAIL}>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef AKONADI_SERIALIZER_%{APPNAMEUC}_H
#define AKONADI_SERIALIZER_%{APPNAMEUC}_H
#include <QObject>
#include <AkonadiCore/ItemSerializerPlugin>
namespace Akonadi
{
class SerializerPlugin%{APPNAME} : public QObject
, public ItemSerializerPlugin
{
Q_OBJECT
Q_INTERFACES(Akonadi::ItemSerializerPlugin)
Q_PLUGIN_METADATA(IID "org.kde.akonadi.SerializerPlugin%{APPNAME}")
public:
bool deserialize(Item &item, const QByteArray &label, QIODevice &data, int version) override;
void serialize(const Item &item, const QByteArray &label, QIODevice &data, int &version) override;
QSet<QByteArray> parts(const Item &item) const;
};
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment