1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the QtOrganizer module of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
42
#include <qorganizermanagerengine.h>
43
#include <qorganizeritems.h>
44
#include <qorganizeritemdetails.h>
45
#include <qorganizeritemfilters.h>
46
#include <qorganizeritemrequests.h>
47
#include <private/qorganizeritemrequests_p.h>
49
#include <QtCore/qmutex.h>
51
QT_BEGIN_NAMESPACE_ORGANIZER
54
\class QOrganizerManagerEngine
55
\brief The QOrganizerManagerEngine class provides the interface to implement functionalities
56
of organizer managers.
58
\ingroup organizer-backends
60
This class should only be used by backend developers. Instances of this class are provided to
61
QOrganizerManager by a QOrganizerManagerEngineFactory instance, which is loaded from a plugin.
63
The default implementation of this interface provides a backend doing nothing, so that backend
64
developers only need to reimplement the functionalities needed.
66
More information on writing a organizer engine plugin is available in the \l{Qt Organizer Manager Engines}
69
\sa QOrganizerManager, QOrganizerManagerEngineFactory
73
\fn QOrganizerManagerEngine::dataChanged()
75
This signal should be emitted if the internal state of the plugin changes, and it is unable to
76
determine the changes which occurred, or if it considers the changes to be radical enough to
77
require clients to reload all data.
79
If this signal is emitted, no other signals will be emitted for the associated changes.
81
\sa itemsAdded(), itemsChanged(), itemsRemoved()
85
\fn QOrganizerManagerEngine::itemsAdded(const QList<QOrganizerItemId> &itemIds);
87
This signal should be emitted at some point once the items identified by \a itemIds have been
90
This signal should not be emitted if the dataChanged() signal was previously emitted for these
97
\fn QOrganizerManagerEngine::itemsChanged(const QList<QOrganizerItemId> &itemIds);
99
This signal should be emitted at some point once the items identified by \a itemIds have been
100
modified in the backend.
102
This signal should not be emitted if the dataChanged() signal was previously emitted for these
109
\fn QOrganizerManagerEngine::itemsRemoved(const QList<QOrganizerItemId> &itemIds);
111
This signal should be emitted at some point once the items identified by \a itemIds have been
112
removed from the backend.
114
This signal should not be emitted if the dataChanged() signal was previously emitted for these
121
\fn QOrganizerManagerEngine::itemsModified(const QList<QPair<QOrganizerItemId, QOrganizerManager::Operation> > &itemIds)
123
This signal should be emitted at some point once the items identified by \a itemIds have been
124
modified in the backend.
126
This signal should not be emitted if the dataChanged() signal was previously emitted for these
133
\fn QOrganizerManagerEngine::collectionsAdded(const QList<QOrganizerCollectionId> &collectionIds)
135
This signal should be emitted at some point once the collections identified by \a collectionIds
136
have been added to the backend.
138
This signal should not be emitted if the dataChanged() signal was previously emitted for these
145
\fn QOrganizerManagerEngine::collectionsChanged(const QList<QOrganizerCollectionId> &collectionIds)
147
This signal should be emitted at some point once the collections identified by \a collectionIds
148
have been changed in the backend.
150
This signal should not be emitted if items in the collections have been added, modified, or
153
This signal should not be emitted if the dataChanged() signal was previously emitted for these
160
\fn QOrganizerManagerEngine::collectionsRemoved(const QList<QOrganizerCollectionId> &collectionIds)
162
This signal should be emitted at some point once the collections identified by \a collectionIds
163
have been removed from the backend.
165
This signal should not be emitted if the dataChanged() signal was previously emitted for these
172
\fn QOrganizerManagerEngine::collectionsModified(const QList<QPair<QOrganizerCollectionId, QOrganizerManager::Operation> > &collectionIds)
174
This signal should be emitted at some point once the collections identified by \a collectionIds
175
have been modified in the backend.
177
This signal should not be emitted if the dataChanged() signal was previously emitted for these
184
Constructs an empty QOrganizerManagerEngine with the given \a parent.
186
QOrganizerManagerEngine::QOrganizerManagerEngine(QObject *parent)
192
This function should be reimplemented to return the name of this backend. The default implementation
193
returns the name "invalid".
195
QString QOrganizerManagerEngine::managerName() const
197
return QString(QStringLiteral("invalid"));
201
This function should be reimplemented to return the parameters used in when constructing this
202
backend. The default implementation returns an empty QMap.
204
If certain paramters are invalid, or discarded by the backend, they should not be returned.
206
QMap<QString, QString> QOrganizerManagerEngine::managerParameters() const
208
return QMap<QString, QString>();
212
Returns the unique URI of this manager, which is built from the manager name and the parameters
213
used to construct it.
215
QString QOrganizerManagerEngine::managerUri() const
217
return QOrganizerManager::buildUri(managerName(), managerParameters());
221
This function should be reimplemented to support synchronous calls to fetch occurrences of the
224
This function is supposed to return a list of a maximum of \a maxCount organizer item instances
225
which are occurrences of the given \a parentItem recurring item, which occur between the given
226
\a startDateTime and the given \a endDateTime date, inclusive. Any error which occurs should be
229
A default-constructed (invalid) \a startDateTime specifies an open start date time (matches anything
230
which occurs up until the \a endDateTime), and a default-constructed (invalid) \a endDateTime
231
specifies an open end date time (matches anything which occurs after the \a startDateTime). If
232
both the \a startDateTime and \a endDateTime are invalid, this function will return the IDs of
235
It's up to the backend to decide how many occurrences are returned if the given \a maxCount is
238
It's up to the backend to decide if fetch hint is supported. If supported, only the details
239
defined by \a fetchHint will be fetched.
241
QList<QOrganizerItem> QOrganizerManagerEngine::itemOccurrences(const QOrganizerItem &parentItem,
242
const QDateTime &startDateTime,
243
const QDateTime &endDateTime, int maxCount,
244
const QOrganizerItemFetchHint &fetchHint,
245
QOrganizerManager::Error *error)
247
Q_UNUSED(parentItem);
248
Q_UNUSED(startDateTime);
249
Q_UNUSED(endDateTime);
253
*error = QOrganizerManager::NotSupportedError;
254
return QList<QOrganizerItem>();
258
This function should be reimplemented to support synchronous calls to fetch organizer item IDs.
260
This function is supposed to return a list of item IDs of persisted organizer items that match
261
the given \a filter, sorted according to the given list of \a sortOrders, for any item which
262
occurs (or has an occurrence which occurs) in the range specified by the given \a startDateTime
263
and \a endDateTime, inclusive. Any error which occurs should be saved in \a error.
265
A default-constructed (invalid) \a startDateTime specifies an open start date time (matches anything
266
which occurs up until the \a endDateTime), and a default-constructed (invalid) \a endDateTime
267
specifies an open end date time (matches anything which occurs after the \a startDateTime). If
268
both the \a startDateTime and \a endDateTime are invalid, this function will return the IDs of
269
all items which match the \a filter criteria.
271
It's up to the backend to decide how filters are supported.
273
QList<QOrganizerItemId> QOrganizerManagerEngine::itemIds(const QOrganizerItemFilter &filter,
274
const QDateTime &startDateTime,
275
const QDateTime &endDateTime,
276
const QList<QOrganizerItemSortOrder> &sortOrders,
277
QOrganizerManager::Error *error)
279
Q_UNUSED(startDateTime)
280
Q_UNUSED(endDateTime)
284
*error = QOrganizerManager::NotSupportedError;
285
return QList<QOrganizerItemId>();
289
This function should be reimplemented to support synchronous calls to fetch organizer items.
291
This function is supposed to return a list of a maximum of \a maxCount organizer items and
292
occurrences that match the given \a filter, which occur in the range specified by the given
293
\a startDateTime and \a endDateTime, inclusive, and sorted according to the given list of
294
\a sortOrders. Any operation error which occurs should be saved in \a error.
296
A default-constructed (invalid) \a startDateTime specifies an open start date time (matches anything
297
which occurs up until the \a endDateTime), and a default-constructed (invalid) \a endDateTime
298
specifies an open end date time (matches anything which occurs after the \a startDateTime). If
299
both the \a startDateTime and \a endDateTime are invalid, this function will return the IDs of
300
all items which match the \a filter criteria.
302
If no sort order is provided, the list is returned sorted by date.
304
It's up to the backend to decide how many items should be returned if \a maxCount is negative.
306
It's up to the backend to decide if filter and fetch hint are supported.
308
QList<QOrganizerItem> QOrganizerManagerEngine::items(const QOrganizerItemFilter &filter, const QDateTime &startDateTime,
309
const QDateTime &endDateTime, int maxCount,
310
const QList<QOrganizerItemSortOrder> &sortOrders,
311
const QOrganizerItemFetchHint &fetchHint, QOrganizerManager::Error *error)
314
Q_UNUSED(startDateTime)
315
Q_UNUSED(endDateTime)
320
*error = QOrganizerManager::NotSupportedError;
321
return QList<QOrganizerItem>();
325
This function should be reimplemented to support synchronous calls to fetch organizer items for
328
This function is supposed to return a list of organizer items that match the given \a filter,
329
sorted according to the given list of \a sortOrders, for any item which occurs (or has an
330
occurrence which occurs) in the range specified by the given \a startDateTime and \a endDateTime,
331
inclusive. Any operation error which occurs should be saved in \a error.
333
Note that event occurrences and TODO occurrences should only be returned when they represent an
334
exceptional occurrence (i.e. the client has specifically saved the occurrence in the backend).
336
A default-constructed (invalid) \a startDateTime specifies an open start date time (matches anything
337
which occurs up until the \a endDateTime), and a default-constructed (invalid) \a endDateTime
338
specifies an open end date time (matches anything which occurs after the \a startDateTime). If
339
both the \a startDateTime and \a endDateTime are invalid, this function will return the IDs of
340
all items which match the \a filter criteria.
342
It's up to the backend to decide if filter and fetch hint are supported. If the fetch hint is
343
supported, only the details defined by \a fetchHint will be fetched.
345
QList<QOrganizerItem> QOrganizerManagerEngine::itemsForExport(const QDateTime &startDateTime,
346
const QDateTime &endDateTime,
347
const QOrganizerItemFilter &filter,
348
const QList<QOrganizerItemSortOrder> &sortOrders,
349
const QOrganizerItemFetchHint &fetchHint,
350
QOrganizerManager::Error *error)
352
Q_UNUSED(startDateTime)
353
Q_UNUSED(endDateTime)
358
*error = QOrganizerManager::NotSupportedError;
359
return QList<QOrganizerItem>();
363
This function should be reimplemented to support synchronous calls to fetch organizer items by
364
their IDs \a itemIds.
366
The items fetched by the backend should have a one-to-one correspondence to the IDs passed into
367
this class. That is, the nth item in the returned list should have an ID which is equal to the
368
nth ID in the list of IDs. Any invalid ID should correspond to an empty QOrganizerItem.
370
It's up to the backend to decide if fetch hint is supported. If supported, only the details
371
defined by \a fetchHint will be fetched.
373
Any operation error which occurs should be saved in \a error. And the per-input errors should be
374
stored in \a errorMap.
377
QList<QOrganizerItem> QOrganizerManagerEngine::items(const QList<QOrganizerItemId> &itemIds, const QOrganizerItemFetchHint &fetchHint,
378
QMap<int, QOrganizerManager::Error> *errorMap, QOrganizerManager::Error *error)
384
*error = QOrganizerManager::NotSupportedError;
385
return QList<QOrganizerItem>();
389
This function should be reimplemented to return the list of filters supported by this backend.
390
The default implementation returns an empty list.
392
QList<QOrganizerItemFilter::FilterType> QOrganizerManagerEngine::supportedFilters() const
394
return QList<QOrganizerItemFilter::FilterType>();
398
This function should be reimplemented to return the list of details supported by this backend
399
for the given \a itemType. The default implementation returns an empty list.
401
QList<QOrganizerItemDetail::DetailType> QOrganizerManagerEngine::supportedItemDetails(QOrganizerItemType::ItemType itemType) const
404
return QList<QOrganizerItemDetail::DetailType>();
408
This function should be reimplemented to return the list of item types supported by this backend.
409
The default implementation returns an empty list.
411
QList<QOrganizerItemType::ItemType> QOrganizerManagerEngine::supportedItemTypes() const
413
return QList<QOrganizerItemType::ItemType>();
417
This function should be reimplemented to support synchronous calls to save organizer items.
419
This function is supposed to save the given list of \a items to the backend, and returns true on
420
success or false otherwise.
422
A new organizer item will be created in the backend store if the item ID of it is null. Otherwise,
423
an existing item with the same ID will be updated. If the given item ID does not exist in the
424
backend, it will result a QOrganizerManager::DoesNotExistError error.
426
If the collection ID of the item is null, it will be saved to the default collection. If the given
427
collection ID doesn't exist, the saving will fail and \a error will be set to QOrganizerManager::InvalidCollectionError.
429
If the \a detailMask is empty, only the details currently existing in the item will be saved.
430
Otherwise, only details masked by the \a detailMask will be saved or updated, others are kept
431
untouched. It's useful to avoid information loss if the items are retrieved with a fetch hint.
433
Note that upon successful saving, the backend may update the item, e.g. item ID for newly saved
434
items, GUID, timestamp, version, etc.
436
Any error which occurs should be saved in \a error, and per-input errors for the operation should
437
be stored in \a errorMap.
439
bool QOrganizerManagerEngine::saveItems(QList<QOrganizerItem> *items, const QList<QOrganizerItemDetail::DetailType> &detailMask,
440
QMap<int, QOrganizerManager::Error> *errorMap, QOrganizerManager::Error *error)
446
*error = QOrganizerManager::NotSupportedError;
451
This function should be reimplemented to support synchronous calls to remove organizer items.
453
This function is supposed to remove all the items whose ID is contained in the given list of
454
\a itemIds, and all the occurrences whose parent ID is containd in the \a itemIds. If the list
455
contains ids which do not identify a valid item in the manager \a error will be set to \c QOrganizerManager::DoesNotExist.
456
Returns true if all the items and occurrences are successfully removed, or false otherwise.
458
Any error which occurs should be saved in \a error, and per-input errors for the operation should
459
be stored in \a errorMap.
461
bool QOrganizerManagerEngine::removeItems(const QList<QOrganizerItemId> &itemIds, QMap<int, QOrganizerManager::Error> *errorMap,
462
QOrganizerManager::Error *error)
467
*error = QOrganizerManager::NotSupportedError;
472
This function should be reimplemented to support synchronous calls to remove organizer items.
474
This function is supposed to remove all the items in the given list of \a items, and all the
475
occurrences whose parent is containd in the \a items. If item in the list is a generated occurrence,
476
an exception date is added to the parent item. If the list contains ids which do not identify a valid
477
item in the manager \a error will be set to \c QOrganizerManager::DoesNotExist. Returns true if all
478
the items and occurrences are successfully removed, or false otherwise.
480
Any error which occurs should be saved in \a error, and per-input errors for the operation should
481
be stored in \a errorMap.
483
bool QOrganizerManagerEngine::removeItems(const QList<QOrganizerItem> *items, QMap<int, QOrganizerManager::Error> *errorMap,
484
QOrganizerManager::Error *error)
489
*error = QOrganizerManager::NotSupportedError;
495
This function should be reimplemented to support synchronous calls to fetch the default collection.
496
Any errors encountered during this operation should be stored to \a error.
498
QOrganizerCollection QOrganizerManagerEngine::defaultCollection(QOrganizerManager::Error* error)
500
*error = QOrganizerManager::NotSupportedError;
501
return QOrganizerCollection();
505
This function should be reimplemented to support synchronous calls to fetch a collection based
506
on its ID. Any errors encountered during this operation should be stored to \a error. If the
507
given \a collectionId does not specify a valid collection, \a error will be set to
508
\c QOrganizerManager::DoesNotExistError.
511
QOrganizerCollection QOrganizerManagerEngine::collection(const QOrganizerCollectionId& collectionId, QOrganizerManager::Error* error)
513
Q_UNUSED(collectionId);
514
*error = QOrganizerManager::NotSupportedError;
515
return QOrganizerCollection();
519
This function should be reimplemented to support synchronous calls to fetch all the collections
520
managed by this backend. Any errors encountered during this operation should be stored to \a error.
522
QList<QOrganizerCollection> QOrganizerManagerEngine::collections(QOrganizerManager::Error* error)
524
*error = QOrganizerManager::NotSupportedError;
525
return QList<QOrganizerCollection>();
529
This function should be reimplemented to support synchronous calls to save a collection.
531
This function is supposed to save the given \a collection to the backend, and returns true on
532
success or false otherwise. Any errors encountered during this operation should be stored to
535
A new collection will be created in the backend store if the collection ID of it is null.
536
Otherwise, an existing collection with the same ID will be updated. If the given collection ID
537
does not exist in the backend, it will result a QOrganizerManager::DoesNotExistError error.
539
Note that upon successful saving, the backend may update the collection, e.g. collection ID for
540
newly saved collections.
542
bool QOrganizerManagerEngine::saveCollection(QOrganizerCollection* collection, QOrganizerManager::Error* error)
544
Q_UNUSED(collection);
546
*error = QOrganizerManager::NotSupportedError;
551
This function should be reimplemented to support synchronous calls to remove a collection.
553
This function is supposed to remove the collection identified by the given \a collectionId, and
554
all items in the collection. Returns true on success, or false otherwise. Any errors encountered
555
during this operation should be stored to \a error.
557
Note that removing the default collection should not be allowed and should result a
558
QOrganizerManager::PermissionsError error.
560
bool QOrganizerManagerEngine::removeCollection(const QOrganizerCollectionId& collectionId, QOrganizerManager::Error* error)
562
Q_UNUSED(collectionId);
564
*error = QOrganizerManager::NotSupportedError;
569
Given an input \a filter, returns the canonical version of the filter.
571
Some of the following transformations may be applied:
573
\li Any QOrganizerItemInvalidFilters contained in a union filter will be removed
574
\li Any default QOrganizerItemFilters contained in an intersection filter will be removed
575
\li Any QOrganizerItemIntersectionFilters with a QOrganizerItemInvalidFilter contained will be
576
replaced with a QOrganizerItemInvalidFilter
577
\li Any QOrganizerItemUnionFilters with a default QOrganizerItemFilter contained will be replaced
578
with a default QOrganizerItemFilter
579
\li An empty QOrganizerItemIntersectionFilter will be replaced with a QOrganizerItemDefaultFilter
580
\li An empty QOrganizerItemUnionFilter will be replaced with a QOrganizerItemInvalidFilter
581
\li An empty QOrganizerItemIdFilter will be replaced with a QOrganizerItemInvalidFilter
582
\li An intersection or union filter with a single entry will be replaced by that entry
583
\li A QOrganizerItemDetailFieldFilter or QOrganizerItemDetailRangeFilter with no definition name will be replaced with a QOrganizerItemInvalidFilter
584
\li A QOrganizerItemDetailRangeFilter with no range specified will be converted to a QOrganizerItemDetailFieldFilter
587
QOrganizerItemFilter QOrganizerManagerEngine::canonicalizedFilter(const QOrganizerItemFilter &filter)
589
switch (filter.type()) {
590
case QOrganizerItemFilter::IntersectionFilter:
592
QOrganizerItemIntersectionFilter f(filter);
593
QList<QOrganizerItemFilter> filters = f.filters();
594
QList<QOrganizerItemFilter>::iterator it = filters.begin();
596
// XXX in theory we can remove duplicates in a set filter
597
while (it != filters.end()) {
598
QOrganizerItemFilter canon = canonicalizedFilter(*it);
599
if (canon.type() == QOrganizerItemFilter::DefaultFilter) {
600
it = filters.erase(it);
601
} else if (canon.type() == QOrganizerItemFilter::InvalidFilter) {
602
return QOrganizerItemInvalidFilter();
609
if (filters.count() == 0)
610
return QOrganizerItemFilter();
611
if (filters.count() == 1)
612
return filters.first();
614
f.setFilters(filters);
619
case QOrganizerItemFilter::UnionFilter:
621
QOrganizerItemUnionFilter f(filter);
622
QList<QOrganizerItemFilter> filters = f.filters();
623
QList<QOrganizerItemFilter>::iterator it = filters.begin();
625
// XXX in theory we can remove duplicates in a set filter
626
while (it != filters.end()) {
627
QOrganizerItemFilter canon = canonicalizedFilter(*it);
628
if (canon.type() == QOrganizerItemFilter::InvalidFilter) {
629
it = filters.erase(it);
630
} else if (canon.type() == QOrganizerItemFilter::DefaultFilter) {
631
return QOrganizerItemFilter();
638
if (filters.count() == 0)
639
return QOrganizerItemInvalidFilter();
640
if (filters.count() == 1)
641
return filters.first();
643
f.setFilters(filters);
648
case QOrganizerItemFilter::IdFilter:
650
QOrganizerItemIdFilter f(filter);
651
if (f.ids().count() == 0)
652
return QOrganizerItemInvalidFilter();
654
break; // fall through to return at end
656
case QOrganizerItemFilter::DetailRangeFilter:
658
QOrganizerItemDetailRangeFilter f(filter);
659
if (f.detailType() == QOrganizerItemDetail::TypeUndefined)
660
return QOrganizerItemInvalidFilter();
661
if (f.minValue() == f.maxValue()
662
&& f.rangeFlags() == (QOrganizerItemDetailRangeFilter::ExcludeLower | QOrganizerItemDetailRangeFilter::ExcludeUpper))
663
return QOrganizerItemInvalidFilter();
664
if ((f.minValue().isNull() && f.maxValue().isNull()) || (f.minValue() == f.maxValue())) {
665
QOrganizerItemDetailFieldFilter df;
666
df.setDetail(f.detailType(), f.detailField());
667
df.setMatchFlags(f.matchFlags());
668
df.setValue(f.minValue());
672
break; // fall through to return at end
674
case QOrganizerItemFilter::DetailFieldFilter:
676
QOrganizerItemDetailFieldFilter f(filter);
677
if (f.detailType() == QOrganizerItemDetail::TypeUndefined)
678
return QOrganizerItemInvalidFilter();
680
break; // fall through to return at end
683
break; // fall through to return at end
689
Compares \a first against \a second. If the types are
690
strings (QVariant::String), the \a sensitivity argument controls
691
case sensitivity when comparing.
694
<0 if \a first is less than \a second
695
0 if \a first is equal to \a second
696
>0 if \a first is greater than \a second.
698
The results are undefined if the variants are different types, or
701
int QOrganizerManagerEngine::compareVariant(const QVariant& first, const QVariant& second, Qt::CaseSensitivity sensitivity)
703
switch(first.type()) {
705
return first.toInt() - second.toInt();
707
case QVariant::LongLong:
708
return first.toLongLong() - second.toLongLong();
713
return first.toUInt() - second.toUInt();
715
case QVariant::ULongLong:
716
return first.toULongLong() - second.toULongLong();
718
case QVariant::String:
719
return first.toString().compare(second.toString(), sensitivity);
721
case QVariant::Double:
723
const double a = first.toDouble();
724
const double b = second.toDouble();
725
return (a < b) ? -1 : ((a == b) ? 0 : 1);
728
case QVariant::DateTime:
730
const QDateTime a = first.toDateTime();
731
const QDateTime b = second.toDateTime();
732
return (a < b) ? -1 : ((a == b) ? 0 : 1);
736
return first.toDate().toJulianDay() - second.toDate().toJulianDay();
740
const QTime a = first.toTime();
741
const QTime b = second.toTime();
742
return (a < b) ? -1 : ((a == b) ? 0 : 1);
751
Returns true if the supplied item \a item matches the supplied filter \a filter.
753
This function will test each condition in the filter, possibly recursing.
755
bool QOrganizerManagerEngine::testFilter(const QOrganizerItemFilter &filter, const QOrganizerItem &item)
757
switch(filter.type()) {
758
case QOrganizerItemFilter::InvalidFilter:
761
case QOrganizerItemFilter::DefaultFilter:
764
case QOrganizerItemFilter::IdFilter:
766
const QOrganizerItemIdFilter idf(filter);
767
if (idf.ids().contains(item.id()))
770
// Fall through to end
772
case QOrganizerItemFilter::DetailFilter:
774
const QOrganizerItemDetailFilter cdf(filter);
776
QOrganizerItemDetail matchingDetail = cdf.detail();
777
if ( (matchingDetail.isEmpty()) || (matchingDetail.type() == QOrganizerItemDetail::TypeUndefined) )
780
/* See if this organizer item has one of these details in it */
781
const QList<QOrganizerItemDetail>& details = item.details(cdf.detail().type());
782
if (details.count() == 0)
783
return false; /* can't match */
785
/* Value equality test */
786
for (int j=0; j < details.count(); j++) {
787
if (details.at(j) == matchingDetail)
792
// Fall through to end
794
case QOrganizerItemFilter::DetailFieldFilter:
796
const QOrganizerItemDetailFieldFilter cdf(filter);
797
if (cdf.detailType() == QOrganizerItemDetail::TypeUndefined)
800
/* See if this organizer item has one of these details in it */
801
const QList<QOrganizerItemDetail>& details = item.details(cdf.detailType());
803
if (details.count() == 0)
804
return false; /* can't match */
806
/* See if we need to check the values */
807
if (cdf.detailField() == -1)
808
return true; /* just testing for the presence of a detail of the specified definition */
810
/* Now figure out what tests we are doing */
811
const bool valueTest = cdf.value().isValid();
812
const bool presenceTest = !valueTest;
814
/* See if we need to test any values at all */
816
for(int j=0; j < details.count(); j++) {
817
const QOrganizerItemDetail& detail = details.at(j);
819
/* Check that the field is present and has a non-empty value */
820
if (detail.values().contains(cdf.detailField()) && !detail.value(cdf.detailField()).isNull())
826
/* Case sensitivity, for those parts that use it */
827
Qt::CaseSensitivity cs = (cdf.matchFlags() & QOrganizerItemFilter::MatchCaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;
829
/* See what flags are requested, since we're looking at a value */
830
if (cdf.matchFlags() & (QOrganizerItemFilter::MatchEndsWith | QOrganizerItemFilter::MatchStartsWith | QOrganizerItemFilter::MatchContains | QOrganizerItemFilter::MatchFixedString)) {
831
/* We're strictly doing string comparisons here */
832
bool matchStarts = (cdf.matchFlags() & 7) == QOrganizerItemFilter::MatchStartsWith;
833
bool matchEnds = (cdf.matchFlags() & 7) == QOrganizerItemFilter::MatchEndsWith;
834
bool matchContains = (cdf.matchFlags() & 7) == QOrganizerItemFilter::MatchContains;
836
/* Value equality test */
837
for(int j=0; j < details.count(); j++) {
838
const QOrganizerItemDetail& detail = details.at(j);
839
const QString& var = detail.value(cdf.detailField()).toString();
840
const QString& needle = cdf.value().toString();
841
if (matchStarts && var.startsWith(needle, cs))
843
if (matchEnds && var.endsWith(needle, cs))
845
if (matchContains && var.contains(needle, cs))
847
if (QString::compare(var, needle, cs) == 0)
852
/* Nope, testing the values as a variant */
853
/* Value equality test */
854
for(int j = 0; j < details.count(); j++) {
855
const QOrganizerItemDetail& detail = details.at(j);
856
const QVariant& var = detail.value(cdf.detailField());
857
if (!var.isNull() && compareVariant(var, cdf.value(), cs) == 0)
864
case QOrganizerItemFilter::DetailRangeFilter:
866
const QOrganizerItemDetailRangeFilter cdf(filter);
867
if (cdf.detailType() == QOrganizerItemDetail::TypeUndefined)
868
return false; /* we do not know which field to check */
870
/* See if this organizer item has one of these details in it */
871
const QList<QOrganizerItemDetail>& details = item.details(cdf.detailType());
873
if (details.count() == 0)
874
return false; /* can't match */
876
/* Check for a detail presence test */
877
if (cdf.detailField() == -1)
880
/* See if this is a field presence test */
881
if (!cdf.minValue().isValid() && !cdf.maxValue().isValid()) {
882
for(int j=0; j < details.count(); j++) {
883
const QOrganizerItemDetail& detail = details.at(j);
884
if (detail.values().contains(cdf.detailField()))
890
/* open or closed interval testing support */
891
const int minComp = cdf.rangeFlags() & QOrganizerItemDetailRangeFilter::ExcludeLower ? 1 : 0;
892
const int maxComp = cdf.rangeFlags() & QOrganizerItemDetailRangeFilter::IncludeUpper ? 1 : 0;
894
const bool testMin = cdf.minValue().isValid();
895
const bool testMax = cdf.maxValue().isValid();
897
/* At this point we know that at least of testMin & testMax is true */
899
/* Case sensitivity, for those parts that use it */
900
Qt::CaseSensitivity cs = (cdf.matchFlags() & QOrganizerItemFilter::MatchCaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;
902
/* See what flags are requested, since we're looking at a value */
903
if (cdf.matchFlags() & (QOrganizerItemFilter::MatchEndsWith | QOrganizerItemFilter::MatchStartsWith | QOrganizerItemFilter::MatchContains | QOrganizerItemFilter::MatchFixedString)) {
904
/* We're strictly doing string comparisons here */
905
//bool matchStarts = (cdf.matchFlags() & 7) == QOrganizerItemFilter::MatchStartsWith;
906
bool matchEnds = (cdf.matchFlags() & 7) == QOrganizerItemFilter::MatchEndsWith;
907
bool matchContains = (cdf.matchFlags() & 7) == QOrganizerItemFilter::MatchContains;
909
/* Min/Max and contains do not make sense */
913
QString minVal = cdf.minValue().toString();
914
QString maxVal = cdf.maxValue().toString();
916
/* Starts with is the normal compare case, endsWith is a bit trickier */
917
for(int j=0; j < details.count(); j++) {
918
const QOrganizerItemDetail& detail = details.at(j);
919
const QString& var = detail.value(cdf.detailField()).toString();
921
// MatchStarts or MatchFixedString
922
if (testMin && QString::compare(var, minVal, cs) < minComp)
924
if (testMax && QString::compare(var, maxVal, cs) >= maxComp)
928
/* Have to test the length of min & max */
929
// using refs means the parameter order is backwards, so negate the result of compare
930
if (testMin && -QString::compare(minVal, var.rightRef(minVal.length()), cs) < minComp)
932
if (testMax && -QString::compare(maxVal, var.rightRef(maxVal.length()), cs) >= maxComp)
937
// Fall through to end
939
/* Nope, testing the values as a variant */
940
for(int j=0; j < details.count(); j++) {
941
const QOrganizerItemDetail& detail = details.at(j);
942
const QVariant& var = detail.value(cdf.detailField());
944
if (testMin && compareVariant(var, cdf.minValue(), cs) < minComp)
946
if (testMax && compareVariant(var, cdf.maxValue(), cs) >= maxComp)
950
// Fall through to end
955
case QOrganizerItemFilter::IntersectionFilter:
957
/* XXX In theory we could reorder the terms to put the native tests first */
958
const QOrganizerItemIntersectionFilter bf(filter);
959
const QList<QOrganizerItemFilter>& terms = bf.filters();
960
if (terms.count() > 0) {
961
for(int j = 0; j < terms.count(); j++) {
962
if (!testFilter(terms.at(j), item)) {
968
// Fall through to end
972
case QOrganizerItemFilter::UnionFilter:
974
/* XXX In theory we could reorder the terms to put the native tests first */
975
const QOrganizerItemUnionFilter bf(filter);
976
const QList<QOrganizerItemFilter>& terms = bf.filters();
977
if (terms.count() > 0) {
978
for(int j = 0; j < terms.count(); j++) {
979
if (testFilter(terms.at(j), item)) {
985
// Fall through to end
989
case QOrganizerItemFilter::CollectionFilter:
991
const QOrganizerItemCollectionFilter cf(filter);
992
const QSet<QOrganizerCollectionId>& ids = cf.collectionIds();
993
if (ids.contains(item.collectionId()))
1002
Returns true if the given \a item (or an occurrence of the item) occurs within the range
1003
specified by the \a startPeriod and the \a endPeriod, inclusive.
1004
A default-constructed \a startPeriod signifies that the lower bound of the range is
1005
infinitely small (i.e., will match anything up to the \a endPeriod) and a default-constructed
1006
\a endPeriod signifies that the upper bound of the range is infinitely large
1007
(i.e., will match anything which occurs after the \a startPeriod).
1009
bool QOrganizerManagerEngine::isItemBetweenDates(const QOrganizerItem& item, const QDateTime& startPeriod, const QDateTime& endPeriod)
1011
if (startPeriod.isNull() && endPeriod.isNull())
1014
QDateTime itemDateStart;
1015
QDateTime itemDateEnd;
1017
if (item.type() == QOrganizerItemType::TypeEvent || item.type() == QOrganizerItemType::TypeEventOccurrence) {
1018
QOrganizerEventTime etr = item.detail(QOrganizerItemDetail::TypeEventTime);
1019
itemDateStart = etr.startDateTime();
1020
itemDateEnd = etr.endDateTime();
1021
} else if (item.type() == QOrganizerItemType::TypeTodo || item.type() == QOrganizerItemType::TypeTodoOccurrence) {
1022
QOrganizerTodoTime ttr = item.detail(QOrganizerItemDetail::TypeTodoTime);
1023
itemDateStart = ttr.startDateTime();
1024
itemDateEnd = ttr.dueDateTime();
1025
} else if (item.type() == QOrganizerItemType::TypeJournal) {
1026
QOrganizerJournal journal = item;
1027
itemDateStart = itemDateEnd = journal.dateTime();
1028
} else if (item.type() == QOrganizerItemType::TypeNote) {
1029
//for note, there is no such start/end datetime so we always return false
1033
// if period start date is not given, check that item is starting or ending before period end
1034
if (startPeriod.isNull()) // endPeriod must be non-null because of initial test
1035
return (!itemDateStart.isNull() && itemDateStart <= endPeriod) ||
1036
(!itemDateEnd.isNull() && itemDateEnd <= endPeriod);
1038
// if period end date is not given, check that item is starting or ending after the period start
1039
if (endPeriod.isNull()) // startPeriod must be non-null because of initial test
1040
return (!itemDateEnd.isNull() && itemDateEnd >= startPeriod) ||
1041
(!itemDateStart.isNull() && itemDateStart >= startPeriod);
1043
// Both startPeriod and endPeriod are not null
1044
// check if item start date is between the period start and end date
1045
if (!itemDateStart.isNull() && itemDateStart >= startPeriod && itemDateStart <= endPeriod)
1048
// check if item end date is between the period start and end date
1049
if (!itemDateEnd.isNull() && itemDateEnd >= startPeriod && itemDateEnd <= endPeriod)
1052
// check if item interval is including the period interval
1053
if (!itemDateStart.isNull() && !itemDateEnd.isNull() && itemDateStart <= startPeriod && itemDateEnd >= endPeriod)
1062
Returns the date associated with \a item that can be used for the purpose of date-sorting the item.
1064
QDateTime getDateForSorting(const QOrganizerItem& item)
1068
QOrganizerEventTime detail = item.detail(QOrganizerItemDetail::TypeEventTime);
1069
if (!detail.isEmpty()) {
1070
retn = detail.startDateTime();
1071
if (!retn.isValid())
1072
retn = detail.endDateTime();
1073
if (retn.isValid() && detail.isAllDay()) {
1074
// set it to a millisecond before the given date to have it sorted correctly
1075
retn.setTime(QTime(23, 59, 59, 999));
1082
QOrganizerTodoTime detail = item.detail(QOrganizerItemDetail::TypeTodoTime);
1083
if (!detail.isEmpty()) {
1084
retn = detail.startDateTime();
1085
if (!retn.isValid())
1086
retn = detail.dueDateTime();
1087
if (retn.isValid() && detail.isAllDay()) {
1088
// set it to a millisecond before the given date to have it sorted correctly
1089
retn.setTime(QTime(23, 59, 59, 999));
1096
// If it's a note, this will just return null, as expected
1097
return item.detail(QOrganizerItemDetail::TypeJournalTime).value(QOrganizerJournalTime::FieldEntryDateTime).toDateTime();
1101
Returns true if and only if \a a is temporally less than \a b. Items with an earlier date are
1102
temporally less than items with a later date, or items with no date. All day items are
1103
temporally less than non-all day items on the same date. For events and todos, the
1104
start date is used, or if null, the end date is used. This function defines a total ordering
1105
suitable for use in a sort function.
1107
bool QOrganizerManagerEngine::itemLessThan(const QOrganizerItem& a, const QOrganizerItem& b)
1109
QDateTime date1 = getDateForSorting(a);
1110
if (!date1.isValid()) {
1113
QDateTime date2 = getDateForSorting(b);
1114
if (!date2.isValid())
1117
return date1 < date2;
1122
Compares two organizer items (\a a and \a b) using the given list of \a sortOrders. Returns a negative number if \a a should appear
1123
before \a b according to the sort order, a positive number if \a a should appear after \a b according to the sort order,
1124
and zero if the two are unable to be sorted.
1126
int QOrganizerManagerEngine::compareItem(const QOrganizerItem& a, const QOrganizerItem& b, const QList<QOrganizerItemSortOrder>& sortOrders)
1128
QList<QOrganizerItemSortOrder> copy = sortOrders;
1129
while (copy.size()) {
1130
// retrieve the next sort order in the list
1131
QOrganizerItemSortOrder sortOrder = copy.takeFirst();
1132
if (!sortOrder.isValid())
1135
// obtain the values which this sort order concerns
1136
const QVariant& aVal = a.detail(sortOrder.detailType()).value(sortOrder.detailField());
1137
const QVariant& bVal = b.detail(sortOrder.detailType()).value(sortOrder.detailField());
1139
bool aIsNull = false;
1140
bool bIsNull = false;
1142
// treat empty strings as null qvariants.
1143
if ((aVal.type() == QVariant::String && aVal.toString().isEmpty()) || aVal.isNull()) {
1146
if ((bVal.type() == QVariant::String && bVal.toString().isEmpty()) || bVal.isNull()) {
1150
// early exit error checking
1151
if (aIsNull && bIsNull)
1152
continue; // use next sort criteria.
1154
return (sortOrder.blankPolicy() == QOrganizerItemSortOrder::BlanksFirst ? -1 : 1);
1156
return (sortOrder.blankPolicy() == QOrganizerItemSortOrder::BlanksFirst ? 1 : -1);
1159
int comparison = compareVariant(aVal, bVal, sortOrder.caseSensitivity()) * (sortOrder.direction() == Qt::AscendingOrder ? 1 : -1);
1160
if (comparison == 0)
1165
return 0; // or according to id? return (a.id() < b.id() ? -1 : 1);
1170
Insert \a toAdd to the \a sorted list, according to the provided \a sortOrders. The index where \a toAdd is inserted
1173
The first one in the \a sortOrders list has the highest priority.
1175
int QOrganizerManagerEngine::addSorted(QList<QOrganizerItem> *sorted, const QOrganizerItem &toAdd, const QList<QOrganizerItemSortOrder> &sortOrders)
1177
if (sortOrders.count() > 0) {
1178
for (int i = 0; i < sorted->size(); ++i) {
1179
// check to see if the new item should be inserted here
1180
int comparison = compareItem(sorted->at(i), toAdd, sortOrders);
1181
if (comparison > 0) {
1182
sorted->insert(i, toAdd);
1188
// hasn't been inserted yet? append to the list.
1189
sorted->append(toAdd);
1190
return sorted->size() - 1;
1194
Insert \a toAdd to the \a defaultSorted map. If \a toAdd does not have valid start or end date,
1195
returns false and does not insert \a toAdd to \a defaultSorted map.
1197
This function provides default sorting, which should be used for sorting fetch results, if no sort order
1198
was defined for the fetch. The default sorting algorithm is to sort based on start time of an item. If start time
1199
does not exist, end time or due time is used instead. For allday events, time 00:00 is used for sorting purposes.
1200
Items with no start or end time are last in the sorting order.
1202
This function sorts items using QMultiMap, where QDateTime is used as a key. To get a sorted list of items,
1203
QMultiMap::values function should be called and items without start and end date added to the end of the list.
1205
bool QOrganizerManagerEngine::addDefaultSorted(QMultiMap<QDateTime, QOrganizerItem> *defaultSorted, const QOrganizerItem &toAdd)
1208
if (toAdd.type() == QOrganizerItemType::TypeEvent || toAdd.type() == QOrganizerItemType::TypeEventOccurrence) {
1209
QOrganizerEventTime eventTime = toAdd.detail(QOrganizerItemDetail::TypeEventTime);
1210
// both start and end times are mandatory for an event in jsondb schema, so all this checking might redundant
1211
if (eventTime.startDateTime().isValid())
1212
sortTime = eventTime.startDateTime();
1213
else if (eventTime.endDateTime().isValid())
1214
sortTime = eventTime.endDateTime();
1216
if (eventTime.isAllDay() && sortTime.isValid())
1217
sortTime.setTime(QTime(0, 0, 0));
1219
} else if (toAdd.type() == QOrganizerItemType::TypeTodo || toAdd.type() == QOrganizerItemType::TypeTodoOccurrence) {
1220
QOrganizerTodoTime todoTime = toAdd.detail(QOrganizerItemDetail::TypeTodoTime);
1221
if (todoTime.startDateTime().isValid())
1222
sortTime = todoTime.startDateTime();
1223
else if (todoTime.dueDateTime().isValid())
1224
sortTime = todoTime.dueDateTime();
1226
if (todoTime.isAllDay() && sortTime.isValid())
1227
sortTime.setTime(QTime(0, 0, 0));
1230
if (sortTime.isValid()) {
1231
// FIXME: sorting of events with exactly the same key
1232
defaultSorted->insert(sortTime, toAdd);
1240
Generates a new occurrence for \a parentItem. All \a parentItem details, except for \l QOrganizerItemType and
1241
\l QOrganizerItemRecurrence copied to the occurrence. Occurrence start date is set to the date given in \a rdate.
1242
End date is modified accordingly. Occurrence's \l QOrganizerItemParent detail contains the id of \a parentItem
1243
and the original date given in \a rdate.
1245
QOrganizerItem QOrganizerManagerEngine::generateOccurrence(const QOrganizerItem &parentItem, const QDateTime &rdate)
1247
QOrganizerItem instanceItem;
1248
if (parentItem.type() == QOrganizerItemType::TypeEvent) {
1249
instanceItem = QOrganizerEventOccurrence();
1251
instanceItem = QOrganizerTodoOccurrence();
1254
instanceItem.setCollectionId(parentItem.collectionId());
1256
// XXX TODO: something better than this linear search...
1257
// Grab all details from the parent item except the recurrence information, and event/todo time range
1258
QList<QOrganizerItemDetail> allDetails = parentItem.details();
1259
QList<QOrganizerItemDetail> occDetails;
1260
foreach (const QOrganizerItemDetail &detail, allDetails) {
1261
if (detail.type() != QOrganizerItemDetail::TypeRecurrence
1262
&& detail.type() != QOrganizerItemDetail::TypeEventTime
1263
&& detail.type() != QOrganizerItemDetail::TypeTodoTime) {
1264
occDetails.append(detail);
1268
// add the detail which identifies exactly which instance this item is.
1269
QOrganizerItemParent parentDetail;
1270
parentDetail.setParentId(parentItem.id());
1271
parentDetail.setOriginalDate(rdate.date());
1272
occDetails.append(parentDetail);
1274
// save those details in the instance.
1275
foreach (const QOrganizerItemDetail &detail, occDetails) {
1276
// copy every detail except the type
1277
if (detail.type() != QOrganizerItemDetail::TypeItemType) {
1278
QOrganizerItemDetail modifiable = detail;
1279
instanceItem.saveDetail(&modifiable);
1283
// and update the time range in the instance based on the current instance date
1284
if (parentItem.type() == QOrganizerItemType::TypeEvent) {
1285
QOrganizerEventTime etr = parentItem.detail(QOrganizerItemDetail::TypeEventTime);
1286
if (!etr.isEmpty()) {
1287
int eventDayCount = 0;
1288
if (etr.startDateTime().isValid() && etr.endDateTime().isValid())
1289
eventDayCount = etr.startDateTime().daysTo(etr.endDateTime());
1290
QDateTime temp = etr.startDateTime();
1291
temp.setDate(rdate.date());
1292
etr.setStartDateTime(temp);
1293
temp = etr.endDateTime();
1294
QDate endDate = rdate.addDays(eventDayCount).date();
1295
temp.setDate(endDate);
1296
etr.setEndDateTime(temp);
1297
instanceItem.saveDetail(&etr);
1302
if (parentItem.type() == QOrganizerItemType::TypeTodo) {
1303
QOrganizerTodoTime ttr = parentItem.detail(QOrganizerItemDetail::TypeTodoTime);
1304
if (!ttr.isEmpty()) {
1305
int todoDayCount = 0;
1306
if (ttr.startDateTime().isValid() && ttr.dueDateTime().isValid())
1307
todoDayCount = ttr.startDateTime().daysTo(ttr.dueDateTime());
1308
QDateTime temp = ttr.startDateTime();
1309
temp.setDate(rdate.date());
1310
ttr.setStartDateTime(temp);
1311
temp = ttr.dueDateTime();
1312
QDate endDate = rdate.addDays(todoDayCount).date();
1313
temp.setDate(endDate);
1314
ttr.setDueDateTime(temp);
1315
instanceItem.saveDetail(&ttr);
1319
return instanceItem;
1323
Generates all start times for recurrence \a rrule during the given time period. The time period is defined by
1324
\a periodStart and \a periodEnd. \a initialDateTime is the start time of the event, which defines the first
1325
start time for \a rrule. \a maxCount can be used to limit the amount of generated start times.
1327
QList<QDateTime> QOrganizerManagerEngine::generateDateTimes(const QDateTime &initialDateTime, QOrganizerRecurrenceRule rrule, const QDateTime &periodStart, const QDateTime &periodEnd, int maxCount)
1329
QList<QDateTime> retn;
1330
if (periodEnd.isValid() || maxCount <= 0)
1331
maxCount = INT_MAX; // count of returned items is unlimited
1333
QDateTime realPeriodEnd(periodEnd);
1334
if (rrule.limitType() == QOrganizerRecurrenceRule::DateLimit
1335
&& rrule.limitDate() < realPeriodEnd.date()) {
1336
realPeriodEnd.setDate(rrule.limitDate());
1337
realPeriodEnd.setTime(QTime(23,59,59,999)); // the last instant of the limit date, since it's prior to the periodEnd.
1341
if (rrule.limitType() == QOrganizerRecurrenceRule::CountLimit)
1342
nextDate = initialDateTime.date();
1344
nextDate = periodStart.date();
1346
inferMissingCriteria(&rrule, initialDateTime.date());
1347
int countLimitDates = 0;
1348
bool periodEndReached = false;
1349
while (!periodEndReached && nextDate <= realPeriodEnd.date() && retn.size() < maxCount) {
1350
if (rrule.limitType() == QOrganizerRecurrenceRule::CountLimit && countLimitDates >= rrule.limitCount())
1351
break; // reached limit count defined in the recurrence rule
1352
// Skip nextDate if it is not the right multiple of intervals away from initialDateTime.
1353
if (inMultipleOfInterval(nextDate, initialDateTime.date(), rrule.frequency(), rrule.interval(), rrule.firstDayOfWeek())) {
1354
// Calculate the inclusive start and inclusive end of nextDate's week/month/year
1355
QDate subPeriodStart(firstDateInPeriod(nextDate, rrule.frequency(), rrule.firstDayOfWeek()));
1356
QDate subPeriodEnd(firstDateInNextPeriod(nextDate, rrule.frequency(), rrule.firstDayOfWeek()).addDays(-1));
1357
// Compute matchesInPeriod to be the set of dates in the current week/month/year that match the rrule
1358
QList<QDate> matchesInPeriod(filterByPosition(
1359
matchingDates(subPeriodStart, subPeriodEnd, rrule),
1360
rrule.positions()));
1361
// A final filter over the dates list before adding it to the returned list
1362
foreach (const QDate &match, matchesInPeriod) {
1364
if (match > realPeriodEnd.date() || retn.size() >= maxCount) {
1368
QDateTime generatedDateTime(initialDateTime);
1370
generatedDateTime.setDate(match);
1372
if (generatedDateTime >= periodStart && generatedDateTime <= realPeriodEnd) {
1373
retn.append(generatedDateTime);
1374
} else if (generatedDateTime > realPeriodEnd) {
1375
// We've gone past the end of the period. Ensure we break both the foreach and
1377
periodEndReached = true;
1380
if (rrule.limitType() == QOrganizerRecurrenceRule::CountLimit && countLimitDates >= rrule.limitCount())
1381
break; // reached limit count defined in the recurrence rule
1384
nextDate = firstDateInNextPeriod(nextDate, rrule.frequency(), rrule.firstDayOfWeek());
1390
Determines if \a rrule is underspecified and if so, fills in missing information based on \a
1393
void QOrganizerManagerEngine::inferMissingCriteria(QOrganizerRecurrenceRule *rrule, const QDate &initialDate)
1395
switch (rrule->frequency()) {
1396
case QOrganizerRecurrenceRule::Weekly:
1397
if (rrule->daysOfWeek().isEmpty()) {
1398
// derive day of week
1399
QSet<Qt::DayOfWeek> days;
1400
days << static_cast<Qt::DayOfWeek>(initialDate.dayOfWeek());
1401
rrule->setDaysOfWeek(days);
1404
case QOrganizerRecurrenceRule::Monthly:
1405
if (rrule->daysOfWeek().isEmpty() && rrule->daysOfMonth().isEmpty()) {
1406
// derive day of month
1408
days << initialDate.day();
1409
rrule->setDaysOfMonth(days);
1412
case QOrganizerRecurrenceRule::Yearly:
1413
if (rrule->monthsOfYear().isEmpty()
1414
&& rrule->weeksOfYear().isEmpty()
1415
&& rrule->daysOfYear().isEmpty()
1416
&& rrule->daysOfMonth().isEmpty()
1417
&& rrule->daysOfWeek().isEmpty()) {
1418
// derive day of month and month of year
1419
QSet<int> daysOfMonth;
1420
daysOfMonth << initialDate.day();
1421
rrule->setDaysOfMonth(daysOfMonth);
1422
QSet<QOrganizerRecurrenceRule::Month> months;
1423
months << static_cast<QOrganizerRecurrenceRule::Month>(initialDate.month());
1424
rrule->setMonthsOfYear(months);
1425
} else if (!rrule->monthsOfYear().isEmpty()
1426
&& rrule->weeksOfYear().isEmpty()
1427
&& rrule->daysOfYear().isEmpty()
1428
&& rrule->daysOfMonth().isEmpty()
1429
&& rrule->daysOfWeek().isEmpty()) {
1430
// derive day of month
1431
QSet<int> daysOfMonth;
1432
daysOfMonth << initialDate.day();
1433
rrule->setDaysOfMonth(daysOfMonth);
1434
} else if (!rrule->weeksOfYear().isEmpty()
1435
&& rrule->daysOfYear().isEmpty()
1436
&& rrule->daysOfMonth().isEmpty()
1437
&& rrule->daysOfWeek().isEmpty()) {
1438
// derive day of week
1439
QSet<Qt::DayOfWeek> days;
1440
days << static_cast<Qt::DayOfWeek>(initialDate.dayOfWeek());
1441
rrule->setDaysOfWeek(days);
1444
case QOrganizerRecurrenceRule::Daily:
1446
case QOrganizerRecurrenceRule::Invalid:
1452
Returns true if the calendar period (specified by \a frequency) of \a date is an \a
1453
interval multiple of periods ahead of the calendar period of \a initialDate. For Weekly frequencies,
1454
\a firstDayOfWeek is used to determine when the week boundary is. eg. If \a frequency is Monthly
1455
and \a interval is 3, then true is returned iff \a date is in the same month as \a initialDate,
1456
in a month 3 months ahead, 6 months ahead, etc.
1458
bool QOrganizerManagerEngine::inMultipleOfInterval(const QDate &date, const QDate &initialDate, QOrganizerRecurrenceRule::Frequency frequency, int interval, Qt::DayOfWeek firstDayOfWeek)
1460
Q_ASSERT(date >= initialDate);
1461
switch (frequency) {
1462
case QOrganizerRecurrenceRule::Yearly: {
1463
uint yearsDelta = date.year() - initialDate.year();
1464
return (yearsDelta % interval == 0);
1466
case QOrganizerRecurrenceRule::Monthly: {
1467
uint monthsDelta = date.month() - initialDate.month() + (12 * (date.year() - initialDate.year()));
1468
return (monthsDelta % interval == 0);
1470
case QOrganizerRecurrenceRule::Weekly: {
1471
// we need to adjust for the week start specified by the client if the interval is greater than 1
1472
// ie, every time we hit the day specified, we increment the week count.
1474
QDate tempDate = initialDate;
1475
while (tempDate < date) {
1476
tempDate = tempDate.addDays(1);
1477
if (static_cast<Qt::DayOfWeek>(tempDate.dayOfWeek()) == firstDayOfWeek) {
1481
return (weekCount % interval == 0);
1483
case QOrganizerRecurrenceRule::Daily: {
1484
uint daysDelta = initialDate.daysTo(date);
1485
return (daysDelta % interval == 0);
1487
case QOrganizerRecurrenceRule::Invalid:
1494
Returns the date which is the first date of the calendar period that \a date resides in. eg. if
1495
the \a frequency is Monthly, then this returns the first day of \a date's month. If the \a
1496
frequency is Weekly, then it returns the first day of \a date's week, considering the week to
1497
start on \a firstDayOfWeek
1499
QDate QOrganizerManagerEngine::firstDateInPeriod(const QDate &date, QOrganizerRecurrenceRule::Frequency frequency, Qt::DayOfWeek firstDayOfWeek)
1502
switch (frequency) {
1503
case QOrganizerRecurrenceRule::Yearly:
1504
retn.setDate(date.year(), 1, 1);
1506
case QOrganizerRecurrenceRule::Monthly:
1507
retn.setDate(date.year(), date.month(), 1);
1509
case QOrganizerRecurrenceRule::Weekly:
1510
while (retn.dayOfWeek() != firstDayOfWeek) {
1511
retn = retn.addDays(-1);
1514
case QOrganizerRecurrenceRule::Daily:
1523
Returns the date which is the first date of the next calendar period after \a date specified by
1524
\a frequency. eg. if \a frequency is Monthly, then this returns the first day of the next month.
1525
If \a frequency is Weekly, then it returns the first \a firstDayOfWeek after \a date.
1527
QDate QOrganizerManagerEngine::firstDateInNextPeriod(const QDate &date, QOrganizerRecurrenceRule::Frequency frequency, Qt::DayOfWeek firstDayOfWeek)
1530
switch (frequency) {
1531
case QOrganizerRecurrenceRule::Yearly:
1532
retn.setDate(date.year()+1, 1, 1);
1534
case QOrganizerRecurrenceRule::Monthly:
1536
int newMonth = date.month() + 1;
1537
int newYear = date.year() + (newMonth==13 ? 1 : 0);
1538
retn.setDate(newYear, newMonth==13 ? 1 : newMonth, 1);
1541
case QOrganizerRecurrenceRule::Weekly:
1543
retn = retn.addDays(1);
1544
} while (retn.dayOfWeek() != firstDayOfWeek);
1546
case QOrganizerRecurrenceRule::Daily:
1547
retn = retn.addDays(1);
1549
case QOrganizerRecurrenceRule::Invalid:
1556
Returns a list of dates between \a periodStart (inclusive) and \a periodEnd (inclusive) which
1557
match the \a rrule. Only daysOfWeek, daysOfMonth, daysOfYear, weeksOfYear and months from the \a
1560
QList<QDate> QOrganizerManagerEngine::matchingDates(const QDate &periodStart, const QDate &periodEnd, const QOrganizerRecurrenceRule &rrule)
1564
QSet<Qt::DayOfWeek> daysOfWeek = rrule.daysOfWeek();
1565
QSet<int> daysOfMonth = rrule.daysOfMonth();
1566
QSet<int> daysOfYear = rrule.daysOfYear();
1567
QSet<int> weeksOfYear = rrule.weeksOfYear();
1568
QSet<QOrganizerRecurrenceRule::Month> monthsOfYear = rrule.monthsOfYear();
1570
QDate tempDate = periodStart;
1571
while (tempDate <= periodEnd) {
1572
if ((monthsOfYear.isEmpty() || monthsOfYear.contains(static_cast<QOrganizerRecurrenceRule::Month>(tempDate.month())))
1573
&& (weeksOfYear.isEmpty() || weeksOfYear.contains(tempDate.weekNumber()))
1574
&& (daysOfYear.isEmpty() || daysOfYear.contains(tempDate.dayOfYear()))
1575
&& (daysOfMonth.isEmpty() || daysOfMonth.contains(tempDate.day()))
1576
&& (daysOfWeek.isEmpty() || daysOfWeek.contains(static_cast<Qt::DayOfWeek>(tempDate.dayOfWeek())))) {
1577
retn.append(tempDate);
1579
tempDate = tempDate.addDays(1);
1585
Returns a list of dates from \a dates which are at the indices specified by \a positions.
1586
For positive values in \a positions, the values represent a 1-based index into \a dates.
1587
For negative values, they represent indices counting from the end of \a dates (eg. -1 means the
1588
last value of \a dates).
1590
QList<QDate> QOrganizerManagerEngine::filterByPosition(const QList<QDate> &dates, const QSet<int> positions)
1592
if (positions.isEmpty()) {
1597
foreach (int i, positions) {
1598
if (i >= 1 && i <= dates.size()) {
1599
// positions is 1-indexed, but the QList is 0-indexed
1600
retn.append(dates[i-1]);
1601
} else if (i <= -1 && i >= -dates.size()) {
1602
// for negative values, count from the end of the list
1603
retn.append(dates[dates.size() + i]);
1610
Returns true if the given organizer item \a oi has any recurrence.
1612
bool QOrganizerManagerEngine::itemHasReccurence(const QOrganizerItem& oi)
1614
if (oi.type() == QOrganizerItemType::TypeEvent || oi.type() == QOrganizerItemType::TypeTodo) {
1615
QOrganizerItemRecurrence recur = oi.detail(QOrganizerItemDetail::TypeRecurrence);
1616
return !recur.recurrenceDates().isEmpty() || !recur.recurrenceRules().isEmpty();
1626
Returns the engine ID from the given item \a id.
1628
The caller does not take ownership of the pointer, and should not delete returned id or undefined
1631
const QOrganizerItemEngineId *QOrganizerManagerEngine::engineItemId(const QOrganizerItemId &id)
1637
Returns the engine ID from the given collection \a id.
1639
The caller does not take ownership of the pointer, and should not delete returned id or undefined
1642
const QOrganizerCollectionEngineId* QOrganizerManagerEngine::engineCollectionId(const QOrganizerCollectionId& id)
1648
This function is called when the given \a request has been destroyed by the client.
1650
When this function is called, it means for the backend:
1652
\li The client doesn't care about the request any more. The engine can still complete it, but
1653
completion is not required.
1654
\li It can't reliably access any properties of the request pointer any more. The pointer will
1655
be invalid once this function returns.
1658
Note that since the \a request may run in another thread, this function should be blocked until
1659
the worker thread gets fully notified.
1661
void QOrganizerManagerEngine::requestDestroyed(QOrganizerAbstractRequest *request)
1667
This function is called when the client tries to start the given asynchronous \a request. Returns
1668
true if the request is started successfully, or false otherwise.
1670
Note that the request is supposed to run in an asynchronous manner that this function should
1671
return as soon as possible. Therefore, it the operation would last sometime, a worker thread
1672
should be used to queue and process the request. In such cases, backend should be aware that
1673
the request may be deleted by the client, and requestDestroyed() function will be called.
1675
bool QOrganizerManagerEngine::startRequest(QOrganizerAbstractRequest* request)
1682
This function is called when the client tries to cancel the given asynchronous \a request. Returns
1683
true if the request is calcelled successfully, or false otherwise.
1685
bool QOrganizerManagerEngine::cancelRequest(QOrganizerAbstractRequest* request)
1692
This function is called when the client wants to be blocked until the given \a request is completed,
1693
or until \a msecs milliseconds have passed. Returns true when the request is completed, or false
1696
bool QOrganizerManagerEngine::waitForRequestFinished(QOrganizerAbstractRequest* request, int msecs)
1704
Updates the given asynchronous request \a req by setting the new \a state
1705
of the request. If the new state is different, the stateChanged() signal
1706
will be emitted by the request.
1708
void QOrganizerManagerEngine::updateRequestState(QOrganizerAbstractRequest* req, QOrganizerAbstractRequest::State state)
1711
QMutexLocker ml(&req->d_ptr->m_mutex);
1712
if (req->d_ptr->m_state != state) {
1713
req->d_ptr->m_state = state;
1715
emit req->stateChanged(state);
1721
Updates the given QOrganizerItemOccurrenceFetchRequest \a req with the latest results \a result, and operation error \a error.
1722
In addition, the state of the request will be changed to \a newState.
1724
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1726
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1728
void QOrganizerManagerEngine::updateItemOccurrenceFetchRequest(QOrganizerItemOccurrenceFetchRequest* req, const QList<QOrganizerItem>& result, QOrganizerManager::Error error, QOrganizerAbstractRequest::State newState)
1731
QPointer<QOrganizerItemOccurrenceFetchRequest> ireq(req); // Take this in case the first emit deletes us
1732
QOrganizerItemOccurrenceFetchRequestPrivate* rd = static_cast<QOrganizerItemOccurrenceFetchRequestPrivate*>(req->d_ptr);
1733
QMutexLocker ml(&rd->m_mutex);
1734
bool emitState = rd->m_state != newState;
1735
rd->m_organizeritems = result;
1736
rd->m_error = error;
1737
rd->m_state = newState;
1739
emit ireq.data()->resultsAvailable();
1740
if (emitState && ireq)
1741
emit ireq.data()->stateChanged(newState);
1746
Updates the given QOrganizerItemIdFetchRequest \a req with the latest results \a result, and operation error \a error.
1747
In addition, the state of the request will be changed to \a newState.
1749
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1751
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1753
void QOrganizerManagerEngine::updateItemIdFetchRequest(QOrganizerItemIdFetchRequest* req, const QList<QOrganizerItemId>& result, QOrganizerManager::Error error, QOrganizerAbstractRequest::State newState)
1756
QPointer<QOrganizerItemIdFetchRequest> ireq(req); // Take this in case the first emit deletes us
1757
QOrganizerItemIdFetchRequestPrivate* rd = static_cast<QOrganizerItemIdFetchRequestPrivate*>(ireq.data()->d_ptr);
1758
QMutexLocker ml(&rd->m_mutex);
1759
bool emitState = rd->m_state != newState;
1761
rd->m_error = error;
1762
rd->m_state = newState;
1764
emit ireq.data()->resultsAvailable();
1765
if (emitState && ireq)
1766
emit ireq.data()->stateChanged(newState);
1771
Updates the given QOrganizerItemFetchByIdRequest \a req with the latest results \a result, and
1772
operation error \a error, and map of input index to individual error \a errorMap. In addition,
1773
the state of the request will be changed to \a newState.
1775
It then causes the request to emit its resultsAvailable() signal to notify clients of the request
1778
If the new request state is different from the previous state, the stateChanged() signal will
1779
also be emitted from the request.
1781
void QOrganizerManagerEngine::updateItemFetchByIdRequest(QOrganizerItemFetchByIdRequest *req, const QList<QOrganizerItem> &result, QOrganizerManager::Error error, const QMap<int, QOrganizerManager::Error> &errorMap, QOrganizerAbstractRequest::State newState)
1784
QPointer<QOrganizerItemFetchByIdRequest> ireq(req); // Take this in case the first emit deletes us
1785
QOrganizerItemFetchByIdRequestPrivate *rd = static_cast<QOrganizerItemFetchByIdRequestPrivate *>(ireq.data()->d_ptr);
1786
QMutexLocker ml(&rd->m_mutex);
1787
bool emitState = rd->m_state != newState;
1788
rd->m_items = result;
1789
rd->m_errors = errorMap;
1790
rd->m_error = error;
1791
rd->m_state = newState;
1793
emit ireq.data()->resultsAvailable();
1794
if (emitState && ireq)
1795
emit ireq.data()->stateChanged(newState);
1800
Updates the given QOrganizerItemFetchRequest \a req with the latest results \a result, and operation error \a error.
1801
In addition, the state of the request will be changed to \a newState.
1803
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1805
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1807
void QOrganizerManagerEngine::updateItemFetchRequest(QOrganizerItemFetchRequest* req, const QList<QOrganizerItem>& result, QOrganizerManager::Error error, QOrganizerAbstractRequest::State newState)
1810
QPointer<QOrganizerItemFetchRequest> ireq(req); // Take this in case the first emit deletes us
1811
QOrganizerItemFetchRequestPrivate* rd = static_cast<QOrganizerItemFetchRequestPrivate*>(ireq.data()->d_ptr);
1812
QMutexLocker ml(&rd->m_mutex);
1813
bool emitState = rd->m_state != newState;
1814
rd->m_organizeritems = result;
1815
rd->m_error = error;
1816
rd->m_state = newState;
1818
emit ireq.data()->resultsAvailable();
1819
if (emitState && ireq)
1820
emit ireq.data()->stateChanged(newState);
1825
Updates the given QOrganizerItemFetchForExportRequest \a req with the latest results \a result, and operation error \a error.
1826
In addition, the state of the request will be changed to \a newState.
1828
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1830
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1832
void QOrganizerManagerEngine::updateItemFetchForExportRequest(QOrganizerItemFetchForExportRequest* req, const QList<QOrganizerItem>& result, QOrganizerManager::Error error, QOrganizerAbstractRequest::State newState)
1835
QPointer<QOrganizerItemFetchForExportRequest> ireq(req); // Take this in case the first emit deletes us
1836
QOrganizerItemFetchForExportRequestPrivate* rd = static_cast<QOrganizerItemFetchForExportRequestPrivate*>(ireq.data()->d_ptr);
1837
QMutexLocker ml(&rd->m_mutex);
1838
bool emitState = rd->m_state != newState;
1839
rd->m_organizeritems = result;
1840
rd->m_error = error;
1841
rd->m_state = newState;
1843
emit ireq.data()->resultsAvailable();
1844
if (emitState && ireq)
1845
emit ireq.data()->stateChanged(newState);
1850
Updates the given QOrganizerItemRemoveRequest \a req with the operation error \a error, and map of input index to individual error \a errorMap.
1851
In addition, the state of the request will be changed to \a newState.
1853
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1855
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1857
void QOrganizerManagerEngine::updateItemRemoveRequest(QOrganizerItemRemoveRequest* req, QOrganizerManager::Error error, const QMap<int, QOrganizerManager::Error>& errorMap, QOrganizerAbstractRequest::State newState)
1860
QPointer<QOrganizerItemRemoveRequest> ireq(req); // Take this in case the first emit deletes us
1861
QOrganizerItemRemoveRequestPrivate* rd = static_cast<QOrganizerItemRemoveRequestPrivate*>(ireq.data()->d_ptr);
1862
QMutexLocker ml(&rd->m_mutex);
1863
bool emitState = rd->m_state != newState;
1864
rd->m_errors = errorMap;
1865
rd->m_error = error;
1866
rd->m_state = newState;
1868
emit ireq.data()->resultsAvailable();
1869
if (emitState && ireq)
1870
emit ireq.data()->stateChanged(newState);
1875
Updates the given QOrganizerItemRemoveByIdRequest \a req with the operation error \a error, and map of input index to individual error \a errorMap.
1876
In addition, the state of the request will be changed to \a newState.
1878
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1880
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1882
void QOrganizerManagerEngine::updateItemRemoveByIdRequest(QOrganizerItemRemoveByIdRequest* req, QOrganizerManager::Error error, const QMap<int, QOrganizerManager::Error>& errorMap, QOrganizerAbstractRequest::State newState)
1885
QPointer<QOrganizerItemRemoveByIdRequest> ireq(req); // Take this in case the first emit deletes us
1886
QOrganizerItemRemoveByIdRequestPrivate* rd = static_cast<QOrganizerItemRemoveByIdRequestPrivate*>(ireq.data()->d_ptr);
1887
QMutexLocker ml(&rd->m_mutex);
1888
bool emitState = rd->m_state != newState;
1889
rd->m_errors = errorMap;
1890
rd->m_error = error;
1891
rd->m_state = newState;
1893
emit ireq.data()->resultsAvailable();
1894
if (emitState && ireq)
1895
emit ireq.data()->stateChanged(newState);
1900
Updates the given QOrganizerItemSaveRequest \a req with the latest results \a result, operation error \a error, and map of input index to individual error \a errorMap.
1901
In addition, the state of the request will be changed to \a newState.
1903
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1905
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1907
void QOrganizerManagerEngine::updateItemSaveRequest(QOrganizerItemSaveRequest* req, const QList<QOrganizerItem>& result, QOrganizerManager::Error error, const QMap<int, QOrganizerManager::Error>& errorMap, QOrganizerAbstractRequest::State newState)
1910
QPointer<QOrganizerItemSaveRequest> ireq(req); // Take this in case the first emit deletes us
1911
QOrganizerItemSaveRequestPrivate* rd = static_cast<QOrganizerItemSaveRequestPrivate*>(ireq.data()->d_ptr);
1912
QMutexLocker ml(&rd->m_mutex);
1913
bool emitState = rd->m_state != newState;
1914
rd->m_organizeritems = result;
1915
rd->m_errors = errorMap;
1916
rd->m_error = error;
1917
rd->m_state = newState;
1919
emit ireq.data()->resultsAvailable();
1920
if (emitState && ireq)
1921
emit ireq.data()->stateChanged(newState);
1926
Updates the given QOrganizerCollectionFetchRequest \a req with the latest results \a result and an operation error \a error.
1927
In addition, the state of the request will be changed to \a newState.
1929
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1930
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1932
void QOrganizerManagerEngine::updateCollectionFetchRequest(QOrganizerCollectionFetchRequest* req, const QList<QOrganizerCollection>& result, QOrganizerManager::Error error, QOrganizerAbstractRequest::State newState)
1935
QPointer<QOrganizerCollectionFetchRequest> ireq(req); // Take this in case the first emit deletes us
1936
QOrganizerCollectionFetchRequestPrivate* rd = static_cast<QOrganizerCollectionFetchRequestPrivate*>(ireq.data()->d_ptr);
1937
QMutexLocker ml(&rd->m_mutex);
1938
bool emitState = rd->m_state != newState;
1939
rd->m_collections = result;
1940
rd->m_error = error;
1941
rd->m_state = newState;
1943
emit ireq.data()->resultsAvailable();
1944
if (emitState && ireq)
1945
emit ireq.data()->stateChanged(newState);
1950
Updates the given QOrganizerCollectionRemoveRequest \a req with the operation error \a error, and map of input index to individual error \a errorMap.
1951
In addition, the state of the request will be changed to \a newState.
1953
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1954
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1956
void QOrganizerManagerEngine::updateCollectionRemoveRequest(QOrganizerCollectionRemoveRequest* req, QOrganizerManager::Error error, const QMap<int, QOrganizerManager::Error>& errorMap, QOrganizerAbstractRequest::State newState)
1959
QPointer<QOrganizerCollectionRemoveRequest> ireq(req); // Take this in case the first emit deletes us
1960
QOrganizerCollectionRemoveRequestPrivate* rd = static_cast<QOrganizerCollectionRemoveRequestPrivate*>(ireq.data()->d_ptr);
1961
QMutexLocker ml(&rd->m_mutex);
1962
bool emitState = rd->m_state != newState;
1963
rd->m_errors = errorMap;
1964
rd->m_error = error;
1965
rd->m_state = newState;
1967
emit ireq.data()->resultsAvailable();
1968
if (emitState && ireq)
1969
emit ireq.data()->stateChanged(newState);
1974
Updates the given QOrganizerCollectionSaveRequest \a req with the latest results \a result, operation error \a error, and map of input index to individual error \a errorMap.
1975
In addition, the state of the request will be changed to \a newState.
1977
It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
1978
If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
1980
void QOrganizerManagerEngine::updateCollectionSaveRequest(QOrganizerCollectionSaveRequest* req, const QList<QOrganizerCollection>& result, QOrganizerManager::Error error, const QMap<int, QOrganizerManager::Error>& errorMap, QOrganizerAbstractRequest::State newState)
1983
QPointer<QOrganizerCollectionSaveRequest> ireq(req); // Take this in case the first emit deletes us
1984
QOrganizerCollectionSaveRequestPrivate* rd = static_cast<QOrganizerCollectionSaveRequestPrivate*>(ireq.data()->d_ptr);
1985
QMutexLocker ml(&rd->m_mutex);
1986
bool emitState = rd->m_state != newState;
1987
rd->m_collections = result;
1988
rd->m_errors = errorMap;
1989
rd->m_error = error;
1990
rd->m_state = newState;
1992
emit ireq.data()->resultsAvailable();
1993
if (emitState && ireq)
1994
emit ireq.data()->stateChanged(newState);
1998
#include "moc_qorganizermanagerengine.cpp"
2000
QT_END_NAMESPACE_ORGANIZER