1/*
2 Copyright (c) 2006 Volker Krause <vkrause@kde.org>
3 2007 Till Adam <adam@kde.org>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#ifndef AKONADI_ITEM_H
22#define AKONADI_ITEM_H
23
24#include "akonadi_export.h"
25
26#include <akonadi/entity.h>
27#include <akonadi/exception.h>
28#include <akonadi/tag.h>
29#include <akonadi/collection.h>
30#include "itempayloadinternals_p.h"
31
32#include <QtCore/QByteArray>
33#include <QtCore/QMetaType>
34#include <QtCore/QSet>
35
36#include <boost/static_assert.hpp>
37#include <boost/type_traits/is_pointer.hpp>
38#include <boost/utility/enable_if.hpp>
39
40#include <typeinfo>
41#include <memory>
42
43class KUrl;
44
45template <typename T>
46class QVector;
47
48namespace Akonadi {
49
50class ItemPrivate;
51
52/**
53 * @short Represents a PIM item stored in Akonadi storage.
54 *
55 * A PIM item consists of one or more parts, allowing a fine-grained access on its
56 * content where needed (eg. mail envelope, mail body and attachments).
57 *
58 * There is also a namespace (prefix) for special parts which are local to Akonadi.
59 * These parts, prefixed by "akonadi-", will never be fetched in the resource.
60 * They are useful for local extensions like agents which might want to add meta data
61 * to items in order to handle them but the meta data should not be stored back to the
62 * resource.
63 *
64 * This class is implicitly shared.
65 *
66 * <h4>Payload</h4>
67 *
68 * This class contains, beside some type-agnostic information (flags, revision),
69 * zero or more payload objects representing its actual data. Which objects these actually
70 * are depends on the mimetype of the item and the corresponding serializer plugin(s).
71 *
72 * Technically the only restriction on payload objects is that they have to be copyable.
73 * For safety reasons, pointer payloads are forbidden as well though, as the
74 * ownership would not be clear. In this case, usage of a shared pointer is
75 * recommended (such as boost::shared_ptr or QSharedPointer).
76 *
77 * Using a shared pointer is also required in case the payload is a polymorphic
78 * type. For supported shared pointer types implicit casting is provided when possible.
79 *
80 * When using a value-based class as payload, it is recommended to use one that does
81 * support implicit sharing as setting and retrieving a payload as well as copying
82 * an Akonadi::Item object imply copying of the payload object.
83 *
84 * Since KDE 4.6, Item supports multiple payload types per mime type,
85 * and will automatically convert between them using the serialiser
86 * plugins (which is slow). It also supports mixing shared pointer
87 * types, e.g. inserting a boost::shared_ptr<Foo> and extracting a
88 * QSharedPointer<Foo>. Since the two shared pointer types cannot
89 * share ownership of the same object, the payload class @c T needs to
90 * provide a @c clone() method with the usual signature, ie.
91 *
92 * @code
93 * virtual T * T::clone() const
94 * @endcode
95 *
96 * If the class that does not have a @c clone() method, asking for an
97 * incompatible shared pointer will throw a PayloadException.
98 *
99 * Since using different shared pointer types and different payload
100 * types for the same mimetype incurs slow conversions (between
101 * payload types) and cloning (between shared pointer types), as well
102 * as manifold memory usage (results of conversions are cached inside
103 * the Item, and only destroyed when a new payload is set by the user
104 * of the class), you want to restrict yourself to just one type and
105 * one shared pointer type. This mechanism was mainly introduced for
106 * backwards compatibility (e.g., putting in a
107 * boost::shared_ptr<KCal::Incidence> and extracting a
108 * QSharedPointer<KCalCore::Incidence>), so it is not optimized for
109 * performance.
110 *
111 * The availability of a payload of a specific type can be checked using hasPayload(),
112 * payloads can be retrieved by using payload() and set by using setPayload(). Refer
113 * to the documentation of those methods for more details.
114 *
115 * @author Volker Krause <vkrause@kde.org>, Till Adam <adam@kde.org>, Marc Mutz <mutz@kde.org>
116 */
117class AKONADI_EXPORT Item : public Entity
118{
119public:
120 /**
121 * Describes a list of items.
122 */
123 typedef QList<Item> List;
124
125 /**
126 * Describes a flag name.
127 */
128 typedef QByteArray Flag;
129
130 /**
131 * Describes a set of flag names.
132 */
133 typedef QSet<QByteArray> Flags;
134
135 /**
136 * Describes the part name that is used to fetch the
137 * full payload of an item.
138 */
139 static const char *FullPayload;
140
141 /**
142 * Creates a new item.
143 */
144 Item();
145
146 /**
147 * Creates a new item with the given unique @p id.
148 */
149 explicit Item(Id id);
150
151 /**
152 * Creates a new item with the given mime type.
153 *
154 * @param mimeType The mime type of the item.
155 */
156 explicit Item(const QString &mimeType);
157
158 /**
159 * Creates a new item from an @p other item.
160 */
161 Item(const Item &other);
162
163 /**
164 * Destroys the item.
165 */
166 ~Item();
167
168 /**
169 * Creates an item from the given @p url.
170 */
171 static Item fromUrl(const KUrl &url);
172
173 /**
174 * Returns all flags of this item.
175 */
176 Flags flags() const;
177
178 /**
179 * Returns the timestamp of the last modification of this item.
180 * @since 4.2
181 */
182 QDateTime modificationTime() const;
183
184 /**
185 * Sets the timestamp of the last modification of this item.
186 * @param datetime the modification time to set
187 * @note Do not modify this value from within an application,
188 * it is updated automatically by the revision checking functions.
189 * @since 4.2
190 */
191 void setModificationTime(const QDateTime &datetime);
192
193 /**
194 * Returns whether the flag with the given @p name is
195 * set in the item.
196 */
197 bool hasFlag(const QByteArray &name) const;
198
199 /**
200 * Sets the flag with the given @p name in the item.
201 */
202 void setFlag(const QByteArray &name);
203
204 /**
205 * Removes the flag with the given @p name from the item.
206 */
207 void clearFlag(const QByteArray &name);
208
209 /**
210 * Overwrites all flags of the item by the given @p flags.
211 */
212 void setFlags(const Flags &flags);
213
214 /**
215 * Removes all flags from the item.
216 */
217 void clearFlags();
218
219 void setTags(const Tag::List &list);
220
221 void setTag(const Tag &tag);
222
223 Tag::List tags() const;
224
225 bool hasTag(const Tag &tag) const;
226
227 void clearTag(const Tag &tag);
228
229 void clearTags();
230
231 /**
232 * Sets the payload based on the canonical representation normally
233 * used for data of this mime type.
234 *
235 * @param data The encoded data.
236 * @see fullPayloadData
237 */
238 void setPayloadFromData(const QByteArray &data);
239
240 /**
241 * Returns the full payload in its canonical representation, e.g. the
242 * binary or textual format usually used for data with this mime type.
243 * This is useful when communicating with non-Akonadi application by
244 * e.g. drag&drop, copy&paste or stored files.
245 */
246 QByteArray payloadData() const;
247
248 /**
249 * Returns the list of loaded payload parts. This is not necessarily
250 * identical to all parts in the cache or to all available parts on the backend.
251 */
252 QSet<QByteArray> loadedPayloadParts() const;
253
254 /**
255 * Marks that the payload shall be cleared from the cache when this
256 * item is passed to an ItemModifyJob the next time.
257 * This will trigger a refetch of the payload from the backend when the
258 * item is accessed afterwards. Only resources should have a need for
259 * this functionality.
260 *
261 * @since 4.5
262 */
263 void clearPayload();
264
265 /**
266 * Sets the @p revision number of the item.
267 * @param revision the revision number to set
268 * @note Do not modify this value from within an application,
269 * it is updated automatically by the revision checking functions.
270 */
271 void setRevision(int revision);
272
273 /**
274 * Returns the revision number of the item.
275 */
276 int revision() const;
277
278 /**
279 * Returns the unique identifier of the collection this item is stored in. There is only
280 * a single such collection, although the item can be linked into arbitrary many
281 * virtual collections.
282 * Calling this method makes sense only after running an ItemFetchJob on the item.
283 * @returns the collection ID if it is known, -1 otherwise.
284 * @since 4.3
285 */
286 Entity::Id storageCollectionId() const;
287
288 /**
289 * Set the size of the item in bytes.
290 * @param size the size of the item in bytes
291 * @since 4.2
292 */
293 void setSize(qint64 size);
294
295 /**
296 * Returns the size of the items in bytes.
297 *
298 * @since 4.2
299 */
300 qint64 size() const;
301
302 /**
303 * Sets the mime type of the item to @p mimeType.
304 */
305 void setMimeType(const QString &mimeType);
306
307 /**
308 * Returns the mime type of the item.
309 */
310 QString mimeType() const;
311
312 /**
313 * Sets the @p gid of the entity.
314 *
315 * @since 4.12
316 */
317 void setGid(const QString &gid);
318
319 /**
320 * Returns the gid of the entity.
321 *
322 * @since 4.12
323 */
324 QString gid() const;
325
326 /**
327 * Sets the virtual @p collections that this item is linked into.
328 *
329 * @note Note that changing this value makes no effect on what collections
330 * this item is linked to. To link or unlink an item to/from a virtual
331 * collection, use LinkJob and UnlinkJob.
332 *
333 * @since 4.14
334 */
335 void setVirtualReferences(const Collection::List &collections);
336
337 /**
338 * Lists virtual collections that this item is linked to.
339 *
340 * @note This value is populated only when this item was retrieved by
341 * ItemFetchJob with fetchVirtualReferences set to true in ItemFetchScope,
342 * otherwise this list is always empty.
343 *
344 * @since 4.14
345 */
346 Collection::List virtualReferences() const;
347
348 /**
349 * Returns a list of metatype-ids, describing the different
350 * variants of payload that are currently contained in this item.
351 *
352 * The result is always sorted (increasing ids).
353 */
354 QVector<int> availablePayloadMetaTypeIds() const;
355
356 /**
357 * Sets the payload object of this PIM item.
358 *
359 * @param p The payload object. Must be copyable and must not be a pointer,
360 * will cause a compilation failure otherwise. Using a type that can be copied
361 * fast (such as implicitly shared classes) is recommended.
362 * If the payload type is polymorphic and you intend to set and retrieve payload
363 * objects with mismatching but castable types, make sure to use a supported
364 * shared pointer implementation (currently boost::shared_ptr and QSharedPointer)
365 * and make sure there is a specialization of Akonadi::super_trait for your class.
366 */
367 template <typename T> void setPayload(const T &p);
368 //@cond PRIVATE
369 template <typename T> void setPayload(T *p);
370 template <typename T> void setPayload(std::auto_ptr<T> p);
371 //@endcond
372
373 /**
374 * Returns the payload object of this PIM item. This method will only succeed if either
375 * you requested the exact same payload type that was put in or the payload uses a
376 * supported shared pointer type (currently boost::shared_ptr and QSharedPointer), and
377 * is castable to the requested type. For this to work there needs to be a specialization
378 * of Akonadi::super_trait of the used classes.
379 *
380 * If a mismatching or non-castable payload type is requested, an Akonadi::PayloadException
381 * is thrown. Therefore it is generally recommended to guard calls to payload() with a
382 * corresponding hasPayload() call.
383 *
384 * Trying to retrieve a pointer type will fail to compile.
385 */
386 template <typename T> T payload() const;
387
388 /**
389 * Returns whether the item has a payload object.
390 */
391 bool hasPayload() const;
392
393 /**
394 * Returns whether the item has a payload of type @c T.
395 * This method will only return @c true if either you requested the exact same payload type
396 * that was put in or the payload uses a supported shared pointer type (currently boost::shared_ptr
397 * and QSharedPointer), and is castable to the requested type. For this to work there needs
398 * to be a specialization of Akonadi::super_trait of the used classes.
399 *
400 * Trying to retrieve a pointer type will fail to compile.
401 */
402 template <typename T> bool hasPayload() const;
403
404 /**
405 * Describes the type of url which is returned in url().
406 */
407 enum UrlType {
408 UrlShort = 0, ///< A short url which contains the identifier only (default)
409 UrlWithMimeType = 1 ///< A url with identifier and mimetype
410 };
411
412 /**
413 * Returns the url of the item.
414 */
415 KUrl url(UrlType type = UrlShort) const;
416
417 /**
418 * Returns the parts available for this item.
419 *
420 * The returned set refers to parts available on the akonadi server or remotely,
421 * but does not include the loadedPayloadParts() of this item.
422 *
423 * @since 4.4
424 */
425 QSet<QByteArray> availablePayloadParts() const;
426
427 /**
428 * Returns the parts available for this item in the cache. The list might be a subset
429 * of the actual parts in cache, as it contains only the requested parts. See @see ItemFetchJob and
430 * @see ItemFetchScope
431 *
432 * The returned set refers to parts available on the akonadi server.
433 *
434 * @since 4.11
435 */
436 QSet<QByteArray> cachedPayloadParts() const;
437
438 /**
439 * Applies the parts of Item @p other to this item.
440 * Any parts or attributes available in other, will be applied to this item,
441 * and the payload parts of other will be inserted into this item, overwriting
442 * any existing parts with the same part name.
443 *
444 * If there is an ItemSerialzerPluginV2 for the type, the merge method in that plugin is
445 * used to perform the merge. If only an ItemSerialzerPlugin class is found, or the merge
446 * method of the -V2 plugin is not implemented, the merge is performed with multiple deserializations
447 * of the payload.
448 * @param other the item to get values from
449 * @since 4.4
450 */
451 void apply(const Item &other);
452
453 /**
454 * Registers \a T as a legacy type for mime type \a mimeType.
455 *
456 * This is required information for Item to return the correct
457 * type from payload() when clients have not been recompiled to
458 * use the new code.
459 * @param mimeType the mimeType to register
460 * @since 4.6
461 */
462 template <typename T> static void addToLegacyMapping(const QString &mimeType);
463 void setCachedPayloadParts(const QSet<QByteArray> &cachedParts);
464
465private:
466 //@cond PRIVATE
467 friend class ItemCreateJob;
468 friend class ItemModifyJob;
469 friend class ItemModifyJobPrivate;
470 friend class ItemSync;
471 friend class ProtocolHelper;
472 PayloadBase *payloadBase() const;
473 void setPayloadBase(PayloadBase *p);
474 PayloadBase *payloadBaseV2(int sharedPointerId, int metaTypeId) const;
475 //std::auto_ptr<PayloadBase> takePayloadBase( int sharedPointerId, int metaTypeId );
476 void setPayloadBaseV2(int sharedPointerId, int metaTypeId, std::auto_ptr<PayloadBase> p);
477 void addPayloadBaseVariant(int sharedPointerId, int metaTypeId, std::auto_ptr<PayloadBase> p) const;
478 static void addToLegacyMappingImpl(const QString &mimeType, int sharedPointerId, int metaTypeId, std::auto_ptr<PayloadBase> p);
479
480 /**
481 * Try to ensure that we have a variant of the payload for metatype id @a mtid.
482 * @return @c true if a type exists or could be created through conversion, @c false otherwise.
483 */
484 bool ensureMetaTypeId(int mtid) const;
485
486 template <typename T>
487 typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic, void>::type
488 setPayloadImpl(const T &p, const int * /*disambiguate*/ = 0);
489 template <typename T>
490 typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic, void>::type
491 setPayloadImpl(const T &p);
492
493 template <typename T>
494 typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic, T>::type
495 payloadImpl(const int * /*disambiguate*/ = 0) const;
496 template <typename T>
497 typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic, T>::type
498 payloadImpl() const;
499
500 template <typename T>
501 typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic, bool>::type
502 hasPayloadImpl(const int * /*disambiguate*/ = 0) const;
503 template <typename T>
504 typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic, bool>::type
505 hasPayloadImpl() const;
506
507 template <typename T>
508 typename boost::enable_if<Internal::is_shared_pointer<T>, bool>::type
509 tryToClone(T *ret, const int * /*disambiguate*/ = 0) const;
510 template <typename T>
511 typename boost::disable_if<Internal::is_shared_pointer<T>, bool>::type
512 tryToClone(T *) const;
513
514 /**
515 * Set the collection ID to where the item is stored in. Should be set only by the ItemFetchJob.
516 * @param collectionId the unique identifier of the collection where this item is stored in.
517 * @since 4.3
518 */
519 void setStorageCollectionId(Entity::Id collectionId);
520
521#if 0
522 /**
523 * Helper function for non-template throwing of PayloadException.
524 */
525 QString payloadExceptionText(int spid, int mtid) const;
526
527 /**
528 * Non-template throwing of PayloadException.
529 * Needs to be inline, otherwise catch (Akonadi::PayloadException)
530 * won't work (only catch (Akonadi::Exception))
531 */
532 inline void throwPayloadException(int spid, int mtid) const {
533 throw PayloadException(payloadExceptionText(spid, mtid));
534 }
535#else
536 void throwPayloadException(int spid, int mtid) const;
537#endif
538 //@endcond
539
540 AKONADI_DECLARE_PRIVATE(Item)
541};
542
543template <typename T>
544T Item::payload() const
545{
546 BOOST_STATIC_ASSERT(!boost::is_pointer<T>::value);
547
548 if (!hasPayload()) {
549 throwPayloadException(-1, -1);
550 }
551
552 return payloadImpl<T>();
553}
554
555template <typename T>
556typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic, T>::type
557Item::payloadImpl(const int *) const
558{
559 typedef Internal::PayloadTrait<T> PayloadType;
560 BOOST_STATIC_ASSERT((PayloadType::isPolymorphic));
561
562 typedef typename Internal::get_hierarchy_root<T>::type Root_T;
563 typedef Internal::PayloadTrait<Root_T> RootType;
564 BOOST_STATIC_ASSERT((!RootType::isPolymorphic)); // prevent endless recursion
565
566 return PayloadType::castFrom(payloadImpl<Root_T>());
567}
568
569template <typename T>
570typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic, T>::type
571Item::payloadImpl() const
572{
573 typedef Internal::PayloadTrait<T> PayloadType;
574 BOOST_STATIC_ASSERT((!PayloadType::isPolymorphic));
575
576 const int metaTypeId = PayloadType::elementMetaTypeId();
577
578 // make sure that we have a payload format represented by 'metaTypeId':
579 if (!ensureMetaTypeId(metaTypeId)) {
580 throwPayloadException(PayloadType::sharedPointerId, metaTypeId);
581 }
582
583 // Check whether we have the exact payload
584 // (metatype id and shared pointer type match)
585 if (const Payload<T> *const p = Internal::payload_cast<T>(payloadBaseV2(PayloadType::sharedPointerId, metaTypeId))) {
586 return p->payload;
587 }
588
589 T ret;
590 if (!tryToClone<T>(&ret)) {
591 throwPayloadException(PayloadType::sharedPointerId, metaTypeId);
592 }
593 return ret;
594}
595
596template <typename T>
597typename boost::enable_if<Internal::is_shared_pointer<T>, bool>::type
598Item::tryToClone(T *ret, const int *) const
599{
600 typedef Internal::PayloadTrait<T> PayloadType;
601 BOOST_STATIC_ASSERT((!PayloadType::isPolymorphic));
602
603 const int metaTypeId = PayloadType::elementMetaTypeId();
604
605 // Check whether we have the same payload in 'the other
606 // shared pointer' (### make it recurse, trying to find one, but
607 // don't introduce infinite recursion):
608 typedef typename Internal::shared_pointer_traits<T>::next_shared_ptr NewT;
609 typedef Internal::PayloadTrait<NewT> NewPayloadType;
610
611 if (const Payload<NewT> *const p = Internal::payload_cast<NewT>(payloadBaseV2(NewPayloadType::sharedPointerId, metaTypeId))) {
612 // If found, attempt to make a clone (required the payload to provide virtual T * T::clone() const)
613 const T nt = PayloadType::clone(p->payload);
614 if (!PayloadType::isNull(nt)) {
615 // if clone succeeded, add the clone to the Item:
616 std::auto_ptr<PayloadBase> npb(new Payload<T>(nt));
617 addPayloadBaseVariant(PayloadType::sharedPointerId, metaTypeId, npb);
618 // and return it
619 if (ret) {
620 *ret = nt;
621 }
622 return true;
623 }
624 }
625
626 return false;
627}
628
629template <typename T>
630typename boost::disable_if<Internal::is_shared_pointer<T>, bool>::type
631Item::tryToClone(T *) const
632{
633 typedef Internal::PayloadTrait<T> PayloadType;
634 BOOST_STATIC_ASSERT((!PayloadType::isPolymorphic));
635
636 return false;
637}
638
639template <typename T>
640bool Item::hasPayload() const
641{
642 BOOST_STATIC_ASSERT(!boost::is_pointer<T>::value);
643 return hasPayload() && hasPayloadImpl<T>();
644}
645
646template <typename T>
647typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic, bool>::type
648Item::hasPayloadImpl(const int *) const
649{
650 typedef Internal::PayloadTrait<T> PayloadType;
651 BOOST_STATIC_ASSERT((PayloadType::isPolymorphic));
652
653 typedef typename Internal::get_hierarchy_root<T>::type Root_T;
654 typedef Internal::PayloadTrait<Root_T> RootType;
655 BOOST_STATIC_ASSERT((!RootType::isPolymorphic)); // prevent endless recursion
656
657 try {
658 return hasPayloadImpl<Root_T>()
659 && PayloadType::canCastFrom(payload<Root_T>());
660 } catch (const Akonadi::PayloadException &) {
661 return false;
662 }
663}
664
665template <typename T>
666typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic, bool>::type
667Item::hasPayloadImpl() const
668{
669 typedef Internal::PayloadTrait<T> PayloadType;
670 BOOST_STATIC_ASSERT((!PayloadType::isPolymorphic));
671
672 const int metaTypeId = PayloadType::elementMetaTypeId();
673
674 // make sure that we have a payload format represented by 'metaTypeId':
675 if (!ensureMetaTypeId(metaTypeId)) {
676 return false;
677 }
678
679 // Check whether we have the exact payload
680 // (metatype id and shared pointer type match)
681 if (const Payload<T> *const p = Internal::payload_cast<T>(payloadBaseV2(PayloadType::sharedPointerId, metaTypeId))) {
682 return true;
683 }
684
685 return tryToClone<T>(0);
686}
687
688template <typename T>
689void Item::setPayload(const T &p)
690{
691 BOOST_STATIC_ASSERT((!boost::is_pointer<T>::value));
692 setPayloadImpl(p);
693}
694
695template <typename T>
696typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic>::type
697Item::setPayloadImpl(const T &p, const int *)
698{
699 typedef Internal::PayloadTrait<T> PayloadType;
700 BOOST_STATIC_ASSERT((PayloadType::isPolymorphic));
701
702 typedef typename Internal::get_hierarchy_root<T>::type Root_T;
703 typedef Internal::PayloadTrait<Root_T> RootType;
704 BOOST_STATIC_ASSERT((!RootType::isPolymorphic)); // prevent endless recursion
705
706 setPayloadImpl<Root_T>(p);
707}
708
709template <typename T>
710typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic>::type
711Item::setPayloadImpl(const T &p)
712{
713 typedef Internal::PayloadTrait<T> PayloadType;
714 std::auto_ptr<PayloadBase> pb(new Payload<T>(p));
715 setPayloadBaseV2(PayloadType::sharedPointerId,
716 PayloadType::elementMetaTypeId(),
717 pb);
718}
719
720template <typename T>
721void Item::setPayload(T *p)
722{
723 p->You_MUST_NOT_use_a_pointer_as_payload;
724}
725
726template <typename T>
727void Item::setPayload(std::auto_ptr<T> p)
728{
729 p.Nice_try_but_a_std_auto_ptr_is_not_allowed_as_payload_either;
730}
731
732template <typename T>
733void Item::addToLegacyMapping(const QString &mimeType) {
734 typedef Internal::PayloadTrait<T> PayloadType;
735 BOOST_STATIC_ASSERT((!PayloadType::isPolymorphic));
736 std::auto_ptr<PayloadBase> p(new Payload<T>);
737 addToLegacyMappingImpl(mimeType, PayloadType::sharedPointerId, PayloadType::elementMetaTypeId(), p);
738}
739
740}
741
742Q_DECLARE_METATYPE(Akonadi::Item)
743Q_DECLARE_METATYPE(Akonadi::Item::List)
744
745#endif
746