1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtOrganizer module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
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 The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
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 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include "qorganizerskeleton_p.h"
35
36#ifndef QT_NO_DEBUG_STREAM
37#include <QtCore/qdebug.h>
38#endif
39
40QT_BEGIN_NAMESPACE_ORGANIZER
41
42QOrganizerManagerEngine* QOrganizerItemSkeletonFactory::engine(const QMap<QString, QString>& parameters, QOrganizerManager::Error* error)
43{
44 Q_UNUSED(parameters);
45 Q_UNUSED(error);
46
47 /* TODO - if you understand any specific parameters. save them in the engine so that engine::managerParameters can return them */
48
49 QOrganizerItemSkeletonEngine* ret = new QOrganizerItemSkeletonEngine(); // manager takes ownership and will clean up.
50 return ret;
51}
52
53QString QOrganizerItemSkeletonFactory::managerName() const
54{
55 /* TODO - put your engine name here */
56 return QStringLiteral("skeleton");
57}
58
59
60QOrganizerItemSkeletonEngine::~QOrganizerItemSkeletonEngine()
61{
62 /* TODO clean up your stuff. Perhaps a QScopedPointer or QSharedDataPointer would be in order */
63}
64
65QString QOrganizerItemSkeletonEngine::managerName() const
66{
67 /* TODO - put your engine name here */
68 return QStringLiteral("skeleton");
69}
70
71QMap<QString, QString> QOrganizerItemSkeletonEngine::managerParameters() const
72{
73 /* TODO - in case you have any actual parameters that are relevant that you saved in the factory method, return them here */
74 return QMap<QString, QString>();
75}
76
77QList<QOrganizerItem> QOrganizerItemSkeletonEngine::itemOccurrences(const QOrganizerItem &parentItem,
78 const QDateTime &startDateTime,
79 const QDateTime &endDateTime, int maxCount,
80 const QOrganizerItemFetchHint &fetchHint,
81 QOrganizerManager::Error *error)
82{
83 /*
84 TODO
85
86 This function should create a list of occurrences that occur in the time period from the supplied item,
87 generated from the parent item.
88
89 The periodStart should always be valid, and either the periodEnd or the maxCount will be valid (if periodEnd is
90 valid, use that. Otherwise use the count). It's permissible to limit the number of items returned...
91
92 Basically, if the parent item is an Event, a list of EventOccurrences should be returned. Similarly for
93 Todo/TodoOccurrence.
94
95 If there are no instances, return an empty list.
96
97 The returned items should have a QOrganizerItemParent detail that points to the parentItem and the
98 original instance that the event would have occurred on (e.g. with an exception).
99
100 They should not have recurrence information details in them.
101
102 We might change the signature to split up the periodStart + periodEnd / periodStart + maxCount cases.
103 */
104
105 return QOrganizerManagerEngine::itemOccurrences(parentItem, startDateTime, endDateTime, maxCount, fetchHint, error);
106}
107
108QList<QOrganizerItem> QOrganizerItemSkeletonEngine::itemsForExport(const QDateTime &startDateTime,
109 const QDateTime &endDateTime,
110 const QOrganizerItemFilter &filter,
111 const QList<QOrganizerItemSortOrder> &sortOrders,
112 const QOrganizerItemFetchHint &fetchHint,
113 QOrganizerManager::Error *error)
114{
115 return QOrganizerManagerEngine::itemsForExport(startDateTime, endDateTime, filter, sortOrders, fetchHint, error);
116}
117
118QList<QOrganizerItemId> QOrganizerItemSkeletonEngine::itemIds(const QOrganizerItemFilter &filter,
119 const QDateTime &startDateTime,
120 const QDateTime &endDateTime,
121 const QList<QOrganizerItemSortOrder> &sortOrders,
122 QOrganizerManager::Error *error)
123{
124 /*
125 TODO
126
127 Given the supplied filter and sort order, fetch the list of items [not instances] that correspond, and return their ids.
128
129 If you don't support the filter or sort orders, you can fetch a partially (or un-) filtered list and ask the helper
130 functions to filter and sort it for you.
131
132 If you do have to fetch, consider setting a fetch hint that restricts the information to that needed for filtering/sorting.
133 */
134
135 *error = QOrganizerManager::NotSupportedError; // TODO <- remove this
136
137 QList<QOrganizerItem> partiallyFilteredItems; // = ..., your code here.. [TODO]
138 QList<QOrganizerItem> ret;
139
140 foreach(const QOrganizerItem& item, partiallyFilteredItems) {
141 if (QOrganizerManagerEngine::isItemBetweenDates(item, startPeriod: startDateTime, endPeriod: endDateTime) && QOrganizerManagerEngine::testFilter(filter, item)) {
142 QOrganizerManagerEngine::addSorted(sorted: &ret, toAdd: item, sortOrders);
143 }
144 }
145
146 return QOrganizerManager::extractIds(items: ret);
147}
148
149QList<QOrganizerItem> QOrganizerItemSkeletonEngine::items(const QOrganizerItemFilter &filter, const QDateTime &startDateTime,
150 const QDateTime &endDateTime, int maxCount,
151 const QList<QOrganizerItemSortOrder> &sortOrders,
152 const QOrganizerItemFetchHint &fetchHint, QOrganizerManager::Error *error)
153{
154 /*
155 TODO
156
157 Given the supplied filter and sort order, fetch the list of items [not instances] that correspond, and return them.
158
159 If you don't support the filter or sort orders, you can fetch a partially (or un-) filtered list and ask the helper
160 functions to filter and sort it for you.
161
162 The fetch hint suggests how much of the item to fetch. You can ignore the fetch hint and fetch everything (but you must
163 fetch at least what is mentioned in the fetch hint).
164 */
165
166 Q_UNUSED(startDateTime)
167 Q_UNUSED(endDateTime)
168 Q_UNUSED(maxCount)
169 Q_UNUSED(fetchHint)
170
171 *error = QOrganizerManager::NotSupportedError; // TODO <- remove this
172
173 QList<QOrganizerItem> partiallyFilteredItems; // = ..., your code here.. [TODO]
174 QList<QOrganizerItem> ret;
175
176 foreach(const QOrganizerItem& item, partiallyFilteredItems) {
177 if (QOrganizerManagerEngine::isItemBetweenDates(item, startPeriod: startDateTime, endPeriod: endDateTime) && QOrganizerManagerEngine::testFilter(filter, item)) {
178 QOrganizerManagerEngine::addSorted(sorted: &ret, toAdd: item, sortOrders);
179 }
180 }
181
182 /* An alternative formulation, depending on how your engine is implemented is just:
183
184 foreach(const QOrganizerItemId& id, itemIds(filter, sortOrders, error)) {
185 ret.append(item(id, fetchHint, error);
186 }
187 */
188
189 return ret;
190}
191
192QList<QOrganizerItem> QOrganizerItemSkeletonEngine::items(const QList<QOrganizerItemId> &itemIds, const QOrganizerItemFetchHint &fetchHint,
193 QMap<int, QOrganizerManager::Error> *errorMap, QOrganizerManager::Error* error)
194{
195 /*
196 TODO
197
198 Fetch a single item by id.
199
200 The fetch hint suggests how much of the item to fetch. You can ignore the fetch hint and fetch everything (but you must
201 fetch at least what is mentioned in the fetch hint).
202
203 */
204 return QOrganizerManagerEngine::items(itemIds, fetchHint, errorMap, error);
205}
206
207bool QOrganizerItemSkeletonEngine::saveItems(QList<QOrganizerItem> *items, const QList<QOrganizerItemDetail::DetailType> &detailMask,
208 QMap<int, QOrganizerManager::Error>* errorMap, QOrganizerManager::Error* error)
209{
210 /*
211 TODO
212
213 Save a list of items into the collection specified in each (or their current collection
214 if no collection is specified and they already exist, or the default collection
215 if no collection is specified and they do not exist).
216
217 For each item, convert it to your type, assign an item id, and update the
218 QOrganizerItem's ID (in the list above - e.g. *items[idx] = updated item).
219 Then, examine the collection id specified in each item and save the item in that collection.
220
221 If you encounter an error (e.g. converting to type, or saving), insert an entry into
222 the map above at the corresponding index (e.g. errorMap->insert(idx, QOIM::InvalidDetailError).
223 You should set the "error" variable as well (first, last, most serious error etc).
224
225 The item passed in should be validated according to the schema.
226 */
227 return QOrganizerManagerEngine::saveItems(items, detailMask, errorMap, error);
228}
229
230bool QOrganizerItemSkeletonEngine::removeItems(const QList<QOrganizerItemId> &itemIds, QMap<int, QOrganizerManager::Error> *errorMap,
231 QOrganizerManager::Error *error)
232{
233 /*
234 TODO
235
236 Remove a list of items, given by their id.
237
238 If you encounter an error, insert an error into the appropriate place in the error map,
239 and update the error variable as well.
240
241 DoesNotExistError should be used if the id refers to a non existent item.
242 */
243 return QOrganizerManagerEngine::removeItems(itemIds, errorMap, error);
244}
245
246QOrganizerCollectionId QOrganizerItemSkeletonEngine::defaultCollectionId() const
247{
248 /*
249 TODO
250
251 This allows clients to determine which collection an item will be saved,
252 if the item is saved via saveItems() without specifying a collection id
253 of a collection in which to save the item, via item->setCollectionId().
254
255 There is always at least one collection in a manager, and all items are
256 saved in exactly one collection.
257 */
258 return QOrganizerManagerEngine::defaultCollectionId();
259}
260
261QOrganizerCollection QOrganizerItemSkeletonEngine::collection(const QOrganizerCollectionId& collectionId, QOrganizerManager::Error* error)
262{
263 /*
264 TODO
265
266 This allows clients to retrieve a collection by (manager) id.
267 Prior to saving items, clients will set which collection the item will/should
268 be saved by calling item->setCollectionId().
269 */
270 return QOrganizerManagerEngine::collection(collectionId, error);
271}
272
273QList<QOrganizerCollection> QOrganizerItemSkeletonEngine::collections(QOrganizerManager::Error* error)
274{
275 /*
276 TODO
277
278 This allows clients to retrieve a list of all of the collections currently
279 in this manager. Some backends will have a prepopulated list of valid
280 collections, others will not. A collection can have properties
281 like colour, description, perhaps a priority, etc etc.
282 */
283 return QOrganizerManagerEngine::collections(error);
284}
285
286bool QOrganizerItemSkeletonEngine::saveCollection(QOrganizerCollection* collection, QOrganizerManager::Error* error)
287{
288 /*
289 TODO
290
291 This allows clients to create or update collections if supported by the
292 backend.
293 */
294 return QOrganizerManagerEngine::saveCollection(collection, error);
295}
296
297bool QOrganizerItemSkeletonEngine::removeCollection(const QOrganizerCollectionId& collectionId, QOrganizerManager::Error* error)
298{
299 /*
300 TODO
301
302 This allows clients to remove collections if supported by the backend.
303
304 When a collection is removed, all items in the collection are removed.
305 That is, they are _not_ transferred to another collection.
306
307 If the user attempts to remove the collection which is the default collection,
308 the backend may decide whether to fail (with a permissions error) or to
309 succeed and arbitrarily choose another collection to be the default collection.
310 */
311 return QOrganizerManagerEngine::removeCollection(collectionId, error);
312}
313
314bool QOrganizerItemSkeletonEngine::startRequest(QOrganizerAbstractRequest* req)
315{
316 /*
317 TODO
318
319 This is the entry point to the async API. The request object describes the
320 type of request (switch on req->type()). Req will not be null when called
321 by the framework.
322
323 Generally, you can queue the request and process them at some later time
324 (probably in another thread).
325
326 Once you start a request, call the updateRequestState and/or the
327 specific updateXXXXXRequest functions to mark it in the active state.
328
329 If your engine is particularly fast, or the operation involves only in
330 memory data, you can process and complete the request here. That is
331 probably not the case, though.
332
333 Note that when the client is threaded, and the request might live on a
334 different thread, you might need to be careful with locking. In particular,
335 the request might be deleted while you are still working on it. In this case,
336 your requestDestroyed function will be called while the request is still valid,
337 and you should block in that function until your worker thread (etc) has been
338 notified not to touch that request any more.
339
340 We plan to provide some boiler plate code that will allow you to:
341
342 1) implement the sync functions, and have the async versions call the sync
343 in another thread
344
345 2) or implement the async versions of the function, and have the sync versions
346 call the async versions.
347
348 It's not ready yet, though.
349
350 Return true if the request can be started, false otherwise. You can set an error
351 in the request if you like.
352 */
353 return QOrganizerManagerEngine::startRequest(request: req);
354}
355
356bool QOrganizerItemSkeletonEngine::cancelRequest(QOrganizerAbstractRequest* req)
357{
358 /*
359 TODO
360
361 Cancel an in progress async request. If not possible, return false from here.
362 */
363 return QOrganizerManagerEngine::cancelRequest(request: req);
364}
365
366bool QOrganizerItemSkeletonEngine::waitForRequestFinished(QOrganizerAbstractRequest* req, int msecs)
367{
368 /*
369 TODO
370
371 Wait for a request to complete (up to a max of msecs milliseconds).
372
373 Return true if the request is finished (including if it was already). False otherwise.
374
375 You should really implement this function, if nothing else than as a delay, since clients
376 may call this in a loop.
377
378 It's best to avoid processing events, if you can, or at least only process non-UI events.
379 */
380 return QOrganizerManagerEngine::waitForRequestFinished(request: req, msecs);
381}
382
383void QOrganizerItemSkeletonEngine::requestDestroyed(QOrganizerAbstractRequest* req)
384{
385 /*
386 TODO
387
388 This is called when a request is being deleted. It lets you know:
389
390 1) the client doesn't care about the request any more. You can still complete it if
391 you feel like it.
392 2) you can't reliably access any properties of the request pointer any more. The pointer will
393 be invalid once this function returns.
394
395 This means that if you have a worker thread, you need to let that thread know that the
396 request object is not valid and block until that thread acknowledges it. One way to do this
397 is to have a QSet<QOIAR*> (or QMap<QOIAR, MyCustomRequestState>) that tracks active requests, and
398 insert into that set in startRequest, and remove in requestDestroyed (or when it finishes or is
399 cancelled). Protect that set/map with a mutex, and make sure you take the mutex in the worker
400 thread before calling any of the QOIAR::updateXXXXXXRequest functions. And be careful of lock
401 ordering problems :D
402
403 */
404 return QOrganizerManagerEngine::requestDestroyed(request: req);
405}
406
407QList<QOrganizerItemFilter::FilterType> QOrganizerItemSkeletonEngine::supportedFilters() const
408{
409 // TODO if you engine can natively support the filter, return true. Otherwise you should emulate support in the item{Ids} functions.
410 return QList<QOrganizerItemFilter::FilterType>();
411}
412
413QList<QOrganizerItemDetail::DetailType> QOrganizerItemSkeletonEngine::supportedItemDetails(QOrganizerItemType::ItemType itemType) const
414{
415 // TODO - return which [predefined] details this engine supports for this item type
416 Q_UNUSED(itemType)
417
418 return QList<QOrganizerItemDetail::DetailType>();
419}
420
421QList<QOrganizerItemType::ItemType> QOrganizerItemSkeletonEngine::supportedItemTypes() const
422{
423 // TODO - return which [predefined] types this engine supports
424 QList<QOrganizerItemType::ItemType> ret;
425
426 ret << QOrganizerItemType::TypeEvent;
427 ret << QOrganizerItemType::TypeEventOccurrence;
428 ret << QOrganizerItemType::TypeJournal;
429 ret << QOrganizerItemType::TypeNote;
430 ret << QOrganizerItemType::TypeTodo;
431 ret << QOrganizerItemType::TypeTodoOccurrence;
432
433 return ret;
434}
435
436#include "moc_qorganizerskeleton_p.cpp"
437
438QT_END_NAMESPACE_ORGANIZER
439

source code of qtpim/src/plugins/organizer/skeleton/qorganizerskeleton.cpp