~ubuntu-branches/ubuntu/quantal/qtmobility/quantal

« back to all changes in this revision

Viewing changes to plugins/declarative/contacts/qdeclarativecontactmodel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-11-16 16:18:07 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20101116161807-k2dzt2nyse975r3l
Tags: 1.1.0-0ubuntu1
* New upstream release
* Syncronise with Debian, no remaining changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 QtDeclarative module of the Qt Toolkit.
 
8
**
 
9
** $QT_BEGIN_LICENSE:LGPL$
 
10
** Commercial Usage
 
11
** Licensees holding valid Qt Commercial licenses may use this file in 
 
12
** accordance with the Qt Commercial License Agreement provided with
 
13
** the Software or, alternatively, in accordance with the terms
 
14
** contained in a written agreement between you and Nokia.
 
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
** GNU General Public License Usage
 
29
** Alternatively, this file may be used under the terms of the GNU
 
30
** General Public License version 3.0 as published by the Free Software
 
31
** Foundation and appearing in the file LICENSE.GPL included in the
 
32
** packaging of this file.  Please review the following information to
 
33
** ensure the GNU General Public License version 3.0 requirements will be
 
34
** met: http://www.gnu.org/copyleft/gpl.html.
 
35
**
 
36
** If you are unsure which license is appropriate for your use, please
 
37
** contact the sales department at qt-sales@nokia.com.
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
#include <qcontactdetails.h>
 
42
 
 
43
#include "qdeclarativecontactmodel_p.h"
 
44
#include "qcontactmanager.h"
 
45
#include "qcontactdetailfilter.h"
 
46
#include "qcontactlocalidfilter.h"
 
47
#include "qversitreader.h"
 
48
#include "qversitwriter.h"
 
49
#include "qversitcontactimporter.h"
 
50
#include "qversitcontactexporter.h"
 
51
#include <QColor>
 
52
#include <QHash>
 
53
#include <QDebug>
 
54
#include <QPixmap>
 
55
#include <QFile>
 
56
#include <QMap>
 
57
 
 
58
#include "qcontactrequests.h"
 
59
 
 
60
/*!
 
61
    \qmlclass ContactModel QDeclarativeContactModel
 
62
    \brief The ContactModel element provides access to contacts from the contacts store.
 
63
    \ingroup qml-contacts
 
64
 
 
65
    This element is part of the \bold{QtMobility.contacts 1.1} module.
 
66
 
 
67
    ContactModel provides a model of contacts from the contacts store.
 
68
    The contents of the model can be specified with \l filter, \l sortOrders and \l fetchHint properties.
 
69
    Whether the model is automatically updated when the store or \l contacts changes, can be
 
70
    controlled with \l ContactModel::autoUpdate property.
 
71
 
 
72
    There are two ways of accessing the contact data: via model by using views and delegates,
 
73
    or alternatively via \l contacts list property. Of the two, the model access is preferred.
 
74
    Direct list access (i.e. non-model) is not guaranteed to be in order set by \l sortOrder.
 
75
 
 
76
    At the moment the model roles provided by ContactModel are display, decoration and \c contact.
 
77
    Through the \c contact role can access any data provided by the Contact element.
 
78
 
 
79
    \sa RelationshipModel, Contact, {QContactManager}
 
80
*/
 
81
 
 
82
 
 
83
 
 
84
 
 
85
 
 
86
class QDeclarativeContactModelPrivate
 
87
{
 
88
public:
 
89
    QDeclarativeContactModelPrivate()
 
90
        :m_manager(0),
 
91
        m_fetchHint(0),
 
92
        m_filter(0),
 
93
        m_autoUpdate(true),
 
94
        m_updatePending(false),
 
95
        m_componentCompleted(false)
 
96
    {
 
97
    }
 
98
    ~QDeclarativeContactModelPrivate()
 
99
    {
 
100
        if (m_manager)
 
101
            delete m_manager;
 
102
    }
 
103
 
 
104
    QList<QDeclarativeContact*> m_contacts;
 
105
    QMap<QContactLocalId, QDeclarativeContact*> m_contactMap;
 
106
    QContactManager* m_manager;
 
107
    QDeclarativeContactFetchHint* m_fetchHint;
 
108
    QList<QDeclarativeContactSortOrder*> m_sortOrders;
 
109
    QDeclarativeContactFilter* m_filter;
 
110
 
 
111
    QVersitReader m_reader;
 
112
    QVersitWriter m_writer;
 
113
    QStringList m_importProfiles;
 
114
 
 
115
    bool m_autoUpdate;
 
116
    bool m_updatePending;
 
117
    bool m_componentCompleted;
 
118
};
 
119
 
 
120
QDeclarativeContactModel::QDeclarativeContactModel(QObject *parent) :
 
121
    QAbstractListModel(parent),
 
122
    d(new QDeclarativeContactModelPrivate)
 
123
{
 
124
    QHash<int, QByteArray> roleNames;
 
125
    roleNames = QAbstractItemModel::roleNames();
 
126
    roleNames.insert(ContactRole, "contact");
 
127
    setRoleNames(roleNames);
 
128
 
 
129
    connect(this, SIGNAL(managerChanged()), SLOT(fetchAgain()));
 
130
    connect(this, SIGNAL(filterChanged()), SLOT(fetchAgain()));
 
131
    connect(this, SIGNAL(fetchHintChanged()), SLOT(fetchAgain()));
 
132
    connect(this, SIGNAL(sortOrdersChanged()), SLOT(fetchAgain()));
 
133
    
 
134
    d->m_manager = new QContactManager();
 
135
    //import vcard
 
136
    connect(&d->m_reader, SIGNAL(stateChanged(QVersitReader::State)), this, SLOT(startImport(QVersitReader::State)));
 
137
}
 
138
 
 
139
/*!
 
140
  \qmlproperty string ContactModel::manager
 
141
 
 
142
  This property holds the manager uri of the contact backend engine.
 
143
  */
 
144
QString QDeclarativeContactModel::manager() const
 
145
{
 
146
    if (d->m_manager)
 
147
        return d->m_manager->managerName();
 
148
    return QString();
 
149
}
 
150
void QDeclarativeContactModel::setManager(const QString& managerName)
 
151
{
 
152
    if (d->m_manager)
 
153
        delete d->m_manager;
 
154
 
 
155
 
 
156
    d->m_manager = new QContactManager(managerName);
 
157
 
 
158
    connect(d->m_manager, SIGNAL(dataChanged()), this, SLOT(fetchAgain()));
 
159
    connect(d->m_manager, SIGNAL(contactsAdded(QList<QContactLocalId>)), this, SLOT(fetchAgain()));
 
160
    connect(d->m_manager, SIGNAL(contactsRemoved(QList<QContactLocalId>)), this, SLOT(contactsRemoved(QList<QContactLocalId>)));
 
161
    connect(d->m_manager, SIGNAL(contactsChanged(QList<QContactLocalId>)), this, SLOT(contactsChanged(QList<QContactLocalId>)));
 
162
    emit managerChanged();
 
163
}
 
164
void QDeclarativeContactModel::componentComplete()
 
165
{
 
166
    d->m_componentCompleted = true;
 
167
    if (!d->m_manager) {
 
168
        d->m_manager = new QContactManager();
 
169
        //connectManager();
 
170
    }
 
171
    if (d->m_autoUpdate) {
 
172
        //TODO
 
173
        //scheduleUpdate();
 
174
    }
 
175
}
 
176
/*!
 
177
  \qmlproperty bool ContactModel::autoUpdate
 
178
 
 
179
  This property indicates whether or not the contact model should be updated automatically, default value is true.
 
180
  */
 
181
void QDeclarativeContactModel::setAutoUpdate(bool autoUpdate)
 
182
{
 
183
    if (autoUpdate == d->m_autoUpdate)
 
184
        return;
 
185
    d->m_autoUpdate = autoUpdate;
 
186
    emit autoUpdateChanged();
 
187
}
 
188
 
 
189
bool QDeclarativeContactModel::autoUpdate() const
 
190
{
 
191
    return d->m_autoUpdate;
 
192
}
 
193
 
 
194
void QDeclarativeContactModel::update()
 
195
{
 
196
    //TODO
 
197
}
 
198
 
 
199
/*!
 
200
  \qmlproperty string ContactModel::error
 
201
 
 
202
  This property holds the latest error code returned by the contact manager.
 
203
 
 
204
  This property is read only.
 
205
  */
 
206
QString QDeclarativeContactModel::error() const
 
207
{
 
208
    switch (d->m_manager->error()) {
 
209
    case QContactManager::DoesNotExistError:
 
210
        return QLatin1String("DoesNotExist");
 
211
    case QContactManager::AlreadyExistsError:
 
212
        return QLatin1String("AlreadyExists");
 
213
    case QContactManager::InvalidDetailError:
 
214
        return QLatin1String("InvalidDetail");
 
215
    case QContactManager::InvalidRelationshipError:
 
216
        return QLatin1String("InvalidRelationship");
 
217
    case QContactManager::LockedError:
 
218
        return QLatin1String("LockedError");
 
219
    case QContactManager::DetailAccessError:
 
220
        return QLatin1String("DetailAccessError");
 
221
    case QContactManager::PermissionsError:
 
222
        return QLatin1String("PermissionsError");
 
223
    case QContactManager::OutOfMemoryError:
 
224
        return QLatin1String("OutOfMemory");
 
225
    case QContactManager::NotSupportedError:
 
226
        return QLatin1String("NotSupported");
 
227
    case QContactManager::BadArgumentError:
 
228
        return QLatin1String("BadArgument");
 
229
    case QContactManager::UnspecifiedError:
 
230
        return QLatin1String("UnspecifiedError");
 
231
    case QContactManager::VersionMismatchError:
 
232
        return QLatin1String("VersionMismatch");
 
233
    case QContactManager::LimitReachedError:
 
234
        return QLatin1String("LimitReached");
 
235
    case QContactManager::InvalidContactTypeError:
 
236
        return QLatin1String("InvalidContactType");
 
237
    default:
 
238
        break;
 
239
    }
 
240
    return QLatin1String("NoError");
 
241
}
 
242
 
 
243
 
 
244
/*!
 
245
  \qmlproperty list<string> ContactModel::availableManagers
 
246
 
 
247
  This property holds the list of available manager names.
 
248
  This property is read only.
 
249
  */
 
250
QStringList QDeclarativeContactModel::availableManagers() const
 
251
{
 
252
    return QContactManager::availableManagers();
 
253
}
 
254
static QString urlToLocalFileName(const QUrl& url)
 
255
{
 
256
   if (!url.isValid()) {
 
257
      return url.toString();
 
258
   } else if (url.scheme() == "qrc") {
 
259
      return url.toString().remove(0, 5).prepend(':');
 
260
   } else {
 
261
      return url.toLocalFile();
 
262
   }
 
263
 
 
264
}
 
265
 
 
266
/*!
 
267
  \qmlmethod ContactModel::importContacts(url url, list<string> profiles)
 
268
 
 
269
  Import contacts from a vcard by the given \a url and optional \a profiles.
 
270
  */
 
271
void QDeclarativeContactModel::importContacts(const QUrl& url, const QStringList& profiles)
 
272
{
 
273
   //qWarning() << "importing contacts from:" << url;
 
274
   d->m_importProfiles = profiles;
 
275
 
 
276
   //TODO: need to allow download vcard from network
 
277
   QFile*  file = new QFile(urlToLocalFileName(url));
 
278
   bool ok = file->open(QIODevice::ReadOnly);
 
279
   if (ok) {
 
280
      d->m_reader.setDevice(file);
 
281
      d->m_reader.startReading();
 
282
   }
 
283
}
 
284
 
 
285
/*!
 
286
  \qmlmethod ContactModel::exportContacts(url url, list<string> profiles)
 
287
 
 
288
  Export contacts into a vcard file to the given \a url by optional \a profiles.
 
289
  At the moment only the local file url is supported in export method.
 
290
  */
 
291
void QDeclarativeContactModel::exportContacts(const QUrl& url, const QStringList& profiles)
 
292
{
 
293
   //qWarning() << "exporting contacts into:" << url;
 
294
 
 
295
   QString profile = profiles.isEmpty()? QString() : profiles.at(0);
 
296
    //only one profile string supported now
 
297
   QVersitContactExporter exporter(profile);
 
298
 
 
299
   QList<QContact> contacts;
 
300
   foreach (QDeclarativeContact* dc, d->m_contacts) {
 
301
       contacts.append(dc->contact());
 
302
   }
 
303
 
 
304
   exporter.exportContacts(contacts, QVersitDocument::VCard30Type);
 
305
   QList<QVersitDocument> documents = exporter.documents();
 
306
   QFile* file = new QFile(urlToLocalFileName(url));
 
307
   bool ok = file->open(QIODevice::ReadWrite);
 
308
   if (ok) {
 
309
      d->m_writer.setDevice(file);
 
310
      d->m_writer.startWriting(documents);
 
311
   }
 
312
}
 
313
 
 
314
void QDeclarativeContactModel::contactsExported(QVersitWriter::State state)
 
315
{
 
316
    if (state == QVersitWriter::FinishedState || state == QVersitWriter::CanceledState) {
 
317
         delete d->m_writer.device();
 
318
         d->m_writer.setDevice(0);
 
319
    }
 
320
}
 
321
 
 
322
int QDeclarativeContactModel::rowCount(const QModelIndex &parent) const
 
323
{
 
324
    Q_UNUSED(parent);
 
325
    return d->m_contacts.count();
 
326
}
 
327
 
 
328
 
 
329
 
 
330
/*!
 
331
  \qmlproperty Filter ContactModel::filter
 
332
 
 
333
  This property holds the filter instance used by the contact model.
 
334
 
 
335
  \sa Filter
 
336
  */
 
337
QDeclarativeContactFilter* QDeclarativeContactModel::filter() const
 
338
{
 
339
    return d->m_filter;
 
340
}
 
341
 
 
342
void QDeclarativeContactModel::setFilter(QDeclarativeContactFilter* filter)
 
343
{
 
344
    d->m_filter = filter;
 
345
    if (d->m_filter) {
 
346
        connect(d->m_filter, SIGNAL(valueChanged()), SLOT(fetchAgain()));
 
347
        emit filterChanged();
 
348
    }
 
349
}
 
350
 
 
351
/*!
 
352
  \qmlproperty FetchHint ContactModel::fetchHint
 
353
 
 
354
  This property holds the fetch hint instance used by the contact model.
 
355
 
 
356
  \sa FetchHint
 
357
  */
 
358
QDeclarativeContactFetchHint* QDeclarativeContactModel::fetchHint() const
 
359
{
 
360
    return d->m_fetchHint;
 
361
}
 
362
void QDeclarativeContactModel::setFetchHint(QDeclarativeContactFetchHint* fetchHint)
 
363
{
 
364
    if (fetchHint && fetchHint != d->m_fetchHint) {
 
365
        if (d->m_fetchHint)
 
366
            delete d->m_fetchHint;
 
367
        d->m_fetchHint = fetchHint;
 
368
        emit fetchHintChanged();
 
369
    }
 
370
}
 
371
 
 
372
/*!
 
373
  \qmlproperty QDeclarativeListProperty ContactModel::contacts
 
374
 
 
375
  This property holds a list of contacts.
 
376
 
 
377
  \sa Contact
 
378
  */
 
379
QDeclarativeListProperty<QDeclarativeContact> QDeclarativeContactModel::contacts()
 
380
{
 
381
    return QDeclarativeListProperty<QDeclarativeContact>(this, d->m_contacts);
 
382
}
 
383
 
 
384
/*!
 
385
  \qmlproperty QDeclarativeListProperty ContactModel::sortOrders
 
386
 
 
387
  This property holds a list of sort orders used by the organizer model.
 
388
 
 
389
  \sa SortOrder
 
390
  */
 
391
QDeclarativeListProperty<QDeclarativeContactSortOrder> QDeclarativeContactModel::sortOrders()
 
392
{
 
393
    return QDeclarativeListProperty<QDeclarativeContactSortOrder>(this, d->m_sortOrders);
 
394
}
 
395
 
 
396
void QDeclarativeContactModel::startImport(QVersitReader::State state)
 
397
{
 
398
    if (state == QVersitReader::FinishedState || state == QVersitReader::CanceledState) {
 
399
        QVersitContactImporter importer(d->m_importProfiles);
 
400
        importer.importDocuments(d->m_reader.results());
 
401
        QList<QContact> contacts = importer.contacts();
 
402
 
 
403
        delete d->m_reader.device();
 
404
        d->m_reader.setDevice(0);
 
405
 
 
406
        if (d->m_manager) {
 
407
            if (d->m_manager->saveContacts(&contacts))
 
408
                qWarning() << "contacts imported.";
 
409
                fetchAgain();
 
410
        }
 
411
    }
 
412
}
 
413
 
 
414
/*!
 
415
  \qmlmethod ContactModel::fetchContacts(list<int> contactIds)
 
416
  Fetch a list of contacts from the contacts store by given \a contactIds.
 
417
  */
 
418
void QDeclarativeContactModel::fetchContacts(const QList<QContactLocalId>& contactIds)
 
419
{
 
420
    QList<QContactSortOrder> sortOrders;
 
421
    foreach (QDeclarativeContactSortOrder* so, d->m_sortOrders) {
 
422
        sortOrders.append(so->sortOrder());
 
423
    }
 
424
    QContactFetchRequest* req = new QContactFetchRequest(this);
 
425
    req->setManager(d->m_manager);
 
426
    req->setSorting(sortOrders);
 
427
 
 
428
    QContactLocalIdFilter filter;
 
429
    filter.setIds(contactIds);
 
430
    req->setFilter(filter);
 
431
 
 
432
    req->setFetchHint(d->m_fetchHint ? d->m_fetchHint->fetchHint() : QContactFetchHint());
 
433
 
 
434
    connect(req,SIGNAL(stateChanged(QContactAbstractRequest::State)), this, SLOT(requestUpdated()));
 
435
 
 
436
    req->start();
 
437
}
 
438
 
 
439
void QDeclarativeContactModel::fetchAgain()
 
440
{
 
441
    d->m_contacts.clear();
 
442
    d->m_contactMap.clear();
 
443
 
 
444
    QList<QContactSortOrder> sortOrders;
 
445
    foreach (QDeclarativeContactSortOrder* so, d->m_sortOrders) {
 
446
        sortOrders.append(so->sortOrder());
 
447
    }
 
448
    QContactFetchRequest* req = new QContactFetchRequest(this);
 
449
    req->setManager(d->m_manager);
 
450
    req->setSorting(sortOrders);
 
451
 
 
452
    req->setFilter(d->m_filter? d->m_filter->filter() : QContactFilter());
 
453
    req->setFetchHint(d->m_fetchHint ? d->m_fetchHint->fetchHint() : QContactFetchHint());
 
454
 
 
455
    connect(req,SIGNAL(stateChanged(QContactAbstractRequest::State)), this, SLOT(requestUpdated()));
 
456
 
 
457
    req->start();
 
458
}
 
459
 
 
460
void QDeclarativeContactModel::requestUpdated()
 
461
{
 
462
    QContactFetchRequest* req = qobject_cast<QContactFetchRequest*>(QObject::sender());
 
463
    if (req && req->isFinished()) {
 
464
        QList<QContact> contacts = req->contacts();
 
465
 
 
466
        QList<QDeclarativeContact*> dcs;
 
467
        foreach(QContact c, contacts) {
 
468
            QDeclarativeContact* dc = new QDeclarativeContact(c, d->m_manager->detailDefinitions(c.type()), this);
 
469
            dcs.append(dc);
 
470
            d->m_contactMap.insert(c.localId(), dc);
 
471
        }
 
472
 
 
473
        reset();
 
474
        beginInsertRows(QModelIndex(), 0, req->contacts().count());
 
475
        d->m_contacts = dcs;
 
476
        endInsertRows();
 
477
        emit contactsChanged();
 
478
        req->deleteLater();
 
479
    }
 
480
}
 
481
 
 
482
/*!
 
483
  \qmlmethod ContactModel::saveContact(Contact contact)
 
484
  Save the given \a contact into the contacts store. Once saved successfully, the dirty flags of this contact will be reset.
 
485
 
 
486
  \sa Contact::modified
 
487
  */
 
488
void QDeclarativeContactModel::saveContact(QDeclarativeContact* dc)
 
489
{
 
490
    if (dc) {
 
491
        QContact c = dc->contact();
 
492
        QContactSaveRequest* req = new QContactSaveRequest(this);
 
493
        req->setManager(d->m_manager);
 
494
        req->setContact(c);
 
495
 
 
496
        connect(req,SIGNAL(stateChanged(QContactAbstractRequest::State)), this, SLOT(contactsSaved()));
 
497
 
 
498
        req->start();
 
499
    }
 
500
}
 
501
 
 
502
 
 
503
void QDeclarativeContactModel::contactsSaved()
 
504
{
 
505
    QContactSaveRequest* req = qobject_cast<QContactSaveRequest*>(QObject::sender());
 
506
    if (req->isFinished()) {
 
507
        if (req->error() == QContactManager::NoError) {
 
508
            QList<QContact> cs = req->contacts();
 
509
            foreach (const QContact& c, cs) {
 
510
                if (d->m_contactMap.contains(c.localId())) {
 
511
                    d->m_contactMap.value(c.localId())->setContact(c);
 
512
                } else {
 
513
                    //new saved contact
 
514
                    QDeclarativeContact* dc = new QDeclarativeContact(c, d->m_manager->detailDefinitions(c.type()) , this);
 
515
                    d->m_contactMap.insert(c.localId(), dc);
 
516
                    beginInsertRows(QModelIndex(), d->m_contacts.count(), d->m_contacts.count());
 
517
                    d->m_contacts.append(dc);
 
518
                    endInsertRows();
 
519
                }
 
520
            }
 
521
        }
 
522
        req->deleteLater();
 
523
    }
 
524
}
 
525
 
 
526
/*!
 
527
  \qmlmethod ContactModel::removeContact(int contactId)
 
528
  Remove the contact from the contacts store by given \a contactId.
 
529
  */
 
530
void QDeclarativeContactModel::removeContact(QContactLocalId id)
 
531
{
 
532
    removeContacts(QList<QContactLocalId>() << id);
 
533
}
 
534
 
 
535
/*!
 
536
  \qmlmethod ContactModel::removeContacts(list<int> contactIds)
 
537
  Remove the list of contacts from the contacts store by given \a contactIds.
 
538
  */
 
539
 
 
540
void QDeclarativeContactModel::removeContacts(const QList<QContactLocalId>& ids)
 
541
{
 
542
    QContactRemoveRequest* req = new QContactRemoveRequest(this);
 
543
    req->setManager(d->m_manager);
 
544
    req->setContactIds(ids);
 
545
 
 
546
    connect(req,SIGNAL(stateChanged(QContactAbstractRequest::State)), this, SLOT(contactRemoved()));
 
547
 
 
548
    req->start();
 
549
}
 
550
 
 
551
void QDeclarativeContactModel::contactsRemoved(const QList<QContactLocalId>& ids)
 
552
{
 
553
    bool emitSignal = false;
 
554
    foreach (const QContactLocalId& id, ids) {
 
555
        if (d->m_contactMap.contains(id)) {
 
556
            int row = 0;
 
557
            //TODO:need a fast lookup
 
558
            for (; row < d->m_contacts.count(); row++) {
 
559
                if (d->m_contacts.at(row)->contactId() == id)
 
560
                    break;
 
561
            }
 
562
 
 
563
            if (row < d->m_contacts.count()) {
 
564
                beginRemoveRows(QModelIndex(), row, row);
 
565
                d->m_contacts.removeAt(row);
 
566
                d->m_contactMap.remove(id);
 
567
                endRemoveRows();
 
568
                emitSignal = true;
 
569
            }
 
570
        }
 
571
    }
 
572
    if (emitSignal)
 
573
        emit contactsChanged();
 
574
}
 
575
 
 
576
void QDeclarativeContactModel::contactsChanged(const QList<QContactLocalId>& ids)
 
577
{
 
578
    QList<QContactLocalId> updatedIds;
 
579
    foreach (const QContactLocalId& id, ids) {
 
580
        if (d->m_contactMap.contains(id)) {
 
581
            updatedIds << id;
 
582
        }
 
583
    }
 
584
 
 
585
    if (updatedIds.count() > 0)
 
586
        fetchContacts(updatedIds);
 
587
}
 
588
 
 
589
void QDeclarativeContactModel::contactsRemoved()
 
590
{
 
591
    QContactRemoveRequest* req = qobject_cast<QContactRemoveRequest*>(QObject::sender());
 
592
 
 
593
 
 
594
    if (req->isFinished()) {
 
595
        QList<QContactLocalId> ids = req->contactIds();
 
596
        QList<int> errorIds = req->errorMap().keys();
 
597
        QList<QContactLocalId> removedIds;
 
598
        for( int i = 0; i < ids.count(); i++) {
 
599
            if (!errorIds.contains(i))
 
600
                removedIds << ids.at(i);
 
601
        }
 
602
        if (!removedIds.isEmpty())
 
603
            contactsRemoved(removedIds);
 
604
        req->deleteLater();
 
605
    }
 
606
}
 
607
 
 
608
 
 
609
QVariant QDeclarativeContactModel::data(const QModelIndex &index, int role) const
 
610
{
 
611
    QDeclarativeContact* dc = d->m_contacts.value(index.row());
 
612
    QContact c = dc->contact();
 
613
 
 
614
    switch(role) {
 
615
        case Qt::DisplayRole:
 
616
            return c.displayLabel();
 
617
        case Qt::DecorationRole:
 
618
            {
 
619
                QContactThumbnail t = c.detail<QContactThumbnail>();
 
620
                if (!t.thumbnail().isNull())
 
621
                    return QPixmap::fromImage(t.thumbnail());
 
622
                return QPixmap();
 
623
            }
 
624
        case ContactRole:
 
625
            return QVariant::fromValue(dc);
 
626
    }
 
627
    return QVariant();
 
628
}
 
629