src/contacts/qcontactabstractrequest.cpp
changeset 0 876b1a06bc25
child 5 603d3f8b6302
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qcontactabstractrequest.h"
       
    43 #include "qcontactabstractrequest_p.h"
       
    44 #include "qcontactmanager.h"
       
    45 #include "qcontactmanager_p.h"
       
    46 #include "qcontactmanagerengine.h"
       
    47 
       
    48 #include <QMutex>
       
    49 #include <QMutexLocker>
       
    50 
       
    51 QTM_BEGIN_NAMESPACE
       
    52 /*!
       
    53   \class QContactAbstractRequest
       
    54 
       
    55   \brief The QContactAbstractRequest class provides a mechanism for
       
    56   asynchronous requests to be made of a manager if it supports them.
       
    57 
       
    58   \ingroup contacts-main
       
    59 
       
    60   It allows a client to asynchronously request some functionality of a
       
    61   particular QContactManager.  Instances of the class will emit signals
       
    62   when the state of the request changes, or when more results become
       
    63   available.
       
    64 
       
    65   Clients should not attempt to create instances of this class directly,
       
    66   but should instead use the use-case-specific classes derived from this
       
    67   class.
       
    68 
       
    69   All such request classes have a similar interface: clients set the
       
    70   parameters of the asynchronous call, including which manager the
       
    71   request will be made of, and then call the start() slot of the request.
       
    72   The manager will then enqueue or begin to process the request, at which
       
    73   point the request's state will transition from \c InactiveState to
       
    74   \c ActiveState.  After any state transition, the request will emit the
       
    75   stateChanged() signal.  The manager may periodically update the request
       
    76   with results, at which point the request will emit the resultsAvailable()
       
    77   signal.  These results are not guaranteed to have a stable ordering.
       
    78   Error information is considered a result, so some requests will emit the
       
    79   resultsAvailable() signal even if no results are possible from the request
       
    80   (for example, a contact remove request) when the manager updates the request
       
    81   with information about any errors which may have occurred.
       
    82 
       
    83   Please see the class documentation of each of the use-case-specific
       
    84   classes derived from this class for information about how to retrieve
       
    85   the results of a request (including error information).  In all cases,
       
    86   those functions are synchronous, and will return the cached result set with
       
    87   which the manager has updated the request instance if the resultsAvailable()
       
    88   signal has been emitted.
       
    89 
       
    90   Clients can choose which signals they wish to handle from a request.
       
    91   If the client is not interested in interim results, they can choose to
       
    92   handle only the stateChanged() signal, and in the slot to which that
       
    93   signal is connected, check whether the state has changed to either
       
    94   \c FinishedState or \c CanceledState (both of which signify that the
       
    95   manager has finished handling the request, and that the request will not
       
    96   be updated with any more results).  If the client is not interested in
       
    97   any results (including error information), they may choose to delete
       
    98   the request after calling \l start(), or simply not connect the
       
    99   request's signals to any slots.
       
   100 
       
   101   If the request is allocated via operator new, the client must
       
   102   delete the request when they are no longer using it in order to avoid
       
   103   leaking memory.  That is, the client retains ownership of the request.
       
   104 
       
   105   The client may delete a heap-allocated request in various ways:
       
   106   by deleting it directly (but not within a slot connected to a signal
       
   107   emitted by the request), or by using the deleteLater() slot to schedule
       
   108   the request for deletion when control returns to the event loop (from
       
   109   within a slot connected to a signal emitted by the request, for example
       
   110   \l stateChanged()).
       
   111 
       
   112   An active request may be deleted by the client, but the client will not
       
   113   receive any notifications about whether the request succeeded or not,
       
   114   nor any results of the request.
       
   115 
       
   116   Because clients retain ownership of any request object, and may delete
       
   117   a request object at any time, manager engine implementors must be careful
       
   118   to ensure that they do not assume that a request has not been deleted
       
   119   at some point during processing of a request, particularly if the engine
       
   120   has a multithreaded implementation.  It is suggested that engine
       
   121   implementors read the \l{Qt Contacts Manager Engines} documentation for
       
   122   more information on this topic.
       
   123  */
       
   124 
       
   125 /*!
       
   126   \fn QContactAbstractRequest::stateChanged(QContactAbstractRequest::State newState)
       
   127   This signal is emitted when the state of the request is changed.  The new state of
       
   128   the request will be contained in \a newState.
       
   129  */
       
   130 
       
   131 
       
   132 /*!
       
   133   \fn QContactAbstractRequest::resultsAvailable()
       
   134   This signal is emitted when new results are available.  Results can include
       
   135   the operation error which may be accessed via error(), or derived-class-specific
       
   136   results which are accessible through the derived class API.
       
   137 
       
   138   \sa error()
       
   139  */
       
   140 
       
   141 /*!
       
   142   \enum QContactAbstractRequest::RequestType
       
   143   Enumerates the various possible types of asynchronous requests
       
   144   \value InvalidRequest An invalid request
       
   145   \value ContactFetchRequest A request to fetch a list of contacts
       
   146   \value ContactLocalIdFetchRequest A request to fetch a list of local contact ids
       
   147   \value ContactRemoveRequest A request to remove a list of contacts
       
   148   \value ContactSaveRequest A request to save a list of contacts
       
   149   \value DetailDefinitionFetchRequest A request to fetch a collection of detail definitions
       
   150   \value DetailDefinitionRemoveRequest A request to remove a list of detail definitions
       
   151   \value DetailDefinitionSaveRequest A request to save a list of detail definitions
       
   152   \value RelationshipFetchRequest A request to fetch relationships between contacts
       
   153   \value RelationshipRemoveRequest A request to remove any relationships which match the request criteria
       
   154   \value RelationshipSaveRequest A request to save a list of relationships
       
   155  */
       
   156 
       
   157 /*!
       
   158   \enum QContactAbstractRequest::State
       
   159   Enumerates the various states that a request may be in at any given time
       
   160   \value InactiveState Operation not yet started
       
   161   \value ActiveState Operation started, not yet finished
       
   162   \value CanceledState Operation is finished due to cancellation
       
   163   \value FinishedState Operation successfully completed
       
   164  */
       
   165 
       
   166 /*!
       
   167   \fn QContactAbstractRequest::QContactAbstractRequest(QObject* parent)
       
   168   Constructs a new, invalid asynchronous request with the specified \a parent
       
   169  */
       
   170 
       
   171 /*!
       
   172   \internal
       
   173   Constructs a new request from the given request data \a otherd with
       
   174   the given parent \a parent
       
   175 */
       
   176 QContactAbstractRequest::QContactAbstractRequest(QContactAbstractRequestPrivate* otherd, QObject* parent)
       
   177     : QObject(parent), d_ptr(otherd)
       
   178 {
       
   179 }
       
   180 
       
   181 /*! Cleans up the memory used by this request */
       
   182 QContactAbstractRequest::~QContactAbstractRequest()
       
   183 {
       
   184      delete d_ptr;
       
   185 }
       
   186 
       
   187 /*!
       
   188   Returns true if the request is in the \c QContactAbstractRequest::InactiveState state; otherwise, returns false
       
   189 
       
   190   \sa state()
       
   191  */
       
   192 bool QContactAbstractRequest::isInactive() const
       
   193 {
       
   194     QMutexLocker ml(&d_ptr->m_mutex);
       
   195     return (d_ptr->m_state == QContactAbstractRequest::InactiveState);
       
   196 }
       
   197 
       
   198 /*!
       
   199   Returns true if the request is in the \c QContactAbstractRequest::ActiveState state; otherwise, returns false
       
   200 
       
   201   \sa state()
       
   202  */
       
   203 bool QContactAbstractRequest::isActive() const
       
   204 {
       
   205     QMutexLocker ml(&d_ptr->m_mutex);
       
   206     return (d_ptr->m_state == QContactAbstractRequest::ActiveState);
       
   207 }
       
   208 
       
   209 /*!
       
   210   Returns true if the request is in the \c QContactAbstractRequest::FinishedState; otherwise, returns false
       
   211 
       
   212   \sa state()
       
   213  */
       
   214 bool QContactAbstractRequest::isFinished() const
       
   215 {
       
   216     QMutexLocker ml(&d_ptr->m_mutex);
       
   217     return (d_ptr->m_state == QContactAbstractRequest::FinishedState);
       
   218 }
       
   219 
       
   220 /*!
       
   221   Returns true if the request is in the \c QContactAbstractRequest::CanceledState; otherwise, returns false
       
   222 
       
   223   \sa state()
       
   224  */
       
   225 bool QContactAbstractRequest::isCanceled() const
       
   226 {
       
   227     QMutexLocker ml(&d_ptr->m_mutex);
       
   228     return (d_ptr->m_state == QContactAbstractRequest::CanceledState);
       
   229 }
       
   230 
       
   231 /*! Returns the overall error of the most recent asynchronous operation */
       
   232 QContactManager::Error QContactAbstractRequest::error() const
       
   233 {
       
   234     QMutexLocker ml(&d_ptr->m_mutex);
       
   235     return d_ptr->m_error;
       
   236 }
       
   237 
       
   238 /*!
       
   239   Returns the type of this asynchronous request
       
   240  */
       
   241 QContactAbstractRequest::RequestType QContactAbstractRequest::type() const
       
   242 {
       
   243     QMutexLocker ml(&d_ptr->m_mutex);
       
   244     return d_ptr->type();
       
   245 }
       
   246 
       
   247 /*!
       
   248   Returns the current state of the request.
       
   249  */
       
   250 QContactAbstractRequest::State QContactAbstractRequest::state() const
       
   251 {
       
   252     QMutexLocker ml(&d_ptr->m_mutex);
       
   253     return d_ptr->m_state;
       
   254 }
       
   255 
       
   256 /*! Returns a pointer to the manager of which this request instance requests operations */
       
   257 QContactManager* QContactAbstractRequest::manager() const
       
   258 {
       
   259     QMutexLocker ml(&d_ptr->m_mutex);
       
   260     return d_ptr->m_manager;
       
   261 }
       
   262 
       
   263 /*!
       
   264     Sets the manager of which this request instance requests operations to \a manager
       
   265 
       
   266     If the request is currently active, this function will return without updating the \a manager object.
       
   267 */
       
   268 void QContactAbstractRequest::setManager(QContactManager* manager)
       
   269 {
       
   270     QMutexLocker ml(&d_ptr->m_mutex);
       
   271     // In theory we might have been active and the manager didn't cancel/finish us
       
   272     if (d_ptr->m_state == QContactAbstractRequest::ActiveState && d_ptr->m_manager)
       
   273         return;
       
   274     d_ptr->m_manager = manager;
       
   275 }
       
   276 
       
   277 /*! Attempts to start the request.  Returns false if the request is not in the \c QContactAbstractRequest::Inactive, \c QContactAbstractRequest::Finished or \c QContactAbstractRequest::Cancelled states,
       
   278     or if the request was unable to be performed by the manager engine; otherwise returns true. */
       
   279 bool QContactAbstractRequest::start()
       
   280 {
       
   281     QMutexLocker ml(&d_ptr->m_mutex);
       
   282     QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
       
   283     if (engine && (d_ptr->m_state == QContactAbstractRequest::CanceledState
       
   284                    || d_ptr->m_state == QContactAbstractRequest::FinishedState
       
   285                    || d_ptr->m_state == QContactAbstractRequest::InactiveState)) {
       
   286         ml.unlock();
       
   287         return engine->startRequest(this);
       
   288     }
       
   289 
       
   290     return false; // unable to start operation; another operation already in progress or no engine.
       
   291 }
       
   292 
       
   293 /*! Attempts to cancel the request.  Returns false if the request is not in the \c QContactAbstractRequest::Active state,
       
   294     or if the request is unable to be cancelled by the manager engine; otherwise returns true. */
       
   295 bool QContactAbstractRequest::cancel()
       
   296 {
       
   297     QMutexLocker ml(&d_ptr->m_mutex);
       
   298     QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
       
   299     if (engine && d_ptr->m_state == QContactAbstractRequest::ActiveState) {
       
   300         ml.unlock();
       
   301         return engine->cancelRequest(this);
       
   302     }
       
   303 
       
   304     return false; // unable to cancel operation; not in progress or no engine.
       
   305 }
       
   306 
       
   307 /*! Blocks until the request has been completed by the manager engine, or until \a msecs milliseconds has elapsed.
       
   308     If \a msecs is zero, this function will block indefinitely.
       
   309     Returns true if the request was cancelled or completed successfully within the given period, otherwise false.
       
   310     Some backends are unable to support this operation safely, and will return false immediately.
       
   311 
       
   312     Note that any signals generated while waiting for the request to complete may be queued and delivered
       
   313     some time after this function has returned, when the calling thread's event loop is dispatched.  If your code
       
   314     depends on your slots being invoked, you may need to process events after calling this function.
       
   315  */
       
   316 bool QContactAbstractRequest::waitForFinished(int msecs)
       
   317 {
       
   318     QMutexLocker ml(&d_ptr->m_mutex);
       
   319     QContactManagerEngine *engine = QContactManagerData::engine(d_ptr->m_manager);
       
   320     if (engine) {
       
   321         switch (d_ptr->m_state) {
       
   322         case QContactAbstractRequest::ActiveState:
       
   323             ml.unlock();
       
   324             return engine->waitForRequestFinished(this, msecs);
       
   325         case QContactAbstractRequest::CanceledState:
       
   326         case QContactAbstractRequest::FinishedState:
       
   327             return true;
       
   328         default:
       
   329             return false;
       
   330         }
       
   331     }
       
   332 
       
   333     return false; // unable to wait for operation; not in progress or no engine.
       
   334 }
       
   335 
       
   336 #include "moc_qcontactabstractrequest.cpp"
       
   337 
       
   338 QTM_END_NAMESPACE