00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef AKONADI_ITEM_H
00022 #define AKONADI_ITEM_H
00023
00024 #include "akonadi_export.h"
00025
00026 #include <akonadi/entity.h>
00027 #include <akonadi/exception.h>
00028 #include "itempayloadinternals_p.h"
00029
00030 #include <QtCore/QByteArray>
00031 #include <QtCore/QMetaType>
00032 #include <QtCore/QSet>
00033
00034 #include <boost/static_assert.hpp>
00035 #include <boost/type_traits/is_pointer.hpp>
00036 #include <boost/utility/enable_if.hpp>
00037
00038 #include <typeinfo>
00039 #include <memory>
00040
00041 class KUrl;
00042
00043 template <typename T>
00044 class QVector;
00045
00046 namespace Akonadi {
00047
00048 class ItemPrivate;
00049
00115 class AKONADI_EXPORT Item : public Entity
00116 {
00117 public:
00121 typedef QList<Item> List;
00122
00126 typedef QByteArray Flag;
00127
00131 typedef QSet<QByteArray> Flags;
00132
00137 static const char* FullPayload;
00138
00142 Item();
00143
00147 explicit Item( Id id );
00148
00154 explicit Item( const QString &mimeType );
00155
00159 Item( const Item &other );
00160
00164 ~Item();
00165
00169 static Item fromUrl( const KUrl &url );
00170
00174 Flags flags() const;
00175
00180 QDateTime modificationTime() const;
00181
00189 void setModificationTime( const QDateTime &datetime );
00190
00195 bool hasFlag( const QByteArray &name ) const;
00196
00200 void setFlag( const QByteArray &name );
00201
00205 void clearFlag( const QByteArray &name );
00206
00210 void setFlags( const Flags &flags );
00211
00215 void clearFlags();
00216
00224 void setPayloadFromData( const QByteArray &data );
00225
00232 QByteArray payloadData() const;
00233
00238 QSet<QByteArray> loadedPayloadParts() const;
00239
00249 void clearPayload();
00250
00257 void setRevision( int revision );
00258
00262 int revision() const;
00263
00272 Entity::Id storageCollectionId() const;
00273
00279 void setSize( qint64 size );
00280
00286 qint64 size() const;
00287
00291 void setMimeType( const QString &mimeType );
00292
00296 QString mimeType() const;
00297
00304 QVector<int> availablePayloadMetaTypeIds() const;
00305
00317 template <typename T> void setPayload( const T &p );
00318
00319 template <typename T> void setPayload( T* p );
00320 template <typename T> void setPayload( std::auto_ptr<T> p );
00321
00322
00336 template <typename T> T payload() const;
00337
00341 bool hasPayload() const;
00342
00352 template <typename T> bool hasPayload() const;
00353
00357 enum UrlType
00358 {
00359 UrlShort = 0,
00360 UrlWithMimeType = 1
00361 };
00362
00366 KUrl url( UrlType type = UrlShort ) const;
00367
00376 QSet<QByteArray> availablePayloadParts() const;
00377
00391 void apply( const Item &other );
00392
00402 template <typename T> static void addToLegacyMapping( const QString & mimeType );
00403
00404 private:
00405
00406 friend class ItemCreateJob;
00407 friend class ItemModifyJob;
00408 friend class ProtocolHelper;
00409 PayloadBase* payloadBase() const;
00410 void setPayloadBase( PayloadBase* );
00411 PayloadBase* payloadBaseV2( int sharedPointerId, int metaTypeId ) const;
00412
00413 void setPayloadBaseV2( int sharedPointerId, int metaTypeId, std::auto_ptr<PayloadBase> p );
00414 void addPayloadBaseVariant( int sharedPointerId, int metaTypeId, std::auto_ptr<PayloadBase> p ) const;
00415 static void addToLegacyMappingImpl( const QString & mimeType, int sharedPointerId, int metaTypeId, std::auto_ptr<PayloadBase> p );
00416
00421 bool ensureMetaTypeId( int mtid ) const;
00422
00423 template <typename T>
00424 typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic,void>::type
00425 setPayloadImpl( const T &, const int * = 0 );
00426 template <typename T>
00427 typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic,void>::type
00428 setPayloadImpl( const T & );
00429
00430 template <typename T>
00431 typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic,T>::type
00432 payloadImpl( const int * = 0 ) const;
00433 template <typename T>
00434 typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic,T>::type
00435 payloadImpl() const;
00436
00437 template <typename T>
00438 typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic,bool>::type
00439 hasPayloadImpl( const int * = 0 ) const;
00440 template <typename T>
00441 typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic,bool>::type
00442 hasPayloadImpl() const;
00443
00444 template <typename T>
00445 typename boost::enable_if<Internal::is_shared_pointer<T>,bool>::type
00446 tryToClone( T *, const int * = 0 ) const;
00447 template <typename T>
00448 typename boost::disable_if<Internal::is_shared_pointer<T>,bool>::type
00449 tryToClone( T * ) const;
00450
00456 void setStorageCollectionId( Entity::Id collectionId);
00457
00458 #if 0
00459
00462 QString payloadExceptionText( int spid, int mtid ) const;
00463
00469 inline void throwPayloadException( int spid, int mtid ) const {
00470 throw PayloadException( payloadExceptionText( spid, mtid ) );
00471 }
00472 #else
00473 void throwPayloadException( int spid, int mtid ) const;
00474 #endif
00475
00476
00477 AKONADI_DECLARE_PRIVATE( Item )
00478 };
00479
00480
00481 template <typename T>
00482 T Item::payload() const
00483 {
00484 BOOST_STATIC_ASSERT( !boost::is_pointer<T>::value );
00485
00486 if ( !hasPayload() )
00487 throwPayloadException( -1, -1 );
00488
00489 return payloadImpl<T>();
00490 }
00491
00492 template <typename T>
00493 typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic,T>::type
00494 Item::payloadImpl( const int * ) const
00495 {
00496 typedef Internal::PayloadTrait<T> PayloadType;
00497 BOOST_STATIC_ASSERT(( PayloadType::isPolymorphic ));
00498
00499 typedef typename Internal::get_hierarchy_root<T>::type Root_T;
00500 typedef Internal::PayloadTrait<Root_T> RootType;
00501 BOOST_STATIC_ASSERT(( !RootType::isPolymorphic ));
00502
00503 return PayloadType::castFrom( payloadImpl<Root_T>() );
00504 }
00505
00506 template <typename T>
00507 typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic,T>::type
00508 Item::payloadImpl() const
00509 {
00510 typedef Internal::PayloadTrait<T> PayloadType;
00511 BOOST_STATIC_ASSERT(( !PayloadType::isPolymorphic ));
00512
00513 const int metaTypeId = PayloadType::elementMetaTypeId();
00514
00515
00516 if ( !ensureMetaTypeId( metaTypeId ) )
00517 throwPayloadException( PayloadType::sharedPointerId, metaTypeId );
00518
00519
00520
00521 if ( const Payload<T> * const p = Internal::payload_cast<T>( payloadBaseV2( PayloadType::sharedPointerId, metaTypeId ) ) )
00522 return p->payload;
00523
00524 T ret;
00525 if ( !tryToClone<T>( &ret ) )
00526 throwPayloadException( PayloadType::sharedPointerId, metaTypeId );
00527 return ret;
00528 }
00529
00530 template <typename T>
00531 typename boost::enable_if<Internal::is_shared_pointer<T>,bool>::type
00532 Item::tryToClone( T * ret, const int * ) const
00533 {
00534 typedef Internal::PayloadTrait<T> PayloadType;
00535 BOOST_STATIC_ASSERT(( !PayloadType::isPolymorphic ));
00536
00537 const int metaTypeId = PayloadType::elementMetaTypeId();
00538
00539
00540
00541
00542 typedef typename Internal::shared_pointer_traits<T>::next_shared_ptr NewT;
00543 typedef Internal::PayloadTrait<NewT> NewPayloadType;
00544
00545 if ( const Payload<NewT> * const p = Internal::payload_cast<NewT>( payloadBaseV2( NewPayloadType::sharedPointerId, metaTypeId ) ) ) {
00546
00547 const T nt = PayloadType::clone( p->payload );
00548 if ( !PayloadType::isNull( nt ) ) {
00549
00550 std::auto_ptr<PayloadBase> npb( new Payload<T>( nt ) );
00551 addPayloadBaseVariant( PayloadType::sharedPointerId, metaTypeId, npb );
00552
00553 if ( ret ) *ret = nt;
00554 return true;
00555 }
00556 }
00557
00558 return false;
00559 }
00560
00561 template <typename T>
00562 typename boost::disable_if<Internal::is_shared_pointer<T>, bool>::type
00563 Item::tryToClone( T * ) const
00564 {
00565 typedef Internal::PayloadTrait<T> PayloadType;
00566 BOOST_STATIC_ASSERT(( !PayloadType::isPolymorphic ));
00567
00568 return false;
00569 }
00570
00571 template <typename T>
00572 bool Item::hasPayload() const
00573 {
00574 BOOST_STATIC_ASSERT( !boost::is_pointer<T>::value );
00575 return hasPayload() && hasPayloadImpl<T>();
00576 }
00577
00578 template <typename T>
00579 typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic,bool>::type
00580 Item::hasPayloadImpl( const int * ) const
00581 {
00582 typedef Internal::PayloadTrait<T> PayloadType;
00583 BOOST_STATIC_ASSERT(( PayloadType::isPolymorphic ));
00584
00585 typedef typename Internal::get_hierarchy_root<T>::type Root_T;
00586 typedef Internal::PayloadTrait<Root_T> RootType;
00587 BOOST_STATIC_ASSERT(( !RootType::isPolymorphic ));
00588
00589 try {
00590 return hasPayloadImpl<Root_T>()
00591 && PayloadType::canCastFrom( payload<Root_T>() );
00592 } catch ( const Akonadi::PayloadException & ) {
00593 return false;
00594 }
00595 }
00596
00597 template <typename T>
00598 typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic,bool>::type
00599 Item::hasPayloadImpl() const
00600 {
00601 typedef Internal::PayloadTrait<T> PayloadType;
00602 BOOST_STATIC_ASSERT(( !PayloadType::isPolymorphic ));
00603
00604 const int metaTypeId = PayloadType::elementMetaTypeId();
00605
00606
00607 if ( !ensureMetaTypeId( metaTypeId ) )
00608 return false;
00609
00610
00611
00612 if ( const Payload<T> * const p = Internal::payload_cast<T>( payloadBaseV2( PayloadType::sharedPointerId, metaTypeId ) ) )
00613 return true;
00614
00615 return tryToClone<T>( 0 );
00616 }
00617
00618 template <typename T>
00619 void Item::setPayload( const T &p )
00620 {
00621 BOOST_STATIC_ASSERT(( !boost::is_pointer<T>::value ));
00622 setPayloadImpl( p );
00623 }
00624
00625 template <typename T>
00626 typename boost::enable_if_c<Internal::PayloadTrait<T>::isPolymorphic>::type
00627 Item::setPayloadImpl( const T & p, const int * )
00628 {
00629 typedef Internal::PayloadTrait<T> PayloadType;
00630 BOOST_STATIC_ASSERT(( PayloadType::isPolymorphic ));
00631
00632 typedef typename Internal::get_hierarchy_root<T>::type Root_T;
00633 typedef Internal::PayloadTrait<Root_T> RootType;
00634 BOOST_STATIC_ASSERT(( !RootType::isPolymorphic ));
00635
00636 setPayloadImpl<Root_T>( p );
00637 }
00638
00639 template <typename T>
00640 typename boost::disable_if_c<Internal::PayloadTrait<T>::isPolymorphic>::type
00641 Item::setPayloadImpl( const T & p )
00642 {
00643 typedef Internal::PayloadTrait<T> PayloadType;
00644 std::auto_ptr<PayloadBase> pb( new Payload<T>( p ) );
00645 setPayloadBaseV2( PayloadType::sharedPointerId,
00646 PayloadType::elementMetaTypeId(),
00647 pb );
00648 }
00649
00650 template <typename T>
00651 void Item::setPayload( T* p )
00652 {
00653 p.You_MUST_NOT_use_a_pointer_as_payload;
00654 }
00655
00656 template <typename T>
00657 void Item::setPayload( std::auto_ptr<T> p )
00658 {
00659 p.Nice_try_but_a_std_auto_ptr_is_not_allowed_as_payload_either;
00660 }
00661
00662 template <typename T>
00663 void Item::addToLegacyMapping( const QString & mimeType ) {
00664 typedef Internal::PayloadTrait<T> PayloadType;
00665 BOOST_STATIC_ASSERT(( !PayloadType::isPolymorphic ));
00666 std::auto_ptr<PayloadBase> p( new Payload<T> );
00667 addToLegacyMappingImpl( mimeType, PayloadType::sharedPointerId, PayloadType::elementMetaTypeId(), p );
00668 }
00669
00670 }
00671
00672 Q_DECLARE_METATYPE(Akonadi::Item)
00673 Q_DECLARE_METATYPE(Akonadi::Item::List)
00674
00675
00676 #endif