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 QtContacts 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 "qcontactdetail.h"
35#include "qcontactdetail_p.h"
36#include "qcontactdetails.h"
37
38#ifndef QT_NO_DATASTREAM
39#include <QtCore/qdatastream.h>
40#endif
41#ifndef QT_NO_DEBUG_STREAM
42#include <QtCore/qdebug.h>
43#endif
44
45#include "qcontactmanager.h"
46
47/*
48 When these conditions are satisfied, QStringLiteral is implemented by
49 gcc's statement-expression extension. However, in this file it will
50 not work, because "statement-expressions are not allowed outside functions
51 nor in template-argument lists".
52
53 Fall back to the less-performant QLatin1String in this case.
54*/
55#if defined(QStringLiteral) && defined(QT_UNICODE_LITERAL_II) && defined(Q_CC_GNU) && !defined(Q_COMPILER_LAMBDA)
56# undef QStringLiteral
57# define QStringLiteral QLatin1String
58#endif
59
60QT_BEGIN_NAMESPACE_CONTACTS
61
62/* Initialise our static private data member */
63QAtomicInt QContactDetailPrivate::lastDetailKey(1);
64
65/*!
66 \class QContactDetail
67
68 \brief The QContactDetail class represents a single, complete detail about a contact.
69 \inmodule QtContacts
70 \ingroup contacts-main
71
72 All of the information for a contact is stored in one or more QContactDetail objects.
73
74 A detail is a group of logically related bits of data - for example, a street address is a single
75 detail that has multiple fields (number, region, country etc).
76 Different contact managers might have different fields
77 for the same detail type, depending on their capabilities. For example, for the QContactName detail
78 one manager might not support the middle name field, while a different manager may add an extra field for
79 specific extra information not present in the default schema.
80
81 One field which is common to all details is the context field. This field is intended to store one or
82 more contexts that this detail is associated with. Commonly this will be something like
83 "Home" and/or "Work", although no limitations are placed on which values may be stored in this field
84 in the default schema.
85
86 There are two other, related fields which are common to all details. The first is
87 \a QContactDetail::FieldDetailUri, which stores the unique URI of the detail if one exists.
88 The field is not mandatory, and backends are not required to verify that the given URI is indeed
89 unique within the contact. The second field is \a QContactDetail::LinkedDetailUris, which stores
90 a list of detail URIs to which this detail is linked. The link is one-way, and can be used to show
91 how or where a detail was derived. This is useful for things like presence information and avatars,
92 which are linked to a particular online account detail of the contact.
93
94 When a QContactDetail has been retrieved in a QContact from a QContactManager, it may have certain
95 access constraints provided with it, like \l ReadOnly or \l Irremovable. This might mean that the
96 supplied detail is calculated or otherwise not modifiable by the user - presence information is a
97 good example. Also, some details may be marked \l Irremovable. These are typically things that
98 a contact has to have - like a QContactType.
99
100 It is possible to inherit from QContactDetail to provide convenience or
101 standardized access to values. For example, \l QContactPhoneNumber provides
102 a convenient API for manipulating a QContactDetail as a phone number, according
103 to the schema.
104
105 In general, QContactDetail and the built in subclasses (like \l QContactPhoneNumber) provide
106 constants for the names of fields (like \l QContactPhoneNumber::FieldNumber), and for predefined
107 common values like \l QContactDetail::ContextHome. Typically the constants for field names start
108 with \c Field, and the constants for predefined values of a field start with the name of that field
109 (e.g. \c ContextHome is a predefined constant for \c FieldContext).
110
111 If you wish to create your own, customized contact detail, you should use
112 the \l QContactExtendedDetail detail.
113 QContactDetail objects act like type checked values. In general, you can assign them
114 to and from and have reasonable behaviour, like the following example.
115
116 \code
117
118 QContactPhoneNumber number;
119 number.setNumber("555-1212");
120 // number.value(QContactPhoneNumber::FieldNumber) == "555-1212";
121 // number.type() == QContactPhoneNumber::Type
122
123 QContactDetail detail = number;
124 // detail.value(QContactPhoneNumber::FieldNumber) == "555-1212";
125 // detail.type() == QContactPhoneNumber::Type
126
127 QContactPhoneNumber otherNumber = detail;
128 // otherNumber.number() == "555-1212";
129 // otherNumber.type() == QContactPhoneNumber::Type
130
131 QContactAddress address = detail;
132 // address is now a default constructed QContactAddress
133 // address.value(QContactPhoneNumber::FieldNumber) is empty
134 // address.type() == QContactAddress::Type
135
136 QContactAddress otherAddress = number;
137 // otherAddress is now a default constructed QContactAddress
138 // otherAddress.value(QContactPhoneNumber::FieldNumber) is empty
139 // otherAddress.type() == QContactAddress::Type
140 \endcode
141
142 \sa QContact, QContactDetail::DetailType, QContactDetailFilter, QContactDetailRangeFilter, Q_DECLARE_CUSTOM_CONTACT_DETAIL
143 */
144
145/*!
146 \macro Q_DECLARE_CUSTOM_CONTACT_DETAIL
147 \relates QContactDetail
148
149 Macro for simplifying declaring custom (leaf) detail classes.
150
151 The first argument is the detail type of the class.
152
153 If you are creating a convenience class for a type of QContactDetail,
154 you should use this macro when declaring your class to ensure that
155 it interoperates with other contact functionality.
156
157 Here is an example of a custom extension class using this macro.
158 Note that the class provides some predefined constants
159 and some convenience methods that return values associated with schema
160 fields.
161
162 \code
163 #include <QContactDetail>
164 class ContactVehicle : public QContactDetail
165 {
166 public:
167 Q_DECLARE_CUSTOM_CONTACT_DETAIL(ContactVehicle)
168
169 enum VehicleField {
170 FieldRegistration = 0,
171 FieldMake,
172 FieldModel,
173 FieldColor
174 };
175
176 QString registration() const { return value(FieldRegistration).toString(); }
177 void setRegistration(const QString& _registration) { setValue(FieldRegistration, _registration);
178
179 QString make() const { return value(FieldMake).toString(); }
180 void setMake(const QString& _make) { setValue(FieldMake, _make); }
181
182 QString model() const { return value(FieldModel).toString(); }
183 void setModel(const QString& _model) { setValue(FieldModel, _model); }
184
185 QString color() const { return value(FieldColor).toString(); }
186 void setColor(const QString &_color) { setValue(FieldColor, _color); }
187 };
188 \endcode
189*/
190
191/*!
192 \enum QContactDetail::DetailType
193
194 This enumeration defines the detail types provided by the contacts API.
195 \value TypeUndefined Convenience value used to represent unknown / undefined detail types.
196 \value TypeAddress Detail type of a QContactAddress detail.
197 \value TypeAnniversary Detail type of a QContactAnniversary detail.
198 \value TypeAvatar Detail type of a QContactAvatar detail.
199 \value TypeBirthday Detail type of a QContactBirthday detail.
200 \value TypeDisplayLabel Detail type of a QContactDisplayLabel detail.
201 \value TypeEmailAddress Detail type of a QContactEmailAddress detail.
202 \value TypeExtendedDetail Detail type of a QContactExtendedDetail detail.
203 \value TypeFamily Detail type of a QContactFamily detail.
204 \value TypeFavorite Detail type of a QContactFavorite detail.
205 \value TypeGender Detail type of a QContactGender detail.
206 \value TypeGeoLocation Detail type of a QContactGeoLocation detail.
207 \value TypeGlobalPresence Detail type of a QContactGlobalPresence detail.
208 \value TypeGuid Detail type of a QContactGuid detail.
209 \value TypeHobby Detail type of a QContactHobby detail.
210 \value TypeName Detail type of a QContactName detail.
211 \value TypeNickname Detail type of a QContactNickname detail.
212 \value TypeNote Detail type of a QContactNote detail.
213 \value TypeOnlineAccount Detail type of a QContactOnlineAccount detail.
214 \value TypeOrganization Detail type of a QContactOrganization detail.
215 \value TypePhoneNumber Detail type of a QContactPhoneNumber detail.
216 \value TypePresence Detail type of a QContactPresence detail.
217 \value TypeRingtone Detail type of a QContactRingtone detail.
218 \value TypeSyncTarget Detail type of a QContactSyncTarget detail.
219 \value TypeTag Detail type of a QContactTag detail.
220 \value TypeTimestamp Detail type of a QContactTimestamp detail.
221 \value TypeType Detail type of a QContactType detail.
222 \value TypeUrl Detail type of a QContactUrl detail.
223 \value TypeVersion Detail type of a QContactVersion detail.
224
225 \sa type()
226 */
227
228/*!
229 \fn QContactDetail::operator!=(const QContactDetail& other) const
230 Returns true if the values or id of this detail is different to those of the \a other detail
231 */
232
233/*!
234 Constructs a new, empty detail
235 */
236QContactDetail::QContactDetail()
237 : d(new QContactDetailPrivate)
238{
239}
240
241/*! Constructs a detail that is a copy of \a other
242 */
243QContactDetail::QContactDetail(const QContactDetail& other)
244 : d(other.d)
245{
246}
247
248/*!
249 * Assigns this detail to \a other
250 */
251QContactDetail& QContactDetail::operator=(const QContactDetail& other)
252{
253 if (this != &other)
254 d = other.d;
255 return *this;
256}
257
258/*! Frees the memory used by this detail */
259QContactDetail::~QContactDetail()
260{
261}
262
263/*!
264 Returns the (unique) enum of the type which defines the semantics and structure of this detail.
265 */
266QContactDetail::DetailType QContactDetail::type() const
267{
268 return static_cast<QContactDetail::DetailType>(d.constData()->m_type);
269}
270
271/*!
272 Compares this detail to \a other. Returns true if the type, access constraints and values of \a other are equal to those of this detail.
273 The keys of each detail are not considered during the comparison, in order to allow details from different contacts to
274 be compared according to their values.
275 */
276bool QContactDetail::operator==(const QContactDetail& other) const
277{
278 return (*d == *other.d);
279}
280
281/*! Returns the hash value for \a key.
282*/
283uint qHash(const QContactDetail &key)
284{
285 uint hash = qHash(key: QString().setNum(n: key.type()))
286 + QT_PREPEND_NAMESPACE(qHash)(key: key.accessConstraints());
287 QMap<int, QVariant> values = key.values();
288 QMap<int, QVariant>::const_iterator it = values.constBegin(), end = values.constEnd();
289 for ( ; it != end; ++it) {
290 hash += QT_PREPEND_NAMESPACE(qHash)(key: it.key())
291 + QT_PREPEND_NAMESPACE(qHash)(key: it.value().toString());
292 }
293 return hash;
294}
295
296#ifndef QT_NO_DEBUG_STREAM
297QDebug operator<<(QDebug dbg, const QContactDetail& detail)
298{
299 dbg.nospace() << "QContactDetail(detailType=" << detail.type() << ", key=" << detail.key();
300 QMap<int, QVariant> fields = detail.values();
301 QMap<int, QVariant>::const_iterator it;
302 for (it = fields.constBegin(); it != fields.constEnd(); ++it) {
303 dbg.nospace() << ", " << it.key() << '=' << it.value();
304 }
305 dbg.nospace() << ')';
306 return dbg.maybeSpace();
307}
308#endif
309
310#ifndef QT_NO_DATASTREAM
311/*!
312 * Writes \a detail to the stream \a out.
313 */
314QDataStream& operator<<(QDataStream& out, const QContactDetail& detail)
315{
316 quint8 formatVersion = 1; // Version of QDataStream format for QContactDetail
317 return out << formatVersion
318 << static_cast<quint32>(detail.type())
319 << static_cast<quint32>(detail.accessConstraints())
320 << detail.values();
321}
322
323/*!
324 * Reads a contact detail from stream \a in into \a detail.
325 */
326QDataStream& operator>>(QDataStream& in, QContactDetail& detail)
327{
328 detail = QContactDetail();
329 quint8 formatVersion;
330 in >> formatVersion;
331 if (formatVersion == 1) {
332 quint32 typeInt;
333 quint32 accessConstraintsInt;
334 QMap<int, QVariant> values;
335 in >> typeInt >> accessConstraintsInt >> values;
336
337 detail = QContactDetail(QContactDetail::DetailType(typeInt));
338 QContactDetail::AccessConstraints accessConstraints(accessConstraintsInt);
339 detail.d->m_access = accessConstraints;
340
341 QMapIterator<int, QVariant> it(values);
342 while (it.hasNext()) {
343 it.next();
344 detail.setValue(field: it.key(), value: it.value());
345 }
346 } else {
347 in.setStatus(QDataStream::ReadCorruptData);
348 }
349 return in;
350}
351#endif
352
353/*!
354 Returns true if no values are contained in this detail. Note that context
355 is stored as a value; hence, if a context is set, this function will return false.
356
357 An empty value (for example, the string "") is still a value contained in this
358 detail, so this function will return false.
359 */
360bool QContactDetail::isEmpty() const
361{
362 return d->isEmpty();
363}
364
365/*!
366 * Returns the key of this detail.
367 *
368 * Be aware that if a contact is retrieved (or reloaded) from the backend, the
369 * keys of any details it contains may have been changed by the backend, or other
370 * threads may have modified the contact details in the backend. Therefore,
371 * clients should reload the detail that they wish to save in or remove from a contact
372 * after retrieving the contact from the backend, in order to ascertain the keys of
373 * any such details.
374 */
375int QContactDetail::key() const
376{
377 return d.constData()->m_detailId;
378}
379
380/*!
381 * Generates a new key (detail id) for the detail.
382 * This ensures that calling QContact::saveDetail() will result in a new detail being saved, rather than
383 * another detail being updated.
384 */
385void QContactDetail::resetKey()
386{
387 d->m_detailId = QContactDetailPrivate::lastDetailKey.fetchAndAddOrdered(valueToAdd: 1);
388}
389
390/*!
391 * Returns the value stored in this detail for the given \a field. An invalid QVariant is returned if
392 * the value of \a field is not set.
393 */
394QVariant QContactDetail::value(int field) const
395{
396 if (!hasValue(field))
397 return QVariant();
398 return d->value(field);
399}
400
401/*!
402 * Returns true if this detail has a field with the given \a field, or false otherwise.
403 */
404bool QContactDetail::hasValue(int field) const
405{
406 return d->hasValue(field);
407}
408
409/*!
410 Inserts \a value into the detail for the given \a field if \a value is valid. If \a value is invalid,
411 removes the field with the given \a field from the detail. Returns true if the given \a value was set
412 for the \a field (if the \a value was valid), or if the given \a field was removed from detail (if the
413 \a value was invalid), and returns false if the field could not be removed (and the \a value was invalid)
414*/
415bool QContactDetail::setValue(int field, const QVariant& _value)
416{
417 if (!_value.isValid())
418 return removeValue(field);
419 return d->setValue(field, _value);
420}
421
422void QContactDetail::setValues(const QMap<int, QVariant> &newValues)
423{
424 QMap<int, QVariant>::const_iterator it = newValues.constBegin(), end = newValues.constEnd();
425 for ( ; it != end; ++it) {
426 setValue(field: it.key(), value: it.value());
427 }
428}
429
430/*!
431 Removes the value stored in this detail for the given \a field. Returns true if a value was stored
432 for the given \a field and the operation succeeded, and false otherwise.
433*/
434bool QContactDetail::removeValue(int field)
435{
436 return d->removeValue(field);
437}
438
439/*!
440 Returns the values stored in this detail as a field-to-value map.
441 */
442QMap<int, QVariant> QContactDetail::values() const
443{
444 return d->values();
445}
446
447/*!
448 \enum QContactDetail::AccessConstraint
449
450 This enum defines the access constraints for a detail. This information is typically provided by
451 the manager when a contact is retrieved.
452
453 \value NoConstraint Users can read, write, and otherwise modify this detail in any manner.
454 \value ReadOnly Users cannot write or modify values in this detail.
455 \value Irremovable Users cannot remove this detail from a contact.
456 */
457
458
459/*!
460 Returns the access constraints associated with the detail.
461
462 Some details may not be written to, while other details may
463 not be removed from a contact.
464
465 \sa QContactDetail::AccessConstraints
466 */
467QContactDetail::AccessConstraints QContactDetail::accessConstraints() const
468{
469 return d.constData()->m_access;
470}
471
472
473/*!
474 \fn QString QContactDetail::provenance() const
475
476 This is a convenience function to return the \c Provenance field of this detail.
477 Any detail in an aggregate contact which originally comes from a \c Facet contact
478 should have provenance information.
479
480 It is equivalent to the following code:
481 \code
482 value(QContactDetail::FieldProvenance);
483 \endcode
484
485 \sa value()
486 */
487
488/*!
489 \enum QContactDetail::DetailContext
490
491 This enum defines the contexts for a detail.
492
493 \value ContextHome The detail data relates to home / private detail about the contact.
494 \value ContextWork The detail data relates to business / work detail about the contact.
495 \value ContextOther Generic context, neither ContextHome nor ContextWork
496 \sa setContexts(), contexts()
497 */
498
499/*!
500 \fn void QContactDetail::setContexts(const QList<int>& contexts)
501
502 This is a convenience function that sets the \c Context field of this detail to the given \a contexts.
503
504 It is equivalent to the following code:
505 \code
506 setValue(QContactDetail::FieldContext, contexts);
507 \endcode
508
509 \sa setValue()
510 */
511
512/*!
513 \fn void QContactDetail::setContexts(int context)
514
515 This is a convenience function that sets the \c Context field of this detail to the given \a context.
516 It is useful if the detail is only valid in a single context.
517
518 It is equivalent to the following code:
519 \code
520 setValue(FieldContext, QList<int>() << context);
521 \endcode
522
523 \sa setValue()
524 */
525
526/*!
527 \fn QStringList QContactDetail::contexts() const
528
529 This is a convenience function to return the \c Context field of this detail.
530
531 It is equivalent to the following code:
532 \code
533 value<QStringList>(QContactDetail::FieldContext);
534 \endcode
535
536 \sa value()
537 */
538
539/*!
540 \enum QContactDetail::DetailField
541
542 This enum defines the common fields supported by any detail.
543
544 \value FieldContext The field containing the contexts of a detail.
545 \value FieldDetailUri The field containing the detail URI of a detail.
546 \value FieldLinkedDetailUris The field containing the URIs of other details linked to a detail.
547 \value FieldProvenance The field containing the provenance information for the detail.
548 \sa setContexts(), contexts()
549 \sa setDetailUri(), detailUri()
550 \sa setLinkedDetailUris(), linkedDetailUris()
551 \sa provenance()
552 */
553
554/*!
555 \fn void QContactDetail::setDetailUri(const QString& detailUri)
556
557 This is a convenience function that sets the \c DetailUri field of this detail to the given \a detailUri.
558 In order to be linked to, a detail must have a specific and (per-contact) unique detail URI set.
559
560 It is equivalent to the following code:
561 \code
562 setValue(FieldDetailUri, detailUri);
563 \endcode
564
565 \sa setValue()
566 */
567
568/*!
569 \fn QString QContactDetail::detailUri() const
570
571 This is a convenience function to return the \c DetailUri field of this detail.
572
573 It is equivalent to the following code:
574 \code
575 value(QContactDetail::FieldDetailUri);
576 \endcode
577
578 \sa value()
579 */
580
581
582/*!
583 \fn void QContactDetail::setLinkedDetailUris(const QStringList& linkedDetailUris)
584
585 This is a convenience function that sets the \c LinkedDetailUris field of this detail to the given \a linkedDetailUris.
586
587 It is equivalent to the following code:
588 \code
589 setValue(QContactDetail::FieldLinkedDetailUris, linkedDetailUris);
590 \endcode
591
592 \sa setValue()
593 */
594
595/*!
596 \fn void QContactDetail::setLinkedDetailUris(const QString& linkedDetailUri)
597
598 This is a convenience function that sets the \c LinkedDetailUris field of this detail to the given \a linkedDetailUri.
599 It is useful if the detail is linked to a single other detail in the contact.
600
601 It is equivalent to the following code:
602 \code
603 setValue(FieldLinkedDetailUris, QStringList(linkedDetailUri));
604 \endcode
605
606 \sa setValue()
607 */
608
609/*!
610 \fn QStringList QContactDetail::linkedDetailUris() const
611
612 This is a convenience function to return the \c Context field of this detail.
613
614 It is equivalent to the following code:
615 \code
616 value<QStringList>(QContactDetail::FieldLinkedDetailUris);
617 \endcode
618
619 \sa value()
620 */
621
622
623QT_END_NAMESPACE_CONTACTS
624

source code of qtpim/src/contacts/qcontactdetail.cpp