1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtOrganizer module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include "qorganizeritemdetail.h"
35#include "qorganizeritemdetail_p.h"
36
37#ifndef QT_NO_DATASTREAM
38#include <QtCore/qdatastream.h>
39#endif
40#ifndef QT_NO_DEBUG_STREAM
41#include <QtCore/qdebug.h>
42#endif
43
44#include "qorganizeritemrecurrence.h"
45
46QT_BEGIN_NAMESPACE_ORGANIZER
47
48/*!
49 \class QOrganizerItemDetail
50
51 \brief The QOrganizerItemDetail class represents a single, complete detail about an organizer item.
52 \inmodule QtOrganizer
53 \ingroup organizer-main
54
55 All of the information for an organizer item is stored in one or more QOrganizerItemDetail objects.
56
57 A detail is a group of logically related bits of data - for example, a QOrganizerItemTimestamp is a single
58 detail that has multiple fields (timestamp of creation, timestamp of last update, etc). Different organizer
59 managers may support different details for different item types, e.g. certain manager may not support the
60 timestamp, while others do.
61
62 In general, QOrganizerItemDetail and the built in subclasses (like \l QOrganizerEventTime) provide
63 convenience and standardized access to values. For example, \l QOrganizerEventTime provides a
64 convenient API for manipulating a QOrganizerItemDetail to describe the start and end time of an
65 event. Subclasses also provide constants for the names of fields (like \l QOrganizerEventTime::FieldStartDateTime).
66 Typically the constants for field names start with \c Field, and the constants for predefined values
67 of a field start with the name of that field (e.g. \c TypeEvent is a predefined constant for \c FieldType).
68
69 QOrganizerItemDetail objects act like type checked values. In general, you can assign them
70 to and fro and have reasonable behaviour, like the following example.
71
72 \code
73 QOrganizerItemDescription description;
74 description.setDescription("Some descriptive text");
75 // description.value(QOrganizerItemDescription::FieldDescription) == "Some descriptive text";
76 // description.type() == QOrganizerItemDetail::TypeDescription
77
78 QOrganizerItemDetail detail = description;
79 // detail.value(QOrganizerItemDescription::FieldDescription) == "Some descriptive text";
80 // detail.type() == QOrganizerItemDetail::TypeDescription
81
82 QOrganizerItemDescription otherDescription = detail;
83 // otherDescription.description() == "Some descriptive text";
84 // otherDescription.type() == QOrganizerItemDetail::TypeDescription
85
86 QOrganizerItemDisplayLabel label = detail;
87 // label is now a default constructed QOrganizerItemDisplayLabel
88 // label.value(QOrganizerItemDescription::FieldDescription) is empty
89 // label.type() == QOrganizerItemDetail::TypeDisplayLabel
90
91 QOrganizerItemDisplayLabel otherLabel = description;
92 // otherLabel is now a default constructed QOrganizerItemDisplayLabel
93 // otherLabel.value(QOrganizerItemDescription::FieldDescription) is empty
94 // otherLabel.type() == QOrganizerItemDetail::TypeDisplayLabel
95 \endcode
96
97 \sa QOrganizerItem, QOrganizerItemDetailFilter, QOrganizerItemDetailFieldFilter, QOrganizerItemDetailRangeFilter
98 */
99
100/*!
101 \enum QOrganizerItemDetail::DetailType
102
103 This enumeration describes the type of the organizer item detail.
104
105 \value TypeUndefined This detail is of type undefined.
106 \value TypeClassification This detail is a classification.
107 \value TypeComment This detail is a comment
108 \value TypeDescription This detail is a description.
109 \value TypeDisplayLabel This detail is a display label.
110 \value TypeItemType This detail is an item type.
111 \value TypeGuid This detail is a GUID.
112 \value TypeLocation This detail is a location.
113 \value TypeParent This detail is a parent. Should not be used in parent items.
114 \value TypePriority This detail is a priority.
115 \value TypeRecurrence This detail is a recurrence. Should not be used in occurrences.
116 \value TypeTag This detail is a tag.
117 \value TypeTimestamp This detail is a timestamp.
118 \value TypeVersion This detail is a version.
119 \value TypeReminder This detail is a reminder. Should not be directly used.
120 \value TypeAudibleReminder This detail is an audible reminder.
121 \value TypeEmailReminder This detail is an email reminder.
122 \value TypeVisualReminder This detail is a visual reminder.
123 \value TypeExtendedDetail This detail is an extended detail.
124 \value TypeEventAttendee This detail is an event attendee.
125 \value TypeEventRsvp This detail is an event RSVP.
126 \value TypeEventTime This detail is an event time.
127 \value TypeJournalTime This detail is a journal time.
128 \value TypeTodoTime This detail is a TODO time.
129 \value TypeTodoProgress This detail is a TODO progress.
130 */
131
132/*!
133 \internal
134 \macro Q_DECLARE_CUSTOM_ORGANIZER_DETAIL
135 \relates QOrganizerItemDetail
136
137 Macro for simplifying declaring leaf detail classes.
138
139 The first argument is the name of the class, and the second argument is the
140 detail definition name.
141
142 If you are creating a leaf detail class for a type of QOrganizerItemDetail,
143 you should use this macro when declaring your class to ensure that
144 it interoperates with other organizer item functionality.
145 */
146
147
148/*!
149 \fn bool QOrganizerItemDetail::operator!=(const QOrganizerItemDetail &other) const
150
151 Returns true if the values or id of this detail is different to those of the \a other detail
152 */
153
154/*!
155 Constructs a new, empty detail of the \a detailType.
156 */
157QOrganizerItemDetail::QOrganizerItemDetail(DetailType detailType)
158 : d(new QOrganizerItemDetailPrivate(detailType))
159{
160}
161
162/*!
163 Constructs a detail that is a copy of \a other.
164 */
165QOrganizerItemDetail::QOrganizerItemDetail(const QOrganizerItemDetail &other)
166 : d(other.d)
167{
168}
169
170/*!
171 \internal
172
173 Constructs a detail that is a copy of \a other if \a other is of the type
174 identified by \a expectedDetailType, else constructs a new, empty detail of the
175 type identified by the \a expectedDetailType.
176*/
177QOrganizerItemDetail::QOrganizerItemDetail(const QOrganizerItemDetail &other, DetailType expectedDetailType)
178{
179 if (other.d->m_detailType == expectedDetailType)
180 d = other.d;
181 else
182 d = new QOrganizerItemDetailPrivate(expectedDetailType);
183}
184
185/*!
186 Assigns this detail to \a other.
187 */
188QOrganizerItemDetail &QOrganizerItemDetail::operator=(const QOrganizerItemDetail &other)
189{
190 d = other.d;
191 return *this;
192}
193
194/*!
195 \internal
196
197 Assigns this detail to \a other if the type of \a other is that identified
198 by the given \a expectedDetailType, else assigns this detail to be a new, empty
199 detail of the type identified by the given \a expectedDetailType.
200 */
201QOrganizerItemDetail &QOrganizerItemDetail::assign(const QOrganizerItemDetail &other, DetailType expectedDetailType)
202{
203 if (d != other.d) {
204 if (other.d->m_detailType == expectedDetailType)
205 d = other.d;
206 else
207 d = new QOrganizerItemDetailPrivate(expectedDetailType);
208 }
209 return *this;
210}
211
212/*!
213 Frees the memory used by this detail.
214 */
215QOrganizerItemDetail::~QOrganizerItemDetail()
216{
217}
218
219/*!
220 Returns the detail type.
221 */
222QOrganizerItemDetail::DetailType QOrganizerItemDetail::type() const
223{
224 return d->m_detailType;
225}
226
227/*!
228 Compares this detail to \a other. Returns true if the type and values of \a other are equal to those of this detail.
229 The keys of each detail are not considered during the comparison, in order to allow details from different organizer items to
230 be compared according to their values.
231 */
232bool QOrganizerItemDetail::operator==(const QOrganizerItemDetail &other) const
233{
234 if (d == other.d)
235 return true;
236
237 // note: id is auto-generated and should not be compared here
238 if (d->m_detailType != other.d->m_detailType)
239 return false;
240
241 // QVariant doesn't support == on QOrganizerItemRecurrence - do it manually
242 if (d->m_detailType == QOrganizerItemDetail::TypeRecurrence)
243 return static_cast<QOrganizerItemRecurrence>(*this) == static_cast<QOrganizerItemRecurrence>(other);
244
245 return d->m_values == other.d->m_values;
246}
247
248/*!
249 \relates QOrganizerItemDetail
250 Returns the hash value for \a key.
251 */
252Q_ORGANIZER_EXPORT uint qHash(const QOrganizerItemDetail &key)
253{
254 uint hash = QT_PREPEND_NAMESPACE(qHash)(key: key.d->m_detailType);
255 QMap<int, QVariant>::const_iterator it = key.d->m_values.constBegin();
256 while (it != key.d->m_values.constEnd()) {
257 hash += QT_PREPEND_NAMESPACE(qHash)(key: it.key()) + QT_PREPEND_NAMESPACE(qHash)(key: it.value().toString());
258 ++it;
259 }
260 return hash;
261}
262
263#ifndef QT_NO_DEBUG_STREAM
264/*!
265 \relates QOrganizerItemDetail
266 Streams the \a detail to the given debug stream \a dbg, and returns the stream.
267 */
268Q_ORGANIZER_EXPORT QDebug operator<<(QDebug dbg, const QOrganizerItemDetail &detail)
269{
270 dbg.nospace() << "QOrganizerItemDetail(name=" << detail.type() << ", key=" << detail.key();
271 QMap<int, QVariant> fields = detail.values();
272 QMap<int, QVariant>::const_iterator it;
273 for (it = fields.constBegin(); it != fields.constEnd(); ++it)
274 dbg.nospace() << ", " << it.key() << '=' << it.value();
275 dbg.nospace() << ')';
276 return dbg.maybeSpace();
277}
278#endif // QT_NO_DEBUG_STREAM
279
280#ifndef QT_NO_DATASTREAM
281/*!
282 \relates QOrganizerItemDetail
283 Writes \a detail to the stream \a out.
284 */
285Q_ORGANIZER_EXPORT QDataStream &operator<<(QDataStream &out, const QOrganizerItemDetail &detail)
286{
287 quint8 formatVersion = 1; // Version of QDataStream format for QOrganizerItemDetail
288 return out << formatVersion
289 << detail.type()
290 << detail.values();
291}
292
293/*!
294 \relates QOrganizerItemDetail
295 Reads an organizer item detail from stream \a in into \a detail.
296 */
297Q_ORGANIZER_EXPORT QDataStream &operator>>(QDataStream &in, QOrganizerItemDetail &detail)
298{
299 quint8 formatVersion;
300 in >> formatVersion;
301 if (formatVersion == 1) {
302 quint32 detailType;
303 QMap<int, QVariant> values;
304 in >> detailType >> values;
305
306 detail = QOrganizerItemDetail(static_cast<QOrganizerItemDetail::DetailType>(detailType));
307
308 QMapIterator<int, QVariant> it(values);
309 while (it.hasNext()) {
310 it.next();
311 detail.setValue(field: it.key(), value: it.value());
312 }
313 } else {
314 in.setStatus(QDataStream::ReadCorruptData);
315 }
316 return in;
317}
318#endif // QT_NO_DATASTREAM
319
320/*!
321 Returns true if no values are contained in this detail.
322 */
323bool QOrganizerItemDetail::isEmpty() const
324{
325 return (d->m_values.isEmpty());
326}
327
328/*!
329 Returns the key of this detail.
330 */
331int QOrganizerItemDetail::key() const
332{
333 return d->m_id;
334}
335
336/*!
337 Causes the implicitly-shared detail to be detached from any other copies, and generates a new key for it.
338 This ensures that calling QOrganizerItem::saveDetail() will result in a new detail being saved, rather than
339 another detail being updated.
340 */
341void QOrganizerItemDetail::resetKey()
342{
343 d->m_id = QOrganizerItemDetailPrivate::lastDetailKey().fetchAndAddOrdered(valueToAdd: 1);
344}
345
346/*!
347 Returns the value stored in this detail for the given \a field. An invalid QVariant is returned if the
348 value of \a field is not set.
349 */
350QVariant QOrganizerItemDetail::value(int field) const
351{
352 return d->m_values.value(akey: field);
353}
354
355/*!
356 Returns true if the value of the given \a field has been set, or false otherwise.
357 */
358bool QOrganizerItemDetail::hasValue(int field) const
359{
360 return d->m_values.contains(akey: field);
361}
362
363/*!
364 Sets the value of the given \a field to be \a value. If the given \a value is invalid or null,
365 removes the given \a field from the detail. Returns true on success, or false otherwise.
366 */
367bool QOrganizerItemDetail::setValue(int field, const QVariant &value)
368{
369 if (!value.isValid() || value.isNull())
370 return removeValue(field);
371
372 d->m_values.insert(akey: field, avalue: value);
373 return true;
374}
375
376/*!
377 Removes the value stored in this detail for the given \a field. Returns true if a value was stored
378 for the given \a field and the removing succeeds, or false otherwise.
379 */
380bool QOrganizerItemDetail::removeValue(int field)
381{
382 return d->m_values.remove(akey: field);
383}
384
385/*!
386 Returns the values stored in this detail as a field-to-value map.
387 */
388QMap<int, QVariant> QOrganizerItemDetail::values() const
389{
390 return d->m_values;
391}
392
393/*!
394 \fn template <typename T> T QOrganizerItemDetail::value(int field) const
395 Returns the value of the template type associated with the given \a field.
396 */
397
398QT_END_NAMESPACE_ORGANIZER
399

source code of qtpim/src/organizer/qorganizeritemdetail.cpp