File indexing completed on 2024-06-23 05:06:55
0001 /* 0002 SPDX-FileCopyrightText: 2014 Christian Mollekopf <mollekopf@kolabsys.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "akonadicore_export.h" 0010 #include "attribute.h" 0011 0012 #include <QDebug> 0013 #include <QSharedPointer> 0014 #include <QString> 0015 #include <QUrl> 0016 0017 namespace Akonadi 0018 { 0019 class TagModifyJob; 0020 class TagPrivate; 0021 0022 /** 0023 * An Akonadi Tag. 0024 */ 0025 class AKONADICORE_EXPORT Tag 0026 { 0027 public: 0028 using List = QList<Tag>; 0029 using Id = qint64; 0030 0031 /** 0032 * The PLAIN type has the following properties: 0033 * * gid == displayName 0034 * * immutable 0035 * * no hierarchy (no parent) 0036 * 0037 * PLAIN tags are general purpose tags that are easy to map by backends. 0038 */ 0039 static const char PLAIN[]; 0040 0041 /** 0042 * The GENERIC type has the following properties: 0043 * * mutable 0044 * * gid is RFC 4122 compatible 0045 * * no hierarchy (no parent) 0046 * 0047 * GENERIC tags are general purpose tags, that are used, if you can change tag name. 0048 */ 0049 static const char GENERIC[]; 0050 0051 Tag(); 0052 explicit Tag(Id id); 0053 /** 0054 * Creates a PLAIN tag 0055 */ 0056 explicit Tag(const QString &name); 0057 0058 Tag(const Tag &); 0059 0060 Tag(Tag &&) noexcept; 0061 0062 ~Tag(); 0063 0064 Tag &operator=(const Tag &); 0065 Tag &operator=(Tag &&) noexcept; 0066 // Avoid slicing 0067 bool operator==(const Tag &) const; 0068 bool operator!=(const Tag &) const; 0069 0070 static Tag fromUrl(const QUrl &url); 0071 0072 /** 0073 * Adds an attribute to the entity. 0074 * 0075 * If an attribute of the same type name already exists, it is deleted and 0076 * replaced with the new one. 0077 * 0078 * @param attribute The new attribute. 0079 * 0080 * @note The entity takes the ownership of the attribute. 0081 */ 0082 void addAttribute(Attribute *attribute); 0083 0084 /** 0085 * Removes and deletes the attribute of the given type @p name. 0086 */ 0087 void removeAttribute(const QByteArray &name); 0088 0089 /** 0090 * Returns @c true if the entity has an attribute of the given type @p name, 0091 * false otherwise. 0092 */ 0093 bool hasAttribute(const QByteArray &name) const; 0094 0095 /** 0096 * Returns a list of all attributes of the entity. 0097 */ 0098 Attribute::List attributes() const; 0099 0100 /** 0101 * Removes and deletes all attributes of the entity. 0102 */ 0103 void clearAttributes(); 0104 0105 /** 0106 * Returns the attribute of the given type @p name if available, 0 otherwise. 0107 */ 0108 const Attribute *attribute(const QByteArray &name) const; 0109 Attribute *attribute(const QByteArray &name); 0110 0111 /** 0112 * Describes the options that can be passed to access attributes. 0113 */ 0114 enum CreateOption { 0115 AddIfMissing, ///< Creates the attribute if it is missing 0116 DontCreate ///< Does not create an attribute if it is missing (default) 0117 }; 0118 0119 /** 0120 * Returns the attribute of the requested type. 0121 * If the entity has no attribute of that type yet, a new one 0122 * is created and added to the entity. 0123 * 0124 * @param option The create options. 0125 */ 0126 template<typename T> 0127 inline T *attribute(CreateOption option = DontCreate); 0128 0129 /** 0130 * Returns the attribute of the requested type or 0 if it is not available. 0131 */ 0132 template<typename T> 0133 inline const T *attribute() const; 0134 0135 /** 0136 * Removes and deletes the attribute of the requested type. 0137 */ 0138 template<typename T> 0139 inline void removeAttribute(); 0140 0141 /** 0142 * Returns whether the entity has an attribute of the requested type. 0143 */ 0144 template<typename T> 0145 inline bool hasAttribute() const; 0146 0147 /** 0148 * Returns the url of the tag. 0149 */ 0150 QUrl url() const; 0151 0152 /** 0153 * Sets the unique @p identifier of the tag. 0154 */ 0155 void setId(Id identifier); 0156 0157 /** 0158 * Returns the unique identifier of the tag. 0159 */ 0160 Id id() const; 0161 0162 void setGid(const QByteArray &gid); 0163 QByteArray gid() const; 0164 0165 void setRemoteId(const QByteArray &remoteId); 0166 QByteArray remoteId() const; 0167 0168 void setType(const QByteArray &type); 0169 QByteArray type() const; 0170 0171 void setName(const QString &name); 0172 QString name() const; 0173 0174 void setParent(const Tag &parent); 0175 Tag parent() const; 0176 0177 bool isValid() const; 0178 0179 /** 0180 * Returns true if the tag is immutable (cannot be modified after creation). 0181 * Note that the immutability does not affect the attributes. 0182 */ 0183 bool isImmutable() const; 0184 0185 /** 0186 * Returns a GENERIC tag with the given name and a valid gid 0187 */ 0188 static Tag genericTag(const QString &name); 0189 0190 private: 0191 bool checkAttribute(const Attribute *attr, const QByteArray &type) const; 0192 void markAttributeModified(const QByteArray &type); 0193 0194 /// @cond PRIVATE 0195 friend class TagModifyJob; 0196 friend class TagFetchJob; 0197 friend class ProtocolHelper; 0198 0199 QSharedDataPointer<TagPrivate> d_ptr; 0200 /// @endcond 0201 }; 0202 0203 AKONADICORE_EXPORT size_t qHash(const Akonadi::Tag &, size_t sed = 0) noexcept; 0204 0205 template<typename T> 0206 inline T *Tag::attribute(CreateOption option) 0207 { 0208 const QByteArray type = T().type(); 0209 markAttributeModified(type); 0210 if (hasAttribute(type)) { 0211 T *attr = dynamic_cast<T *>(attribute(type)); 0212 if (checkAttribute(attr, type)) { 0213 return attr; 0214 } 0215 } else if (option == AddIfMissing) { 0216 T *attr = new T(); 0217 addAttribute(attr); 0218 return attr; 0219 } 0220 0221 return nullptr; 0222 } 0223 0224 template<typename T> 0225 inline const T *Tag::attribute() const 0226 { 0227 const QByteArray type = T().type(); 0228 if (hasAttribute(type)) { 0229 const T *attr = dynamic_cast<const T *>(attribute(type)); 0230 if (checkAttribute(attr, type)) { 0231 return attr; 0232 } 0233 } 0234 0235 return nullptr; 0236 } 0237 0238 template<typename T> 0239 inline void Tag::removeAttribute() 0240 { 0241 const T dummy; 0242 removeAttribute(dummy.type()); 0243 } 0244 0245 template<typename T> 0246 inline bool Tag::hasAttribute() const 0247 { 0248 const T dummy; 0249 return hasAttribute(dummy.type()); 0250 } 0251 0252 } // namespace Akonadi 0253 0254 AKONADICORE_EXPORT QDebug operator<<(QDebug debug, const Akonadi::Tag &tag); 0255 0256 Q_DECLARE_METATYPE(Akonadi::Tag) 0257 Q_DECLARE_METATYPE(Akonadi::Tag::List) 0258 Q_DECLARE_METATYPE(QSet<Akonadi::Tag>) 0259 Q_DECLARE_TYPEINFO(Akonadi::Tag, Q_RELOCATABLE_TYPE);