This section provides some examples of common usage of the Qt Organizer API.
Users of the items API can define which backend they wish to access if a manager for that backend is available. The list of available managers can be queried programmatically at run-time, and the capabilities of different managers can be ascertained by inspecting a QOrganizerItemManager instance. Furthermore, some managers can be constructed with parameters which affect the operation of the backend. In this example, the client constructs a particular backend, but does not construct it with any special parameters:
QOrganizerItemManager specificManager("KCal");
Most users of the API will want to use the default manager for the platform, which provides access to the system address book. Instantiating a manager by using the default constructor will result in the default manager for that platform being instantiated:
QOrganizerItemManager defaultManager;
The default constructor can either be used to create a manager on the stack, in which case it will be deleted automatically when it goes out of scope, or it can be used explicitly to create a manager on the heap, in which case the client must ensure that they delete the manager when they are finished with it in order to avoid a memory leak.
Different managers will support different capabilities and details. Clients can use the meta data reporting functions of QOrganizerItemManager to determine what the capabilities of the manager they have instantiated might be.
The client can choose to load a manager for a specific backend. While the engine could be found and retrieved using a more advanced plugin framework (such as the Qt Service Framework), this code assumes that the client has prior knowledge of the backend in question:
QOrganizerItemManager specificManager("KCal");
Clients may wish to use this feature of the API if they wish to store or retrieve item information to a particular manager (for example, one that interfaces with a particular online service).
The client can loads a manager with specific parameters defined. The parameters which are available are backend specific, and so the client has to know which parameters are valid for a particular backend, and what argument it takes.
Once an item has been created (or retrieved from a manager), the client can retrieve, create, update or delete details from the item. Since QOrganizerItem and QOrganizerItemDetail are both container (value) classes, the API offered for these operations is purely synchronous.
An item consists of the details it contains, as well as an id. Some details are read-only (such as the modification timestamp of an item) or irremovable (like the type of an item), but most are freely modifiable by clients. The QOrganizerItem::details(), QOrganizerItem::detail(), QOrganizerItem::saveDetail() and QOrganizerItem::removeDetail() functions can be used to manipulate these details.
To aid in the manipulation of common details, convenience functions are provided in QOrganizerItem like setDisplayLabel() and setDescription() which set and access the details directly. Many details are specific to particular types of items, and convenience functions for these are provided in the subclasses of QOrganizerItem. For example, the QOrganizerEvent class provides the function setStartDateTime(), which is equivalent to getting the QOrganizerEventTimeRange detail, setting the StartDateTime field and resaving it.
It is important to note that details are implicitly shared objects with particular semantics surrounding saving, removal and modification.
After instantiating a manager, clients will wish to retrieve or modify item information (detail definitions) which is persistently stored in the manager (for example, in a database or online cloud). This may be done synchronously or asynchronously. And example of synchronous usage is as follows:
If the client wishes to use the asynchronous API, it is suggested that their class uses member variables for the manager and requests. This allows them to define slots which deal with the data as required when the state of the request changes.
Note that if the client is interested in receiving the results of the request as they become available, rather than only the final set of results once the request changes state (to FinishedState, for example), the client should instead connect the QOrganizerItemAbstractRequest::resultsAvailable() signal to the slot which deals with the results.
Clients can create a new item simply by instantiating one and saving it a manager. The save operation will succeed if the item initially had a zero-id, and if the manager supports the details in the item. The item may be saved either synchronously by directly calling QOrganizerItemManager::saveItem() or asynchronously using a QOrganizerItemSaveRequest and connecting to that request's change signals. Alternatively, the client can explicitly block execution until the request is complete, by calling waitForFinished().
// a default constructed journal will have it's date/time set to the current date/time.
QOrganizerJournal journal;
journal.setDescription("The conference went well. We all agree that marshmallows are awesome, "\
"but we were unable to reach any agreement as to how we could possibly "\
"increase our intake of marshmallows. Several action points were assigned "\
"to various members of the group; I have been tasked with finding a good "\
"recipe that combines both marshmallows and chocolate, by next Wednesday.");
defaultManager.saveItem(&journal);
The client requests all items from the manager which match a particular filter, sorted according to a particular sort order.
// XXX TODO: make this more convenient. // QOrganizerItemLocation::matchLocationName("Meeting Room 8") ? QOrganizerItemDetailFilter locationFilter; locationFilter.setDetailDefinitionName(QOrganizerItemLocation::DefinitionName, QOrganizerItemLocation::FieldLocationName); locationFilter.setValue("Meeting Room 8"); QList<QOrganizerItem> entries = defaultManager.items(locationFilter);
The client can also retrieve a particular existing item from a manager, by directly requesting the item with a particular (previously known) id. With the asynchronous API, this takes the form of another filter. The synchronous API provides the QOrganizerItemManager::item() function specifically for this purpose.
Some items which clients are interested in may not be explicitly stored in the manager, but rather dynamically generated given a recurrence rule which is saved in a particular item. These are known as occurrences and may be retrieved by calling itemInstances(). Once retrieved, a generated occurrence may be saved into the manager, at which point it becomes an exception to the original item.
// the following line should be made simpler via QOIM::itemInstances(item, startDateTime, endDateTime, count)... QOrganizerEventOccurrence nextMarshmallowMeeting = QOrganizerEventOccurrence(defaultManager.itemInstances().value(0)); // should use dfil. nextMarshmallowMeeting.setStartDateTime(QDateTime::fromString("13.05.2010 18:00:00", "dd.MM.yy hh:mm:ss")); nextMarshmallowMeeting.setEndDateTime(QDateTime::fromString("13.05.2010 20:00:00", "dd.MM.yy hh:mm:ss")); nextMarshmallowMeeting.addComment("The next meeting will go for an hour longer (starting one "\ "hour earlier than usual), since we have scheduled one hour"\ "to taste the results of the recipe that I will be presenting "\ "at the meeting."); defaultManager.saveItem(&nextMarshmallowMeeting);
The client updates a previously saved item by saving the updated version of the item. Any item whose id is the same as that of the updated item will be overwritten as a result of the save request.
journal.addComment("Serves: 8. Ingredients: 500g Milk Chocolate, 500g Marshmallows. Step 1: Put the marshmallows into 8 separate bowls. Step 2: Melt the chocolate. Step 3: Pour the chocolate over the marshmallows in the bowls. Step 4: Put the bowls into the refrigerator for 20 minutes; serve chilled."); if (!defaultManager.saveItem(&journal)) qDebug() << "Unable to save updated journal! Error:" << defaultManager.error();
The client may remove an item from the manager by specifying its local id.
Clients can inform the manager that they do not require certain details from an item, which can allow a manager to optimize item retrieval. In this way, the client can inform the manager that they are not interested in any binary blob data (e.g., images) in retrieved items.
A client may query the schema supported by a manager, and check to see if a particular detail definition supports a certain field.
A client may attempt to modify a particular detail definition by extending it so that it supports an extra field, or add a new detail definition, or remove an existing one. These operations are not necessarily supported on various backends, and even those backends which do support a mutable schema may not allow modification of the default detail definitions.
Note that some managers do not support mutable definitions, and hence attempting to modify or remove detail definitions in those managers will fail.
A recurring item is an item that occurs more than once; for example, a meeting that occurs every week for the next 10 weeks. A recurring item is created by creating a QOrganizerEvent or QOrganizerTodo and adding a QOrganizerItemRecurrence detail to it to specify the rules for when it should recur. While the item occurs multiple times, the client only has to create it once and save it once. When QOrganizerItemManager::itemInstances() is called, any recurring items are expanded into multiple QOrganizerEventOccurrence and QOrganizerTodoOccurrence items by the manager. Each generated occurrence item has a local id of zero.
The client is able to make an exception for an occurrence by taking a generated item occurrence from the manager, making the necessary modifications, and resaving it. When the manager is then queried with QOrganizerItemManager::itemInstances(), it will return the list of occurrences as before, but with the modifications in place. The modified item will be given a non-zero local id, and replaces the generated one in the list.
The client can also query the manager for a list of unexpanded items by calling QOrganizerItemManager::items(). The list of returned items will contain all items that have been saved to the manager with a call to saveItem() (of course, without any items removed with removeItem()). That is, recurring events will be returned as is, and event occurrences will not appear unless they are exceptions (ie. have a non-zero local id). Fetching the list in this way can be useful for transfering items to other managers or for exporting to iCalendar with QtVersit.
It may be useful for clients to separate their organizer items into different organizers (eg. Personal and Work) and work with different views that show items from one, some or all of these organizers. This is functionality has not been implemented in this technical preview, but we currently are investigating the best model to use to offer this.