File: Mainpage.dox

package info (click to toggle)
akonadi 4:16.04.3-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 8,736 kB
  • sloc: cpp: 96,665; xml: 1,630; sh: 48; makefile: 23
file content (1137 lines) | stat: -rw-r--r-- 56,082 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
/**
\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