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 QtQml 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 "qdeclarativecontactrelationshipmodel_p.h"
35
36#include <QtGui/qpixmap.h>
37
38#include <QtQml/qqmlinfo.h>
39
40#include <QtContacts/qcontactmanager.h>
41#include <QtContacts/qcontactrequests.h>
42
43QTCONTACTS_USE_NAMESPACE
44
45QT_BEGIN_NAMESPACE
46
47/*!
48 \qmltype RelationshipModel
49 \instantiates QDeclarativeContactRelationshipModel
50 \brief The RelationshipModel provides a model of contact relationships from the contacts store.
51
52 \ingroup qml-contacts-main
53 \inqmlmodule QtContacts
54
55 This element is part of the \b{QtContacts} module.
56
57 The contents of the model can be specified with \l participantId, \l role and \l relationshipType properties.
58 Whether the model is automatically updated when the store or filter changes, can be controlled
59 with \l RelationshipModel::autoUpdate property.
60
61 There are two ways of accessing the relationship data: through model by using views and delegates,
62 or alternatively via \l relationships list property.
63
64 At the moment only data role provided by the model is \c relationship (\l Relationship).
65 Through that one can access any data provided by the Relationship element.
66
67 \sa Relationship, {QContactRelationship}
68 */
69
70class QDeclarativeContactRelationshipModelPrivate
71{
72public:
73 QDeclarativeContactRelationshipModelPrivate()
74 : m_manager(0)
75 , m_participant(0)
76 , m_role(QDeclarativeContactRelationship::Either)
77 {
78 }
79
80 ~QDeclarativeContactRelationshipModelPrivate()
81 {
82 delete m_manager;
83 }
84
85 QContactManager *m_manager;
86 QDeclarativeContactRelationship m_relationshipTypeHolder;
87 QDeclarativeContact* m_participant;
88 QDeclarativeContactRelationship::RelationshipRole m_role;
89 QList<QContactRelationship> m_relationships;
90 QList<QDeclarativeContactRelationship *> m_declarativeRelationships;
91};
92
93QDeclarativeContactRelationshipModel::QDeclarativeContactRelationshipModel(QObject *parent)
94 : QAbstractListModel(parent)
95 , d(new QDeclarativeContactRelationshipModelPrivate)
96{
97 QHash<int, QByteArray> roleNames;
98 roleNames = QAbstractItemModel::roleNames();
99 roleNames.insert(akey: RelationshipRole, avalue: "relationship");
100 setRoleNames(roleNames);
101 connect(asender: this, SIGNAL(managerChanged()), SLOT(fetchAgain()));
102 connect(asender: this, SIGNAL(participantChanged()), SLOT(fetchAgain()));
103 connect(asender: this, SIGNAL(relationshipTypeChanged()), SLOT(fetchAgain()));
104 connect(asender: this, SIGNAL(roleChanged()), SLOT(fetchAgain()));
105}
106
107QDeclarativeContactRelationshipModel::~QDeclarativeContactRelationshipModel()
108{
109 delete d;
110}
111
112/*!
113 \qmlproperty string RelationshipModel::manager
114
115 This property holds the manager uri of the contact backend engine.
116 */
117QString QDeclarativeContactRelationshipModel::manager() const
118{
119 if (d->m_manager)
120 return d->m_manager->managerName();
121 return QString();
122}
123
124
125/*!
126 \qmlproperty string RelationshipModel::error
127
128 This property holds the latest error code returned by the contact manager.
129
130 This property is read only.
131 */
132QString QDeclarativeContactRelationshipModel::error() const
133{
134 switch (d->m_manager->error()) {
135 case QContactManager::DoesNotExistError:
136 return QStringLiteral("DoesNotExist");
137 case QContactManager::AlreadyExistsError:
138 return QStringLiteral("AlreadyExists");
139 case QContactManager::InvalidDetailError:
140 return QStringLiteral("InvalidDetail");
141 case QContactManager::InvalidRelationshipError:
142 return QStringLiteral("InvalidRelationship");
143 case QContactManager::LockedError:
144 return QStringLiteral("LockedError");
145 case QContactManager::DetailAccessError:
146 return QStringLiteral("DetailAccessError");
147 case QContactManager::PermissionsError:
148 return QStringLiteral("PermissionsError");
149 case QContactManager::OutOfMemoryError:
150 return QStringLiteral("OutOfMemory");
151 case QContactManager::NotSupportedError:
152 return QStringLiteral("NotSupported");
153 case QContactManager::BadArgumentError:
154 return QStringLiteral("BadArgument");
155 case QContactManager::UnspecifiedError:
156 return QStringLiteral("UnspecifiedError");
157 case QContactManager::VersionMismatchError:
158 return QStringLiteral("VersionMismatch");
159 case QContactManager::LimitReachedError:
160 return QStringLiteral("LimitReached");
161 case QContactManager::InvalidContactTypeError:
162 return QStringLiteral("InvalidContactType");
163 default:
164 break;
165 }
166 return QStringLiteral("NoError");
167}
168void QDeclarativeContactRelationshipModel::setManager(const QString& manager)
169{
170 if (d->m_manager == 0 || manager != d->m_manager->managerName() ) {
171 d->m_manager = new QContactManager(manager,QMap<QString,QString>(), this);
172 connect(sender: d->m_manager,SIGNAL(relationshipsAdded(QList<QContactId>)), receiver: this, SLOT(fetchAgain()));
173 connect(sender: d->m_manager,SIGNAL(relationshipsRemoved(QList<QContactId>)), receiver: this, SLOT(fetchAgain()));
174 emit managerChanged();
175 }
176}
177
178
179/*!
180 \qmlproperty int RelationshipModel::participantId
181
182 This property holds the participant which the list of relationships returned by RelationshipModel should contain.
183
184 \sa RelationshipFilter::relatedContactId
185 \sa RelationshipModel::role
186 */
187QDeclarativeContact* QDeclarativeContactRelationshipModel::participant() const
188{
189 return d->m_participant;
190}
191void QDeclarativeContactRelationshipModel::setParticipant(QDeclarativeContact* participant)
192{
193 if (d->m_participant != participant) {
194 d->m_participant = participant;
195 emit participantChanged();
196 }
197}
198
199/*!
200 \qmlproperty variant RelationshipModel::relationshipType
201
202 This property holds the relationship type which the list of relationships returned by RelationshipModel should contain.
203
204 \sa Relationship::type
205 */
206QVariant QDeclarativeContactRelationshipModel::relationshipType() const
207{
208 return d->m_relationshipTypeHolder.relationshipType();
209}
210void QDeclarativeContactRelationshipModel::setRelationshipType(const QVariant& type)
211{
212 if (type != relationshipType()) {
213 d->m_relationshipTypeHolder.setRelationshipType(type);
214 emit relationshipTypeChanged();
215 }
216}
217
218/*!
219 \qmlproperty enumeration RelationshipModel::role
220
221 This property holds the relationship role which the list of relationships returned by RelationshipModel should contain.
222
223 \sa RelationshipFilter::relatedContactRole
224 */
225QDeclarativeContactRelationship::RelationshipRole QDeclarativeContactRelationshipModel::role() const
226{
227 return d->m_role;
228}
229void QDeclarativeContactRelationshipModel::setRole(QDeclarativeContactRelationship::RelationshipRole role)
230{
231 if (d->m_role != role) {
232 d->m_role = role;
233 emit roleChanged();
234 }
235}
236
237/*!
238 \qmlproperty bool RelationshipModel::autoUpdate
239
240 This property indicates whether or not the relationship model should be updated automatically, default value is true.
241 */
242bool QDeclarativeContactRelationshipModel::autoUpdate() const
243{
244 //TODO
245 return true;
246}
247void QDeclarativeContactRelationshipModel::setAutoUpdate(bool autoUpdate)
248{
249 Q_UNUSED(autoUpdate);
250 //TODO
251}
252
253/*!
254 \qmlproperty list<Relationship> RelationshipModel::relationships
255
256 This property holds a list of relationships.
257
258 \sa Relationship
259 */
260QQmlListProperty<QDeclarativeContactRelationship> QDeclarativeContactRelationshipModel::relationships()
261{
262 return QQmlListProperty<QDeclarativeContactRelationship>(this, d->m_declarativeRelationships);
263}
264
265int QDeclarativeContactRelationshipModel::rowCount(const QModelIndex &parent) const
266{
267 Q_UNUSED(parent);
268 return d->m_declarativeRelationships.count();
269}
270
271QVariant QDeclarativeContactRelationshipModel::data(const QModelIndex &index, int role) const
272{
273 QDeclarativeContactRelationship* dcr = d->m_declarativeRelationships.value(i: index.row());
274 if (role == RelationshipRole) {
275 return QVariant::fromValue(value: dcr);
276 } else if (role == Qt::DisplayRole) {
277 return QString(QStringLiteral("%1 %2 %3")).arg(a: dcr->relationship().first().toString()).arg(a: dcr->relationship().relationshipType()).arg(a: dcr->relationship().second().toString());
278 }
279 return QVariant();
280}
281
282void QDeclarativeContactRelationshipModel::fetchAgain()
283{
284 if (d->m_manager) {
285 QContactRelationshipFetchRequest* req = new QContactRelationshipFetchRequest(this);
286 req->setManager(d->m_manager);
287 if (d->m_participant) {
288 QContact contact (d->m_participant->contact());
289 if (d->m_role == QDeclarativeContactRelationship::First || d->m_role == QDeclarativeContactRelationship::Either)
290 req->setFirst(contact.id());
291 if (d->m_role == QDeclarativeContactRelationship::Second || d->m_role == QDeclarativeContactRelationship::Either)
292 req->setSecond(contact.id());
293 req->setRelationshipType(d->m_relationshipTypeHolder.relationship().relationshipType());
294 connect(sender: req,SIGNAL(stateChanged(QContactAbstractRequest::State)), receiver: this, SLOT(requestUpdated()));
295 req->start();
296 }
297 }
298}
299
300/*!
301 \qmlmethod RelationshipModel::addRelationship(relationship)
302 Addes the given \a relationship to the backend store.
303 */
304void QDeclarativeContactRelationshipModel::addRelationship(QDeclarativeContactRelationship* dcr)
305{
306 if (dcr) {
307 QContactRelationship cr = dcr->relationship();
308 QContactRelationshipSaveRequest* req = new QContactRelationshipSaveRequest(this);
309 req->setManager(d->m_manager);
310 req->setRelationship(cr);
311 connect(sender: req, SIGNAL(stateChanged(QContactAbstractRequest::State)), receiver: this, SLOT(relationshipsSaved()));
312 req->start();
313 }
314}
315
316/*!
317 \qmlmethod RelationshipModel::removeRelationship(relationship)
318 Removes the given \a relationship from the backend store.
319 */
320void QDeclarativeContactRelationshipModel::removeRelationship(QDeclarativeContactRelationship* dcr)
321{
322 if (dcr) {
323 QContactRelationship cr = dcr->relationship();
324 QContactRelationshipRemoveRequest* req = new QContactRelationshipRemoveRequest(this);
325 req->setManager(d->m_manager);
326 req->setRelationship(cr);
327 connect(sender: req,SIGNAL(stateChanged(QContactAbstractRequest::State)), receiver: this, SLOT(relationshipsRemoved()));
328 req->start();
329 }
330}
331
332void QDeclarativeContactRelationshipModel::requestUpdated()
333{
334 QContactRelationshipFetchRequest* req = qobject_cast<QContactRelationshipFetchRequest*>(object: sender());
335 Q_ASSERT(req);
336 if (req->isFinished() && req->error() == QContactManager::NoError) {
337
338 QList<QContactRelationship> relationships = req->relationships();
339
340 reset();
341 beginInsertRows(parent: QModelIndex(), first: 0, last: relationships.count());
342
343 foreach(QDeclarativeContactRelationship* dcr, d->m_declarativeRelationships) {
344 dcr->deleteLater();
345 }
346 d->m_declarativeRelationships.clear();
347 d->m_relationships.clear();
348
349 foreach (const QContactRelationship& cr, relationships) {
350 QDeclarativeContactRelationship* dcr = new QDeclarativeContactRelationship(this);
351 dcr->setRelationship(cr);
352 d->m_declarativeRelationships.append(t: dcr);
353 d->m_relationships.append(t: cr);
354 }
355 endInsertRows();
356 req->deleteLater();
357 emit relationshipsChanged();
358 }
359}
360
361void QDeclarativeContactRelationshipModel::relationshipsSaved()
362{
363 QContactRelationshipSaveRequest* req = qobject_cast<QContactRelationshipSaveRequest*>(object: sender());
364 Q_ASSERT(req);
365 if (req->isFinished()) {
366 QList<QContactRelationship> rs = req->relationships();
367 QList<int> errorIds = req->errorMap().keys();
368
369 for( int i = 0; i < rs.count(); i++) {
370 if (!errorIds.contains(t: i)) {
371 //saved
372 QContactRelationship r = rs.at(i);
373
374 if (!d->m_relationships.contains(t: r)) {
375 //new relationship saved
376 QDeclarativeContactRelationship* dcr = new QDeclarativeContactRelationship(this);
377 dcr->setRelationship(r);
378 beginInsertRows(parent: QModelIndex(), first: d->m_declarativeRelationships.count(), last: d->m_declarativeRelationships.count());
379 d->m_declarativeRelationships.append(t: dcr);
380 d->m_relationships.append(t: r);
381 endInsertRows();
382 }
383 }
384 }
385 req->deleteLater();
386 }
387}
388
389void QDeclarativeContactRelationshipModel::relationshipsRemoved()
390{
391 QContactRelationshipRemoveRequest* req = qobject_cast<QContactRelationshipRemoveRequest*>(object: sender());
392 Q_ASSERT(req);
393 if (req->isFinished()) {
394 QList<QContactRelationship> rs = req->relationships();
395 QList<int> errorIds = req->errorMap().keys();
396
397
398 for( int i = 0; i < rs.count(); i++) {
399 if (!errorIds.contains(t: i)) {
400 int row = 0;
401 QContactRelationship r = rs.at(i);
402 for (; row < d->m_relationships.count(); row++) {
403 if (d->m_relationships.at(i: row) == r)
404 break;
405 }
406 if (row < d->m_relationships.count()) {
407 beginRemoveRows(parent: QModelIndex(), first: row, last: row);
408 d->m_declarativeRelationships.removeAt(i: row);
409 d->m_relationships.removeAt(i: row);
410 endRemoveRows();
411 } else {
412 //impossible?
413 qmlInfo(me: this) << tr(s: "this relationship '") << row << tr(s: "' was already removed!");
414 }
415 }
416 }
417 req->deleteLater();
418 }
419}
420
421#include "moc_qdeclarativecontactrelationshipmodel_p.cpp"
422
423QT_END_NAMESPACE
424

source code of qtpim/src/imports/contacts/qdeclarativecontactrelationshipmodel.cpp