Akonadi

item.h
1 /*
2  SPDX-FileCopyrightText: 2006 Volker Krause <[email protected]>
3  2007 Till Adam <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #ifndef AKONADI_ITEM_H
9 #define AKONADI_ITEM_H
10 
11 #include "akonadicore_export.h"
12 #include "attribute.h"
13 #include "exceptionbase.h"
14 #include "tag.h"
15 #include "collection.h"
16 #include "relation.h"
17 #include "itempayloadinternals_p.h"
18 #include "job.h"
19 
20 #include <QByteArray>
21 #include <QMetaType>
22 #include <QSet>
23 
24 #include <type_traits>
25 #include <typeinfo>
26 #include <memory>
27 
28 class QUrl;
29 
30 template <typename T>
31 class QVector;
32 
33 namespace Akonadi
34 {
35 
36 class ItemPrivate;
37 
103 class AKONADICORE_EXPORT Item
104 {
105 public:
109  typedef qint64 Id;
110 
114  typedef QVector<Item> List;
115 
119  typedef QByteArray Flag;
120 
124  typedef QSet<QByteArray> Flags;
125 
130  static const char FullPayload[];
131 
135  Item();
136 
140  explicit Item(Id id);
141 
147  explicit Item(const QString &mimeType);
148 
152  Item(const Item &other);
153 
157  Item(Item &&) noexcept;
158 
162  ~Item();
163 
167  static Item fromUrl(const QUrl &url);
168 
172  void setId(Id identifier);
173 
177  Id id() const;
178 
182  void setRemoteId(const QString &id);
183 
187  QString remoteId() const;
188 
198  void setRemoteRevision(const QString &revision);
199 
206  QString remoteRevision() const;
207 
211  bool isValid() const;
212 
216  bool operator==(const Item &other) const;
217 
221  bool operator!=(const Item &other) const;
222 
227  Item &operator=(const Item &other);
228 
234  bool operator<(const Item &other) const;
235 
242  Collection parentCollection() const;
243 
250  Collection &parentCollection();
251 
261  void setParentCollection(const Collection &parent);
262 
273  void addAttribute(Attribute *attribute);
274 
278  void removeAttribute(const QByteArray &name);
279 
284  bool hasAttribute(const QByteArray &name) const;
285 
293  Attribute::List attributes() const;
294 
298  void clearAttributes();
299 
303  Attribute *attribute(const QByteArray &name);
304  const Attribute *attribute(const QByteArray &name) const;
305 
309  enum CreateOption {
310  AddIfMissing,
311  DontCreate
312  };
313 
321  template <typename T>
322  inline T *attribute(CreateOption option = DontCreate);
323 
327  template <typename T>
328  inline const T *attribute() const;
329 
333  template <typename T>
334  inline void removeAttribute();
335 
339  template <typename T>
340  inline bool hasAttribute() const;
341 
345  Flags flags() const;
346 
351  QDateTime modificationTime() const;
352 
360  void setModificationTime(const QDateTime &datetime);
361 
366  bool hasFlag(const QByteArray &name) const;
367 
371  void setFlag(const QByteArray &name);
372 
376  void clearFlag(const QByteArray &name);
377 
381  void setFlags(const Flags &flags);
382 
386  void clearFlags();
387 
388  void setTags(const Tag::List &list);
389 
390  void setTag(const Tag &tag);
391 
392  Tag::List tags() const;
393 
394  bool hasTag(const Tag &tag) const;
395 
396  void clearTag(const Tag &tag);
397 
398  void clearTags();
399 
405  Relation::List relations() const;
406 
414  void setPayloadFromData(const QByteArray &data);
415 
422  QByteArray payloadData() const;
423 
428  QSet<QByteArray> loadedPayloadParts() const;
429 
439  void clearPayload();
440 
447  void setRevision(int revision);
448 
452  int revision() const;
453 
462  Collection::Id storageCollectionId() const;
463 
469  void setSize(qint64 size);
470 
476  qint64 size() const;
477 
481  void setMimeType(const QString &mimeType);
482 
486  QString mimeType() const;
487 
493  void setGid(const QString &gid);
494 
500  QString gid() const;
501 
511  void setVirtualReferences(const Collection::List &collections);
512 
522  Collection::List virtualReferences() const;
523 
530  QVector<int> availablePayloadMetaTypeIds() const;
531 
549  void setPayloadPath(const QString &filePath);
550 
557  QString payloadPath() const;
558 
571  template <typename T> void setPayload(const T &p);
572  //@cond PRIVATE
573  template <typename T> void setPayload(T *p);
574 
575 // We know that auto_ptr is deprecated, but we still want to handle the case
576 // without compilers yelling at us all the time just because item.h gets included
577 // virtually everywhere
578 #if __cplusplus < 201703L
579 #ifdef __GNUC__
580 #ifdef __clang__
581 #pragma clang diagnostic push
582 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
583 #else
584 #pragma GCC diagnostic push
585 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
586 #endif
587 #endif
588  template <typename T> void setPayload(std::auto_ptr<T> p);
589 #ifdef __GNUC__
590 #ifdef __clang__
591 #pragma clang diagnostic pop
592 #else
593 #pragma GCC diagnostic pop
594 #endif
595 #endif
596 #endif
597  template <typename T> void setPayload(std::unique_ptr<T> p);
598  //@endcond
599 
613  template <typename T> T payload() const;
614 
618  bool hasPayload() const;
619 
629  template <typename T> bool hasPayload() const;
630 
634  enum UrlType {
635  UrlShort = 0,
636  UrlWithMimeType = 1
637  };
638 
642  QUrl url(UrlType type = UrlShort) const;
643 
652  QSet<QByteArray> availablePayloadParts() const;
653 
663  QSet<QByteArray> cachedPayloadParts() const;
664 
678  void apply(const Item &other);
679 
680  void setCachedPayloadParts(const QSet<QByteArray> &cachedParts);
681 
682 private:
683  //@cond PRIVATE
684  friend class ItemCreateJob;
685  friend class ItemCreateJobPrivate;
686  friend class ItemModifyJob;
687  friend class ItemModifyJobPrivate;
688  friend class ItemSync;
689  friend class ProtocolHelper;
690  Internal::PayloadBase *payloadBaseV2(int sharedPointerId, int metaTypeId) const;
691  void setPayloadBaseV2(int sharedPointerId, int metaTypeId,
692  std::unique_ptr<Internal::PayloadBase> &p);
693  void addPayloadBaseVariant(int sharedPointerId, int metaTypeId,
694  std::unique_ptr<Internal::PayloadBase> &p) const;
695 
700  bool ensureMetaTypeId(int mtid) const;
701 
702  template <typename T>
703  typename std::enable_if<Internal::PayloadTrait<T>::isPolymorphic, void>::type
704  setPayloadImpl(const T &p, const int * /*disambiguate*/ = nullptr);
705  template <typename T>
706  typename std::enable_if < !Internal::PayloadTrait<T>::isPolymorphic, void >::type
707  setPayloadImpl(const T &p);
708 
709  template <typename T>
710  typename std::enable_if<Internal::PayloadTrait<T>::isPolymorphic, T>::type
711  payloadImpl(const int * /*disambiguate*/ = nullptr) const;
712  template <typename T>
713  typename std::enable_if < !Internal::PayloadTrait<T>::isPolymorphic, T >::type
714  payloadImpl() const;
715 
716  template <typename T>
717  typename std::enable_if<Internal::PayloadTrait<T>::isPolymorphic, bool>::type
718  hasPayloadImpl(const int * /*disambiguate*/ = nullptr) const;
719  template <typename T>
720  typename std::enable_if < !Internal::PayloadTrait<T>::isPolymorphic, bool >::type
721  hasPayloadImpl() const;
722 
723  template <typename T>
724  typename std::enable_if<Internal::is_shared_pointer<T>::value, bool>::type
725  tryToClone(T *ret, const int * /*disambiguate*/ = nullptr) const;
726  template <typename T>
727  typename std::enable_if < !Internal::is_shared_pointer<T>::value, bool >::type
728  tryToClone(T *ret) const;
729 
730  template <typename T, typename NewT>
731  typename std::enable_if < !std::is_same<T, NewT>::value, bool >::type
732  tryToCloneImpl(T *ret, const int * /*disambiguate*/ = nullptr) const;
733  template <typename T, typename NewT>
734  typename std::enable_if<std::is_same<T, NewT>::value, bool>::type
735  tryToCloneImpl(T *ret) const;
736 
742  void setStorageCollectionId(Collection::Id collectionId);
743 
744 #if 0
745 
748  QString payloadExceptionText(int spid, int mtid) const;
749 
755  inline void throwPayloadException(int spid, int mtid) const
756  {
757  throw PayloadException(payloadExceptionText(spid, mtid));
758  }
759 #else
760  void throwPayloadException(int spid, int mtid) const;
761 #endif
762 
764  friend class ItemPrivate;
765  //@endcond
766 };
767 
768 AKONADICORE_EXPORT uint qHash(const Akonadi::Item &item);
769 
770 template <typename T>
771 inline T *Item::attribute(Item::CreateOption option)
772 {
773  const QByteArray type = T().type();
774  if (hasAttribute(type)) {
775  if (T *attr = dynamic_cast<T *>(attribute(type))) {
776  return attr;
777  }
778  qWarning() << "Found attribute of unknown type" << type
779  << ". Did you forget to call AttributeFactory::registerAttribute()?";
780  } else if (option == AddIfMissing) {
781  T *attr = new T();
782  addAttribute(attr);
783  return attr;
784  }
785 
786  return nullptr;
787 }
788 
789 template <typename T>
790 inline const T *Item::attribute() const
791 {
792  const QByteArray type = T().type();
793  if (hasAttribute(type)) {
794  if (const T *attr = dynamic_cast<const T *>(attribute(type))) {
795  return attr;
796  }
797  qWarning() << "Found attribute of unknown type" << type
798  << ". Did you forget to call AttributeFactory::registerAttribute()?";
799  }
800 
801  return nullptr;
802 }
803 
804 template <typename T>
805 inline void Item::removeAttribute()
806 {
807  removeAttribute(T().type());
808 }
809 
810 template <typename T>
811 inline bool Item::hasAttribute() const
812 {
813  return hasAttribute(T().type());
814 }
815 
816 template <typename T>
817 T Item::payload() const
818 {
819  static_assert(!std::is_pointer<T>::value, "Payload must not be a pointer");
820 
821  if (!hasPayload()) {
822  throwPayloadException(-1, -1);
823  }
824 
825  return payloadImpl<T>();
826 }
827 
828 template <typename T>
829 typename std::enable_if<Internal::PayloadTrait<T>::isPolymorphic, T>::type
830 Item::payloadImpl(const int *) const
831 {
832  typedef Internal::PayloadTrait<T> PayloadType;
833  static_assert(PayloadType::isPolymorphic,
834  "Non-polymorphic payload type in polymorphic implementation is not allowed");
835 
836  typedef typename Internal::get_hierarchy_root<T>::type Root_T;
837  typedef Internal::PayloadTrait<Root_T> RootType;
838  static_assert(!RootType::isPolymorphic,
839  "Root type of payload type must not be polymorphic"); // prevent endless recursion
840 
841  return PayloadType::castFrom(payloadImpl<Root_T>());
842 }
843 
844 template <typename T>
845 typename std::enable_if < !Internal::PayloadTrait<T>::isPolymorphic, T >::type
846 Item::payloadImpl() const
847 {
848  typedef Internal::PayloadTrait<T> PayloadType;
849  static_assert(!PayloadType::isPolymorphic,
850  "Polymorphic payload type in non-polymorphic implementation is not allowed");
851 
852  const int metaTypeId = PayloadType::elementMetaTypeId();
853 
854  // make sure that we have a payload format represented by 'metaTypeId':
855  if (!ensureMetaTypeId(metaTypeId)) {
856  throwPayloadException(PayloadType::sharedPointerId, metaTypeId);
857  }
858 
859  // Check whether we have the exact payload
860  // (metatype id and shared pointer type match)
861  if (const Internal::Payload<T> *const p = Internal::payload_cast<T>(payloadBaseV2(PayloadType::sharedPointerId, metaTypeId))) {
862  return p->payload;
863  }
864 
865  T ret;
866  if (!tryToClone<T>(&ret)) {
867  throwPayloadException(PayloadType::sharedPointerId, metaTypeId);
868  }
869  return ret;
870 }
871 
872 template<typename T, typename NewT>
873 typename std::enable_if < !std::is_same<T, NewT>::value, bool >::type
874 Item::tryToCloneImpl(T *ret, const int *) const
875 {
876  typedef Internal::PayloadTrait<T> PayloadType;
877  typedef Internal::PayloadTrait<NewT> NewPayloadType;
878 
879  const int metaTypeId = PayloadType::elementMetaTypeId();
880  Internal::PayloadBase *payloadBase = payloadBaseV2(NewPayloadType::sharedPointerId, metaTypeId);
881  if (const Internal::Payload<NewT> *const p = Internal::payload_cast<NewT>(payloadBase)) {
882  // If found, attempt to make a clone (required the payload to provide virtual T * T::clone() const)
883  const T nt = PayloadType::clone(p->payload);
884  if (!PayloadType::isNull(nt)) {
885  // if clone succeeded, add the clone to the Item:
886  std::unique_ptr<Internal::PayloadBase> npb(new Internal::Payload<T>(nt));
887  addPayloadBaseVariant(PayloadType::sharedPointerId, metaTypeId, npb);
888  // and return it
889  if (ret) {
890  *ret = nt;
891  }
892  return true;
893  }
894  }
895 
896  return tryToCloneImpl<T, typename Internal::shared_pointer_traits<NewT>::next_shared_ptr>(ret);
897 }
898 
899 template <typename T, typename NewT>
900 typename std::enable_if<std::is_same<T, NewT>::value, bool>::type
901 Item::tryToCloneImpl(T *) const
902 {
903  return false;
904 }
905 
906 template <typename T>
907 typename std::enable_if<Internal::is_shared_pointer<T>::value, bool>::type
908 Item::tryToClone(T *ret, const int *) const
909 {
910  typedef Internal::PayloadTrait<T> PayloadType;
911  static_assert(!PayloadType::isPolymorphic,
912  "Polymorphic payload type in non-polymorphic implementation is not allowed");
913 
914  return tryToCloneImpl<T, typename Internal::shared_pointer_traits<T>::next_shared_ptr>(ret);
915 }
916 
917 template <typename T>
918 typename std::enable_if < !Internal::is_shared_pointer<T>::value, bool >::type
919 Item::tryToClone(T *) const
920 {
921  typedef Internal::PayloadTrait<T> PayloadType;
922  static_assert(!PayloadType::isPolymorphic,
923  "Polymorphic payload type in non-polymorphic implementation is not allowed");
924 
925  return false;
926 }
927 
928 template <typename T>
929 bool Item::hasPayload() const
930 {
931  static_assert(!std::is_pointer<T>::value, "Payload type cannot be a pointer");
932  return hasPayload() && hasPayloadImpl<T>();
933 }
934 
935 template <typename T>
936 typename std::enable_if<Internal::PayloadTrait<T>::isPolymorphic, bool>::type
937 Item::hasPayloadImpl(const int *) const
938 {
939  typedef Internal::PayloadTrait<T> PayloadType;
940  static_assert(PayloadType::isPolymorphic,
941  "Non-polymorphic payload type in polymorphic implementation is no allowed");
942 
943  typedef typename Internal::get_hierarchy_root<T>::type Root_T;
944  typedef Internal::PayloadTrait<Root_T> RootType;
945  static_assert(!RootType::isPolymorphic,
946  "Root type of payload type must not be polymorphic"); // prevent endless recursion
947 
948  try {
949  return hasPayloadImpl<Root_T>()
950  && PayloadType::canCastFrom(payload<Root_T>());
951  } catch (const Akonadi::PayloadException &e) {
952  qDebug() << e.what();
953  Q_UNUSED(e)
954  return false;
955  }
956 }
957 
958 template <typename T>
959 typename std::enable_if < !Internal::PayloadTrait<T>::isPolymorphic, bool >::type
960 Item::hasPayloadImpl() const
961 {
962  typedef Internal::PayloadTrait<T> PayloadType;
963  static_assert(!PayloadType::isPolymorphic,
964  "Polymorphic payload type in non-polymorphic implementation is not allowed");
965 
966  const int metaTypeId = PayloadType::elementMetaTypeId();
967 
968  // make sure that we have a payload format represented by 'metaTypeId':
969  if (!ensureMetaTypeId(metaTypeId)) {
970  return false;
971  }
972 
973  // Check whether we have the exact payload
974  // (metatype id and shared pointer type match)
975  if (const Internal::Payload<T> *const p = Internal::payload_cast<T>(payloadBaseV2(PayloadType::sharedPointerId, metaTypeId))) {
976  return true;
977  }
978 
979  return tryToClone<T>(nullptr);
980 }
981 
982 template <typename T>
983 void Item::setPayload(const T &p)
984 {
985  static_assert(!std::is_pointer<T>::value, "Payload type must not be a pointer");
986  setPayloadImpl(p);
987 }
988 
989 template <typename T>
990 typename std::enable_if<Internal::PayloadTrait<T>::isPolymorphic>::type
991 Item::setPayloadImpl(const T &p, const int *)
992 {
993  typedef Internal::PayloadTrait<T> PayloadType;
994  static_assert(PayloadType::isPolymorphic,
995  "Non-polymorphic payload type in polymorphic implementation is not allowed");
996 
997  typedef typename Internal::get_hierarchy_root<T>::type Root_T;
998  typedef Internal::PayloadTrait<Root_T> RootType;
999  static_assert(!RootType::isPolymorphic,
1000  "Root type of payload type must not be polymorphic"); // prevent endless recursion
1001 
1002  setPayloadImpl<Root_T>(p);
1003 }
1004 
1005 template <typename T>
1006 typename std::enable_if < !Internal::PayloadTrait<T>::isPolymorphic >::type
1007 Item::setPayloadImpl(const T &p)
1008 {
1009  typedef Internal::PayloadTrait<T> PayloadType;
1010  std::unique_ptr<Internal::PayloadBase> pb(new Internal::Payload<T>(p));
1011  setPayloadBaseV2(PayloadType::sharedPointerId,
1012  PayloadType::elementMetaTypeId(),
1013  pb);
1014 }
1015 
1016 template <typename T>
1017 void Item::setPayload(T *p)
1018 {
1019  p->You_MUST_NOT_use_a_pointer_as_payload;
1020 }
1021 
1022 #if __cplusplus < 201703L
1023 #ifdef __GNUC__
1024 #ifdef __clang__
1025 #pragma clang diagnostic push
1026 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1027 #else
1028 #pragma GCC diagnostic push
1029 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1030 #endif
1031 #endif
1032 template <typename T>
1033 void Item::setPayload(std::auto_ptr<T> p)
1034 {
1035  p.Nice_try_but_a_std_auto_ptr_is_not_allowed_as_payload_either;
1036 }
1037 #ifdef __GNUC__
1038 #ifdef __clang__
1039 #pragma clang diagnostic pop
1040 #else
1041 #pragma GCC diagnostic pop
1042 #endif
1043 #endif
1044 #endif
1045 
1046 template <typename T>
1047 void Item::setPayload(std::unique_ptr<T> p)
1048 {
1049  p.Nope_even_std_unique_ptr_is_not_allowed;
1050 }
1051 
1052 } // namespace Akonadi
1053 
1054 Q_DECLARE_METATYPE(Akonadi::Item)
1055 Q_DECLARE_METATYPE(Akonadi::Item::List)
1056 
1057 #endif
Type type(const QString &mimeType)
qint64 Id
Describes the unique id type.
Definition: collection.h:69
A glue between Qt and the standard library.
QVector< Collection > List
Describes a list of collections.
Definition: collection.h:74
KCRASH_EXPORT void setFlags(KCrash::CrashFlags flags)
KIOCORE_EXPORT SimpleJob * setModificationTime(const QUrl &url, const QDateTime &mtime)
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
Definition: item.h:31
Helper integration between Akonadi and Qt.
KGuiItem apply()
QString mimeType(Type)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Jul 8 2020 23:15:03 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.