|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include <QSet> |
|
43 #include <QDebug> |
|
44 |
|
45 #include "qcontact.h" |
|
46 #include "qcontact_p.h" |
|
47 #include "qcontactdetail_p.h" |
|
48 #include "qcontactmanager_p.h" |
|
49 #include "qcontactaction.h" |
|
50 |
|
51 QTM_BEGIN_NAMESPACE |
|
52 |
|
53 /*! |
|
54 \class QContact |
|
55 |
|
56 \brief The QContact class represents an addressbook contact. |
|
57 |
|
58 \ingroup contacts-main |
|
59 |
|
60 Individual contacts, groups, and other types of contacts are represented with |
|
61 a QContact object. In addition to the type, a QContact consists of information |
|
62 that belongs to the contact, some information about the relationships that the |
|
63 contact has, and the preferred ways to interact with the contact. |
|
64 |
|
65 A QContact object has a collection of details (like a name, phone numbers and |
|
66 email addresses). Each detail (which can have multiple fields) is stored |
|
67 in an appropriate subclass of QContactDetail, and the QContact allows |
|
68 retrieving these details in various ways. |
|
69 |
|
70 Depending on the details of the QContact, certain actions are available for a |
|
71 contact. An instance of a QContact can return a list of actions that can be |
|
72 performed on it, and a list of details supported by a specific action can be |
|
73 retrieved (for example - a list of phone numbers supported by a specific "Call" action). |
|
74 It is also possible to store one detail for each type of action that is the "preferred" |
|
75 detail to use. |
|
76 |
|
77 A QContact may have zero or more relationships with other contacts. For example, |
|
78 a group contact would have a \c "HasMember" relationship with the QContacts that |
|
79 are its members. Spouses, managers and assistants can also be represented this |
|
80 way. |
|
81 |
|
82 A QContact instance represents the in-memory version of an addressbook contact, |
|
83 and has no tie to a specific QContactManager. It is possible for the contents |
|
84 of a QContact to change independently of the contents that are stored persistently |
|
85 in a QContactManager. A QContact has an ID associated with it when it is first |
|
86 retrieved from a QContactManager, or after it has been first saved, and this allows |
|
87 clients to track changes using the signals in QContactManager. |
|
88 |
|
89 A QContact has a number of mandatory details: |
|
90 \list |
|
91 \o A QContactType, with the type of the contact (individual contact, group etc) |
|
92 \o A QContactDisplayLabel, representing the text to display |
|
93 \endlist |
|
94 |
|
95 If you have edited the contents of a QContact (via saving or removing details), |
|
96 you will need to ask a specific QContactManager for the new display label for the |
|
97 contact, since system settings (like the order of first or last names) can vary |
|
98 between managers. |
|
99 |
|
100 \sa QContactManager, QContactDetail |
|
101 */ |
|
102 |
|
103 /*! |
|
104 * \fn QList<T> QContact::details() const |
|
105 * Returns a list of details of the template parameter type. The type must be |
|
106 * a subclass of QContactDetail. |
|
107 * |
|
108 * For example: |
|
109 * \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 3 |
|
110 */ |
|
111 |
|
112 /*! |
|
113 * \fn QList<T> QContact::details(const QString& fieldName, const QString& value) const |
|
114 * Returns a list of details of the template parameter type which have field called \a fieldName, with matching \a value. |
|
115 * The type must be a subclass of QContactDetail. |
|
116 * |
|
117 * For example: |
|
118 * \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 4 |
|
119 */ |
|
120 |
|
121 /*! |
|
122 * \fn T QContact::detail() const |
|
123 * Returns the first detail of the template parameter type, as returned by the template details() function. |
|
124 * The type must be a subclass of QContactDetail. |
|
125 */ |
|
126 |
|
127 /*! |
|
128 * \fn QContact::operator!=(const QContact &other) const |
|
129 * Returns true if this contacts id or details are different to those of the \a other contact. |
|
130 */ |
|
131 |
|
132 /*! |
|
133 Construct an empty contact. |
|
134 |
|
135 The contact will have an empty display label, an empty id, and have type \l QContactType::TypeContact. |
|
136 The isEmpty() function will return true. |
|
137 */ |
|
138 QContact::QContact() |
|
139 : d(new QContactData) |
|
140 { |
|
141 clearDetails(); |
|
142 } |
|
143 |
|
144 /*! Initializes this QContact from \a other */ |
|
145 QContact::QContact(const QContact& other) |
|
146 : d(other.d) |
|
147 { |
|
148 } |
|
149 |
|
150 /*! |
|
151 * Returns true if this QContact is empty, false if not. |
|
152 * |
|
153 * An empty QContact has an empty label and no extra details. |
|
154 * The type of the contact is irrelevant. |
|
155 */ |
|
156 bool QContact::isEmpty() const |
|
157 { |
|
158 /* Every contact has a display label field.. */ |
|
159 if (d->m_details.count() > 2) |
|
160 return false; |
|
161 |
|
162 /* We know we have two details (a display label and a type) */ |
|
163 const QContactDisplayLabel& label = d->m_details.at(0); |
|
164 return label.label().isEmpty(); |
|
165 } |
|
166 |
|
167 /*! |
|
168 * Removes all details of the contact. |
|
169 * This function does not modify the id or type of the contact. |
|
170 * Calling isEmpty() after calling this function will return true. |
|
171 */ |
|
172 void QContact::clearDetails() |
|
173 { |
|
174 d->m_details.clear(); |
|
175 |
|
176 // insert the contact's display label detail. |
|
177 QContactDisplayLabel contactLabel; |
|
178 contactLabel.setValue(QContactDisplayLabel::FieldLabel, QString()); |
|
179 contactLabel.d->m_access = QContactDetail::Irremovable | QContactDetail::ReadOnly; |
|
180 d->m_details.insert(0, contactLabel); |
|
181 |
|
182 // and the contact type detail. |
|
183 QContactType contactType; |
|
184 contactType.setType(QContactType::TypeContact); |
|
185 contactType.d->m_access = QContactDetail::Irremovable; |
|
186 d->m_details.insert(1, contactType); |
|
187 } |
|
188 |
|
189 /*! Replace the contents of this QContact with \a other */ |
|
190 QContact& QContact::operator=(const QContact& other) |
|
191 { |
|
192 d = other.d; |
|
193 return *this; |
|
194 } |
|
195 |
|
196 /*! Frees the memory used by this QContact */ |
|
197 QContact::~QContact() |
|
198 { |
|
199 } |
|
200 |
|
201 /*! |
|
202 Returns the QContactId that identifies this contact. |
|
203 |
|
204 This may have been set when the contact was retrieved from |
|
205 a particular manager, or when the contact was first saved |
|
206 in a manager. The QContactId is only valid with a specific |
|
207 manager. See \l QContactManager::saveContact() for more |
|
208 information. |
|
209 |
|
210 \sa localId() |
|
211 */ |
|
212 QContactId QContact::id() const |
|
213 { |
|
214 return d->m_id; |
|
215 } |
|
216 |
|
217 /*! |
|
218 Returns the QContactLocalId that identifies this contact within its manager |
|
219 |
|
220 This may have been set when the contact was retrieved from |
|
221 a particular manager, or when the contact was first saved |
|
222 in a manager. The QContactLocalId is associated with a specific |
|
223 manager, but other contacts with the same local id might exist in |
|
224 different managers. |
|
225 |
|
226 See \l QContactManager::saveContact() for more |
|
227 information. |
|
228 |
|
229 \sa id() |
|
230 */ |
|
231 QContactLocalId QContact::localId() const |
|
232 { |
|
233 return d->m_id.localId(); |
|
234 } |
|
235 |
|
236 /*! |
|
237 * Returns the type of the contact. Every contact has exactly one type which |
|
238 * is either set manually (by saving a modified copy of the QContactType |
|
239 * in the contact, or by calling \l setType()) or synthesized automatically. |
|
240 * |
|
241 * \sa setType() |
|
242 */ |
|
243 QString QContact::type() const |
|
244 { |
|
245 // type is detail 1 |
|
246 QString type = d->m_details.at(1).value(QContactType::FieldType); |
|
247 if (type.isEmpty()) |
|
248 return QString(QLatin1String(QContactType::TypeContact)); |
|
249 return type; |
|
250 } |
|
251 |
|
252 /*! |
|
253 * Sets the type of the contact to the given \a type. |
|
254 */ |
|
255 void QContact::setType(const QString& type) |
|
256 { |
|
257 // type is detail 1 |
|
258 QContactType newType; |
|
259 newType.setType(type); |
|
260 newType.d->m_access = QContactDetail::Irremovable; |
|
261 |
|
262 d->m_details[1] = newType; |
|
263 } |
|
264 |
|
265 /*! |
|
266 * Sets the type of the contact to the given \a type detail. |
|
267 */ |
|
268 void QContact::setType(const QContactType& type) |
|
269 { |
|
270 // type is detail 1 |
|
271 d->m_details[1] = type; |
|
272 d->m_details[1].d->m_access = QContactDetail::Irremovable; |
|
273 } |
|
274 |
|
275 /*! |
|
276 * Returns the display label of this contact. |
|
277 * |
|
278 * A contact which has been retrieved from a manager will have a display label set when |
|
279 * the contact is retrieved. |
|
280 * |
|
281 * The display label is usually read-only, since some managers do not support arbitrary |
|
282 * labels (see also \l QContactName::setCustomLabel()). If you modify the contact in a way |
|
283 * that would affect the display label, you can call QContactManager::synthesizeContactDisplayLabel() to get an |
|
284 * up-to-date display label. |
|
285 * |
|
286 * See the following example for more information: |
|
287 * \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp Updating the display label of a contact |
|
288 * |
|
289 * \sa QContactManager::synthesizeContactDisplayLabel() |
|
290 */ |
|
291 QString QContact::displayLabel() const |
|
292 { |
|
293 return d->m_details.at(0).value(QContactDisplayLabel::FieldLabel); |
|
294 } |
|
295 |
|
296 /*! |
|
297 * Sets the id of this contact to \a id. |
|
298 * |
|
299 * Note that this only affects this object, not any corresponding structures stored |
|
300 * by a QContactManager. |
|
301 * |
|
302 * If you change the id of a contact and save the contact |
|
303 * in a manager, the previously existing contact will still |
|
304 * exist. You can do this to create copies (possibly modified) |
|
305 * of an existing contact, or to save a contact in a different manager. |
|
306 * |
|
307 * \sa QContactManager::saveContact() |
|
308 */ |
|
309 void QContact::setId(const QContactId& id) |
|
310 { |
|
311 d->m_id = id; |
|
312 } |
|
313 |
|
314 /*! |
|
315 \fn QContactDetail QContact::detail(const QLatin1Constant& definitionName) const |
|
316 Returns the first detail stored in the contact which with the given \a definitionName. |
|
317 The \a definitionName argument is typically the detail name constant provided by a |
|
318 specific subclass of QContactDetail. For example: |
|
319 |
|
320 \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 0 |
|
321 |
|
322 It would usually be more convenient to use the template version of this function, in |
|
323 the following manner: |
|
324 |
|
325 \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 1 |
|
326 */ |
|
327 |
|
328 /*! |
|
329 \fn QList<QContactDetail> QContact::details(const QLatin1Constant& definitionName) const |
|
330 Returns a list of details of the given \a definitionName. |
|
331 |
|
332 The \a definitionName argument is typically the detail name constant provided by a |
|
333 specific subclass of QContactDetail. For example: |
|
334 |
|
335 \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 2 |
|
336 |
|
337 It would usually be more convenient to use the template version of this function, in |
|
338 the following manner: |
|
339 |
|
340 \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 3 |
|
341 */ |
|
342 |
|
343 /*! |
|
344 \fn QList<QContactDetail> QContact::details(const QLatin1Constant& definitionName, const QLatin1Constant& fieldName, const QString& value) |
|
345 Returns a list of details of the given \a definitionName, with fields named \a fieldName and with value \a value. |
|
346 */ |
|
347 |
|
348 /*! |
|
349 \fn QList<T> QContact::details(const char* fieldName, const QString& value) const |
|
350 \internal |
|
351 |
|
352 Returns a list of details of the template type which match the \a fieldName and \a value criteria |
|
353 */ |
|
354 |
|
355 /*! |
|
356 Returns the first detail stored in the contact with the given \a definitionName |
|
357 */ |
|
358 QContactDetail QContact::detail(const QString& definitionName) const |
|
359 { |
|
360 if (definitionName.isEmpty()) |
|
361 return d->m_details.first(); |
|
362 |
|
363 // build the sub-list of matching details. |
|
364 for (int i = 0; i < d->m_details.size(); i++) { |
|
365 const QContactDetail& existing = d->m_details.at(i); |
|
366 if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName) { |
|
367 return existing; |
|
368 } |
|
369 } |
|
370 |
|
371 return QContactDetail(); |
|
372 } |
|
373 |
|
374 /*! Returns a list of details with the given \a definitionName |
|
375 The definitionName string can be determined by the DefinitionName attribute |
|
376 of defined objects (e.g. QContactPhoneNumber::DefinitionName) or by |
|
377 requesting a list of all the definitions synchronously with |
|
378 \l {QContactManager::detailDefinitions()}{detailDefinitions()} or |
|
379 asynchronously with a |
|
380 \l {QContactDetailDefinitionFetchRequest}{detail definition fetch request}, |
|
381 and then inspecting the |
|
382 \l{QContactDetailDefinition::name()}{name()} of each |
|
383 definition. If \a definitionName is empty, all details of any definition |
|
384 will be returned. |
|
385 */ |
|
386 QList<QContactDetail> QContact::details(const QString& definitionName) const |
|
387 { |
|
388 // build the sub-list of matching details. |
|
389 QList<QContactDetail> sublist; |
|
390 |
|
391 // special case |
|
392 if (definitionName.isEmpty()) { |
|
393 sublist = d->m_details; |
|
394 } else { |
|
395 for (int i = 0; i < d->m_details.size(); i++) { |
|
396 const QContactDetail& existing = d->m_details.at(i); |
|
397 if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName) { |
|
398 sublist.append(existing); |
|
399 } |
|
400 } |
|
401 } |
|
402 |
|
403 return sublist; |
|
404 } |
|
405 |
|
406 /*! |
|
407 Returns a list of details of the given \a definitionName, with fields named \a fieldName and with value \a value. |
|
408 The definitionName string can be determined by the DefinitionName attribute |
|
409 of defined objects (e.g. QContactPhoneNumber::DefinitionName) or by |
|
410 requesting a list of all the definitions synchronously with |
|
411 \l {QContactManager::detailDefinitions()}{detailDefinitions()} or |
|
412 asynchronously with a |
|
413 \l {QContactDetailDefinitionFetchRequest}{detail definition fetch request}, |
|
414 and then inspecting the |
|
415 \l{QContactDetailDefinition::name()}{name()} of each |
|
416 definition. If \a definitionName is empty, all details of any definition |
|
417 will be returned. |
|
418 */ |
|
419 QList<QContactDetail> QContact::details(const QString& definitionName, const QString& fieldName, const QString& value) const |
|
420 { |
|
421 // build the sub-list of matching details. |
|
422 QList<QContactDetail> sublist; |
|
423 |
|
424 // special case |
|
425 if (fieldName.isEmpty()) { |
|
426 sublist = details(definitionName); |
|
427 } else { |
|
428 for (int i = 0; i < d->m_details.size(); i++) { |
|
429 const QContactDetail& existing = d->m_details.at(i); |
|
430 if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName |
|
431 && existing.hasValue(fieldName) && value == existing.value(fieldName)) { |
|
432 sublist.append(existing); |
|
433 } |
|
434 } |
|
435 } |
|
436 |
|
437 return sublist; |
|
438 } |
|
439 |
|
440 /*! |
|
441 \internal |
|
442 Returns the first detail stored in the contact which with the given \a definitionName |
|
443 */ |
|
444 QContactDetail QContact::detail(const char* definitionName) const |
|
445 { |
|
446 if (definitionName == 0) |
|
447 return d->m_details.first(); |
|
448 |
|
449 // build the sub-list of matching details. |
|
450 for (int i = 0; i < d->m_details.size(); i++) { |
|
451 const QContactDetail& existing = d->m_details.at(i); |
|
452 if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName) { |
|
453 return existing; |
|
454 } |
|
455 } |
|
456 |
|
457 return QContactDetail(); |
|
458 } |
|
459 |
|
460 /*! |
|
461 \internal |
|
462 Returns a list of details with the given \a definitionName |
|
463 */ |
|
464 QList<QContactDetail> QContact::details(const char* definitionName) const |
|
465 { |
|
466 // build the sub-list of matching details. |
|
467 QList<QContactDetail> sublist; |
|
468 |
|
469 // special case |
|
470 if (definitionName == 0) { |
|
471 sublist = d->m_details; |
|
472 } else { |
|
473 for (int i = 0; i < d->m_details.size(); i++) { |
|
474 const QContactDetail& existing = d->m_details.at(i); |
|
475 if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName) { |
|
476 sublist.append(existing); |
|
477 } |
|
478 } |
|
479 } |
|
480 |
|
481 return sublist; |
|
482 } |
|
483 |
|
484 /*! |
|
485 \internal |
|
486 Returns a list of details with the given \a definitionName, \a fieldName and field \a value |
|
487 */ |
|
488 QList<QContactDetail> QContact::details(const char* definitionName, const char* fieldName, const QString& value) const |
|
489 { |
|
490 // build the sub-list of matching details. |
|
491 QList<QContactDetail> sublist; |
|
492 |
|
493 // special case |
|
494 if (fieldName == 0) { |
|
495 sublist = details(definitionName); |
|
496 } else { |
|
497 for (int i = 0; i < d->m_details.size(); i++) { |
|
498 const QContactDetail& existing = d->m_details.at(i); |
|
499 if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName |
|
500 && existing.hasValue(fieldName) && value == existing.value(fieldName)) { |
|
501 sublist.append(existing); |
|
502 } |
|
503 } |
|
504 } |
|
505 |
|
506 return sublist; |
|
507 } |
|
508 |
|
509 /*! |
|
510 * Saves the given \a detail in the list of stored details, and sets the detail's id. |
|
511 * If another detail of the same type and id has been previously saved in |
|
512 * this contact, that detail is overwritten. Otherwise, a new id is generated |
|
513 * and set in the detail, and the detail is added to the contact. |
|
514 * |
|
515 * If the detail's access constraint includes \c QContactDetail::ReadOnly, |
|
516 * this function will return true and save the detail in the contact, |
|
517 * however attempting to save the contact in a manager may fail (if that manager |
|
518 * decides that the read only detail should not be updated). |
|
519 * Details with the \c QContactDetail::ReadOnly constraint set are typically provided |
|
520 * in a contact by the manager, and are usually information that is either |
|
521 * synthesized, or not intended to be changed by the user (e.g. presence information |
|
522 * for other contacts). |
|
523 * |
|
524 * If \a detail is a QContactType, the existing contact type will |
|
525 * be overwritten with \a detail. There is never more than one contact type |
|
526 * in a contact. |
|
527 * |
|
528 * If \a detail is a QContactDisplayLabel, the contact will not be updated, |
|
529 * and the function will return false. Since the display label formatting is specific |
|
530 * to each manager, use the QContactManager::synthesizeContactDisplayLabel() function |
|
531 * instead. |
|
532 * |
|
533 * Be aware that if a contact is retrieved (or reloaded) from the backend, the |
|
534 * keys of any details it contains may have been changed by the backend, or other |
|
535 * threads may have modified the contact details in the backend. Therefore, |
|
536 * clients should reload the detail that they wish to save in a contact after retrieving |
|
537 * the contact, in order to avoid creating unwanted duplicated details. |
|
538 * |
|
539 * Returns true if the detail was saved successfully, otherwise returns false. |
|
540 * |
|
541 * Note that the caller retains ownership of the detail. |
|
542 * \sa QContactManager::synthesizeContactDisplayLabel() |
|
543 */ |
|
544 bool QContact::saveDetail(QContactDetail* detail) |
|
545 { |
|
546 if (!detail) |
|
547 return false; |
|
548 |
|
549 /* Also handle contact type specially - only one of them. */ |
|
550 if (QContactDetailPrivate::detailPrivate(*detail)->m_definitionName == QContactType::DefinitionName.latin1()) { |
|
551 detail->d->m_access |= QContactDetail::Irremovable; |
|
552 d->m_details[1] = *detail; |
|
553 return true; |
|
554 } |
|
555 |
|
556 /* And display label.. */ |
|
557 if (QContactDetailPrivate::detailPrivate(*detail)->m_definitionName == QContactDisplayLabel::DefinitionName.latin1()) { |
|
558 return false; |
|
559 } |
|
560 |
|
561 // try to find the "old version" of this field |
|
562 // ie, the one with the same type and id, but different value or attributes. |
|
563 for (int i = 0; i < d->m_details.size(); i++) { |
|
564 const QContactDetail& curr = d->m_details.at(i); |
|
565 if (detail->d->m_definitionName == curr.d->m_definitionName && detail->d->m_id == curr.d->m_id) { |
|
566 // update the detail constraints of the supplied detail |
|
567 detail->d->m_access = d->m_details[i].accessConstraints(); |
|
568 // Found the old version. Replace it with this one. |
|
569 d->m_details[i] = *detail; |
|
570 return true; |
|
571 } |
|
572 } |
|
573 |
|
574 // this is a new detail! add it to the contact. |
|
575 d->m_details.append(*detail); |
|
576 return true; |
|
577 } |
|
578 |
|
579 /*! |
|
580 * Removes the \a detail from the contact. |
|
581 * |
|
582 * The detail in the contact which has the same key as that of the given \a detail |
|
583 * will be removed if it exists. Only the key is used for comparison - that is, the |
|
584 * information in the detail may be different. |
|
585 * |
|
586 * Any action preferences for the matching detail is also removed. |
|
587 * |
|
588 * Be aware that if a contact is retrieved (or reloaded) from the backend, the |
|
589 * keys of any details it contains may have been changed by the backend, or other |
|
590 * threads may have modified the contact details in the backend. Therefore, |
|
591 * clients should reload the detail that they wish to remove from a contact after retrieving |
|
592 * the contact, in order to ensure that the remove operation is successful. |
|
593 * |
|
594 * If the detail's access constraint includes \c QContactDetail::Irremovable, |
|
595 * this function will return false. |
|
596 * |
|
597 * Returns true if the detail was removed successfully, false if an error occurred. |
|
598 * |
|
599 * Note that the caller retains ownership of the detail. |
|
600 */ |
|
601 bool QContact::removeDetail(QContactDetail* detail) |
|
602 { |
|
603 if (!detail) |
|
604 return false; |
|
605 |
|
606 // find the detail stored in the contact which has the same key as the detail argument |
|
607 int removeIndex = -1; |
|
608 for (int i = 0; i < d->m_details.size(); i++) { |
|
609 if (d->m_details.at(i).key() == detail->key()) { |
|
610 removeIndex = i; |
|
611 break; |
|
612 } |
|
613 } |
|
614 |
|
615 // make sure the detail exists (in some form) in the contact. |
|
616 if (removeIndex < 0) |
|
617 return false; |
|
618 |
|
619 if (detail->accessConstraints() & QContactDetail::Irremovable) |
|
620 return false; |
|
621 |
|
622 if (!d->m_details.contains(*detail)) |
|
623 return false; |
|
624 |
|
625 // remove any preferences we may have stored for the detail. |
|
626 QStringList keys = d->m_preferences.keys(); |
|
627 for (int i = 0; i < keys.size(); i++) { |
|
628 QString prefKey = keys.at(i); |
|
629 if (d->m_preferences.value(prefKey) == detail->d->m_id) { |
|
630 d->m_preferences.remove(prefKey); |
|
631 } |
|
632 } |
|
633 |
|
634 // then remove the detail. |
|
635 d->m_details.removeAt(removeIndex); |
|
636 return true; |
|
637 } |
|
638 |
|
639 /*! Returns true if this contact is equal to the \a other contact, false if either the id or stored details are not the same */ |
|
640 bool QContact::operator==(const QContact& other) const |
|
641 { |
|
642 return other.d->m_id == d->m_id && |
|
643 other.d->m_details == d->m_details; |
|
644 } |
|
645 |
|
646 /*! |
|
647 \relates QContact |
|
648 Returns the hash value for \a key. |
|
649 */ |
|
650 uint qHash(const QContact &key) |
|
651 { |
|
652 uint hash = qHash(key.id()); |
|
653 foreach (const QContactDetail& detail, key.details()) { |
|
654 hash += qHash(detail); |
|
655 } |
|
656 return hash; |
|
657 } |
|
658 |
|
659 QDebug operator<<(QDebug dbg, const QContact& contact) |
|
660 { |
|
661 dbg.nospace() << "QContact(" << contact.id() << ")"; |
|
662 foreach (const QContactDetail& detail, contact.details()) { |
|
663 dbg.space() << '\n' << detail; |
|
664 } |
|
665 return dbg.maybeSpace(); |
|
666 } |
|
667 |
|
668 |
|
669 /*! |
|
670 \deprecated |
|
671 */ |
|
672 QContactDetail QContact::detailWithAction(const QString& actionName) const |
|
673 { |
|
674 qWarning("QContact::detailWithAction(const QString&) This function is deprecated and will be removed after the transition period has elapsed. Use the function which takes a pointer to an action implementation instance instead!"); |
|
675 return QContactDetail(); |
|
676 } |
|
677 |
|
678 /*! |
|
679 \deprecated |
|
680 */ |
|
681 QList<QContactDetail> QContact::detailsWithAction(const QString& actionName) const |
|
682 { |
|
683 qWarning("QContact::detailsWithAction(const QString&) This function is deprecated and will be removed after the transition period has elapsed. Use the function which takes a pointer to an action implementation instance instead!"); |
|
684 return QList<QContactDetail>(); |
|
685 } |
|
686 |
|
687 /*! |
|
688 Retrieve the first detail in this contact supported by the given \a action. |
|
689 |
|
690 If there is a preferred detail set for this action name, and that detail is |
|
691 supported by the given \a action, that preferred detail will be returned. |
|
692 |
|
693 Otherwise, the first detail in the list returned by detailsWithAction() will |
|
694 be returned. |
|
695 |
|
696 \sa detailsWithAction() |
|
697 */ |
|
698 QContactDetail QContact::detailWithAction(QContactAction* action) const |
|
699 { |
|
700 if (action) { |
|
701 QContactDetail pref = preferredDetail(action->actionDescriptor().actionName()); |
|
702 if (!pref.isEmpty() && action->isDetailSupported(pref, *this)) |
|
703 return pref; |
|
704 foreach (const QContactDetail& detail, d->m_details) { |
|
705 if (action->isDetailSupported(detail, *this)) { |
|
706 return detail; |
|
707 } |
|
708 } |
|
709 } |
|
710 return QContactDetail(); |
|
711 } |
|
712 |
|
713 /*! |
|
714 Retrieve any details supported by the given \a action. |
|
715 |
|
716 If the action does not exist, an empty list will be returned. Otherwise, |
|
717 the details in this contact will be tested by the action and a list of the |
|
718 details supported will be returned. |
|
719 |
|
720 If a preferred detail for this action name has been set, and it is supported |
|
721 by the given \a action, that detail will be the first detail returned in the list. |
|
722 |
|
723 See this example for usage: |
|
724 \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp Details with action |
|
725 */ |
|
726 QList<QContactDetail> QContact::detailsWithAction(QContactAction* action) const |
|
727 { |
|
728 QList<QContactDetail> retn; |
|
729 |
|
730 if (action) { |
|
731 QContactDetail preferred = preferredDetail(action->actionDescriptor().actionName()); |
|
732 foreach (const QContactDetail& detail, d->m_details) { |
|
733 if (action->isDetailSupported(detail, *this)) { |
|
734 if (detail == preferred) |
|
735 retn.prepend(detail); |
|
736 else |
|
737 retn.append(detail); |
|
738 } |
|
739 } |
|
740 } |
|
741 return retn; |
|
742 } |
|
743 |
|
744 /*! |
|
745 Returns a list of relationships of the given \a relationshipType in which this contact is a participant. |
|
746 |
|
747 If \a relationshipType is empty, all relationships will be returned. |
|
748 |
|
749 \note This function only examines the relationships that were present when this contact |
|
750 was retrieved from a manager. You can also query the manager directly, if you require |
|
751 the most up to date information. |
|
752 |
|
753 \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 5 |
|
754 |
|
755 \sa QContactRelationshipFetchRequest, QContactManager::relationships() |
|
756 */ |
|
757 QList<QContactRelationship> QContact::relationships(const QString& relationshipType) const |
|
758 { |
|
759 // if empty, then they want all relationships |
|
760 if (relationshipType.isEmpty()) |
|
761 return d->m_relationshipsCache; |
|
762 |
|
763 // otherwise, filter on type. |
|
764 QList<QContactRelationship> retn; |
|
765 for (int i = 0; i < d->m_relationshipsCache.size(); i++) { |
|
766 QContactRelationship curr = d->m_relationshipsCache.at(i); |
|
767 if (curr.relationshipType() == relationshipType) { |
|
768 retn.append(curr); |
|
769 } |
|
770 } |
|
771 |
|
772 return retn; |
|
773 } |
|
774 |
|
775 /*! |
|
776 Returns a list of the ids of contacts which have a relationship of the given \a relationshipType with this contact. |
|
777 The \a role parameter describes the role that the related contacts have in the relationship. |
|
778 |
|
779 If \a relationshipType is empty, relationships of all types will be considered. |
|
780 |
|
781 \note This function only examines the relationships that were present when this contact |
|
782 was retrieved from a manager. You can also query the manager directly, if you require |
|
783 the most up to date information. |
|
784 |
|
785 \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 6 |
|
786 |
|
787 \sa QContactRelationshipFetchRequest, QContactManager::relationships() |
|
788 */ |
|
789 QList<QContactId> QContact::relatedContacts(const QString& relationshipType, QContactRelationship::Role role) const |
|
790 { |
|
791 QList<QContactId> retn; |
|
792 for (int i = 0; i < d->m_relationshipsCache.size(); i++) { |
|
793 QContactRelationship curr = d->m_relationshipsCache.at(i); |
|
794 if (relationshipType.isEmpty() || curr.relationshipType() == relationshipType) { |
|
795 // check that the other contacts fill the given role |
|
796 if (role == QContactRelationship::First) { |
|
797 if (curr.first() != d->m_id) { |
|
798 if (!retn.contains(curr.first())) { |
|
799 retn.append(curr.first()); |
|
800 } |
|
801 } |
|
802 } else if (role == QContactRelationship::Second) { |
|
803 if (curr.first() == d->m_id) { |
|
804 if (!retn.contains(curr.second())) { |
|
805 retn.append(curr.second()); |
|
806 } |
|
807 } |
|
808 } else { // role == Either. |
|
809 if (curr.first() == d->m_id) { |
|
810 if (!retn.contains(curr.second())) { |
|
811 retn.append(curr.second()); |
|
812 } |
|
813 } else { |
|
814 if (!retn.contains(curr.first())) { |
|
815 retn.append(curr.first()); |
|
816 } |
|
817 } |
|
818 } |
|
819 } |
|
820 } |
|
821 |
|
822 return retn; |
|
823 } |
|
824 |
|
825 /*! |
|
826 * Return a list of descriptors for the actions available to be performed on this contact. |
|
827 * |
|
828 * The actions considered can be restricted by the optional parameters |
|
829 * \list |
|
830 * \o The actions can be restricted to those provided by a specific vendor with the \a vendorName parameter. |
|
831 * If \a vendorName is empty, actions from all vendors will be considered. |
|
832 * \o A specific version of an action can also be requested with \a implementationVersion. If \c -1 is |
|
833 * passed (the default), all versions will be considered. This is usually useful in conjunction with a specific vendor. |
|
834 * \endlist |
|
835 * |
|
836 * Each action that matches the above criteria will be tested to see if this contact is supported |
|
837 * by the action, and a list of the action descriptors that are supported will be returned. |
|
838 */ |
|
839 QList<QContactActionDescriptor> QContact::availableActions(const QString& vendorName, int implementationVersion) const |
|
840 { |
|
841 // check every action implementation to see if it supports me. |
|
842 QSet<QContactActionDescriptor> retn; |
|
843 QList<QContactActionDescriptor> descriptors = QContactManagerData::actionDescriptors(); |
|
844 for (int i = 0; i < descriptors.size(); i++) { |
|
845 QContactActionDescriptor currDescriptor = descriptors.at(i); |
|
846 if ((vendorName.isEmpty() || currDescriptor.vendorName() == vendorName) && |
|
847 (implementationVersion == -1 || currDescriptor.implementationVersion() == implementationVersion)) { |
|
848 QScopedPointer<QContactAction> currImpl(QContactManagerData::action(currDescriptor)); |
|
849 if (QContactManagerEngine::testFilter(currImpl->contactFilter(), *this)) { |
|
850 retn.insert(currDescriptor); |
|
851 } |
|
852 } |
|
853 } |
|
854 |
|
855 return retn.toList(); |
|
856 } |
|
857 |
|
858 /*! |
|
859 * Set a particular detail (\a preferredDetail) as the preferred detail for any actions with the given \a actionName. |
|
860 * |
|
861 * The \a preferredDetail object must exist in this object, and the \a actionName cannot be empty. |
|
862 * |
|
863 * Returns true if the preference could be recorded, and false otherwise. |
|
864 * |
|
865 * \sa preferredDetail() |
|
866 */ |
|
867 bool QContact::setPreferredDetail(const QString& actionName, const QContactDetail& preferredDetail) |
|
868 { |
|
869 // if the given action name is empty, bad argument. |
|
870 if (actionName.isEmpty()) |
|
871 return false; |
|
872 |
|
873 // check to see whether the the given preferredDetail is saved in this contact |
|
874 if (!d->m_details.contains(preferredDetail)) |
|
875 return false; |
|
876 |
|
877 // otherwise, save the preference. |
|
878 d->m_preferences.insert(actionName, preferredDetail.d->m_id); |
|
879 return true; |
|
880 } |
|
881 |
|
882 /*! |
|
883 * Returns true if the given \a detail is a preferred detail for the given \a actionName, |
|
884 * or for any action if the \a actionName is empty. |
|
885 * |
|
886 * \sa preferredDetail() |
|
887 */ |
|
888 bool QContact::isPreferredDetail(const QString& actionName, const QContactDetail& detail) const |
|
889 { |
|
890 if (!d->m_details.contains(detail)) |
|
891 return false; |
|
892 |
|
893 if (actionName.isEmpty()) |
|
894 return d->m_preferences.values().contains(detail.d->m_id); |
|
895 |
|
896 QMap<QString, int>::const_iterator it = d->m_preferences.find(actionName); |
|
897 if (it != d->m_preferences.end() && it.value() == detail.d->m_id) |
|
898 return true; |
|
899 |
|
900 return false; |
|
901 } |
|
902 |
|
903 /*! |
|
904 * Returns the preferred detail for a given \a actionName. |
|
905 * |
|
906 * If the \a actionName is empty, or there is no preference recorded for |
|
907 * the supplied \a actionName, returns an empty QContactDetail. |
|
908 * |
|
909 * \sa preferredDetails() |
|
910 */ |
|
911 QContactDetail QContact::preferredDetail(const QString& actionName) const |
|
912 { |
|
913 // if the given action name is empty, bad argument. |
|
914 if (actionName.isEmpty()) |
|
915 return QContactDetail(); |
|
916 |
|
917 if (!d->m_preferences.contains(actionName)) |
|
918 return QContactDetail(); |
|
919 |
|
920 QContactDetail retn; |
|
921 int detId = d->m_preferences.value(actionName); |
|
922 for (int i = 0; i < d->m_details.size(); i++) { |
|
923 QContactDetail det = d->m_details.at(i); |
|
924 if (det.d->m_id == detId) { |
|
925 // found it. |
|
926 retn = det; |
|
927 break; |
|
928 } |
|
929 } |
|
930 |
|
931 return retn; |
|
932 } |
|
933 |
|
934 /*! |
|
935 * Returns the recorded detail preferences for action names. |
|
936 * |
|
937 * Each entry in the map has the action name as the key, and the corresponding |
|
938 * preferred detail as the value. |
|
939 */ |
|
940 QMap<QString, QContactDetail> QContact::preferredDetails() const |
|
941 { |
|
942 QMap<QString, QContactDetail> ret; |
|
943 QMap<QString, int>::const_iterator it = d->m_preferences.constBegin(); |
|
944 while (it != d->m_preferences.constEnd()) { |
|
945 ret.insert(it.key(), d->m_details.at(it.value())); |
|
946 ++it; |
|
947 } |
|
948 |
|
949 return ret; |
|
950 } |
|
951 |
|
952 QTM_END_NAMESPACE |