aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vrátil <dvratil@kde.org>2016-08-05 00:47:08 (GMT)
committerDaniel Vrátil <dvratil@kde.org>2016-08-05 00:47:57 (GMT)
commitfd7e958536ca35709f048e90ad7031f4cd5555ac (patch)
tree9ab0d202058455d3517ea29c1fc9aff4b35a33df
parent324f087e7ff8671e00e4b49d61d85a0e261fa5d8 (diff)
Update Akonadi documentation, enable docs generation on api.kde.org
This adds metainfo.yaml with metadata for kapidox running on api.kde.org so we get documentation generated there. It also switches from .dox to markdown syntax in documentation, as recommended by kapidox. The high-level documentation is painfully outdated and needs a lot of love. I fixed only the most obvious issues I noticed (like mentions of Nepomuk or Akonadi::Entity class), but more things need to be updated and the documentation needs to be better structured. We should also have some more examples.
-rw-r--r--Mainpage.dox1137
-rw-r--r--README.md23
-rw-r--r--docs/client_libraries.md685
-rw-r--r--docs/history.md46
-rw-r--r--docs/images/bufferedcaching1.png (renamed from dox/bufferedcaching1.png)bin37509 -> 37509 bytes
-rw-r--r--docs/images/bufferedcaching2.png (renamed from dox/bufferedcaching2.png)bin41430 -> 41430 bytes
-rw-r--r--docs/images/bufferedcaching3.png (renamed from dox/bufferedcaching3.png)bin47782 -> 47782 bytes
-rw-r--r--docs/images/bufferedcaching4.png (renamed from dox/bufferedcaching4.png)bin50736 -> 50736 bytes
-rw-r--r--docs/images/bufferedcaching6.png (renamed from dox/bufferedcaching6.png)bin49369 -> 49369 bytes
-rw-r--r--docs/images/descendantentitiesproxymodel-colfilter.png (renamed from dox/descendantentitiesproxymodel-colfilter.png)bin6144 -> 6144 bytes
-rw-r--r--docs/images/descendantentitiesproxymodel-withansecnames.png (renamed from dox/descendantentitiesproxymodel-withansecnames.png)bin10346 -> 10346 bytes
-rw-r--r--docs/images/descendantentitiesproxymodel.png (renamed from dox/descendantentitiesproxymodel.png)bin8783 -> 8783 bytes
-rw-r--r--docs/images/entitytreemodel-collections.png (renamed from dox/entitytreemodel-collections.png)bin4292 -> 4292 bytes
-rw-r--r--docs/images/entitytreemodel-showroot.png (renamed from dox/entitytreemodel-showroot.png)bin9304 -> 9304 bytes
-rw-r--r--docs/images/entitytreemodel-showrootwithname.png (renamed from dox/entitytreemodel-showrootwithname.png)bin9663 -> 9663 bytes
-rw-r--r--docs/images/entitytreemodel.png (renamed from dox/entitytreemodel.png)bin9035 -> 9035 bytes
-rw-r--r--docs/images/mailmodelapp.png (renamed from dox/mailmodelapp.png)bin13528 -> 13528 bytes
-rw-r--r--docs/images/selectionproxymodel-ordered.png (renamed from dox/selectionproxymodel-ordered.png)bin16296 -> 16296 bytes
-rw-r--r--docs/images/selectionproxymodelmultipleselection-withdescendant.png (renamed from dox/selectionproxymodelmultipleselection-withdescendant.png)bin10232 -> 10232 bytes
-rw-r--r--docs/images/selectionproxymodelmultipleselection.png (renamed from dox/selectionproxymodelmultipleselection.png)bin8826 -> 8826 bytes
-rw-r--r--docs/images/selectionproxymodelsimpleselection.png (renamed from dox/selectionproxymodelsimpleselection.png)bin7434 -> 7434 bytes
-rw-r--r--docs/images/treeandlistapp.png (renamed from dox/treeandlistapp.png)bin19079 -> 19079 bytes
-rw-r--r--docs/images/treeandlistappwithdesclist.png (renamed from dox/treeandlistappwithdesclist.png)bin18041 -> 18041 bytes
-rw-r--r--docs/internals.md33
-rw-r--r--docs/kontact.svg88
-rw-r--r--docs/server.md244
-rw-r--r--metainfo.yaml47
27 files changed, 1166 insertions, 1137 deletions
diff --git a/Mainpage.dox b/Mainpage.dox
deleted file mode 100644
index 5746f47..0000000
--- a/Mainpage.dox
+++ /dev/null
@@ -1,1137 +0,0 @@
-/**
-\mainpage %Akonadi
-
-Akonadi aims to be an extensible cross-desktop storage service for PIM data
-and meta data providing concurrent read, write, and query access.
-It provides unique desktop-wide object identification and retrieval.
-
-Akonadi framework provides two parts: the server, and client libraries to
-access the data managed by the server.
-
-\page akonadi_server Akonadi Server
-
-<p><b>
-Overview |
-\ref akonadi_server_definitions |
-\ref akonadi_server_srclayout
-</b></p>
-
-
-This is the API documentation for the Akonadi server. If you are using Akonadi
-from within KDE, you almost certainly want the
-<a href="http://api.kde.org/4.x-api/kdepimlibs-apidocs/akonadi/html/index.html">KDE client library documentation</a>.
-This API reference is more useful to people implementing client libraries or
-working on the Akonadi server itself.
-
-For additional information, see the <a href="http://community.kde.org/KDE_PIM/Akonadi">Akonadi website</a>.
-
-\section akonadi_server_architecture Architecture
-
-<img src="http://community.kde.org/images.community/8/8e/Akonadi_Architecture.png"/>
-
-The Akonadi framework uses a client/server architecture. The Akonadi server has the following primary tasks:
-\li Abstract access to data from arbitrary sources, using toolkit-agnostic protocols and data formats
-\li Provide a data cache shared among several clients
-\li Provide change notifications and conflict detection
-\li Support offline change recording and change replay for remote data
-
-\subsection akonadi_server_design_principles Design Principles
-
-The Akonadi architecture is based on the following four design principles:
-
-\li <em>Functionality is spread over different processes.</em><br>
- This separation has the big advantage that if one process crashes because of
- a programming error it doesn't affect the other components. That results in
- robustness of the whole system. A disadvantage might be that there is an additional
- overhead due to inter-process communication.
-\li <em>Communication protocol is split into data and control channel.</em><br>
- When doing communication between processes you have to differentiate between the type of data
- that is being transferred. For a large amount of data a high-performance
- protocol should be used and for control data a low-latency protocol.
- Matching both requirements in one protocol is mostly impossible and hard to
- achieve with currently available software.
-\li <em>Separate logic from storage.</em><br>
- By separating the logic from the storage, the storage can be used to store data
- of any type. In this case, the storage is a kind of service, which is available for
- other components of the system. The logic is located in separated components and so
- 3rd-party developers can extend the system by providing their own components.
-\li <em>Keep communication asynchronous.</em><br>
- To allow a non-blocking GUI, all the communication with the back-end and within the
- back-end itself must be asynchronous. You can easily provide a synchronous convenience
- for the application developer; the back-end, however, must communicate asynchronously.
-
-\subsection akonadi_server_components Components
-
-The Akonadi server itself consists of a number of components:
-\li The Akonadi control process (\c akonadi_control). It is responsible for managing all other server components
-and Akonadi agents.
-\li The Akonadi server process (\c akonadiserver). The actual data access and caching server.
-\li The Akonadi agent server (\c akonadi_agent_server). Allows running of multiple Akonadi agents in one process.
-\li The Akonadi agent launcher (\c akonadi_agent_launcher). A helper process for running Akonadi agents.
-\li The Akonadi control tool (\c akonadictl). A tool to start/stop/restart the Akonadi server system and query its status.
- This is the only program of these listed here you should ever run manually.
-\li The Akonadi protocol library (\c libakonadiprotocolinternals), Contains protocol definitions and protocol parsing methods
- useful for client implementations.
-
-\subsubsection akonadi_server_components_server The Akonadi server process
-
-The %Akonadi server process (\c akonadiserver) has the following tasks:
-\li Provide a transaction-safe data store.
-\li Provide operations to add/modify/delete items and collections in the local store, implementing the server side of the ASAP protocol.
-\li Cache management of cached remote contents.
-\li Manage virtual collections representing search results.
-\li Provide change notifications for all known Akonadi objects over D-Bus.
-
-\subsubsection akonadi_server_components_control The Akonadi server control process
-
-The %Akondi control process (\c akonadi_control) has the following tasks:
-\li Manage and monitor the other server processes.
-\li Lifecycle management of agent instances using the various supported agent launch methods.
-\li Monitor agent instances and provide crash recovery.
-\li Provide D-Bus API to manage agents.
-\li Provide change notifications on agent types and agent instances.
-
-
-\section akonadi_server_objects Objects and Data Types
-
-The %Akonadi server operates on two basic object types, called items and collections. They are comparable to files and directories
-and are described in more detail in this section.
-
-\subsection akonadi_server_objects_items Akonadi Items
-
-An item is a generic container for whatever you want to store in Akonadi (eg. mails,
-events, contacts, etc.). An item consists of some generic information (such as identifier,
-mimetype, change date, flags, etc.) and a set of data fields, the item parts. Items
-are independent of the type of stored data, the semantics of the actual content is only
-known on the client side.
-
-\subsubsection akonadi_server_objects_items_parts Item Parts
-
-%Akonadi items can have one or more parts, e.g. an email message consists of the
-envelope, the body and possible one or more attachments. Item parts are identified
-by an identifier string. There are a few special pre-defined part identifiers (ALL,
-ENVELOPE, etc.), but in general the part identifiers are defined by the type specific
-extensions (ie. resource, serializer plugin, type specific client library).
-
-\subsubsection akonadi_server_objects_items_attributes Item Tags
-
-%Tags are self-contained entities stored in separate database table. A tag is a
-relation between multiple items. Tags can have different types (PLAIN, ...) and applications
-can define their own type to describe application-specific relations. Tags can also have
-attributes to store additional metadata about the relation the tag describes.
-
-\subsubsection akonadi_server_objects_items_serializer Payload Data Serialization
-
-Item payload data is typically serialized in a standard format to ensure interoperability between different
-client library implementations. However, the %Akonadi server does not enforce any format,
-payload data is handled as an opaque binary blob.
-
-\subsection akonadi_server_objects_collections Collections
-
-Collections are sets of items. Every item is stored in exactly one
-collection, this is sometimes also referred to as the "physical" storage location of the item.
-An item might also be visible in several other collections - so called "virtual collections" -
-which are defined as the result set of a search query.
-
-Collections are organized hierarchically, i.e. a collection can have child
-collections, thus defining a collection tree.
-
-Collections are uniquely identified by their identifier in
-contrast to their path, which is more robust with regard to renaming and moving.
-
-\subsubsection akonadi_server_objects_collections_akonadi Collection Properties
-
-Every collection has a set of supported content types.
-These are the mimetypes of items the collection can contain.
-Example: A collection of a folder-less iCal file resource would only support
-"text/calendar" items, a folder on an IMAP server "message/rfc822" but also
-"inode/directory" if it can contain sub-folders.
-
-There is a cache policy associated with every collection which defines how much
-of its content should be kept in the local cache and for how long.
-
-Additionally, collections can contain an arbitrary set of attributes to represent
-various other collection properties such as ACLs, quotas or backend-specific data
-used for incremental synchronization. Evaluation of such attributes is the responsibility
-of client implementations, the %Akonadi server does not interpret properties
-other than content types and cache policies.
-
-\subsubsection akonadi_server_objects_collections_tree Collection Tree
-
-There is a single collection tree in Akonadi, consisting of several parts:
-
-- A root node, id 0
-- One or more top-level collections for each resource. Think of these as mount-points
- for the resource. The resources must put their items and sub-collections into their
- corresponding top-level collection.
-- Resource-dependent sub-collections below the resource top-level collections.
- If the resource represents data that is organized in folders (e.g. an IMAP
- resource), it can create additional collections below its top-level
- collection. These have to be synched with the corresponding backend by the
- resource.
- Resources which represent folder-less data (e.g. an iCal file) don't need
- any sub-collections and put their items directly into the top-level collection.
-- A top-level collection containing virtual collections.
-
-Example:
-
-\verbatim
-+-+ resource-folder1
-| +- sub-folder1
-| +- sub-folder2
-| ...
-+-+ resource-folder2
-| ...
-|
-+-+ Searches
- +- search-folder1
- +- search-folder2
- ...
-\endverbatim
-
-
-\subsection akonadi_server_objects_identification Object Identification
-
-\subsubsection akonadi_server_objects_identification_uid Unique Identifier
-
-Every object stored in %Akonadi (collections and items) has a unique
-identifier in the form of an integer value. This identifier cannot be changed in
-any way and will stay the same, regardless of any modifications to the referred
-object. A unique identifier will never be used twice and is globally unique,
-therefore it is possible to retrieve an item without knowing the collection it belongs to.
-
-\subsubsection akonadi_server_objects_identification_rid Remote Identifier
-
-Every object can also have an optional so-called remote identifier. This is an
-identifier used by the corresponding resource to identify the object on its
-backend (e.g., a groupware server).
-
-The remote identifier can be changed by the owning resource agent only.
-
-Special case applies for Tags, where each tag can have multiple remote IDs. This fact is
-however opaque to resources as each resource is shown only the remote ID that it had
-provided when inserting the tag into Akonadi.
-
-\subsubsection akonadi_server_objects_identification_gid Global Identifier
-
-Every item can has also so called GID, an identifier specific to the content (payload)
-of the item. The GID is extracted from the payload by client serializer when storing the
-item in Akonadi. For example, contacts have vCard "UID" field as their GID, emails can
-use value of "Message-Id" header.
-
-\section akonadi_server_protocols Communication Protocols
-
-For communication within the Akonadi server infrastructure and for communication with Akonadi clients, two communication technologies are used:
-\li \em D-Bus Used for management tasks and change notifications.
-\li \em ASAP (Akonadi Server Access Protocol), used for high-throughput data transfer. ASAP is based on the well-known IMAP protocol (RFC 3501)
- which has been proven it's ability to handle large quantities of data in practice already.
-
-\todo add protocol documentation
-
-
-\section akonadi_server_interaction Interacting with Akonadi
-
-There are various possibilities to interact with %Akonadi.
-
-\section akonadi_server_interaction_client_libraray Akonadi Client Libraries
-
-Accessing the %Akonadi server using the ASAP and D-Bus interfaces directly is cumbersome.
-Therefore you'd usually use a client library implementing the low-level protocol handling
-and providing convenient high-level APIs for %Akonadi operations.
-
-Currently, the most complete implementation is the
-<a href="http://api.kde.org/4.x-api/kdepimlibs-apidocs/akonadi/html/index.html">KDE %Akonadi client library</a>.
-
-<!--
-// Afaik there are no "other ones"? -- dvratil
-\todo add links to the other ones
-//-->
-
-\subsection akonadi_server_interaction_agents Akonadi Agents
-
-%Akonadi agents are processes which are controlled by the Akonadi server itself. Agents typically
-operate autonomously (ie. without much user interaction) on the objects handled by Akonadi, mostly
-by reacting to change notifications sent by the %Akonadi server.
-
-Agents can implement specialized interfaces to provide additional functionality.
-The most important ones are the so-called resource agents.
-
-Resource agents are connectors that provide access to data from an external source, and replay local changes
-back to their corresponding backend.
-
-
-\section akonadi_server_implementation Implementation Details
-
-\subsection akonadi_server_implementation_storage Data and Metadata Storage
-
-The Akonadi server uses two mechanisms for data storage:
-\li A SQL databases for metadata and small payload data
-\li Plain files for large payload data
-
-More details on the SQL database layout can be found here: \ref akonadi_server_database.
-
-The following SQL databases are supported by the Akonadi server:
-\li \em MySQL using the default QtSQL driver shipped with Qt
-\li \em Sqlite using the improved QtSQL driver shipped with the Akonadi server
-\li \em PostgreSQL using the default QtSQL driver shipped with Qt
-
-For details on how to configure the various backends, see Akonadi::DataStore.
-
-
-
-
-\page akonadi_server_definitions Type Definitions
-
-<p><b>
-\ref index "Overview" |
-\ref Type Definitions |
-\ref akonadi_server_srclayout
-</b></p>
-
-To let all components play together nicely, we have to use some common encoding
-definitions.
-
-\li <em>Collection names</em><br>
- Collection names and paths are Unicode strings (QString) to allow custom names by the user.
-\li <em>Data references</em><br>
- The persistent identifier is an unsigned integer and the external URL is
- a Unicode string (QString).
-\li <em>Transferred data over ASAP</em><br/>
- The data transferred over ASAP are byte arrays (QByteArray). If Unicode strings are
- transferred over ASAP, UTF-8 encoding is applied.
-\li <em>Error and status messages</em><br>
- Error and status messages are visible to the user, so they have to be
- Unicode strings (QString).
-
-
-
-
-\page akonadi_server_srclayout Source Code Layout
-
-<p><b>
-\ref index "Overview" |
-\ref akonadi_server_definitions |
-\ref Source Code Layout
-</b></p>
-
-The code of the storage and control components is located in the \c server sub-directory.
-The different parts are laid out as follows:
-
-<ul>
-<li> \e control <br>
- Contains the source code of the \ref akonadi_design_control "control" component.
-<li> \e interfaces <br>
- Contains the D-Bus interface descriptions of the Akonadi components
-<li> \e src <br>
- Contains the source code of the \ref akonadi_design_storage "storage" component.
-<li> \e src/handler <br>
- Contains the source code for the handlers of the single ASAP commands.
- See <a href="group__akonadi__server__handler.html">command handlers module</a>
-<li> \e src/storage <br>
- Contains the source code for accessing the storage back-end.<br>
- <ul>
- <li> entity.{h,cpp} <br>
- The files contain classes which reflect records in the tables of the database.
- They are generated by XSL transformation from akonadidb.xml and entities.xsl
- <li> datastore.{h,cpp} <br>
- The files contain a class which provides the access to the underlaying database tables.
- </ul>
-</ul>
-
-
-\page libakonadi Akonadi client library
-
-\section libakonadi_intro Introduction
-
-libakonadi is the client access library for using the Akonadi PIM data server.
-All processes accessing Akonadi, including those which communicate with a remote
-server (\ref akonadi_design_agents "agents"), are considered clients.
-
-Functionality provided by libakonadi:
-
-- \ref libakonadi_objects
-- \ref libakonadi_collections
-- \ref libakonadi_pimitems
-- \ref libakonadi_jobs
-- \ref libakonadi_monitor
-- \ref libakonadi_serializer
-- \ref libakonadi_resource
-- \ref libakonadi_integration
-
-Additional information about Akonadi:
-
-- <a href="http://api.kde.org/kdesupport-api/akonadi-apidocs/">Akonadi Server documentation</a>
-- \ref akonadi_history
-- <a href="https://community.kde.org/KDE_PIM/Akonadi">Website</a>
-- <a href="https://techbase.kde.org/index.php?title=Projects/PIM/Akonadi">Wiki</a>
-
-Tools for developers:
-
-- <a href="http://my.cdash.org/index.php?project=kdepimlibs">CDash</a>
-- <a href="https://bugs.kde.org/buglist.cgi?query_format=advanced&product=Akonadi&component=libakonadi&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED">Bugtracker</a>
-
-
-\section libakonadi_objects Akonadi Objects
-
-Akonadi works on two basic object types: collections and items.
-
-Collections are comparable to folders in a file system and are represented by
-the class Akonadi::Collection. Every collection has an associated cache policy
-represented by the class Akonadi::CachePolicy which defines what part of its
-content is cached for how long. All available ways to work with collections are
-listed in the \ref libakonadi_collections "Collections" section.
-
-Akonadi items are comparable to files in a file system and are represented by
-the class Akonadi::Item. Each item represents a single PIM object such as a mail
-or a contact. The actual object it represents is its so-called payload. All
-available ways to work with items are listed in the \ref libakonadi_pimitems "Items"
-section.
-
-Both items and collections are identified by a persistent unique identifier.
-Also, they can contain arbitrary attributes (derived from Akonadi::Attribute) to
-attach general or application specific meta data to them. Functionality common
-to both is provided by their base class Akonadi::Entity.
-
-
-\section libakonadi_collections Collection retrieval and manipulation
-
-A collection is represented by the Akonadi::Collection class.
-
-Classes to retrieve information about collections:
-
-- Akonadi::CollectionFetchJob
-- Akonadi::CollectionStatisticsJob
-
-Classes to manipulate collections:
-
-- Akonadi::CollectionCreateJob
-- Akonadi::CollectionCopyJob
-- Akonadi::CollectionModifyJob
-- Akonadi::CollectionDeleteJob
-
-There is also Akonadi::CollectionModel, which is a self-updating model class which can
-be used in combination with Akonadi::CollectionView. Akonadi::CollectionFilterProxyModel
-can be used to limit a displayed collection tree to collections supporting a certain
-type of PIM items. Akonadi::CollectionPropertiesDialog provides an extensible properties
-dialog for collections. Often needed KAction for collection operations are provided by
-Akonadi::StandardActionManager.
-
-
-\section libakonadi_pimitems PIM item retrieval and manipulation
-
-PIM items are represented by classes derived from Akonadi::Item.
-Items can be retrieved using Akonadi::ItemFetchJob.
-
-The following classes are provided to manipulate PIM items:
-
-- Akonadi::ItemCreateJob
-- Akonadi::ItemCopyJob
-- Akonadi::ItemModifyJob
-- Akonadi::ItemDeleteJob
-
-Akonadi::ItemModel provides a self-updating model class which can be used to display the content
-of a collection. Akonadi::ItemView is the base class for a corresponding view. Often needed KAction
-for item operations are provided by Akonadi::StandardActionManager.
-
-
-\section libakonadi_jobs Low-level access to the Akonadi server
-
-Accessing the Akonadi server is done using job classes derived from Akonadi::Job. The
-communication channel with the server is provided by Akonadi::Session.
-
-To use server-side transactions, the following jobs are provided:
-
-- Akonadi::TransactionBeginJob
-- Akonadi::TransactionCommitJob
-- Akonadi::TransactionRollbackJob
-
-There also is Akonadi::TransactionSequence which can be used to automatically group
-a set of jobs into a single transaction.
-
-
-\section libakonadi_monitor Change notifications
-
-The Akonadi::Monitor class allows you to monitor specific resources,
-collections and PIM items for changes. Akonadi::ChangeRecorder augments this
-by providing a way to record and replay change notifications.
-
-
-\section libakonadi_serializer PIM item serializer
-
-The class Akonadi::ItemSerializer is responsible for converting between the stored (binary) representation
-of a PIM item and the objects used to handle these items provided by the corresponding libraries (kabc, kcal, etc.).
-
-Serializer plugins allow you to add support for new kinds of PIM items to Akonadi.
-Akonadi::ItemSerializerPlugin can be used as a base class for such a plugin.
-
-
-\section libakonadi_resource Agents and Resources
-
-Agents are independent processes that watch the Akonadi store for changes and react to them if necessary.
-Example: The Nepomuk feeder (kdepim/runtime/agents/nepomukfeeder/) is an agent that watches Akonadi for
-new emails, retrieves the new items, and feeds them to Nepomuk for indexing.
-
-The class Akonadi::AgentBase is the common base class for all agents. It provides commonly needed
-functionality such as change monitoring and recording.
-
-Resources are a special kind of agents. They are used as the actual backend for whatever data the resource represents.
-In this situation the akonadi server acts more like a proxy service. It caches data on behalf of its clients
-(client here being the Resource), not permanently storing it. The Akonadi server forwards item retrieval requests to the
-corresponding resource, if the item is not in the cache.
-Example: The imap resource is responsible for storing and fetching emails from an imap server.
-
-Akonadi::ResourceBase is the base class for them. It provides the
-necessary interfaces to the server as well as many convenience functions to make implementing
-a new resource as easy as possible. Note that a collection contains items belonging to a single
-resource, although there are plans in the future for 'virtual' collections which will contain
-the results of a search query spanning multiple resources.
-
-A resource can support multiple mimetypes. There are two places where a resource can specify
-mimetypes: in its desktop files, and in the content mimetypes field of
-collections created by it. The ones in the desktop file are used for
-filtering agent types, e.g. in the resource creation dialogs. The collection
-content mimetypes specify what you can actually put into a collection, which
-is not necessarily the same (e.g. the Kolab resource supports contacts and events, but not
-in the same folder).
-
-
-
-\page libakonadi_integration Integration in your Application
-
-Akonadi::Control provides ways to ensure that the Akonadi server is running, to monitor its availability
-and provide help on server-side errors. A more low-level interface to the Akonadi server is provided
-by Akonadi::ServerManager.
-
-A set of standard actions is provided by Akonadi::StandardActionManager. These provide consistent
-look and feel across applications.
-
-
-This library provides classes for KDE applications to communicate with the Akonadi server. The most high-level interface to Akonadi is the Models and Views provided in this library. Ready to use models are provided for use with views to interact with a tree of collections, a list of items in a collection, or a combined tree of Collections and items.
-
-\subsection collections_and_items Collections and Items
-
-In the Akonadi concept, Items are individual objects of PIM data, e.g. emails, contacts, events, notes etc. The data in an item is stored in a typed payload. For example, if an Akonadi Item holds a contact, the contact is available as a KABC::Addressee:
-
-@code
- if (item.hasPayload<KABC::Addressee>())
- {
- KABC::Addressee addr = item.payload<KABC::Addressee>();
- // use addr in some way...
- }
-@endcode
-
-Additionally, an Item must have a mimetype which corresponds to the type of payload it holds.
-
-Collections are simply containers of Items. A Collection has a name and a list of mimetypes that it may contain. A collection may for example contain events if it can contain the mimetype 'text/calendar'. A Collection itself (as opposed to its contents) has a mimetype, which is the same for all Collections. A Collection which can itself contain Collections must be able to contain the Collection mimetype.
-
-@code
- Collection col;
- // This collection can contain events and nested collections.
- col.setContentMimetypes( QStringList() << Collection::mimeType() << "text/calendar" );
-@endcode
-
-This system makes it simple to create PIM applications. For example, to create an application for viewing and editing events, you simply need to tell %Akonadi to retrieve all items matching the mimetype 'text/calendar'.
-
-\subsection convenience_mimetype_accessors Convenience Mimetype Accessors
-
-In order to avoid typos, improve readability, and to encapsulate the correct mimetypes for particular pim items, many of the standard classes have an accessor for the kind of mimetype the can handle. For example, you can use KMime::Message::mimeType() for emails, KABC::Addressee::mimeType() for contacts etc. It makes sense to define a similar static function in your own types.
-
-@code
- col.setContentMimetypes( QStringList() << Collection::mimeType() << KABC::Addressee::mimeType() << KMime::Message::mimeType() );
-@endcode
-
-
-<h2> Models and Views</h2>
-%Akonadi models and views are a high level way to interact with the %Akonadi server. Most applications will use these classes. See the EntityTreeModel documentation for more information.
-
-Models provide an interface for viewing, deleting and moving Items and Collections. New Items can also be created by dropping data of the appropriate type on a model. Additionally, the models are updated automatically if another application changes the data or inserts or deletes items etc.
-
-%Akonadi provides several models for particular uses, e.g. the MailModel is used for emails and the ContactsModel is used for showing contacts. Additional specific models can be implemented using EntityTreeModel as a base class.
-
-A typical use of these would be to create a model and use proxy models to make the view show different parts of the model. For example, show a collection tree in on one side and show items in a selected collection in another view.
-
-@code
- mailModel = new MailModel( session, monitor, this);
-
- collectionTree = new EntityMimeTypeFilterModel(this);
- collectionTree->setSourceModel(mailModel);
- // Filter out everything that is not a collection.
- collectionTree->addMimeTypeInclusionFilter( Collection::mimeType() );
- collectionTree->setHeaderSet(EntityTreeModel::CollectionTreeHeaders);
-
- collectionView = new EntityTreeView(this);
- collectionView->setModel(collectionTree);
-
- itemList = new EntityMimeTypeFilterModel(this);
- itemList->setSourceModel(mailModel);
- // Filter out collections
- itemList->addMimeTypeExclusionFilter( Collection::mimeType() );
- itemList->setHeaderSet(EntityTreeModel::ItemListHeaders);
-
- itemView = new EntityTreeView(this);
- itemView->setModel(itemList);
-@endcode
-
-\image html dox/mailmodelapp.png "An email application using MailModel"
-
-The content of the model is determined by the configuration of the Monitor passed into it. The examples below show a use of the EntityTreeModel and some proxy models for a simple heirarchical note collection. As the model is generic, the configuration and proxy models will also work with any other mimetype.
-
-@code
-
-// Configure what should be shown in the model:
-Monitor *monitor = new Monitor( this );
-monitor->fetchCollection( true );
-monitor->setItemFetchScope( scope );
-monitor->setCollectionMonitored( Collection::root() );
-monitor->setMimeTypeMonitored( MyEntity::mimeType() );
-
-Session *session = new Session( QByteArray( "MyEmailApp-" ) + QByteArray::number( qrand() ), this );
-monitor->setSession(session);
-
-EntityTreeModel *entityTree = new Akonadi::EntityTreeModel(monitor, this);
-@endcode
-
-\image html dox/entitytreemodel.png "A plain EntityTreeModel in a view"
-
-The EntityTreeModel can be further configured for certain behaviours such as fetching of collections and items.
-
-To create a model of only a collection tree and no items, set that in the model. This is just like CollectionModel:
-
-@code
-entityTree->setItemPopulationStrategy(EntityTreeModel::NoItemPopulation);
-@endcode
-
-
-\image html dox/entitytreemodel-collections.png "A plain EntityTreeModel which does not fetch items."
-
-Or, create a model of only items and not child collections. This is just like ItemModel:
-
-@code
-entityTree->setRootCollection(myCollection);
-entityTree->setCollectionFetchStrategy(EntityTreeModel::FetchNoCollections);
-@endcode
-
-Or, to create a model which includes items and first level collections:
-
-@code
-entityTree->setCollectionFetchStrategy(EntityTreeModel::FetchFirstLevelCollections);
-@endcode
-
-The items in the model can also be inserted lazily for performance reasons. The Collection tree is always built immediately.
-
-Additionally, a KDescendantsProxyModel may be used to alter how the items in the tree are presented.
-
-@code
-// ... Create an entityTreeModel
-KDescendantsProxyModel *descProxy = new KDescendantsProxyModel(this);
-descProxy->setSourceModel(entityTree);
-view->setModel(descProxy);
-@endcode
-
-\image html dox/descendantentitiesproxymodel.png "A KDescendantsProxyModel wrapping an EntityTreeModel"
-
-KDescendantsProxyModel can also display ancestors of each Entity in the list.
-
-@code
-// ... Create an entityTreeModel
-KDescendantsProxyModel *descProxy = new KDescendantsProxyModel(this);
-descProxy->setSourceModel(entityTree);
-
-// #### This is new
-descProxy->setDisplayAncestorData(true, QString(" / "));
-
-view->setModel(descProxy);
-
-@endcode
-
-\image html dox/descendantentitiesproxymodel-withansecnames.png "A DescendantEntitiesProxyModel with ancestor names."
-
-This proxy can be combined with a filter to for example remove collections.
-
-@code
-// ... Create an entityTreeModel
-DescendantEntitiesProxyModel *descProxy = new DescendantEntitiesProxyModel(this);
-descProxy->setSourceModel(entityTree);
-
-// #### This is new.
-EntityMimeTypeFilterModel *filterModel = new EntityMimeTypeFilterModel(this);
-filterModel->setSourceModel(descProxy);
-filterModel->setExclusionFilter(QStringList() << Collection::mimeType());
-
-view->setModel(filterModel);
-@endcode
-
-\image html dox/descendantentitiesproxymodel-colfilter.png "An EntityMimeTypeFilterModel wrapping a DescendantEntitiesProxyModel wrapping an EntityTreeModel"
-
-It is also possible to show the root item as part of the selectable model:
-
-@code
-
-entityTree->setIncludeRootCollection(true);
-
-@endcode
-
-\image html dox/entitytreemodel-showroot.png "An EntityTreeModel showing Collection::root"
-
-By default the displayed name of the root collection is '[*]', because it doesn't require i18n, and is generic. It can be changed too.
-
-@code
-entityTree->setIncludeRootCollection(true);
-entityTree->setRootCollectionDisplayName(i18nc("Name of top level for all collections in the application", "[All]"))
-@endcode
-
-\image html dox/entitytreemodel-showrootwithname.png "An EntityTreeModel showing Collection::root with an application specific name."
-
-These can of course be combined to create an application which uses one EntityTreeModel along with several proxies and views.
-
-@code
-// ... create an EntityTreeModel.
-EntityMimeTypeFilterModel *collectionTree = new EntityMimeTypeFilterModel(this);
-collectionTree->setSourceModel(entityTree);
-// Filter to include collections only:
-collectionTree->setInclusionFilter(QStringList() << Collection::mimeType());
-EntityTreeView *treeView = new EntityTreeView(this);
-treeView->setModel(collectionTree);
-
-EntityMimeTypeFilterModel *itemList = new EntityMimeTypeFilterModel(this);
-itemList->setSourceModel(entityTree);
-// Filter *out* collections
-itemList->setExclusionFilter(QStringList() << Collection::mimeType());
-EntityTreeView *listView = new EntityTreeView(this);
-listView->setModel(itemList);
-@endcode
-
-
-\image html dox/treeandlistapp.png "A single EntityTreeModel with several views and proxies."
-
-Or to also show items of child collections in the list:
-
-@code
- // ... Create an entityTreeModel
- collectionTree = new EntityMimeTypeFilterModel(this);
- collectionTree->setSourceModel(entityTree);
-
- // Include only collections in this proxy model.
- collectionTree->addMimeTypeInclusionFilter( Collection::mimeType() );
-
- treeview->setModel(collectionTree);
-
- descendedList = new DescendantEntitiesProxyModel(this);
- descendedList->setSourceModel(entityTree);
-
- itemList = new EntityMimeTypeFilterModel(this);
- itemList->setSourceModel(descendedList);
-
- // Exclude collections from the list view.
- itemList->addMimeTypeExclusionFilter( Collection::mimeType() );
-
- listView = new EntityTreeView(this);
- listView->setModel(itemList);
-@endcode
-
-\image html dox/treeandlistappwithdesclist.png "Showing descendants of all Collections in the list"
-
-Note that it is important in this case to use the DescendantEntitesProxyModel before the EntityMimeTypeFilterModel. Otherwise, by filtering out the collections first, you would also be filtering out their child items.
-
-A SelectionProxyModel can be used to simplify managing selection in one view through multiple proxy models to a representation in another view. The selectionModel of the initial view is used to create a proxied model which includes only the selected indexes and their children.
-
-@code
- // ... Create an entityTreeModel
- collectionTree = new EntityMimeTypeFilterModel(this);
- collectionTree->setSourceModel(entityTree);
-
- // Include only collections in this proxy model.
- collectionTree->addMimeTypeInclusionFilter( Collection::mimeType() );
-
- treeview->setModel(collectionTree);
-
- // SelectionProxyModel can handle complex selections:
- treeview->setSelectionMode(QAbstractItemView::ExtendedSelection);
-
- SelectionProxyModel *selProxy = new SelectionProxyModel(treeview->selectionModel(), this);
- selProxy->setSourceModel(entityTree);
-
- EntityTreeView *selView = new EntityTreeView(splitter);
- selView->setModel(selProxy);
-@endcode
-
-\image html dox/selectionproxymodelsimpleselection.png "A Selection in one view creating a model for use with another view."
-
-The SelectionProxyModel can handle complex selections.
-
-\image html dox/selectionproxymodelmultipleselection.png "Non-contiguous selection creating a new simple model in a second view."
-
-If an index and one or more of its descendants are selected, only the top-most selected index (including all of its descendants) are included in the proxy model. (Though this is configurable. See below)
-
-\image html dox/selectionproxymodelmultipleselection-withdescendant.png "Selecting an item and its descendant."
-
-SelectionProxyModel allows configuration using the methods setStartWithChildTrees, setOmitDescendants, setIncludeAllSelected. See testapp/proxymodeltestapp to try out the 5 valid configurations.
-
-Obviously, the SelectionProxyModel may be used in a view, or further processed with other proxy models. See the example_contacts application for example which uses a further DescendantEntitiesProxyModel and EntityMimeTypeFilterModel on top of a SelectionProxyModel.
-
-The SelectionProxyModel orders its items in the same top-to-bottom order as they appear in the source model. Note that this order may be different to the order in the selection model if there is a QSortFilterProxyModel between the selection and the source model.
-
-\image html dox/selectionproxymodel-ordered.png "Ordered items in the SelectionProxyModel"
-
-
-<h2>Jobs and Monitors</h2>
-
-The lower level way to interact with Akonadi is to use Jobs and Monitors (This is what models use internally). Jobs are used to make changes to akonadi, and in some cases (e.g., a fetch job) emit a signal with data resulting from the job. A Monitor reports changes made to the data stored in Akonadi (e.g., creating, updating, deleting or moving an item or collection ) via signals.
-
-Typically, an application will configure a monitor to report changes to a particular Collection, mimetype or resource, and then connect to the signals it emits.
-
-Most applications will use some of the low level api for actions unrelated to a model-tree view, such as creating new items and collections.
-
-<h2>Tricky details</h2>
-
-<h3>Change Conflicts</h3>
-It is possible that while an application is editing an item, that item gets updated in akonadi. Akonadi will notify the application that that item has changed via a Monitor signal. It is the responsibility of the application to handle the conflict by for example offering the user a dialog to resolve it. Alternatively, the application could ignore the dataChanged signal for that item, and will get another chance to resolve the conflict when trying to save the result back to akonadi. In that case, the ItemModifyJob will fail and report that the revision number of the item on the server differs from its revision number as reported by the job. Again, it is up to the application to handle this case.
-
-This is something that every application using akonadi will have to handle.
-
-<h3>Using Entity::Id as an identifier</h3>
-
-Items and Collections have a id() member which is a unique identifier used by akonadi. It can be useful to use the id() as an identifier when storing Collections or Items.
-
-However, as an item and a collection can have the same id(), if you need to store both Collections and Items together by a simple identifier, conflicts can occur.
-
-@code
- QString getRemoteIdById( Entity::Id id )
- {
- // Note:
- // m_items is QHash<Entity::Id, Item>
- // m_collections is QHash<Entity::Id, Collection>
- if ( m_items.contains( id ) )
- {
- // Oops, we could accidentally match a collection here.
- return m_items.value( id ).remoteId();
- } else if ( m_collections.contains( id ) )
- {
- return m_collections.value( id ).remoteId();
- }
- return QString();
- }
-@endcode
-
-In this case, it makes more sense to use a normal qint64 as the internal identifier, and use the sign bit to determine if the identifier refers to a Collection or an Item. This is done in the implementation of EntityTreeModel to tell Collections and Items apart.
-
-@code
- QString getRemoteIdByInternalIdentifier( qint64 internalIdentifier )
- {
- // Note:
- // m_items is QHash<Entity::Id, Item>
- // m_collections is QHash<Entity::Id, Collection>
-
- // If the id is negative, it refers to an Item
- // Otherwise it refers to a Collection.
-
- if ( internalIdentifier < 0 )
- {
- // Reverse the sign of the id before using it.
- return m_items.value( internalIdentifier * -1 ).remoteId();
- } else
- {
- return m_collections.value( internalIdentifier ).remoteId();
- }
- }
-@endcode
-
-<h3>Unordered Lists</h3>
-Collection and Item both provide a ::List to represent groups of objects. However the objects in the list are usually not ordered in any particular way, even though the API provides methods to work with an ordered list. It makes more sense to think of it as a Set instead of a list in most cases.
-
-For example, when using an ItemFetchJob to fetch the items in a collection, the items could be in any order when returned from the job. The order that a Monitor emits notices of changes is also indeterminate. By using a Transaction however, it is sometimes possible to retrieve objects in order. Additionally, using s constructor overload in the CollectionFetchJob it is possible to retrieve collections in a particular order.
-
-@code
- Collection::List getCollections(QList<Collection::Id> idsToGet)
- {
- Collection::List getList;
- foreach ( Collection::Id id, idsToGet ) {
- getList << Collection(id);
- }
- CollectionFetchJob *job = CollectionFetchJob(getList);
- if (job->exec())
- {
- // job->collections() is in the same order as the ids in idsToGet.
- }
- }
-
-@endcode
-
-<h2>Resources</h2>
-The KDEPIM module includes resources for handling many types of PIM data, such as imap email, vcard files and vcard directories, ical event files etc. These cover many of the sources for your PIM data, but in the case that you need to use data from another source (for example a website providing a contacts storage service and an api), you simply have to write a new resource.
-
-http://techbase.kde.org/Development/Tutorials/Akonadi/Resources
-
-<h2>Serializers</h2>
-Serializers provide the functionality of converting raw data, for example from a file, to a strongly typed object of PIM data. For example, the addressee serializer reads data from a file and creates a KABC::Addressee object.
-
-New serializers can also easily be written if the data you are dealing with is not one of the standard PIM data types.
-
-<h1>Implementation details</h1>
-
-<h3>Updating Akonadi Models</h3>
-
-@note The details here are only relevant if you are writing a new view using EntityTreeModel, or writing a new model.
-
-Because communication with akonadi happens asynchronously, and the models only hold a cached copy of the data on the akonadi server, some typical behaviours of models are not followed by Akonadi models.
-
-For example, when setting data on a model via a view, most models syncronously update their internal store and notify akonadi to update its view of the data by returning <tt>true</tt>.
-
-@dot
-digraph utmg {
- rankdir = LR;
- { node [label="",style=invis, height=0, width=0 ];
- V_Set_Data; V_Result; V_Data_Changed;
- M_Set_Data; M_Result;
- }
- { node [shape=box, fillcolor=lightyellow, style=filled,fontsize=26];
- View [label=":View"]; Model [label=":Model"];
- }
- { node [style=invis];
- View_EOL; Model_EOL;
- }
- {
- V_Set_Data -> M_Set_Data [label="Set Data"];
- M_Result -> V_Result [label="Success",arrowhead="vee", style="dashed"];
- V_Result -> V_Data_Changed [label="Update View \n[ Success = True ]"];
- }
-
- // Dashed Vertical lines for object lifetimes.
- edge [style=dashed, arrowhead=none];
- { rank = same; View -> V_Set_Data -> V_Result -> V_Data_Changed -> View_EOL; }
- { rank = same; Model -> M_Set_Data -> M_Result -> Model_EOL; }
-
- // Make sure top nodes are in a straight line.
- { View -> Model [style=invis]; }
- // And the bottom nodes.
- { View_EOL -> Model_EOL [style=invis]; }
-}
-@enddot
-
-Akonadi models only cache data from the akonadi server. To update data on an Akonadi::Entity stored in a model, the model makes a request to the akonadi server to update the model data. At that point the data cached internally in the model is not updated, so <tt>false</tt> is always returned from setData. If the request to update data on the akonadi server is successful, an Akonadi::Monitor notifies the model that the data on that item has changed. The model then updates its internal data store and notifies the view that the data has changed. The details of how the Monitor communicates with akonadi are omitted for clarity.
-
-@dot
-digraph utmg {
- rankdir = LR;
- { node [label="",style=invis, height=0, width=0 ];
- ETV_Set_Data; ETV_Result; ETV_Data_Changed;
- ETM_Set_Data; ETM_Result; ETM_Changed;
- M_Dummy_1; M_Changed;
- AS_Modify;
- }
- { node [shape=box, fillcolor=lightyellow, style=filled,fontsize=26];
- EntityTreeView [label=":View"]; EntityTreeModel [label=":Model"]; Monitor [label=":Monitor"]; Akonadi_Server [label=":Akonadi"];
- }
- { node [style=invis];
- EntityTreeView_EOL; EntityTreeModel_EOL; Monitor_EOL; Akonadi_Server_EOL;
- }
- {
- { rank = same; ETV_Set_Data -> ETM_Set_Data [label="Set Data"]; }
- { rank = same; ETM_Result -> ETV_Result [label="False",arrowhead="vee", style="dashed"]; }
- { rank = same; ETM_Result -> M_Dummy_1 [style=invis]; }
- { rank = same; ETM_Set_Data -> AS_Modify [arrowhead="vee",taillabel="Modify Item", labeldistance=14.0, labelangle=10]; }
- { rank = same; M_Changed -> ETM_Changed [arrowhead="vee",label="Item Changed"]; }
- { rank = same; ETM_Changed -> ETV_Data_Changed [arrowhead="vee",label="Update View"]; }
- }
-
- // Dashed Vertical lines for object lifetimes.
- edge [style=dashed, arrowhead=none];
- { rank = same; EntityTreeView -> ETV_Set_Data -> ETV_Result -> ETV_Data_Changed -> EntityTreeView_EOL; }
- { rank = same; EntityTreeModel -> ETM_Set_Data -> ETM_Result -> ETM_Changed -> EntityTreeModel_EOL; }
- { rank = same; Monitor -> M_Dummy_1 -> M_Changed -> Monitor_EOL; }
- { rank = same; Akonadi_Server -> AS_Modify -> Akonadi_Server_EOL; }
-
- // Make sure top nodes are in a straight line.
- { EntityTreeView -> EntityTreeModel -> Monitor -> Akonadi_Server [style=invis]; }
- // And the bottom nodes.
- { EntityTreeView_EOL -> EntityTreeModel_EOL -> Monitor_EOL -> Akonadi_Server_EOL [style=invis]; }
-}
-@enddot
-
-Similarly, in drag and drop operations, most models would update an internal data store and return <tt>true</tt> from dropMimeData if the drop is successful.
-
-@dot
-digraph utmg {
- rankdir = LR;
- { node [label="",style=invis, height=0, width=0 ];
- Left_Phantom; Left_Phantom_DropEvent;
- V_DropEvent; V_Result; V_Data_Changed; V_Dummy_1;
- M_DropMimeData; M_Result;
- }
- { node [shape=box, fillcolor=lightyellow, style=filled,fontsize=26];
- View [label=":View"]; Model [label=":Model"];
- }
- { node [style=invis];
- Left_Phantom_EOL;
- View_EOL; Model_EOL;
- }
- {
- Left_Phantom_DropEvent -> V_DropEvent [label="DropEvent"];
- V_DropEvent -> M_DropMimeData [label="DropMimeData"];
- M_Result -> V_Result [label="Success",arrowhead="vee", style="dashed"];
- V_Result -> V_Data_Changed [label="Update View \n[Success = True]"];
- }
-
- // Dashed Vertical lines for object lifetimes.
- edge [style=dashed, arrowhead=none];
- { rank = same; View -> V_DropEvent -> V_Result -> V_Dummy_1 -> V_Data_Changed -> View_EOL; }
- { rank = same; Model -> M_DropMimeData -> M_Result -> Model_EOL; }
-
- //Phantom line
- { rank= same; Left_Phantom -> Left_Phantom_DropEvent -> Left_Phantom_EOL [style=invis]; }
-
- // Make sure top nodes are in a straight line.
- { Left_Phantom -> View -> Model [style=invis]; }
- // And the bottom nodes.
- { Left_Phantom_EOL -> View_EOL -> Model_EOL [style=invis]; }
-}
-
-@enddot
-
-Akonadi models, for the same reason as above, always return false from dropMimeData. At the same time a suitable request is sent to the akonadi server to make the changes resulting from the drop (for example, moving or copying an entity, or adding a new entity to a collection etc). If that request is successful, the Akonadi::Monitor notifies the model that the data is changed and the model updates its internal store and notifies the view that the model data is changed.
-
-@dot
-
-digraph utmg {
- rankdir = LR;
- { node [label="",style=invis, height=0, width=0 ];
- Left_Phantom; Left_Phantom_DropEvent;
- ETV_DropEvent; ETV_Result; ETV_Data_Changed;
- ETM_DropMimeData; ETM_Result; ETM_Changed;
- M_Dummy_1; M_Changed;
- AS_Modify;
- }
- { node [shape=box, fillcolor=lightyellow, style=filled,fontsize=26];
- EntityTreeView [label=":View"];
- EntityTreeModel [label=":Model"];
- Monitor [label=":Monitor"];
- Akonadi_Server [label=":Akonadi"];
- }
- { node [style=invis];
- Left_Phantom_EOL;
- EntityTreeView_EOL; EntityTreeModel_EOL; Monitor_EOL; Akonadi_Server_EOL;
- }
-
- {
- { rank = same; Left_Phantom_DropEvent -> ETV_DropEvent [label="DropEvent"]; }
- { rank = same; ETV_DropEvent -> ETM_DropMimeData [label="Drop MimeData"]; }
- { rank = same; ETM_Result -> ETV_Result [label="False",arrowhead="vee", style="dashed"]; }
- { rank = same; ETM_Result -> M_Dummy_1 [style=invis]; }
- { rank = same; ETM_DropMimeData -> AS_Modify [arrowhead="vee",taillabel="Action", labeldistance=14.0, labelangle=10]; }
- { rank = same; M_Changed -> ETM_Changed [arrowhead="vee",label="Item Changed"]; }
- { rank = same; ETM_Changed -> ETV_Data_Changed [arrowhead="vee",label="Update View"]; }
- }
-
- // Dashed Vertical lines for object lifetimes.
- edge [style=dashed, arrowhead=none];
- { rank = same; EntityTreeView -> ETV_DropEvent -> ETV_Result -> ETV_Data_Changed -> EntityTreeView_EOL; }
- { rank = same; EntityTreeModel -> ETM_DropMimeData -> ETM_Result -> ETM_Changed -> EntityTreeModel_EOL; }
- { rank = same; Monitor -> M_Dummy_1 -> M_Changed -> Monitor_EOL; }
- { rank = same; Akonadi_Server -> AS_Modify -> Akonadi_Server_EOL; }
-
- //Phantom line
- { rank= same; Left_Phantom -> Left_Phantom_DropEvent -> Left_Phantom_EOL [style=invis]; }
-
- // Make sure top nodes are in a straight line.
- { Left_Phantom -> EntityTreeView -> EntityTreeModel -> Monitor -> Akonadi_Server [style=invis]; }
- // And the bottom nodes.
- { Left_Phantom_EOL -> EntityTreeView_EOL -> EntityTreeModel_EOL -> Monitor_EOL -> Akonadi_Server_EOL [style=invis]; }
-}
-
-
-@enddot
-
-@section lazy-model-population Lazy Model Population
-
-@note This page is not part of the %Akonadi API. It is provided as internal documentation for %Akonadi maintainers. It was originally a blog post here: http://steveire.wordpress.com/2009/10/06/cache-invalidation-in-akonadi-models/
-@internal
-
-If using EntityTreeModel::LazyPopulation with your model, items will be fetched into the model when the collection they are a part of is selected. This ensures that the model is as sparsely populated as possible for performance reasons. As a consequence however, it is necessary to purge unused items from the model too. This is handled automatically when using an Akonadi::SelectionProxyModel.
-
-The problem is knowing when to invalidate the cache. If no application is currently showing the contents of a Collection, there is no need for the Items in that Collection to be fetched, cached and kept up to date in the model. The effect we would like to achieve is to purge the Items in a Collection when those items are no longer shown anywhere in the application. Generally, that will mean that the Collection is not selected.
-
-In Qt Model-View, the application data is stored in a model, and there may be one or more views attached to it displaying its contents. The model doesn’t have any knowledge of the views, and so it can’t know whether any particular Collection is selected, and purge its Iitems.
-
-To solve this, we use the KSelectionProxyModel, which already has a lot of code for managing the selection a user makes in a view. A subclass, Akonadi::SelectionProxyModel implements a reference counting system which increments the refcount of a Collection when it is selected, and decrements it when deselected. If the reference count of a Collection goes down to zero, it is put in a queue to be purged. It is not purged immediately, but queued because if the user is clicking around several Collection in a short time, we don’t want to purge the Collections each click or we’d lose the benefit of the caching. Like other <a href="http://qt-project.org/doc/qt-4.7/qobject.html#id-aa43c933-c869-42eb-af14-ff17b8304c96">similar optimisation techniques</a>, this violates the object-oriented principle of modularity, but it is worth it for the benefit it brings. The effect can be seen in the akonadiconsole tool by not filtering out the items from the tree.
-
-In the screenshots below I removed the filtering out of Items in the tree so that the fetching/purging can be seen. In real applications, the Items in the tree on the left would not be visible.
-
-@image html dox/bufferedcaching1.png "When a Collection is clicked, its Items are put into the model. The rest of the Collections have no items."
-
-@image html dox/bufferedcaching2.png "The Inbox Collection is selected, so its items are fetched. Personal Contacts is no longer selected, so it is put into a queue to be purged."
-
-@image html dox/bufferedcaching3.png "Select another Collection and its items are fetched too."
-
-@image html dox/bufferedcaching4.png "Another Collection is selected, pushing the Personal contacts out of the queue and purging them"
-
-@image html dox/bufferedcaching6.png "If the Collection is selected again, its Items are refetched"
-
-For this example, I used a queue length of just two Collections, so that if a Collection was deselected two clicks ago, it will be purged. In real applications, a longer queue length will be used, but it’s harder to illustrate in screenshots. Another unrealistic part of this demo is that this feature will like be used in applications like KMail where Collections can contain tens of thousands of Items and fetching them is an expensive operation.
-
-This feature should be totally invisible to users and even developers using Akonadi, but it should offset the main disadvantage of using a cache of Items in the EntityTreeModel.
-
-*/
-
-
-/**
-\page akonadi_history Historical Background
-
-\section akonadi_history_general General
-
-During the last 5 years, after the release of KDE 3.0, the requirements of our users
-have constantly increased. While it was sufficient that our PIM solution was able to handle 100 contacts,
-300 events and maybe 1000 mails in 2001, nowadays users expect the software to be able to
-handle a multiple of that. Over the years, the KDE PIM developers tried to catch up with the new
-requirements; however, since KDE 3.x had to stay binary compatible, they were limited in their
-efforts.
-
-With the new major release KDE 4.0 it's possible to completely redesign the PIM libraries from
-the ground up and use new concepts to face the requirements of 2006 and beyond.
-
-After some discussion at the annual KDE PIM meeting in Osnabrück in January 2006, the PIM developers
-came to the conclusion that a service is needed which acts as a local cache on the user's desktop
-and provides search facilities. The name Akonadi comes from a divinity from Ghana and was chosen since
-all other nice names were already used by other projects on the Internet ;)
-
-\section akonadi_history_problems Problems with the implementation of KDE 3.x
-
-Before digging into the internals of Akonadi, we want to take a look at the implementation of the
-old KDE PIM libraries to understand the problems and conceptual shortcomings.
-
-The main PIM libraries libkabc (contacts) and libkcal (events) where designed at a time when the
-address book and calendar were files on the local file system, so there was no reason to think
-about access time and mode. The libraries accessed the files synchronously and loaded all data of the
-file into memory to be able to perform search queries on the data set. It worked well for local files,
-but over time plug-ins for loading data from groupware servers were written, so the synchronous access blocked
-applications which used libkabc/libkcal, and loading all 2000 contacts from a server is not only
-time consuming but also needs a lot of memory to store them locally. The KDE PIM developers tried to
-address the first issue by adding an asynchronous API, but it was not well implemented and was difficult to use.
-In the end, the design decisions caused the following problems:
-
-\li Bad Performance
-\li High Memory Consumption
-
-Another important but missing thing in the libraries was support for notifications and locking.
-The former was partly implemented (at least reflected by the API) but only implemented in the local
-file plug-in, so it was in practice unusable. The latter was also partly implemented but never really tested and
-lead to deadlocks sometimes, so the following problems appeared as well:
-
-\li Missing Notifications
-\li Missing Locking
-
-The main aim of Akonadi is to solve these issues and make use of the goodies which the new design brings.
-*/
-
-
-/**
-
-\defgroup AkonadiMacros Akonadi Macros
-
-*/
-
-// DOXYGEN_EXCLUDE = src/qsqlite src/akonadicontrol src/akonadictl autotests tests
-// DOXYGEN_PROJECTNAME=Akonadi
-// DOXYGEN_PROJECTVERSION=5.1.52
-// DOXYGEN_REFERENCES = kdecore kdeui
-// DOXYGEN_SET_RECURSIVE = YES
-// vim:ts=4:sw=4:expandtab:filetype=doxygen
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5c9fdb2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+# Akonadi
+
+Akonadi aims to be an extensible cross-desktop storage service for PIM data
+and meta data providing concurrent read, write, and query access.
+It provides unique desktop-wide object identification and retrieval.
+
+Akonadi framework provides two parts: the server, and client libraries to
+access the data managed by the server.
+
+## Client Libraries
+
+If you are an application developer and want to access and interact with data
+stored in Akonadi, you should read the [Akonadi client libraries documentation](@ref client_libraries).
+
+## Akonadi Server
+
+If you are interested in working on the Akonadi framework itself, you can read
+more about the internals of the Akonadi Server and the protocol in the
+[Akonadi server documentation](@ref server).
+
+## History
+
+You can also read a bit more about [history of Akonadi](@ref history)
diff --git a/docs/client_libraries.md b/docs/client_libraries.md
new file mode 100644
index 0000000..6b9885c
--- /dev/null
+++ b/docs/client_libraries.md
@@ -0,0 +1,685 @@
+# Akonadi client libraries {#client_libraries}
+
+[TOC]
+
+Akonadi client libraries consist of three libraries that provide tools to access
+the Akonadi PIM data server: AkonadiCore, AkonadiWidgets and AkonadiAgentBase.
+All processes accessing Akonadi, including those which communicate with a remote
+server "[agents](@ref agents)", are considered clients.
+
+<!--
+Additional information about Akonadi:
+
+- <a href="http://api.kde.org/kdesupport-api/akonadi-apidocs/">Akonadi Server documentation</a>
+- \ref akonadi_history
+- <a href="https://community.kde.org/KDE_PIM/Akonadi">Website</a>
+- <a href="https://techbase.kde.org/index.php?title=Projects/PIM/Akonadi">Wiki</a>
+
+Tools for developers:
+
+- <a href="http://my.cdash.org/index.php?project=kdepimlibs">CDash</a>
+- <a href="https://bugs.kde.org/buglist.cgi?query_format=advanced&product=Akonadi&component=libakonadi&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED">Bugtracker</a>
+//-->
+
+# Akonadi Objects {#objects}
+
+Akonadi works on two basic object types: collections and items.
+
+Collections are comparable to folders in a file system and are represented by
+the class Akonadi::Collection. Every collection has an associated cache policy
+represented by the class Akonadi::CachePolicy which defines what part of its
+content is cached for how long. All available ways to work with collections are
+listed in the "[Collections](#collections)" section.
+
+Akonadi items are comparable to files in a file system and are represented by
+the class Akonadi::Item. Each item represents a single PIM object such as a mail
+or a contact. The actual object it represents is its so-called payload. All
+available ways to work with items are listed in the "[Items](#items)"
+section.
+
+Both items and collections are identified by a persistent unique identifier.
+Also, they can contain arbitrary attributes (derived from Akonadi::Attribute) to
+attach general or application specific meta data to them.
+
+# Collection retrieval and manipulation {#collections}
+
+A collection is represented by the Akonadi::Collection class.
+
+Classes to retrieve information about collections:
+
+* Akonadi::CollectionFetchJob
+* Akonadi::CollectionStatisticsJob
+
+Classes to manipulate collections:
+
+* Akonadi::CollectionCreateJob
+* Akonadi::CollectionCopyJob
+* Akonadi::CollectionModifyJob
+* Akonadi::CollectionDeleteJob
+
+There is also Akonadi::CollectionModel, which is a self-updating model class which can
+be used in combination with Akonadi::CollectionView. Akonadi::CollectionFilterProxyModel
+can be used to limit a displayed collection tree to collections supporting a certain
+type of PIM items. Akonadi::CollectionPropertiesDialog provides an extensible properties
+dialog for collections. Often needed KAction for collection operations are provided by
+Akonadi::StandardActionManager.
+
+# PIM item retrieval and manipulation {#items}
+
+PIM items are represented by classes derived from Akonadi::Item.
+Items can be retrieved using Akonadi::ItemFetchJob.
+
+The following classes are provided to manipulate PIM items:
+
+* Akonadi::ItemCreateJob
+* Akonadi::ItemCopyJob
+* Akonadi::ItemModifyJob
+* Akonadi::ItemDeleteJob
+
+Akonadi::ItemModel provides a self-updating model class which can be used to display the content
+of a collection. Akonadi::ItemView is the base class for a corresponding view. Often needed KAction
+for item operations are provided by Akonadi::StandardActionManager.
+
+# Low-level access to the Akonadi server {#jobs}
+
+Accessing the Akonadi server is done using job classes derived from Akonadi::Job. The
+communication channel with the server is provided by Akonadi::Session.
+
+To use server-side transactions, the following jobs are provided:
+
+* Akonadi::TransactionBeginJob
+* Akonadi::TransactionCommitJob
+* Akonadi::TransactionRollbackJob
+
+There also is Akonadi::TransactionSequence which can be used to automatically group
+a set of jobs into a single transaction.
+
+
+# Change notifications (Monitor) {#monitor}
+
+The Akonadi::Monitor class allows you to monitor specific resources,
+collections and PIM items for changes. Akonadi::ChangeRecorder augments this
+by providing a way to record and replay change notifications.
+
+# PIM item serializer {#serializer}
+
+The class Akonadi::ItemSerializer is responsible for converting between the stored (binary) representation
+of a PIM item and the objects used to handle these items provided by the corresponding libraries (kabc, kcal, etc.).
+
+Serializer plugins allow you to add support for new kinds of PIM items to Akonadi.
+Akonadi::ItemSerializerPlugin can be used as a base class for such a plugin.
+
+# Agents and Resources {#resource}
+
+Agents are independent processes that watch the Akonadi store for changes and react to them if necessary.
+Example: The Akonadi Indexing Agent is an agent that watches Akonadi for new emails, calendar events, etc.,
+retrieves the new items and indexes them into a special database.
+
+The class Akonadi::AgentBase is the common base class for all agents. It provides commonly needed
+functionality such as change monitoring and recording.
+
+Resources are a special kind of agents. They are used as the actual backend for whatever data the resource represents.
+In this situation the akonadi server acts more like a proxy service. It caches data on behalf of its clients
+(client here being the Resource), not permanently storing it. The Akonadi server forwards item retrieval requests to the
+corresponding resource, if the item is not in the cache.
+Example: The imap resource is responsible for storing and fetching emails from an imap server.
+
+Akonadi::ResourceBase is the base class for them. It provides the
+necessary interfaces to the server as well as many convenience functions to make implementing
+a new resource as easy as possible. Note that a collection contains items belonging to a single
+resource, although there are plans in the future for 'virtual' collections which will contain
+the results of a search query spanning multiple resources.
+
+A resource can support multiple mimetypes. There are two places where a resource can specify
+mimetypes: in its desktop files, and in the content mimetypes field of
+collections created by it. The ones in the desktop file are used for
+filtering agent types, e.g. in the resource creation dialogs. The collection
+content mimetypes specify what you can actually put into a collection, which
+is not necessarily the same (e.g. the Kolab resource supports contacts and events, but not
+in the same folder).
+
+
+# Integration in your Application {#integration}
+
+Akonadi::Control provides ways to ensure that the Akonadi server is running, to monitor its availability
+and provide help on server-side errors. A more low-level interface to the Akonadi server is provided
+by Akonadi::ServerManager.
+
+A set of standard actions is provided by Akonadi::StandardActionManager. These provide consistent
+look and feel across applications.
+
+
+This library provides classes for KDE applications to communicate with the Akonadi server. The most high-level interface to Akonadi is the Models and Views provided in this library. Ready to use models are provided for use with views to interact with a tree of collections, a list of items in a collection, or a combined tree of Collections and items.
+
+## Collections and Items {#collections_and_items}
+
+In the Akonadi concept, Items are individual objects of PIM data, e.g. emails, contacts, events, notes etc. The data in an item is stored in a typed payload. For example, if an Akonadi Item holds a contact, the contact is available as a KABC::Addressee:
+
+~~~~~~~~~~~~~{.cpp}
+if (item.hasPayload<KABC::Addressee>()) {
+ KABC::Addressee addr = item.payload<KABC::Addressee>();
+ // use addr in some way...
+}
+~~~~~~~~~~~~~
+
+Additionally, an Item must have a mimetype which corresponds to the type of payload it holds.
+
+Collections are simply containers of Items. A Collection has a name and a list of mimetypes that it may contain. A collection may for example contain events if it can contain the mimetype 'text/calendar'. A Collection itself (as opposed to its contents) has a mimetype, which is the same for all Collections. A Collection which can itself contain Collections must be able to contain the Collection mimetype.
+
+~~~~~~~~~~~~~{.cpp}
+Collection col;
+// This collection can contain events and nested collections.
+col.setContentMimetypes({ Akonadi::Collection::mimeType(),
+ QStringLiteral("text/calendar") });
+~~~~~~~~~~~~~
+
+This system makes it simple to create PIM applications. For example, to create an application for viewing and editing events, you simply need to tell %Akonadi to retrieve all items matching the mimetype 'text/calendar'.
+
+## Convenience Mimetype Accessors {#convenience_mimetype_accessors}
+
+In order to avoid typos, improve readability, and to encapsulate the correct mimetypes for particular pim items, many of the standard classes have an accessor for the kind of mimetype the can handle. For example, you can use KMime::Message::mimeType() for emails, KABC::Addressee::mimeType() for contacts etc. It makes sense to define a similar static function in your own types.
+
+~~~~~~~~~~~~~{.cpp}
+col.setContentMimetypes({ Akonadi::Collection::mimeType(),
+ KABC::Addressee::mimeType(),
+ KMime::Message::mimeType() });
+~~~~~~~~~~~~~
+
+## Models and Views {#models_and_views}
+Akonadi models and views are a high level way to interact with the Akonadi server. Most applications will use these classes. See the EntityTreeModel documentation for more information.
+
+Models provide an interface for viewing, deleting and moving Items and Collections. New Items can also be created by dropping data of the appropriate type on a model. Additionally, the models are updated automatically if another application changes the data or inserts or deletes items etc.
+
+Akonadi provides several models for particular uses, e.g. the MailModel is used for emails and the ContactsModel is used for showing contacts. Additional specific models can be implemented using EntityTreeModel as a base class.
+
+A typical use of these would be to create a model and use proxy models to make the view show different parts of the model. For example, show a collection tree in on one side and show items in a selected collection in another view.
+
+~~~~~~~~~~~~~{.cpp}
+mailModel = new MailModel(session, monitor, this);
+
+collectionTree = new Akonadi::EntityMimeTypeFilterModel(this);
+collectionTree->setSourceModel(mailModel);
+// Filter out everything that is not a collection.
+collectionTree->addMimeTypeInclusionFilter(Akonadi::Collection::mimeType());
+collectionTree->setHeaderSet(Akonadi::EntityTreeModel::CollectionTreeHeaders);
+
+collectionView = new Akonadi::EntityTreeView(this);
+collectionView->setModel(collectionTree);
+
+itemList = new Akonadi::EntityMimeTypeFilterModel(this);
+itemList->setSourceModel(mailModel);
+// Filter out collections
+itemList->addMimeTypeExclusionFilter(Akonadi::Collection::mimeType());
+itemList->setHeaderSet(Akonadi::EntityTreeModel::ItemListHeaders);
+
+itemView = new Akonadi::EntityTreeView(this);
+itemView->setModel(itemList);
+~~~~~~~~~~~~~
+
+![An email application using MailModel](/docs/images/mailmodelapp.png "An email application using MailModel")
+
+The content of the model is determined by the configuration of the Monitor passed into it. The examples below show a use of the EntityTreeModel and some proxy models for a simple heirarchical note collection. As the model is generic, the configuration and proxy models will also work with any other mimetype.
+
+~~~~~~~~~~~~~{.cpp}
+// Configure what should be shown in the model:
+Monitor *monitor = new Akonadi::Monitor(this);
+monitor->fetchCollection(true);
+monitor->setItemFetchScope(scope);
+monitor->setCollectionMonitored(Akonadi::Collection::root());
+monitor->setMimeTypeMonitored(MyEntity::mimeType());
+
+Akonadi::Session *session = new Akonadi::Session(QByteArray("MyEmailApp-") + QByteArray::number(qrand()), this);
+monitor->setSession(session);
+
+Akonadi::EntityTreeModel *entityTree = new Akonadi::EntityTreeModel(monitor, this);
+~~~~~~~~~~~~~
+
+![A plain EntityTreeModel in a view](/docs/images/entitytreemodel.png "A plain EntityTreeModel in a view")
+
+The EntityTreeModel can be further configured for certain behaviours such as fetching of collections and items.
+
+To create a model of only a collection tree and no items, set that in the model. This is just like CollectionModel:
+
+~~~~~~~~~~~~~{.cpp}
+entityTree->setItemPopulationStrategy(Akonadi::EntityTreeModel::NoItemPopulation);
+~~~~~~~~~~~~~
+
+![A plain EntityTreeModel which does not fetch items.](/docs/images/entitytreemodel-collections.png "A plain EntityTreeModel which does not fetch items.")
+
+Or, create a model of only items and not child collections. This is just like ItemModel:
+
+~~~~~~~~~~~~~{.cpp}
+entityTree->setRootCollection(myCollection);
+entityTree->setCollectionFetchStrategy(Akonadi::EntityTreeModel::FetchNoCollections);
+~~~~~~~~~~~~~
+
+Or, to create a model which includes items and first level collections:
+
+~~~~~~~~~~~~~{.cpp}
+entityTree->setCollectionFetchStrategy(Akonadi::EntityTreeModel::FetchFirstLevelCollections);
+~~~~~~~~~~~~~
+
+The items in the model can also be inserted lazily for performance reasons. The Collection tree is always built immediately.
+
+Additionally, a KDescendantsProxyModel may be used to alter how the items in the tree are presented.
+
+~~~~~~~~~~~~~{.cpp}
+// ... Create an entityTreeModel
+KDescendantsProxyModel *descProxy = new KDescendantsProxyModel(this);
+descProxy->setSourceModel(entityTree);
+view->setModel(descProxy);
+~~~~~~~~~~~~~
+
+![A KDescendantsProxyModel wrapping an EntityTreeModel](/docs/images/descendantentitiesproxymodel.png "A KDescendantsProxyModel wrapping an EntityTreeModel")
+
+KDescendantsProxyModel can also display ancestors of each Entity in the list.
+
+~~~~~~~~~~~~~{.cpp}
+// ... Create an entityTreeModel
+KDescendantsProxyModel *descProxy = new KDescendantsProxyModel(this);
+descProxy->setSourceModel(entityTree);
+
+// #### This is new
+descProxy->setDisplayAncestorData(true, QLatin1String(" / "));
+
+view->setModel(descProxy);
+~~~~~~~~~~~~~
+
+![A DescendantEntitiesProxyModel with ancestor names.](/docs/images/descendantentitiesproxymodel-withansecnames.png "A DescendantEntitiesProxyModel with ancestor names.")
+
+This proxy can be combined with a filter to for example remove collections.
+
+~~~~~~~~~~~~~{.cpp}
+// ... Create an entityTreeModel
+DescendantEntitiesProxyModel *descProxy = new DescendantEntitiesProxyModel(this);
+descProxy->setSourceModel(entityTree);
+
+// #### This is new.
+Akonadi::EntityMimeTypeFilterModel *filterModel = new Akonadi::EntityMimeTypeFilterModel(this);
+filterModel->setSourceModel(descProxy);
+filterModel->setExclusionFilter({ Akonadi::Collection::mimeType() });
+
+view->setModel(filterModel);
+~~~~~~~~~~~~~
+
+![An EntityMimeTypeFilterModel wrapping a DescendantEntitiesProxyModel wrapping an EntityTreeModel](/docs/images/descendantentitiesproxymodel-colfilter.png "An EntityMimeTypeFilterModel wrapping a DescendantEntitiesProxyModel wrapping an EntityTreeModel")
+
+It is also possible to show the root item as part of the selectable model:
+
+~~~~~~~~~~~~~{.cpp}
+entityTree->setIncludeRootCollection(true);
+~~~~~~~~~~~~~
+
+![An EntityTreeModel showing Collection::root](/docs/images/entitytreemodel-showroot.png "An EntityTreeModel showing Collection::root")
+
+By default the displayed name of the root collection is '[*]', because it doesn't require i18n, and is generic. It can be changed too.
+
+~~~~~~~~~~~~~{.cpp}
+entityTree->setIncludeRootCollection(true);
+entityTree->setRootCollectionDisplayName(i18nc("Name of top level for all collections in the application", "[All]"))
+~~~~~~~~~~~~~
+
+![An EntityTreeModel showing Collection::root with an application specific name.](/docs/images/entitytreemodel-showrootwithname.png "An EntityTreeModel showing Collection::root with an application specific name.")
+
+These can of course be combined to create an application which uses one EntityTreeModel along with several proxies and views.
+
+~~~~~~~~~~~~~{.cpp}
+// ... create an EntityTreeModel.
+Akonadi::EntityMimeTypeFilterModel *collectionTree = new Akonadi::EntityMimeTypeFilterModel(this);
+collectionTree->setSourceModel(entityTree);
+// Filter to include collections only:
+collectionTree->setInclusionFilter({ Akonadi:: Collection::mimeType() });
+Akonadi::EntityTreeView *treeView = new Akonadi::EntityTreeView(this);
+treeView->setModel(collectionTree);
+
+Akonadi::EntityMimeTypeFilterModel *itemList = new Akonadi::EntityMimeTypeFilterModel(this);
+itemList->setSourceModel(entityTree);
+// Filter *out* collections
+itemList->setExclusionFilter({ Akonadi::Collection::mimeType() });
+Akonadi::EntityTreeView *listView = new Akonadi::EntityTreeView(this);
+listView->setModel(itemList);
+~~~~~~~~~~~~~
+
+![A single EntityTreeModel with several views and proxies.](/docs/images/treeandlistapp.png "A single EntityTreeModel with several views and proxies.")
+
+Or to also show items of child collections in the list:
+
+~~~~~~~~~~~~~{.cpp}
+// ... Create an entityTreeModel
+collectionTree = new Akonadi::EntityMimeTypeFilterModel(this);
+collectionTree->setSourceModel(entityTree);
+
+// Include only collections in this proxy model.
+collectionTree->addMimeTypeInclusionFilter(Akonadi::Collection::mimeType());
+
+treeview->setModel(collectionTree);
+
+descendedList = new DescendantEntitiesProxyModel(this);
+descendedList->setSourceModel(entityTree);
+
+itemList = new Akonadi::EntityMimeTypeFilterModel(this);
+itemList->setSourceModel(descendedList);
+
+// Exclude collections from the list view.
+itemList->addMimeTypeExclusionFilter(Akonadi::Collection::mimeType());
+
+listView = new EntityTreeView(this);
+listView->setModel(itemList);
+~~~~~~~~~~~~~
+
+![Showing descendants of all Collections in the list](/docs/images/treeandlistappwithdesclist.png "Showing descendants of all Collections in the list")
+
+Note that it is important in this case to use the DescendantEntitesProxyModel before the EntityMimeTypeFilterModel. Otherwise, by filtering out the collections first, you would also be filtering out their child items.
+
+A SelectionProxyModel can be used to simplify managing selection in one view through multiple proxy models to a representation in another view. The selectionModel of the initial view is used to create a proxied model which includes only the selected indexes and their children.
+
+
+~~~~~~~~~~~~~{.cpp}
+// ... Create an entityTreeModel
+collectionTree = new Akonadi::EntityMimeTypeFilterModel(this);
+collectionTree->setSourceModel(entityTree);
+
+// Include only collections in this proxy model.
+collectionTree->addMimeTypeInclusionFilter(Akonadi::Collection::mimeType());
+
+treeview->setModel(collectionTree);
+
+// SelectionProxyModel can handle complex selections:
+treeview->setSelectionMode(QAbstractItemView::ExtendedSelection);
+
+SelectionProxyModel *selProxy = new SelectionProxyModel(treeview->selectionModel(), this);
+selProxy->setSourceModel(entityTree);
+
+Akonadi::EntityTreeView *selView = new Akonadi::EntityTreeView(splitter);
+selView->setModel(selProxy);
+~~~~~~~~~~~~~
+
+![A Selection in one view creating a model for use with another view.](/docs/images/selectionproxymodelsimpleselection.png "A Selection in one view creating a model for use with another view.")
+
+The SelectionProxyModel can handle complex selections.
+
+![Non-contiguous selection creating a new simple model in a second view](/docs/images//selectionproxymodelmultipleselection.png "Non-contiguous selection creating a new simple model in a second view.")
+
+If an index and one or more of its descendants are selected, only the top-most selected index (including all of its descendants) are included in the proxy model. (Though this is configurable. See below)
+
+![Selecting an item and its descendant](/docs/images/selectionproxymodelmultipleselection-withdescendant.png "Selecting an item and its descendant.")
+
+SelectionProxyModel allows configuration using the methods setStartWithChildTrees, setOmitDescendants, setIncludeAllSelected. See testapp/proxymodeltestapp to try out the 5 valid configurations.
+
+Obviously, the SelectionProxyModel may be used in a view, or further processed with other proxy models. See the example_contacts application for example which uses a further DescendantEntitiesProxyModel and EntityMimeTypeFilterModel on top of a SelectionProxyModel.
+
+The SelectionProxyModel orders its items in the same top-to-bottom order as they appear in the source model. Note that this order may be different to the order in the selection model if there is a QSortFilterProxyModel between the selection and the source model.
+
+![Ordered items in the SelectionProxyModel](/docs/images/selectionproxymodel-ordered.png "Ordered items in the SelectionProxyModel")
+
+Details on the actual implementation of lazy population are described on [this page](@ref internals).
+
+# Jobs and Monitors {#jobs_and_monitors}
+
+The lower level way to interact with Akonadi is to use Jobs and Monitors (This is what models use internally). Jobs are used to make changes to akonadi, and in some cases (e.g., a fetch job) emit a signal with data resulting from the job. A Monitor reports changes made to the data stored in Akonadi (e.g., creating, updating, deleting or moving an item or collection ) via signals.
+
+Typically, an application will configure a monitor to report changes to a particular Collection, mimetype or resource, and then connect to the signals it emits.
+
+Most applications will use some of the low level api for actions unrelated to a model-tree view, such as creating new items and collections.
+
+# Tricky details {#tricky_details}
+
+## Change Conflicts {#change_conflicts}
+It is possible that while an application is editing an item, that item gets updated in akonadi. Akonadi will notify the application that that item has changed via a Monitor signal. It is the responsibility of the application to handle the conflict by for example offering the user a dialog to resolve it. Alternatively, the application could ignore the dataChanged signal for that item, and will get another chance to resolve the conflict when trying to save the result back to akonadi. In that case, the ItemModifyJob will fail and report that the revision number of the item on the server differs from its revision number as reported by the job. Again, it is up to the application to handle this case.
+
+This is something that every application using akonadi will have to handle.
+
+## Using Item::Id or Collection::Id as an identifier {#using_id_as_an_identifier}
+
+Items and Collections have a id() member which is a unique identifier used by akonadi. It can be useful to use the id() as an identifier when storing Collections or Items.
+
+However, as an item and a collection can have the same id(), if you need to store both Collections and Items together by a simple identifier, conflicts can occur.
+
+~~~~~~~~~~~~~{.cpp}
+QString getRemoteIdById(Item::Id id)
+{
+ // Note:
+ // m_items is QHash<Item::Id, Item>
+ // m_collections is QHash<Collection::Id, Collection>
+ if (m_items.contains(id)) {
+ // Oops, we could accidentally match a collection here.
+ return m_items.value(id).remoteId();
+ } else if (m_collections.contains(id)) {
+ return m_collections.value(id).remoteId();
+ }
+ return QString();
+}
+~~~~~~~~~~~~~
+
+In this case, it makes more sense to use a normal qint64 as the internal identifier, and use the sign bit to determine if the identifier refers to a Collection or an Item. This is done in the implementation of EntityTreeModel to tell Collections and Items apart.
+
+~~~~~~~~~~~~~{.cpp}
+qstring getremoteidbyinternalidentifier(qint64 internalidentifier)
+{
+ // note:
+ // m_items is qhash<item::id, item>
+ // m_collections is qhash<collection::id, collection>
+
+ // if the id is negative, it refers to an item
+ // otherwise it refers to a collection.
+
+ if (internalidentifier < 0) {
+ // reverse the sign of the id before using it.
+ return m_items.value(-internalidentifier).remoteid();
+ } else {
+ return m_collections.value(internalidentifier).remoteid();
+ }
+}
+~~~~~~~~~~~~~
+
+
+### Unordered Lists {#unordered_lists}
+Collection and Item both provide a ::List to represent groups of objects. However the objects in the list are usually not ordered in any particular way, even though the API provides methods to work with an ordered list. It makes more sense to think of it as a Set instead of a list in most cases.
+
+For example, when using an ItemFetchJob to fetch the items in a collection, the items could be in any order when returned from the job. The order that a Monitor emits notices of changes is also indeterminate. By using a Transaction however, it is sometimes possible to retrieve objects in order. Additionally, using s constructor overload in the CollectionFetchJob it is possible to retrieve collections in a particular order.
+
+~~~~~~~~~~~~~{.cpp}
+Collection::List getCollections(const QList<Collection::Id> &idsToGet)
+{
+ Collection::List getList;
+ for (Collection::Id id : idsToGet) {
+ getList << Collection(id);
+ }
+ CollectionFetchJob *job = CollectionFetchJob(getList);
+ if (job->exec()) {
+ // job->collections() is in the same order as the ids in idsToGet.
+ }
+}
+~~~~~~~~~~~~~
+
+# Resources {#resources}
+The KDEPIM module includes resources for handling many types of PIM data, such as imap email, vcard files and vcard directories, ical event files etc. These cover many of the sources for your PIM data, but in the case that you need to use data from another source (for example a website providing a contacts storage service and an api), you simply have to write a new resource.
+
+http://techbase.kde.org/Development/Tutorials/Akonadi/Resources
+
+# Serializers {#serializers}
+Serializers provide the functionality of converting raw data, for example from a file, to a strongly typed object of PIM data. For example, the addressee serializer reads data from a file and creates a KABC::Addressee object.
+
+New serializers can also easily be written if the data you are dealing with is not one of the standard PIM data types.
+
+# Implementation details {#implementation_details}
+
+## Updating Akonadi Models {#updating_models}
+
+NOTE: The details here are only relevant if you are writing a new view using EntityTreeModel, or writing a new model.
+
+Because communication with Akonadi happens asynchronously, and the models only hold a cached copy of the data on the akonadi server, some typical behaviours of models are not followed by Akonadi models.
+
+For example, when setting data on a model via a view, most models syncronously update their internal store and notify akonadi to update its view of the data by returning <tt>true</tt>.
+
+<!--
+TODO: Render this manually
+@dot
+digraph utmg {
+ rankdir = LR;
+ { node [label="",style=invis, height=0, width=0 ];
+ V_Set_Data; V_Result; V_Data_Changed;
+ M_Set_Data; M_Result;
+ }
+ { node [shape=box, fillcolor=lightyellow, style=filled,fontsize=26];
+ View [label=":View"]; Model [label=":Model"];
+ }
+ { node [style=invis];
+ View_EOL; Model_EOL;
+ }
+ {
+ V_Set_Data -> M_Set_Data [label="Set Data"];
+ M_Result -> V_Result [label="Success",arrowhead="vee", style="dashed"];
+ V_Result -> V_Data_Changed [label="Update View \n[ Success = True ]"];
+ }
+
+ // Dashed Vertical lines for object lifetimes.
+ edge [style=dashed, arrowhead=none];
+ { rank = same; View -> V_Set_Data -> V_Result -> V_Data_Changed -> View_EOL; }
+ { rank = same; Model -> M_Set_Data -> M_Result -> Model_EOL; }
+
+ // Make sure top nodes are in a straight line.
+ { View -> Model [style=invis]; }
+ // And the bottom nodes.
+ { View_EOL -> Model_EOL [style=invis]; }
+}
+@enddot
+//-->
+
+Akonadi models only cache data from the Akonadi server. To update data on an Akonadi::Entity stored in a model, the model makes a request to the Akonadi server to update the model data. At that point the data cached internally in the model is not updated, so <tt>false</tt> is always returned from setData. If the request to update data on the Akonadi server is successful, an Akonadi::Monitor notifies the model that the data on that item has changed. The model then updates its internal data store and notifies the view that the data has changed. The details of how the Monitor communicates with akonadi are omitted for clarity.
+
+<!--
+TODO: Render this into PNG
+@dot
+digraph utmg {
+ rankdir = LR;
+ { node [label="",style=invis, height=0, width=0 ];
+ ETV_Set_Data; ETV_Result; ETV_Data_Changed;
+ ETM_Set_Data; ETM_Result; ETM_Changed;
+ M_Dummy_1; M_Changed;
+ AS_Modify;
+ }
+ { node [shape=box, fillcolor=lightyellow, style=filled,fontsize=26];
+ EntityTreeView [label=":View"]; EntityTreeModel [label=":Model"]; Monitor [label=":Monitor"]; Akonadi_Server [label=":Akonadi"];
+ }
+ { node [style=invis];
+ EntityTreeView_EOL; EntityTreeModel_EOL; Monitor_EOL; Akonadi_Server_EOL;
+ }
+ {
+ { rank = same; ETV_Set_Data -> ETM_Set_Data [label="Set Data"]; }
+ { rank = same; ETM_Result -> ETV_Result [label="False",arrowhead="vee", style="dashed"]; }
+ { rank = same; ETM_Result -> M_Dummy_1 [style=invis]; }
+ { rank = same; ETM_Set_Data -> AS_Modify [arrowhead="vee",taillabel="Modify Item", labeldistance=14.0, labelangle=10]; }
+ { rank = same; M_Changed -> ETM_Changed [arrowhead="vee",label="Item Changed"]; }
+ { rank = same; ETM_Changed -> ETV_Data_Changed [arrowhead="vee",label="Update View"]; }
+ }
+
+ // Dashed Vertical lines for object lifetimes.
+ edge [style=dashed, arrowhead=none];
+ { rank = same; EntityTreeView -> ETV_Set_Data -> ETV_Result -> ETV_Data_Changed -> EntityTreeView_EOL; }
+ { rank = same; EntityTreeModel -> ETM_Set_Data -> ETM_Result -> ETM_Changed -> EntityTreeModel_EOL; }
+ { rank = same; Monitor -> M_Dummy_1 -> M_Changed -> Monitor_EOL; }
+ { rank = same; Akonadi_Server -> AS_Modify -> Akonadi_Server_EOL; }
+
+ // Make sure top nodes are in a straight line.
+ { EntityTreeView -> EntityTreeModel -> Monitor -> Akonadi_Server [style=invis]; }
+ // And the bottom nodes.
+ { EntityTreeView_EOL -> EntityTreeModel_EOL -> Monitor_EOL -> Akonadi_Server_EOL [style=invis]; }
+}
+@enddot
+//-->
+
+Similarly, in drag and drop operations, most models would update an internal data store and return <tt>true</tt> from dropMimeData if the drop is successful.
+
+<!--
+TODO: Render this to PNG
+@dot
+digraph utmg {
+ rankdir = LR;
+ { node [label="",style=invis, height=0, width=0 ];
+ Left_Phantom; Left_Phantom_DropEvent;
+ V_DropEvent; V_Result; V_Data_Changed; V_Dummy_1;
+ M_DropMimeData; M_Result;
+ }
+ { node [shape=box, fillcolor=lightyellow, style=filled,fontsize=26];
+ View [label=":View"]; Model [label=":Model"];
+ }
+ { node [style=invis];
+ Left_Phantom_EOL;
+ View_EOL; Model_EOL;
+ }
+ {
+ Left_Phantom_DropEvent -> V_DropEvent [label="DropEvent"];
+ V_DropEvent -> M_DropMimeData [label="DropMimeData"];
+ M_Result -> V_Result [label="Success",arrowhead="vee", style="dashed"];
+ V_Result -> V_Data_Changed [label="Update View \n[Success = True]"];
+ }
+
+ // Dashed Vertical lines for object lifetimes.
+ edge [style=dashed, arrowhead=none];
+ { rank = same; View -> V_DropEvent -> V_Result -> V_Dummy_1 -> V_Data_Changed -> View_EOL; }
+ { rank = same; Model -> M_DropMimeData -> M_Result -> Model_EOL; }
+
+ //Phantom line
+ { rank= same; Left_Phantom -> Left_Phantom_DropEvent -> Left_Phantom_EOL [style=invis]; }
+
+ // Make sure top nodes are in a straight line.
+ { Left_Phantom -> View -> Model [style=invis]; }
+ // And the bottom nodes.
+ { Left_Phantom_EOL -> View_EOL -> Model_EOL [style=invis]; }
+}
+@enddot
+//--->
+
+Akonadi models, for the same reason as above, always return false from dropMimeData. At the same time a suitable request is sent to the akonadi server to make the changes resulting from the drop (for example, moving or copying an entity, or adding a new entity to a collection etc). If that request is successful, the Akonadi::Monitor notifies the model that the data is changed and the model updates its internal store and notifies the view that the model data is changed.
+
+<!--
+TODO: Render this to PNG
+@dot
+digraph utmg {
+ rankdir = LR;
+ { node [label="",style=invis, height=0, width=0 ];
+ Left_Phantom; Left_Phantom_DropEvent;
+ ETV_DropEvent; ETV_Result; ETV_Data_Changed;
+ ETM_DropMimeData; ETM_Result; ETM_Changed;
+ M_Dummy_1; M_Changed;
+ AS_Modify;
+ }
+ { node [shape=box, fillcolor=lightyellow, style=filled,fontsize=26];
+ EntityTreeView [label=":View"];
+ EntityTreeModel [label=":Model"];
+ Monitor [label=":Monitor"];
+ Akonadi_Server [label=":Akonadi"];
+ }
+ { node [style=invis];
+ Left_Phantom_EOL;
+ EntityTreeView_EOL; EntityTreeModel_EOL; Monitor_EOL; Akonadi_Server_EOL;
+ }
+
+ {
+ { rank = same; Left_Phantom_DropEvent -> ETV_DropEvent [label="DropEvent"]; }
+ { rank = same; ETV_DropEvent -> ETM_DropMimeData [label="Drop MimeData"]; }
+ { rank = same; ETM_Result -> ETV_Result [label="False",arrowhead="vee", style="dashed"]; }
+ { rank = same; ETM_Result -> M_Dummy_1 [style=invis]; }
+ { rank = same; ETM_DropMimeData -> AS_Modify [arrowhead="vee",taillabel="Action", labeldistance=14.0, labelangle=10]; }
+ { rank = same; M_Changed -> ETM_Changed [arrowhead="vee",label="Item Changed"]; }
+ { rank = same; ETM_Changed -> ETV_Data_Changed [arrowhead="vee",label="Update View"]; }
+ }
+
+ // Dashed Vertical lines for object lifetimes.
+ edge [style=dashed, arrowhead=none];
+ { rank = same; EntityTreeView -> ETV_DropEvent -> ETV_Result -> ETV_Data_Changed -> EntityTreeView_EOL; }
+ { rank = same; EntityTreeModel -> ETM_DropMimeData -> ETM_Result -> ETM_Changed -> EntityTreeModel_EOL; }
+ { rank = same; Monitor -> M_Dummy_1 -> M_Changed -> Monitor_EOL; }
+ { rank = same; Akonadi_Server -> AS_Modify -> Akonadi_Server_EOL; }
+
+ //Phantom line
+ { rank= same; Left_Phantom -> Left_Phantom_DropEvent -> Left_Phantom_EOL [style=invis]; }
+
+ // Make sure top nodes are in a straight line.
+ { Left_Phantom -> EntityTreeView -> EntityTreeModel -> Monitor -> Akonadi_Server [style=invis]; }
+ // And the bottom nodes.
+ { Left_Phantom_EOL -> EntityTreeView_EOL -> EntityTreeModel_EOL -> Monitor_EOL -> Akonadi_Server_EOL [style=invis]; }
+}
+@enddot
+//-->
diff --git a/docs/history.md b/docs/history.md
new file mode 100644
index 0000000..f3d4c20
--- /dev/null
+++ b/docs/history.md
@@ -0,0 +1,46 @@
+# Historical background {#history}
+
+## General
+
+During the last 5 years, after the release of KDE 3.0, the requirements of our users
+have constantly increased. While it was sufficient that our PIM solution was able to handle 100 contacts,
+300 events and maybe 1000 mails in 2001, nowadays users expect the software to be able to
+handle a multiple of that. Over the years, the KDE PIM developers tried to catch up with the new
+requirements; however, since KDE 3.x had to stay binary compatible, they were limited in their
+efforts.
+
+With the new major release KDE 4.0 it's possible to completely redesign the PIM libraries from
+the ground up and use new concepts to face the requirements of 2006 and beyond.
+
+After some discussion at the annual KDE PIM meeting in Osnabrück in January 2006, the PIM developers
+came to the conclusion that a service is needed which acts as a local cache on the user's desktop
+and provides search facilities. The name Akonadi comes from a divinity from Ghana and was chosen since
+all other nice names were already used by other projects on the Internet ;)
+
+## Problems with the implementation of KDE 3.x
+
+Before digging into the internals of Akonadi, we want to take a look at the implementation of the
+old KDE PIM libraries to understand the problems and conceptual shortcomings.
+
+The main PIM libraries libkabc (contacts) and libkcal (events) where designed at a time when the
+address book and calendar were files on the local file system, so there was no reason to think
+about access time and mode. The libraries accessed the files synchronously and loaded all data of the
+file into memory to be able to perform search queries on the data set. It worked well for local files,
+but over time plug-ins for loading data from groupware servers were written, so the synchronous access blocked
+applications which used libkabc/libkcal, and loading all 2000 contacts from a server is not only
+time consuming but also needs a lot of memory to store them locally. The KDE PIM developers tried to
+address the first issue by adding an asynchronous API, but it was not well implemented and was difficult to use.
+In the end, the design decisions caused the following problems:
+
+* Bad Performance
+* High Memory Consumption
+
+Another important but missing thing in the libraries was support for notifications and locking.
+The former was partly implemented (at least reflected by the API) but only implemented in the local
+file plug-in, so it was in practice unusable. The latter was also partly implemented but never really tested and
+lead to deadlocks sometimes, so the following problems appeared as well:
+
+* Missing Notifications
+* Missing Locking
+
+The main aim of Akonadi is to solve these issues and make use of the goodies which the new design brings.
diff --git a/dox/bufferedcaching1.png b/docs/images/bufferedcaching1.png
index 918eaf7..918eaf7 100644
--- a/dox/bufferedcaching1.png
+++ b/docs/images/bufferedcaching1.png
Binary files differ
diff --git a/dox/bufferedcaching2.png b/docs/images/bufferedcaching2.png
index 869e1b9..869e1b9 100644
--- a/dox/bufferedcaching2.png
+++ b/docs/images/bufferedcaching2.png
Binary files differ
diff --git a/dox/bufferedcaching3.png b/docs/images/bufferedcaching3.png
index bbee1a9..bbee1a9 100644
--- a/dox/bufferedcaching3.png
+++ b/docs/images/bufferedcaching3.png
Binary files differ
diff --git a/dox/bufferedcaching4.png b/docs/images/bufferedcaching4.png
index dbe08e0..dbe08e0 100644
--- a/dox/bufferedcaching4.png
+++ b/docs/images/bufferedcaching4.png
Binary files differ
diff --git a/dox/bufferedcaching6.png b/docs/images/bufferedcaching6.png
index 1f97cf6..1f97cf6 100644
--- a/dox/bufferedcaching6.png
+++ b/docs/images/bufferedcaching6.png
Binary files differ
diff --git a/dox/descendantentitiesproxymodel-colfilter.png b/docs/images/descendantentitiesproxymodel-colfilter.png
index 1c9232a..1c9232a 100644
--- a/dox/descendantentitiesproxymodel-colfilter.png
+++ b/docs/images/descendantentitiesproxymodel-colfilter.png
Binary files differ
diff --git a/dox/descendantentitiesproxymodel-withansecnames.png b/docs/images/descendantentitiesproxymodel-withansecnames.png
index f1cdc1d..f1cdc1d 100644
--- a/dox/descendantentitiesproxymodel-withansecnames.png
+++ b/docs/images/descendantentitiesproxymodel-withansecnames.png
Binary files differ
diff --git a/dox/descendantentitiesproxymodel.png b/docs/images/descendantentitiesproxymodel.png
index 01be72f..01be72f 100644
--- a/dox/descendantentitiesproxymodel.png
+++ b/docs/images/descendantentitiesproxymodel.png
Binary files differ
diff --git a/dox/entitytreemodel-collections.png b/docs/images/entitytreemodel-collections.png
index 526de57..526de57 100644
--- a/dox/entitytreemodel-collections.png
+++ b/docs/images/entitytreemodel-collections.png
Binary files differ
diff --git a/dox/entitytreemodel-showroot.png b/docs/images/entitytreemodel-showroot.png
index df9804d..df9804d 100644
--- a/dox/entitytreemodel-showroot.png
+++ b/docs/images/entitytreemodel-showroot.png
Binary files differ
diff --git a/dox/entitytreemodel-showrootwithname.png b/docs/images/entitytreemodel-showrootwithname.png
index 3b3820e..3b3820e 100644
--- a/dox/entitytreemodel-showrootwithname.png
+++ b/docs/images/entitytreemodel-showrootwithname.png
Binary files differ
diff --git a/dox/entitytreemodel.png b/docs/images/entitytreemodel.png
index 2b46121..2b46121 100644
--- a/dox/entitytreemodel.png
+++ b/docs/images/entitytreemodel.png
Binary files differ
diff --git a/dox/mailmodelapp.png b/docs/images/mailmodelapp.png
index 23b86e4..23b86e4 100644
--- a/dox/mailmodelapp.png
+++ b/docs/images/mailmodelapp.png
Binary files differ
diff --git a/dox/selectionproxymodel-ordered.png b/docs/images/selectionproxymodel-ordered.png
index 5c79d55..5c79d55 100644
--- a/dox/selectionproxymodel-ordered.png
+++ b/docs/images/selectionproxymodel-ordered.png
Binary files differ
diff --git a/dox/selectionproxymodelmultipleselection-withdescendant.png b/docs/images/selectionproxymodelmultipleselection-withdescendant.png
index 9a7a69d..9a7a69d 100644
--- a/dox/selectionproxymodelmultipleselection-withdescendant.png
+++ b/docs/images/selectionproxymodelmultipleselection-withdescendant.png
Binary files differ
diff --git a/dox/selectionproxymodelmultipleselection.png b/docs/images/selectionproxymodelmultipleselection.png
index b98c1bc..b98c1bc 100644
--- a/dox/selectionproxymodelmultipleselection.png
+++ b/docs/images/selectionproxymodelmultipleselection.png
Binary files differ
diff --git a/dox/selectionproxymodelsimpleselection.png b/docs/images/selectionproxymodelsimpleselection.png
index 798535d..798535d 100644
--- a/dox/selectionproxymodelsimpleselection.png
+++ b/docs/images/selectionproxymodelsimpleselection.png
Binary files differ
diff --git a/dox/treeandlistapp.png b/docs/images/treeandlistapp.png
index 0867b14..0867b14 100644
--- a/dox/treeandlistapp.png
+++ b/docs/images/treeandlistapp.png
Binary files differ
diff --git a/dox/treeandlistappwithdesclist.png b/docs/images/treeandlistappwithdesclist.png
index c5b790b..c5b790b 100644
--- a/dox/treeandlistappwithdesclist.png
+++ b/docs/images/treeandlistappwithdesclist.png
Binary files differ
diff --git a/docs/internals.md b/docs/internals.md
new file mode 100644
index 0000000..1a7ebef
--- /dev/null
+++ b/docs/internals.md
@@ -0,0 +1,33 @@
+# Internals documentation for Akonadi developers {#internals}
+
+## Lazy Model Population
+
+NOTE: This page is not part of the Akonadi API. It is provided as internal documentation for Akonadi maintainers. It was originally a blog post here: http://steveire.wordpress.com/2009/10/06/cache-invalidation-in-akonadi-models/
+@internal
+
+If using EntityTreeModel::LazyPopulation with your model, items will be fetched into the model when the collection they are a part of is selected. This ensures that the model is as sparsely populated as possible for performance reasons. As a consequence however, it is necessary to purge unused items from the model too. This is handled automatically when using an Akonadi::SelectionProxyModel.
+
+The problem is knowing when to invalidate the cache. If no application is currently showing the contents of a Collection, there is no need for the Items in that Collection to be fetched, cached and kept up to date in the model. The effect we would like to achieve is to purge the Items in a Collection when those items are no longer shown anywhere in the application. Generally, that will mean that the Collection is not selected.
+
+In Qt Model-View, the application data is stored in a model, and there may be one or more views attached to it displaying its contents. The model doesn’t have any knowledge of the views, and so it can’t know whether any particular Collection is selected, and purge its Iitems.
+
+To solve this, we use the KSelectionProxyModel, which already has a lot of code for managing the selection a user makes in a view. A subclass, Akonadi::SelectionProxyModel implements a reference counting system which increments the refcount of a Collection when it is selected, and decrements it when deselected. If the reference count of a Collection goes down to zero, it is put in a queue to be purged. It is not purged immediately, but queued because if the user is clicking around several Collection in a short time, we don’t want to purge the Collections each click or we’d lose the benefit of the caching. Like other <a href="http://qt-project.org/doc/qt-4.7/qobject.html#id-aa43c933-c869-42eb-af14-ff17b8304c96">similar optimisation techniques</a>, this violates the object-oriented principle of modularity, but it is worth it for the benefit it brings. The effect can be seen in the akonadiconsole tool by not filtering out the items from the tree.
+
+In the screenshots below I removed the filtering out of Items in the tree so that the fetching/purging can be seen. In real applications, the Items in the tree on the left would not be visible.
+
+@image html dox/bufferedcaching1.png "When a Collection is clicked, its Items are put into the model. The rest of the Collections have no items."
+
+@image html dox/bufferedcaching2.png "The Inbox Collection is selected, so its items are fetched. Personal Contacts is no longer selected, so it is put into a queue to be purged."
+
+@image html dox/bufferedcaching3.png "Select another Collection and its items are fetched too."
+
+@image html dox/bufferedcaching4.png "Another Collection is selected, pushing the Personal contacts out of the queue and purging them"
+
+@image html dox/bufferedcaching6.png "If the Collection is selected again, its Items are refetched"
+
+For this example, I used a queue length of just two Collections, so that if a Collection was deselected two clicks ago, it will be purged. In real applications, a longer queue length will be used, but it’s harder to illustrate in screenshots. Another unrealistic part of this demo is that this feature will like be used in applications like KMail where Collections can contain tens of thousands of Items and fetching them is an expensive operation.
+
+This feature should be totally invisible to users and even developers using Akonadi, but it should offset the main disadvantage of using a cache of Items in the EntityTreeModel.
+
+*/
+
diff --git a/docs/kontact.svg b/docs/kontact.svg
new file mode 100644
index 0000000..74457a3
--- /dev/null
+++ b/docs/kontact.svg
@@ -0,0 +1,88 @@
+<svg width="48" xmlns="http://www.w3.org/2000/svg" height="48" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <linearGradient id="a" y1="44" y2="20" x2="0" gradientUnits="userSpaceOnUse" gradientTransform="translate(384.57 499.8)">
+ <stop stop-color="#eef1f2"/>
+ <stop offset="1" stop-color="#f9fafb"/>
+ </linearGradient>
+ <linearGradient id="b" y1="529.8" x1="419.57" y2="536.8" x2="426.57" gradientUnits="userSpaceOnUse">
+ <stop/>
+ <stop offset="1" stop-opacity="0"/>
+ </linearGradient>
+ <linearGradient id="c" y1="519.8" y2="504.8" x2="0" gradientUnits="userSpaceOnUse" gradientTransform="translate(0 1)">
+ <stop stop-color="#bd8d48"/>
+ <stop offset="1" stop-color="#e8b971"/>
+ </linearGradient>
+ <linearGradient xlink:href="#c" id="d" y1="519.8" y2="504.8" x2="0" gradientUnits="userSpaceOnUse" gradientTransform="translate(0-1)"/>
+ <linearGradient id="e" x1="428.57" x2="406.57" gradientUnits="userSpaceOnUse">
+ <stop stop-color="#e3dfd6"/>
+ <stop offset="1" stop-color="#f4f1e8"/>
+ </linearGradient>
+ <linearGradient id="f" y1="516.8" x1="392.57" y2="508.8" x2="400.57" gradientUnits="userSpaceOnUse" gradientTransform="translate(0 1)">
+ <stop stop-color="#f39c12"/>
+ <stop offset="1" stop-color="#f5ab35"/>
+ </linearGradient>
+ <linearGradient id="g" x1="427.71" x2="437.71" gradientUnits="userSpaceOnUse">
+ <stop stop-color="#ebc69a"/>
+ <stop offset="1" stop-color="#f4e0c8"/>
+ </linearGradient>
+ <linearGradient xlink:href="#g" id="h" y1="541.51" x1="428.76" y2="528.51" gradientUnits="userSpaceOnUse" x2="430.47"/>
+ <linearGradient xlink:href="#b" id="i" y1="531.79" y2="544.79" x2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(.70711-.70711.70711.70711-649.01-56.06)"/>
+ </defs>
+ <g transform="translate(-384.57-499.8)">
+ <g stroke-linejoin="round" stroke-linecap="round" color="#000000">
+ <g transform="matrix(.96593-.25882.25882.96593-120.32 121.71)">
+ <rect width="19" x="392.57" y="509.8" fill="url(#f)" height="16"/>
+ <rect width="19" x="392.57" opacity=".2" y="509.8" fill="#ffffff" height="3"/>
+ </g>
+ <rect width="22" x="406.57" y="504.8" fill="url(#d)" height="33"/>
+ <rect width="22" x="406.57" y="505.8" fill="url(#e)" height="33"/>
+ <rect width="22" x="406.57" y="506.8" fill="url(#c)" height="33"/>
+ </g>
+ <g fill="url(#g)" transform="translate(-15.14-17.993)">
+ <path opacity=".2" fill="url(#i)" stroke-linejoin="round" color="#000000" d="m35.12 11.879l-4.242 4.242 2.637 2.637-3.891.148-.625 1.094v3l8.984.229 2.086 2.086 4.244-4.244z" transform="translate(399.71 517.79)"/>
+ <path fill="url(#h)" d="m432.71 528.79c-1.662 0-3 1.338-3 3 0 1.662 1.338 3 3 3 1.662 0 3-1.338 3-3 0-1.662-1.338-3-3-3m0 7c-2.77 0-5 .892-5 2v6h10v-6c0-1.108-2.23-2-5-2m0 1c2.216 0 4 .636 4 1.428v4.572h-8v-4.572c0-.791 1.784-1.428 4-1.428"/>
+ </g>
+ <path fill="url(#a)" d="m388.57 519.8v24h40v-24z"/>
+ <rect width="40" x="388.57" y="542.8" fill="#d1d3d4" height="1"/>
+ <g fill-rule="evenodd">
+ <path fill="#c0392b" d="m391.57 543.8l1-2h2l-1 2z"/>
+ <path fill="#2980b9" d="m399.57 543.8l1-2h2l-1 2z"/>
+ <path fill="#c0392b" d="m407.57 543.8l1-2h2l-1 2z"/>
+ <path fill="#2980b9" d="m415.57 543.8l1-2h2l-1 2z"/>
+ <path fill="#c0392b" d="m423.57 543.8l1-2h2l-1 2z"/>
+ <path fill="#2980b9" d="m426.57 537.8l2 1v2l-2-1z"/>
+ <path fill="#c0392b" d="m426.57 529.8l2 1v2l-2-1z"/>
+ <g fill="#2980b9">
+ <path d="m426.57 521.8l2 1v2l-2-1z"/>
+ <path d="m390.57 538.8l-2 1v2l2-1z"/>
+ </g>
+ <path fill="#c0392b" d="m390.57 530.8l-2 1v2l2-1z"/>
+ <path fill="#2980b9" d="m390.57 522.8l-2 1v2l2-1z"/>
+ <path fill="#c0392b" d="m390.57 519.8l1 2h2l-1-2z"/>
+ <path fill="#2980b9" d="m398.57 519.8l1 2h2l-1-2z"/>
+ <path fill="#c0392b" d="m406.57 519.8l1 2h2l-1-2z"/>
+ <path fill="#2980b9" d="m414.57 519.8l1 2h2l-1-2z"/>
+ <path fill="#c0392b" d="m422.57 519.8l1 2h2l-1-2z"/>
+ <path opacity=".2" fill="url(#b)" d="m424.57 523.8l4 4v11l-9-9z"/>
+ </g>
+ <g stroke-linejoin="round" stroke-linecap="round" color="#000000">
+ <rect width="5" x="419.57" y="523.8" fill="#fcfcfc" height="6"/>
+ <rect width="3" x="420.57" y="524.8" fill="#16a085" height="4"/>
+ <g fill="#bdc3c7">
+ <rect width="7" x="404.57" y="528.8" height="1"/>
+ <rect width="4" x="404.57" y="530.8" height="1"/>
+ <rect width="10" x="404.57" y="532.8" height="1"/>
+ <rect width="5" x="404.57" y="534.8" height="1"/>
+ <rect width="4" x="392.57" y="523.8" height="1"/>
+ <rect width="7" x="392.57" y="525.8" height="1"/>
+ <rect width="6" x="392.57" y="527.8" height="1"/>
+ </g>
+ <g fill="#7f8c8d">
+ <rect width="1" x="409.57" y="503.8" height="4"/>
+ <rect width="1" x="424.57" y="503.8" height="4"/>
+ <rect width="1" x="414.57" y="503.8" height="4"/>
+ <rect width="1" x="419.57" y="503.8" height="4"/>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/docs/server.md b/docs/server.md
new file mode 100644
index 0000000..ee8a5a1
--- /dev/null
+++ b/docs/server.md
@@ -0,0 +1,244 @@
+# Akonadi Server {#server}
+
+[TOC]
+
+This is the API documentation for the Akonadi server. If you are using Akonadi
+from within KDE, you almost certainly want the [client library documentation][client_libs_documentation].
+This API reference is more useful to people implementing client libraries or
+working on the Akonadi server itself.
+
+For additional information, see the <a href="http://community.kde.org/KDE_PIM/Akonadi">Akonadi website</a>.
+
+## Architecture
+
+<img src="http://community.kde.org/images.community/8/8e/Akonadi_Architecture.png"/>
+
+The Akonadi framework uses a client/server architecture. The Akonadi server has the following primary tasks:
+* Abstract access to data from arbitrary sources, using toolkit-agnostic protocols and data formats
+* Provide a data cache shared among several clients
+* Provide change notifications and conflict detection
+* Support offline change recording and change replay for remote data
+
+## Design Principles
+
+The Akonadi architecture is based on the following four design principles:
+
+* _Functionality is spread over different processes._
+ This separation has the big advantage that if one process crashes because of
+ a programming error it doesn't affect the other components. That results in
+ robustness of the whole system. A disadvantage might be that there is an additional
+ overhead due to inter-process communication.
+* _Communication protocol is split into data and control channel._
+ When doing communication between processes you have to differentiate between the type of data
+ that is being transferred. For a large amount of data a high-performance
+ protocol should be used and for control data a low-latency protocol.
+ Matching both requirements in one protocol is mostly impossible and hard to
+ achieve with currently available software.
+* _Separate logic from storage._
+ By separating the logic from the storage, the storage can be used to store data
+ of any type. In this case, the storage is a kind of service, which is available for
+ other components of the system. The logic is located in separated components and so
+ 3rd-party developers can extend the system by providing their own components.
+* _Keep communication asynchronous._
+ To allow a non-blocking GUI, all the communication with the back-end and within the
+ back-end itself must be asynchronous. You can easily provide a synchronous convenience
+ for the application developer; the back-end, however, must communicate asynchronously.
+
+## Components
+The Akonadi server itself consists of a number of components:
+* The Akonadi control process (`akonadi_control`). It is responsible for managing all other server components and Akonadi agents.
+* The Akonadi server process (`akonadiserver`). The actual data access and caching server.
+* The Akonadi agent server (`akonadi_agent_server`). Allows running of multiple Akonadi agents in one process.
+* The Akonadi agent launcher (`akonadi_agent_launcher`). A helper process for running Akonadi agents.
+* The Akonadi control tool (`akonadictl`). A tool to start/stop/restart the Akonadi server system and query its status.
+ This is the only program of these listed here you should ever run manually.
+* The Akonadi protocol library (`libakonadiprotocolinternals`), Contains protocol definitions and protocol parsing methods
+ useful for client implementations.
+
+### The Akonadi server process
+
+The Akonadi server process (`akonadiserver`) has the following tasks:
+* Provide a transaction-safe data store.
+* Provide operations to add/modify/delete items and collections in the local store, implementing the server side of the ASAP protocol.
+* Cache management of cached remote contents.
+* Manage virtual collections representing search results.
+* Provide change notifications for all known Akonadi objects over D-Bus.
+
+### The Akonadi server control process
+
+The Akondi control process (\c akonadi_control) has the following tasks:
+* Manage and monitor the other server processes.
+* Lifecycle management of agent instances using the various supported agent launch methods.
+* Monitor agent instances and provide crash recovery.
+* Provide D-Bus API to manage agents.
+* Provide change notifications on agent types and agent instances.
+
+## Objects and Data Types
+
+The Akonadi server operates on two basic object types, called items and collections. They are comparable to files and directories
+and are described in more detail in this section.
+
+## Akonadi Items
+
+An item is a generic container for whatever you want to store in Akonadi (eg. mails,
+events, contacts, etc.). An item consists of some generic information (such as identifier,
+mimetype, change date, flags, etc.) and a set of data fields, the item parts. Items
+are independent of the type of stored data, the semantics of the actual content is only
+known on the client side.
+
+## Items Parts
+
+Akonadi items can have one or more parts, e.g. an email message consists of the
+envelope, the body and possible one or more attachments. Item parts are identified
+by an identifier string. There are a few special pre-defined part identifiers (ALL,
+ENVELOPE, etc.), but in general the part identifiers are defined by the type specific
+extensions (ie. resource, serializer plugin, type specific client library).
+
+## Item Tags
+
+Tags are self-contained entities stored in separate database table. A tag is a
+relation between multiple items. Tags can have different types (PLAIN, ...) and applications
+can define their own type to describe application-specific relations. Tags can also have
+attributes to store additional metadata about the relation the tag describes.
+
+## Payload Data Serialization
+
+Item payload data is typically serialized in a standard format to ensure interoperability between different
+client library implementations. However, the %Akonadi server does not enforce any format,
+payload data is handled as an opaque binary blob.
+
+## Collections
+
+Collections are sets of items. Every item is stored in exactly one
+collection, this is sometimes also referred to as the "physical" storage location of the item.
+An item might also be visible in several other collections - so called "virtual collections" -
+which are defined as the result set of a search query.
+
+Collections are organized hierarchically, i.e. a collection can have child
+collections, thus defining a collection tree.
+
+Collections are uniquely identified by their identifier in
+contrast to their path, which is more robust with regard to renaming and moving.
+
+## Collection Properties
+
+Every collection has a set of supported content types.
+These are the mimetypes of items the collection can contain.
+Example: A collection of a folder-less iCal file resource would only support
+"text/calendar" items, a folder on an IMAP server "message/rfc822" but also
+"inode/directory" if it can contain sub-folders.
+
+There is a cache policy associated with every collection which defines how much
+of its content should be kept in the local cache and for how long.
+
+Additionally, collections can contain an arbitrary set of attributes to represent
+various other collection properties such as ACLs, quotas or backend-specific data
+used for incremental synchronization. Evaluation of such attributes is the responsibility
+of client implementations, the %Akonadi server does not interpret properties
+other than content types and cache policies.
+
+## Collection Tree
+
+There is a single collection tree in Akonadi, consisting of several parts:
+
+* A root node, id 0
+* One or more top-level collections for each resource. Think of these as mount-points
+ for the resource. The resources must put their items and sub-collections into their
+ corresponding top-level collection.
+* Resource-dependent sub-collections below the resource top-level collections.
+ If the resource represents data that is organized in folders (e.g. an IMAP
+ resource), it can create additional collections below its top-level
+ collection. These have to be synched with the corresponding backend by the
+ resource.
+ Resources which represent folder-less data (e.g. an iCal file) don't need
+ any sub-collections and put their items directly into the top-level collection.
+* A top-level collection containing virtual collections.
+
+Example:
+
+ +-+ resource-folder1
+ | +- sub-folder1
+ | +- sub-folder2
+ | ...
+ +-+ resource-folder2
+ | ...
+ |
+ +-+ Searches
+ +- search-folder1
+ +- search-folder2
+ ...
+
+
+## Object Identification
+
+### Unique Identifier
+
+Every object stored in %Akonadi (collections and items) has a unique
+identifier in the form of an integer value. This identifier cannot be changed in
+any way and will stay the same, regardless of any modifications to the referred
+object. A unique identifier will never be used twice and is globally unique,
+therefore it is possible to retrieve an item without knowing the collection it belongs to.
+
+### Remote Identifier
+
+Every object can also have an optional so-called remote identifier. This is an
+identifier used by the corresponding resource to identify the object on its
+backend (e.g., a groupware server).
+
+The remote identifier can be changed by the owning resource agent only.
+
+Special case applies for Tags, where each tag can have multiple remote IDs. This fact is
+however opaque to resources as each resource is shown only the remote ID that it had
+provided when inserting the tag into Akonadi.
+
+### Global Identifier
+
+Every item can has also so called GID, an identifier specific to the content (payload)
+of the item. The GID is extracted from the payload by client serializer when storing the
+item in Akonadi. For example, contacts have vCard "UID" field as their GID, emails can
+use value of "Message-Id" header.
+
+## Communication Protocols
+
+For communication within the Akonadi server infrastructure and for communication with Akonadi clients, two communication technologies are used:
+* D-Bus Used for management tasks and change notifications.
+* ASAP (Akonadi Server Access Protocol), used for high-throughput data transfer. ASAP is based on the well-known IMAP protocol (RFC 3501) which has been proven it's ability to handle large quantities of data in practice already.
+
+## Interacting with Akonadi
+
+There are various possibilities to interact with Akonadi.
+
+### Akonadi Client Libraries
+
+Accessing the Akonadi server using the ASAP and D-Bus interfaces directly is cumbersome.
+Therefore you'd usually use a client library implementing the low-level protocol handling
+and providing convenient high-level APIs for Akonadi operations.
+
+### Akonadi Agents
+
+Akonadi agents are processes which are controlled by the Akonadi server itself. Agents typically
+operate autonomously (ie. without much user interaction) on the objects handled by Akonadi, mostly
+by reacting to change notifications sent by the Akonadi server.
+
+Agents can implement specialized interfaces to provide additional functionality.
+The most important ones are the so-called resource agents.
+
+Resource agents are connectors that provide access to data from an external source, and replay local changes
+back to their corresponding backend.
+
+## Implementation Details
+
+### Data and Metadata Storage
+
+The Akonadi server uses two mechanisms for data storage:
+* A SQL databases for metadata and small payload data
+* Plain files for large payload data
+
+More details on the SQL database layout can be found here: \ref akonadi_server_database.
+
+The following SQL databases are supported by the Akonadi server:
+* MySQL using the default QtSQL driver shipped with Qt
+* Sqlite using the improved QtSQL driver shipped with the Akonadi server
+* PostgreSQL using the default QtSQL driver shipped with Qt
+
+For details on how to configure the various backends, see Akonadi::DataStore.
diff --git a/metainfo.yaml b/metainfo.yaml
new file mode 100644
index 0000000..ba8799a
--- /dev/null
+++ b/metainfo.yaml
@@ -0,0 +1,47 @@
+name: akonadi
+description: PIM Storage Framework
+group: kdepim
+platforms:
+ - name: Linux
+public_lib: true
+libraries:
+ - qmake: AkonadiCore
+ cmake: KF5::AkonadiCore
+ cmakename: KF5AkonadiCore
+ - qmake: AkonadiAgentBase
+ cmake: KF5::AkonadiAgentBase
+ cmakename: KF5AkonadiAgentBase
+ - qmake: AkonadiWidgets
+ cmake: KF5::AkonadiWidgets
+ cmakename: KF5AkonadiWidgets
+ - qmake: AkonadiXml
+ cmake: KF5::AkonadiXml
+ cmakename: KF5AkonadiXml
+irc: akonadi
+
+group_info:
+ fancyname: KDE PIM
+ maintainer: mlaurent dvratil
+ irc: kontact
+ mailinglist: kde-pim
+ platforms:
+ - Linux
+ description: KDE PIM provides set of libraries and application to access and
+ manage personal information like emails, contacts, events, etc.
+ logo: docs/kontact.svg
+ long_description:
+ - KDE PIM provides a set of libraries and applications to access and
+ manage personal information like emails, contacts, events, etc.
+ - KDE PIM provides a set of libraries to parse and interact with various
+ standardized PIM data formats, like RFC822 (KMime), ICAL (KCalendarCore)
+ or VCARD (KContacts).
+ - The backbone of the entire suite is Akonadi, the PIM storage framework.
+ Akonadi provides unified API to access and manage any kind of PIM data
+ regardless of the actual storage backend.
+ - There are quite a few other libraries that provide PIM-specific widgets
+ and utilities and can be useful for application developers who need to
+ work with PIM data in their projects.
+ - Please note that unless stated otherwise, none of the libraries have
+ stable API or ABI as of now. We are trying to keep the changes small and
+ we always announce big changes ahead on the mailing lists, but as the
+ project evolves we might need to adjust some API here and there.