Home · All Classes · Grouped Classes · Annotated · Functions

Qtopia Data Sharing (QDS)

Introduction

Qtopia Data Sharing (QDS) provides an API to efficiently share and process data between applications, and provides mechanisms for finding and interacting with applications which provide desired QDS services. For example an application may want to display a street map for a location, instead of doing the conversion itself the application can search for a QDS service which takes a street address and returns an image of the street map.

How it Works

QDS is a form of remote procedure call, layered on top of Qtopia services, which is optimised for data processing and sharing. QDS encapsulates data into a typed data object (QDSData) which is provided for the request, the response or both.

QDS models the procedure call as an action. Actions are invoked in applications to request a service from an application which provides a QDS service. The provider then handles the action request and responds with any data.

Using QDS

Applications can utilise QDS through the QDS classes:

As mentioned previously, the QDSData store class is used to manage the sharing and transfer of temporary or persistent data. The data in an QDSData object is made persistent by calling QDSData::store(), each application which needs the data in the future must call QDSData::store(). QDSData::remove() should be called when the data is no longer required by an application. This is required to manage the data lifetime.

Finding QDS services

Applications use the QDSServices class to search for available QDS services. The search is defined on a combination of request data type, response data type, attributes, and Qtopia service.

If the details of a QDSService are already known a QDSServiceInfo object can be constructed directly, and used to validate the existence of the QDS service.

Requesting QDS services

An application uses a QDS service by constructing a QDSAction object with a valid QDSServiceInfo object. Depending on the suitability to the application, requests for the QDS service can then be made synchronously or asynchronously using the QDSAction object.

Example of synchronous request

    QDSServiceInfo service( "getImage", "ExampleService" );
    QDSAction action( service);
    if ( action.exec() != QDSAction::Complete ) {
        qWarning() << "Couldn't use QDS service setImage from ExampleService";
    }

Example of asynchronous request

    void MyWidget::getImage()
    {
        QDSServiceInfo service( "getImage", "ExampleService" );
        QDSAction* action = new QDSAction( service );

        connect( action,
                 SIGNAL( response( const QLocalUniqueId&, const QDSData& ) ),
                 this,
                 SLOT( response( const QLocalUniqueId&, const QDSData& ) ) );

        action->invoke();
    }

    void MyWidget::response( const QLocalUniqueId& actionId, const QDSData& responseData )
    {
        if ( ( action != 0 ) && ( action->id() == actionId ) ) {
            QByteArray imageKey = responseData.store();
            QSettings settings( "MySoft", "MyWidget" );
            settings.setValue( "imageKey", imageKey );
            action->deleteLater();
        }
    }

Note in a typical implementation you should also connect to the QDSAction::error() signal to catch any errors that occur with the request.

Security Policy

For devices which use SXE the application's project file must including qds in the package domain as well as the domain which provides access to the Qtopia service. For example file for a QDS client application is provided below:

    qtopia_project(qtopia app)
    TARGET=myapp

    HEADERS=myapp.h
    SOURCES=main.cpp myapp.cpp

    desktop.files=myapp.desktop
    desktop.path=/apps/Applications

    INSTALLS+=desktop

    pkg.name=myapp
    pkg.desc=myapp
    pkg.version=4.1
    pkg.maintainer=Trolltech (www.trolltech.com)
    pkg.license=GPL
    pkg.domain=window,qds,ExampleService

Providing QDS services

Any application can provide a number of QDS services. A public slot must be added to the application's Qtopia service class for each QDS service it provides. The slot must match the message constructed by QDSAction, which is of the form void ClassName( const QDSActionRequest& request ). QDS services can be made dependent on features defined in QtopiaFeatures, when these features are not present the service will not be available, and requests for the service will fail. For more details about service implementations see Qtopia's service documentation. Finally, each QDS service should be described in the QDS service file (see QDSServiceInfo for details).

The example below demonstrates a server application which allows an image to set and restored.

    MyServer::MyServer( QWidget *parent, Qt::WFlags f )
    :   QMainWindow( parent, f )
    {
        ...

        service = new ExampleService( this );

        ....
    }

    void MyServer::getImage( const QDSActionRequest& request )
    {
        QDSActionRequest requestCopy( request );
        QSettings settings( "MySoft", "MyServer" );
        QByteArray imageKey = settings.getValue( "imageKey" );
        requestCopy.respond( QDSData( imageKey ) );
    }

    void MyServer::setImage( const QDSActionRequest& request )
    {
        QDSActionRequest requestCopy( request );
        QByteArray imageKey = requestCopy.requestData().store();
        QSettings settings( "MySoft", "MyServer" );
        settings.setValue( "imageKey", imageKey );
        requestCopy.respond();
    }

    class ExampleService : public QtopiaAbstractService
    {
        Q_OBJECT
        friend class MyServer;
    private:
        ExampleService( MyServer *parent )
        :   QtopiaAbstractService( "ExampleService", parent )
        {
            this->parent = parent;
            publishAll();
        }

    public slots:
        void getImage( const QDSActionRequest& request )
        {
            parent->getImage( request );
        }

        void setImage( const QDSActionRequest& request )
        {
            parent->setImage( request );
        }

    private:
        MyServer *parent;
    };

If the processing of the QDS service request is going to take substantial time, i.e. more than second, or requires user input a copy of the QDSActionRequest should be made as is done in the MyServer::getImage() and MyServer::setImage() methods above. This ensures that the client is informed that the request is being processed and a timeout error is not generated.

Security Policy

As with client applications, for devices which use SXE an application providing a QDS service must include qds in the package domain in the project file (see above for details), as well as the domain which provides access to the service class.

Extensibility

As QDSData is typed, QDS provides an extensible API which can be used with user-defined classes by defining a MIME type for the class.

The example below shows to create a QDSData instance of a VCard using a streaming operator to pack the VCard into a QByteArray.

    VCard vcard;
    QByteArray vCardArray;
    {
        QDataStream stream( &vCardArray, QIODevice::WriteOnly );
        stream << vcard;
    }
    QDSData vCardData( vCardArray, QMimeType( "text/x-vCard" ) );

This allows services to be provided for text/x-vCard data assuming that there has streaming operator defined in the VCard class.

For example

    //declare the streaming function in the VCard's header file
    QDataStream& operator<<( QDataStream& stream, const VCard& vcard );

    ...

    //implement the streaming function in the VCard's cpp file
    QDataStream& operator<<( QDataStream& stream, const VCard& vcard )
    {
    ...
    }


Copyright © 2008 Nokia Trademarks
Qtopia 4.3.3