akonadi
item.h
00001 /* 00002 Copyright (c) 2006 Volker Krause <vkrause@kde.org> 00003 2007 Till Adam <adam@kde.org> 00004 00005 This library is free software; you can redistribute it and/or modify it 00006 under the terms of the GNU Library General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or (at your 00008 option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, but WITHOUT 00011 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to the 00017 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00018 02110-1301, USA. 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 //@cond PRIVATE 00319 template <typename T> void setPayload( T* p ); 00320 template <typename T> void setPayload( std::auto_ptr<T> p ); 00321 //@endcond 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 //@cond PRIVATE 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 //std::auto_ptr<PayloadBase> takePayloadBase( int sharedPointerId, int metaTypeId ); 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 * /*disambiguate*/ = 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 * /*disambiguate*/ = 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 * /*disambiguate*/ = 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 * /*disambiguate*/ = 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 //@endcond 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 )); // prevent endless recursion 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 // make sure that we have a payload format represented by 'metaTypeId': 00516 if ( !ensureMetaTypeId( metaTypeId ) ) 00517 throwPayloadException( PayloadType::sharedPointerId, metaTypeId ); 00518 00519 // Check whether we have the exact payload 00520 // (metatype id and shared pointer type match) 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 // Check whether we have the same payload in 'the other 00540 // shared pointer' (### make it recurse, trying to find one, but 00541 // don't introduce infinite recursion): 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 // If found, attempt to make a clone (required the payload to provide virtual T * T::clone() const) 00547 const T nt = PayloadType::clone( p->payload ); 00548 if ( !PayloadType::isNull( nt ) ) { 00549 // if clone succeeded, add the clone to the Item: 00550 std::auto_ptr<PayloadBase> npb( new Payload<T>( nt ) ); 00551 addPayloadBaseVariant( PayloadType::sharedPointerId, metaTypeId, npb ); 00552 // and return it 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 )); // prevent endless recursion 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 // make sure that we have a payload format represented by 'metaTypeId': 00607 if ( !ensureMetaTypeId( metaTypeId ) ) 00608 return false; 00609 00610 // Check whether we have the exact payload 00611 // (metatype id and shared pointer type match) 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 )); // prevent endless recursion 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