1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the Qt Mobility Components.
8
** $QT_BEGIN_LICENSE:LGPL$
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 Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
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 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
42
#include <qcontactsglobal.h>
43
#include <qcontacts.h>
44
#include "requestexample.h"
47
#include <QCoreApplication>
51
QTCONTACTS_USE_NAMESPACE
53
static void loadDefault();
54
static void queryManagerCapabilities();
55
static void contactDetailManipulation();
56
static void contactManipulation();
57
static void addContact(QContactManager*);
58
static void callContact(QContactManager*);
59
static void matchCall(QContactManager*, const QString&);
60
static void viewSpecificDetail(QContactManager*);
61
static void viewDetails(QContactManager*);
62
static void detailSharing(QContactManager*);
63
static void addPlugin(QContactManager*);
64
static void editView(QContactManager*);
65
static void loadManager();
66
static void loadManagerWithParameters();
68
int stopCompilerWarnings()
70
// manager configuration examples
72
loadManagerWithParameters();
74
// synchronous API examples
75
QContactManager* cm = new QContactManager();
78
matchCall(cm, "111-222-333"); // unknown number.
79
matchCall(cm, "12345678"); // alice's number.
80
viewSpecificDetail(cm);
86
// asynchronous API example
89
QTimer::singleShot(10, &re, SLOT(performRequest()));
92
// more doc snippet examples
94
queryManagerCapabilities();
95
contactDetailManipulation();
96
contactManipulation();
98
// async doc snippet examples
99
AsyncRequestExample example;
100
QTimer::singleShot(10, &example, SLOT(performRequests()));
108
//! [Loading the default manager for the platform]
109
QContactManager stackDefaultContactManager;
110
//! [Loading the default manager for the platform]
112
//! [Loading the default manager for the platform on heap]
113
QContactManager *heapDefaultContactManager = new QContactManager;
114
// ... perform contact manipulation
115
delete heapDefaultContactManager;
116
//! [Loading the default manager for the platform on heap]
119
void queryManagerCapabilities()
121
//! [Querying a manager for capabilities]
123
qDebug() << "The default manager for the platform is:" << cm.managerName();
124
qDebug() << "It" << (cm.isRelationshipTypeSupported(QContactRelationship::HasAssistant()) ? "supports" : "does not support") << "assistant relationships.";
125
qDebug() << "It" << (cm.supportedContactTypes().contains(QContactType::TypeGroup) ? "supports" : "does not support") << "groups.";
126
//! [Querying a manager for capabilities]
129
void contactDetailManipulation()
131
//! [Adding a detail to a contact]
132
QContact exampleContact;
134
QContactName nameDetail;
135
nameDetail.setFirstName("Adam");
136
nameDetail.setLastName("Unlikely");
138
QContactPhoneNumber phoneNumberDetail;
139
phoneNumberDetail.setNumber("+123 4567");
141
exampleContact.saveDetail(&nameDetail);
142
exampleContact.saveDetail(&phoneNumberDetail);
143
//! [Adding a detail to a contact]
145
//! [Updating a detail in a contact]
146
phoneNumberDetail.setNumber("+123 9876");
147
exampleContact.saveDetail(&phoneNumberDetail); // overwrites old value on save
148
//! [Updating a detail in a contact]
150
//! [Removing a detail from a contact]
151
exampleContact.removeDetail(&phoneNumberDetail);
152
//! [Removing a detail from a contact]
155
void contactManipulation()
157
QContactManager m_manager("memory");
158
//! [Synchronously creating a new contact in a manager]
159
QContact exampleContact;
161
QContactName nameDetail;
162
nameDetail.setFirstName("Adam");
163
nameDetail.setLastName("Unlikely");
165
QContactPhoneNumber phoneNumberDetail;
166
phoneNumberDetail.setNumber("+123 4567");
168
exampleContact.saveDetail(&nameDetail);
169
exampleContact.saveDetail(&phoneNumberDetail);
171
// save the newly created contact in the manager
172
if (!m_manager.saveContact(&exampleContact))
173
qDebug() << "Error" << m_manager.error() << "occurred whilst saving contact!";
174
//! [Synchronously creating a new contact in a manager]
176
//! [Synchronously filtering contacts from a manager]
177
QList<QContact> results = m_manager.contacts(QContactPhoneNumber::match("+123 4567"));
178
//! [Synchronously filtering contacts from a manager]
180
//! [Synchronously retrieving an existing contact from a manager]
181
QContact existing = m_manager.contact(exampleContact.id());
182
//! [Synchronously retrieving an existing contact from a manager]
184
//! [Synchronously updating an existing contact in a manager]
185
phoneNumberDetail.setNumber("+123 9876");
186
exampleContact.saveDetail(&phoneNumberDetail);
187
m_manager.saveContact(&exampleContact);
188
//! [Synchronously updating an existing contact in a manager]
190
//! [Synchronously removing a contact from a manager]
191
m_manager.removeContact(exampleContact.id());
192
//! [Synchronously removing a contact from a manager]
194
//! [Synchronously creating a new relationship between two contacts]
195
// first, create the group and the group member
196
QContact exampleGroup;
197
exampleGroup.setType(QContactType::TypeGroup);
198
QContactNickname groupName;
199
groupName.setNickname("Example Group");
200
exampleGroup.saveDetail(&groupName);
202
QContact exampleGroupMember;
203
QContactName groupMemberName;
204
groupMemberName.setFirstName("Member");
205
exampleGroupMember.saveDetail(&groupMemberName);
207
// second, save those contacts in the manager
208
QMap<int, QContactManager::Error> errorMap;
209
QList<QContact> saveList;
210
saveList << exampleGroup << exampleGroupMember;
211
m_manager.saveContacts(&saveList, &errorMap);
213
// third, create the relationship between those contacts
214
QContactRelationship groupRelationship;
215
groupRelationship.setFirst(exampleGroup);
216
groupRelationship.setRelationshipType(QContactRelationship::HasMember());
217
groupRelationship.setSecond(exampleGroupMember);
219
// finally, save the relationship in the manager
220
m_manager.saveRelationship(&groupRelationship);
221
//! [Synchronously creating a new relationship between two contacts]
223
//! [Synchronously retrieving relationships between contacts]
224
QList<QContactRelationship> groupRelationships = m_manager.relationships(exampleGroup, QContactRelationship::First);
225
QList<QContactRelationship> result;
226
for (int i = 0; i < groupRelationships.size(); i++) {
227
if (groupRelationships.at(i).second() == exampleGroupMember) {
228
result.append(groupRelationships.at(i));
231
//! [Synchronously retrieving relationships between contacts]
233
//! [Retrieving relationships from cache]
234
exampleGroup = m_manager.contact(exampleGroup.id()); // refresh the group contact
235
groupRelationships = exampleGroup.relationships(QContactRelationship::HasMember());
236
for (int i = 0; i < groupRelationships.size(); i++) {
237
if (groupRelationships.at(i).second() == exampleGroupMember) {
238
result.append(groupRelationships.at(i));
241
//! [Retrieving relationships from cache]
243
//! [Synchronously providing a fetch hint]
244
QContactFetchHint hasMemberRelationshipsOnly;
245
hasMemberRelationshipsOnly.setRelationshipTypesHint(QStringList(QContactRelationship::HasMember()));
247
// retrieve all contacts, with no specified sort order, requesting that
248
// HasMember relationships be included in the cache of result contacts
249
QList<QContact> allContacts = m_manager.contacts(QContactFilter(), QList<QContactSortOrder>(), hasMemberRelationshipsOnly);
250
//! [Synchronously providing a fetch hint]
252
//! [Synchronously removing a relationship]
253
m_manager.removeRelationship(groupRelationship);
254
//! [Synchronously removing a relationship]
257
//! [Creating a new contact]
258
void addContact(QContactManager* cm)
262
QContactDisplayLabel displayLabel;
263
displayLabel.setLabel("Ally Jones");
264
alice.saveDetail(&displayLabel);
266
/* Set the contact's name */
267
QContactName aliceName;
268
aliceName.setFirstName("Alice");
269
aliceName.setLastName("Jones");
270
alice.saveDetail(&aliceName);
272
/* Add a phone number */
273
QContactPhoneNumber number;
274
QList<int> subTypeMobile;
275
subTypeMobile << QContactPhoneNumber::SubTypeMobile;
276
number.setSubTypes(subTypeMobile);
277
number.setContexts(QContactDetail::ContextHome);
278
number.setSubTypes(subTypeMobile);
279
number.setNumber("12345678");
280
alice.saveDetail(&number);
281
alice.setPreferredDetail("DialAction", number);
283
/* Add a second phone number */
284
QContactPhoneNumber number2;
285
QList<int> subTypeLandline;
286
subTypeLandline << QContactPhoneNumber::SubTypeMobile;
287
number.setSubTypes(subTypeLandline);
288
number2.setContexts(QContactDetail::ContextWork);
289
number2.setSubTypes(subTypeLandline);
290
number2.setNumber("555-4444");
291
alice.saveDetail(&number2);
293
/* Save the contact */
294
cm->saveContact(&alice) ? qDebug() << "Successfully saved"
295
: qDebug() << "Failed to save";
296
qDebug() << "The display label for the contact:" << alice.details(QContactDisplayLabel::Type).value(1).value(QContactDisplayLabel::FieldLabel);
298
//! [Creating a new contact]
300
void callContact(QContactManager* cm)
302
QList<QContactId> contactIds = cm->contactIds();
303
QContact a = cm->contact(contactIds.first());
305
/* Get this contact's first phone number */
308
//! [Details with action]
309
// Get the first "Call" action
310
QContactActionDescriptor callDescriptor = QContactAction::actionDescriptors("Call").value(0);
311
QContactAction* action = QContactAction::action(callDescriptor);
312
QSet<QContactActionTarget> targets = callDescriptor.supportedTargets(contact);
314
if (targets.count() == 0) {
315
// Can't call this contact
316
} else if (targets.count() == 1) {
317
// Just call this specific detail
318
action->invokeAction(*targets.begin());
320
// Offer the user the choice of details to call
323
//! [Details with action]
326
//! [Filtering by definition and value]
327
void matchCall(QContactManager* cm, const QString& incomingCallNbr)
329
QContactDetailFilter phoneFilter;
330
phoneFilter.setDetailType(QContactPhoneNumber::Type, QContactPhoneNumber::FieldNumber);
331
phoneFilter.setValue(incomingCallNbr);
332
phoneFilter.setMatchFlags(QContactFilter::MatchExactly);
334
QList<QContactId> matchingContacts = cm->contactIds(phoneFilter);
335
if (matchingContacts.size() == 0) {
336
qDebug() << "Incoming call from unknown contact (" << incomingCallNbr << ")";
338
QContact match = cm->contact(matchingContacts.at(0));
339
QContactDisplayLabel displayLabel;
340
displayLabel.setLabel("Match");
341
match.saveDetail(&displayLabel);
342
qDebug() << "Incoming call from"
343
<< match.details(QContactDisplayLabel::Type).value(0).value(QContactDisplayLabel::FieldLabel)
344
<< "(" << incomingCallNbr << ")";
347
//! [Filtering by definition and value]
349
//! [Viewing a specific detail of a contact]
350
void viewSpecificDetail(QContactManager* cm)
352
QList<QContactId> contactIds = cm->contactIds();
353
QContact exampleContact = cm->contact(contactIds.first());
354
qDebug() << "The first phone number is" << exampleContact.detail(QContactPhoneNumber::Type).value(QContactPhoneNumber::FieldNumber);
356
//! [Viewing a specific detail of a contact]
358
//! [Viewing the details of a contact]
359
void viewDetails(QContactManager* cm)
361
QList<QContactId> contactIds = cm->contactIds();
362
QContact exampleContact = cm->contact(contactIds.first());
364
QList<QContactDetail> allDetails = exampleContact.details();
365
for (int i = 0; i < allDetails.size(); i++) {
366
QContactDetail detail = allDetails.at(i);
367
QMap<int, QVariant> fields = detail.values();
369
qDebug("\tDetail #%d (%d):", i, detail.type());
370
foreach (const int& fieldKey, fields.keys()) {
371
qDebug() << "\t\t" << fieldKey << "(" << fields.value(fieldKey) << ") =" << detail.value(fieldKey);
376
//! [Viewing the details of a contact]
378
//! [Demonstration of detail sharing semantics]
379
void detailSharing(QContactManager* cm)
381
QList<QContactId> contactIds = cm->contactIds();
382
QContact a = cm->contact(contactIds.first());
384
/* Create a new phone number detail. */
385
QContactPhoneNumber newNumber;
386
newNumber.setNumber("123123123");
387
qDebug() << "\tThe new phone number is" << newNumber.number();
390
* Create a copy of that detail. These will be implicitly shared;
391
* changes to nnCopy will not affect newNumber, and vice versa.
392
* However, attempting to save them will cause overwrite to occur.
393
* Removal is done purely via key() checking, also.
395
QContactPhoneNumber nnCopy(newNumber);
396
nnCopy.setNumber("456456456");
397
qDebug() << "\tThat number is still" << newNumber.number() << ", the copy is" << nnCopy.number();
399
/* Save the detail in the contact, then remove via the copy, then resave. */
400
a.saveDetail(&newNumber);
401
a.removeDetail(&nnCopy); // identical to a.removeDetail(&newNumber);
402
a.saveDetail(&newNumber); // since newNumber.key() == nnCopy.key();
404
/* Saving will cause overwrite */
405
qDebug() << "\tPrior to saving nnCopy has" << a.details().count() << "details.";
406
a.saveDetail(&nnCopy);
407
qDebug() << "\tAfter saving nnCopy still has" << a.details().count() << "details.";
409
/* In order to save nnCopy as a new detail, we must reset its key */
411
qDebug() << "\tThe copy key is now" << nnCopy.key() << ", whereas the original key is" << newNumber.key();
412
qDebug() << "\tPrior to saving (key reset) nnCopy has" << a.details().count() << "details.";
413
a.saveDetail(&nnCopy);
414
qDebug() << "\tAfter saving (key reset) nnCopy still has" << a.details().count() << "details.";
415
a.removeDetail(&nnCopy);
418
* Note that changes made to details are not
419
* propagated automatically to the contact.
420
* To persist changes to a detail, you must call saveDetail().
422
QList<QContactPhoneNumber> allNumbers = a.details<QContactPhoneNumber>();
423
foreach (const QContactPhoneNumber& savedPhn, allNumbers) {
424
if (savedPhn.key() != newNumber.key()) {
429
* This phone number is the saved copy of the newNumber detail.
430
* It is detached from the newNumber detail, so changes to newNumber
431
* shouldn't affect savedPhn until saveDetail() is called again.
433
qDebug() << "\tCurrently, the (stack) newNumber is" << newNumber.number()
434
<< ", and the saved newNumber is" << savedPhn.number();
435
newNumber.setNumber("678678678");
436
qDebug() << "\tNow, the (stack) newNumber is" << newNumber.number()
437
<< ", but the saved newNumber is" << savedPhn.number();
441
* Removal of the detail depends only on the key of the detail; the fact
442
* that the values differ is not taken into account by the remove operation.
444
a.removeDetail(&newNumber) ? qDebug() << "\tSucceeded in removing the temporary detail."
445
: qDebug() << "\tFailed to remove the temporary detail.\n";
447
//! [Demonstration of detail sharing semantics]
449
//! [Modifying an existing contact]
450
void editView(QContactManager* cm)
452
QList<QContactId> contactIds = cm->contactIds();
453
QContact a = cm->contact(contactIds.first());
455
/* Change the first phone number */
456
QList<QContactDetail> numbers = a.details(QContactPhoneNumber::Type);
457
QContactPhoneNumber phone = numbers.value(0);
458
phone.setNumber("123-4445");
460
/* Add an email address */
461
QContactEmailAddress email;
462
email.setEmailAddress("alice.jones@example");
463
email.setContexts(QContactDetail::ContextHome);
464
int emailField = QContactEmailAddress::FieldEmailAddress;
465
email.setValue(emailField, "Alice's Work Email Address");
467
/* Save the updated details to the contact. */
468
a.saveDetail(&phone);
469
a.saveDetail(&email);
471
/* Now we must save the updated contact back to the database. */
475
//! [Modifying an existing contact]
479
QContactManager *manager = new QContactManager();
481
//! [Updating the display label of a contact]
482
/* Retrieve a contact */
483
QContact exampleContact = manager->contact(myId);
485
/* Set the display label */
486
QContactDisplayLabel displayLabel;
487
displayLabel.setLabel("Abigail Arkansas");
488
exampleContact.saveDetail(&displayLabel);
490
/* Update some fields that might influence the display label */
491
QContactName name = exampleContact.detail<QContactName>();
492
name.setFirstName("Abigail");
493
name.setLastName("Arkansas");
494
exampleContact.saveDetail(&name);
496
qDebug() << "The display label for the contact:" << exampleContact.details(QContactDisplayLabel::Type).value(1).value(QContactDisplayLabel::FieldLabel);
497
//! [Updating the display label of a contact]
500
//! [Asynchronous contact request]
501
void RequestExample::performRequest()
503
// retrieve any contact whose first name is "Alice"
504
QContactDetailFilter dfil;
505
dfil.setDetailType(QContactName::Type, QContactName::FieldFirstName);
506
dfil.setValue("Alice");
507
dfil.setMatchFlags(QContactFilter::MatchExactly);
509
// m_fetchRequest was created with m_fetchRequest = new QContactFetchRequest() in the ctor.
510
m_fetchRequest->setManager(this->m_manager); // m_manager is a QContactManager*.
511
m_fetchRequest->setFilter(dfil);
512
connect(m_fetchRequest, SIGNAL(resultsAvailable()), this, SLOT(printContacts()));
513
connect(m_fetchRequest, SIGNAL(stateChanged(QContactAbstractRequest::State)),
514
this, SLOT(stateChanged(QContactAbstractRequest::State)));
515
if (!m_fetchRequest->start()) {
516
qDebug() << "Unable to request contacts!";
517
QCoreApplication::exit(0);
519
qDebug() << "Requested contacts; awaiting results...";
523
void RequestExample::printContacts()
525
QList<QContact> results = m_fetchRequest->contacts();
526
for (m_previousLastIndex = 0; m_previousLastIndex < results.size(); ++m_previousLastIndex) {
527
qDebug() << "Found an Alice:" << results.at(m_previousLastIndex);
531
void RequestExample::stateChanged(QContactAbstractRequest::State state)
533
// once we've finished retrieving results, stop processing events.
534
if (state == QContactAbstractRequest::FinishedState
535
|| state == QContactAbstractRequest::CanceledState) {
536
qDebug() << "Finished displaying asynchronously retrieved contacts!";
537
QCoreApplication::exit(0);
540
//! [Asynchronous contact request]
546
QContact groupContact;
549
QContactDetail detail = contact.detail(QContactName::Type);
552
QContactName name = contact.detail<QContactName>();
555
QList<QContactDetail> details = contact.details(QContactPhoneNumber::Type);
558
QList<QContactPhoneNumber> phoneNumbers = contact.details<QContactPhoneNumber>();
561
//QList<QContactPhoneNumber> homePhones = contact.details(QContactPhoneNumber::Type).value(0).value(QContactPhoneNumber::FieldContext);
564
QList<QContactRelationship> spouseRelationships = contact.relationships(QContactRelationship::HasSpouse());
565
// For each relationship in spouseRelationships, contact.id() will either be first() or second()
568
// Who are the members of a group contact?
569
QList<QContact> groupMembers = groupContact.relatedContacts(QContactRelationship::HasMember(), QContactRelationship::Second);
570
// What groups is this contact in?
571
QList<QContact> contactGroups = contact.relatedContacts(QContactRelationship::HasMember(), QContactRelationship::First);
572
// An alternative to QContact::relationships()
573
QList<QContact> spouses = contact.relatedContacts(QContactRelationship::HasSpouse(), QContactRelationship::Either);
574
if (spouses.count() > 1) {
575
// Custom relationship type
576
QList<QContact> therapists = contact.relatedContacts("HasTherapist", QContactRelationship::Second);
579
//! [Getting all tags]
581
foreach (const QContactTag& tag, contact.details<QContactTag>()) {
582
tags.insert(tag.tag());
584
//! [Getting all tags]
585
//! [Checking for a specific tag]
586
if (contact.details<QContactTag>().count() > 0) {
587
// Do something with it
589
//! [Checking for a specific tag]
595
//! [Loading a specific manager backend]
596
QContactManager contactManager("KABC");
597
//! [Loading a specific manager backend]
600
void loadManagerWithParameters()
602
//! [Loading a specific manager backend with parameters]
603
QMap<QString, QString> parameters;
604
parameters.insert("Settings", "~/.qcontactmanager-kabc-settings.ini");
605
QContactManager contactManager("KABC", parameters);
606
//! [Loading a specific manager backend with parameters]