Qt API | Qtopia API | Qtopia Documentation | ![]() |
Warning: The Qtopia Desktop synchronization framework is still experimental. Note that the API may be changed for the next Qtopia release.
Qtopia Desktop is the Qtopia application that runs on a end-users desktop. It provides the end-user with the following functionality:
Qtopia Desktop can easily be extended by the developer to be able to extend the above functionality for their application's data. In fact, most existing functionality provided by Qtopia Desktop is provided by Trolltech using this architecture. Every icon seen on the left hand column of Qtopia Desktop is using the same architecture and APIs that is exposed to any developer.
For historical reasons, you may see the name Palmtop Center in function names or the code. This was an earlier name for Qtopia Desktop.
Qtopia Desktop has modular and flexible design allowing end-users to easily install plugins to integrate Qtopia into their daily work environment.
Developers can access this architecture by writing a plugin for Qtopia Desktop. A plugin is written by implementing interfaces defined by Qtopia Desktop.
The available interfaces allow the developer to:
Qtopia Desktop provides each plugin with access to the CenterInterface. The CenterInterface class allows each plugin to use the functionality provided by Qtopia Desktop.
When Qtopia Desktop starts up it scans for plugins and registers any
plugins that support the interfaces. Qtopia Desktop will look in the
subdirectory under the installed directory called lib. Plugin
installations should place their shared object libraries in the
Qtopia Desktop contains the algorithms for synchronization for any
plugin.
Qtopia Desktop handles synchronizing multiple plugins working on the
same application data. So there can be multiple plugins that
synchronize Contacts data such as Qtopia's Contacts and My
Desktop PIM Application's address book.
The sync algorithm remembers the last state of each plugin when it was
last synced. It then uses that information to determine what changes
have occured in each plugin. A master document is created by
merging those changes. Each plugin is then given a list of changes
that it should apply so that its contents will be same as the
master document.
The diffs are performed at a field level, so a conflict is created if
the user modifies the same field of the same record in multiple
plugins or interfaces. The algorithm used for conflict resolution of
two records depends on what the user has selected in the
Settings->Sync dialog (currently, the user can choose from duplicating
records, or letting the pda or the desktop win).
This algorirthm requires two main methods for each plugin:
Currently, the only architecture supported is synchronizing
that data that needs to be merged together. Future versions will
support plugins that simply wish to transfer a set of files and possibly
do manual operations on those files.
Qtopia Desktop requires each plugin to convert it's data between the
plugin's internal representation of its data and a generic way to
define any data. Qtopia Desktop uses MergeML::Record as a generic
storage class for anyone's data. MergeML::Record stores its data in
an QMap<int, QString>, where the key refers to the type of field in the map.
For the core pims (Contacts, Todo List and Calendar), the integer
values used in the QMap<int, QString> have been defined in their PIM
library classes. There are individual record classes for these data
sets, which are Contact, Task and Event, respectively. These classes
provide convenience methods which convert to and from a
QMap<int,QString> . Each class has a toMap()
method and a constructor that takes the QMap<int,QString> in their
constructor.
There are static templated methods provided in mergeml.h that help the
developer convert between a lists of QMap<int,QString> and a list of
these PIM classes. They are MergeML::convertToML() and
MergeML::convertFromML(). These templated methods will be helpfull for the
developer when implementing SyncAppInterface::load() and
SyncAppInterface::save().
Each plugin implementation needs to define some pure virtual methods defined
in the plugin hierarchy. Each plugin must define the following methods:
The name() method and queryInterface() are the most important. The
description(), version() and author() methods are all purely
informational and not currently displayed by Qtopia Desktop but maybe
in the future.
The PluginInterface::name() method defines the display name shown in
the plugin selection area on the left hand side of the screen. The
name() method is purely descriptive for all other interfaces.
The implementation of queryInterface() allows Qtopia
Desktop determine what type of interface your plugin implements when
it registers your plugin at startup.
In the the interfaces .cpp file, the following code must be present
The exact implementation of the queryInterface() method depends on
which interfaces your plugin is implementing. Each plugin should
only have one implementation of queryInterface. Each plugin can
implement more than one interface as shown above. (And multiple
interfaces can be implemented by the same class as shown
above). Every interface other than SyncAppInterface implements both
QUnknownInterface and QComponentInformationInterface and should
return as such as shown above.
Synchronization Architecture and Algorithms
Data Conversion during Synchronization
Implementing a Plugin
QRESULT queryInterface( const QUuid&, QUnknownInterface** );
Q_REFCOUNT
QString name() const;
QString description() const;
QString version() const;
QString author() const;
Q_EXPORT_INTERFACE()
{
Q_CREATE_INSTANCE( AddressBook )
}
QRESULT AddressBook::queryInterface( const QUuid &uuid,
QUnknownInterface** iface )
{
*iface = 0;
if ( uuid == IID_QUnknown )
*iface = (QUnknownInterface*) (PluginInterface*) this;
else if ( uuid == IID_QComponentInformation )
*iface = (QComponentInformationInterface*)(PluginInterface *) this;
else if ( uuid == IID_PalmtopCenterPlugin )
*iface = (PluginInterface*)this;
else if ( uuid == IID_SyncAppInterface )
*iface = (SyncAppInterface*)this;
else if ( uuid == IID_MergeInterface )
*iface = (MergeInterface*)this;
else
return QE_NOINTERFACE;
(*iface)->addRef();
return QS_OK;
}
Copyright © 2001-2002 Trolltech Trademarks