• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.14.10 API Reference
  • KDE Home
  • Contact Us
 

akonadi/contact

  • akonadi
  • contact
contactgroupmodel.cpp
1/*
2 This file is part of Akonadi Contact.
3
4 Copyright (c) 2009 Tobias Koenig <tokoe@kde.org>
5
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Library General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at your
9 option) any later version.
10
11 This library is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14 License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA.
20*/
21
22#include "contactgroupmodel_p.h"
23
24#include <akonadi/itemfetchjob.h>
25#include <akonadi/itemfetchscope.h>
26#include <kabc/addressee.h>
27#include <kicon.h>
28#include <kiconloader.h>
29#include <klocalizedstring.h>
30
31using namespace Akonadi;
32
33struct GroupMember
34{
35 GroupMember()
36 : isReference(false), loadingError( false )
37 {
38 }
39
40 KABC::ContactGroup::ContactReference reference;
41 KABC::ContactGroup::Data data;
42 KABC::Addressee referencedContact;
43 bool isReference;
44 bool loadingError;
45};
46
47class ContactGroupModel::Private
48{
49 public:
50 Private( ContactGroupModel *parent )
51 : mParent( parent )
52 {
53 }
54
55 void resolveContactReference( const KABC::ContactGroup::ContactReference &reference, int row )
56 {
57 Item item;
58 if ( !reference.gid().isEmpty() ) {
59 item.setGid( reference.gid() );
60 } else {
61 item.setId( reference.uid().toLongLong() );
62 }
63 ItemFetchJob *job = new ItemFetchJob( item, mParent );
64 job->setProperty( "row", row );
65 job->fetchScope().fetchFullPayload();
66
67 mParent->connect( job, SIGNAL(result(KJob*)), SLOT(itemFetched(KJob*)) );
68 }
69
70 void itemFetched( KJob *job )
71 {
72 const int row = job->property( "row" ).toInt();
73
74 if ( job->error() ) {
75 mMembers[ row ].loadingError = true;
76 emit mParent->dataChanged( mParent->index( row, 0, QModelIndex() ), mParent->index( row, 1, QModelIndex() ) );
77 return;
78 }
79
80 ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
81
82 if ( fetchJob->items().count() != 1 ) {
83 mMembers[ row ].loadingError = true;
84 emit mParent->dataChanged( mParent->index( row, 0, QModelIndex() ), mParent->index( row, 1, QModelIndex() ) );
85 return;
86 }
87
88 const Item item = fetchJob->items().first();
89 const KABC::Addressee contact = item.payload<KABC::Addressee>();
90
91 GroupMember &member = mMembers[ row ];
92 member.referencedContact = contact;
93 emit mParent->dataChanged( mParent->index( row, 0, QModelIndex() ), mParent->index( row, 1, QModelIndex() ) );
94 }
95
96 void normalizeMemberList()
97 {
98 // check whether a normalization is needed or not
99 bool needsNormalization = false;
100 if ( mMembers.isEmpty() ) {
101 needsNormalization = true;
102 } else {
103 for ( int i = 0; i < mMembers.count(); ++i ) {
104 const GroupMember &member = mMembers[ i ];
105 if ( !member.isReference && !( i == mMembers.count() - 1 ) ) {
106 if ( member.data.name().isEmpty() && member.data.email().isEmpty() ) {
107 needsNormalization = true;
108 break;
109 }
110 }
111 }
112
113 const GroupMember &member = mMembers.last();
114 if ( member.isReference || !( member.data.name().isEmpty() && member.data.email().isEmpty() ) ) {
115 needsNormalization = true;
116 }
117 }
118
119 // if not, avoid to update the model and view
120 if ( !needsNormalization ) {
121 return;
122 }
123
124 bool foundEmpty = false;
125
126 // add an empty line at the end
127 mParent->beginInsertRows( QModelIndex(), mMembers.count(), mMembers.count() );
128 GroupMember member;
129 member.isReference = false;
130 mMembers.append( member );
131 mParent->endInsertRows();
132
133 // remove all empty lines first except the last line
134 do {
135 foundEmpty = false;
136 for ( int i = 0; i < mMembers.count(); ++i ) {
137 const GroupMember &member = mMembers[ i ];
138 if ( !member.isReference && !( i == mMembers.count() - 1 ) ) {
139 if ( member.data.name().isEmpty() && member.data.email().isEmpty() ) {
140 mParent->beginRemoveRows( QModelIndex(), i, i );
141 mMembers.remove( i );
142 mParent->endRemoveRows();
143 foundEmpty = true;
144 break;
145 }
146 }
147 }
148 } while ( foundEmpty );
149 }
150
151 ContactGroupModel *mParent;
152 QVector<GroupMember> mMembers;
153 KABC::ContactGroup mGroup;
154 QString mLastErrorMessage;
155};
156
157ContactGroupModel::ContactGroupModel( QObject *parent )
158 : QAbstractItemModel( parent ), d( new Private( this ) )
159{
160}
161
162ContactGroupModel::~ContactGroupModel()
163{
164 delete d;
165}
166
167void ContactGroupModel::loadContactGroup( const KABC::ContactGroup &contactGroup )
168{
169 emit layoutAboutToBeChanged();
170
171 d->mMembers.clear();
172 d->mGroup = contactGroup;
173
174 for ( uint i = 0; i < d->mGroup.dataCount(); ++i ) {
175 const KABC::ContactGroup::Data data = d->mGroup.data( i );
176 GroupMember member;
177 member.isReference = false;
178 member.data = data;
179
180 d->mMembers.append( member );
181 }
182
183 for ( uint i = 0; i < d->mGroup.contactReferenceCount(); ++i ) {
184 const KABC::ContactGroup::ContactReference reference = d->mGroup.contactReference( i );
185 GroupMember member;
186 member.isReference = true;
187 member.reference = reference;
188
189 d->mMembers.append( member );
190
191 d->resolveContactReference( reference, d->mMembers.count() - 1 );
192 }
193
194 d->normalizeMemberList();
195
196 emit layoutChanged();
197}
198
199bool ContactGroupModel::storeContactGroup( KABC::ContactGroup &group ) const
200{
201 group.removeAllContactReferences();
202 group.removeAllContactData();
203
204 for ( int i = 0; i < d->mMembers.count(); ++i ) {
205 const GroupMember &member = d->mMembers[ i ];
206 if ( member.isReference ) {
207 group.append( member.reference );
208 } else {
209 if ( i != ( d->mMembers.count() - 1 ) ) {
210 if ( member.data.email().isEmpty() ) {
211 d->mLastErrorMessage =
212 i18n( "The member with name <b>%1</b> is missing an email address",
213 member.data.name() );
214 return false;
215 }
216 group.append( member.data );
217 }
218 }
219 }
220
221 return true;
222}
223
224QString ContactGroupModel::lastErrorMessage() const
225{
226 return d->mLastErrorMessage;
227}
228
229QModelIndex ContactGroupModel::index( int row, int col, const QModelIndex& ) const
230{
231 return createIndex( row, col);
232}
233
234QModelIndex ContactGroupModel::parent( const QModelIndex& ) const
235{
236 return QModelIndex();
237}
238
239QVariant ContactGroupModel::data( const QModelIndex &index, int role ) const
240{
241 if ( !index.isValid() ) {
242 return QVariant();
243 }
244
245 if ( index.row() < 0 || index.row() >= d->mMembers.count() ) {
246 return QVariant();
247 }
248
249 if ( index.column() < 0 || index.column() > 1 ) {
250 return QVariant();
251 }
252
253 const GroupMember &member = d->mMembers[ index.row() ];
254
255 if ( role == Qt::DisplayRole ) {
256 if ( member.loadingError ) {
257 if ( index.column() == 0 ) {
258 return i18n( "Contact does not exist any more" );
259 } else {
260 return QString();
261 }
262 }
263
264 if ( member.isReference ) {
265 if ( index.column() == 0 ) {
266 return member.referencedContact.realName();
267 } else {
268 if ( !member.reference.preferredEmail().isEmpty() ) {
269 return member.reference.preferredEmail();
270 } else {
271 return member.referencedContact.preferredEmail();
272 }
273 }
274 } else {
275 if ( index.column() == 0 ) {
276 return member.data.name();
277 } else {
278 return member.data.email();
279 }
280 }
281 }
282
283 if ( role == Qt::DecorationRole ) {
284 if ( index.column() == 1 ) {
285 return QVariant();
286 }
287
288 if ( member.loadingError ) {
289 return KIcon( QLatin1String( "emblem-important" ) );
290 }
291
292 if ( index.row() == ( d->mMembers.count() - 1 ) ) {
293 return KIcon( QLatin1String( "contact-new" ) );
294 }
295
296 if ( member.isReference ) {
297 return KIcon( QLatin1String( "x-office-contact" ), KIconLoader::global(),
298 QStringList() << QLatin1String( "emblem-symbolic-link" ) );
299 } else {
300 return KIcon( QLatin1String( "x-office-contact" ) );
301 }
302 }
303
304 if ( role == Qt::EditRole ) {
305 if ( member.isReference ) {
306 if ( index.column() == 0 ) {
307 return member.referencedContact.realName();
308 } else {
309 if ( !member.reference.preferredEmail().isEmpty() ) {
310 return member.reference.preferredEmail();
311 } else {
312 return member.referencedContact.preferredEmail();
313 }
314 }
315 } else {
316 if ( index.column() == 0 ) {
317 return member.data.name();
318 } else {
319 return member.data.email();
320 }
321 }
322 }
323
324 if ( role == IsReferenceRole ) {
325 return member.isReference;
326 }
327
328 if ( role == AllEmailsRole ) {
329 if ( member.isReference ) {
330 return member.referencedContact.emails();
331 } else {
332 return QStringList();
333 }
334 }
335
336 return QVariant();
337}
338
339bool ContactGroupModel::setData( const QModelIndex &index, const QVariant &value, int role )
340{
341 if ( !index.isValid() ) {
342 return false;
343 }
344
345 if ( index.row() < 0 || index.row() >= d->mMembers.count() ) {
346 return false;
347 }
348
349 if ( index.column() < 0 || index.column() > 1 ) {
350 return false;
351 }
352
353 GroupMember &member = d->mMembers[ index.row() ];
354
355 if ( role == Qt::EditRole ) {
356 if ( member.isReference ) {
357 if ( index.column() == 0 ) {
358 member.reference.setUid( QString::number( value.toLongLong() ) );
359 d->resolveContactReference( member.reference, index.row() );
360 }
361 if ( index.column() == 1 ) {
362 const QString email = value.toString();
363 if ( email != member.referencedContact.preferredEmail() ) {
364 member.reference.setPreferredEmail( email );
365 } else {
366 member.reference.setPreferredEmail( QString() );
367 }
368 }
369 } else {
370 if ( index.column() == 0 ) {
371 member.data.setName( value.toString() );
372 } else {
373 member.data.setEmail( value.toString() );
374 }
375 }
376
377 d->normalizeMemberList();
378
379 return true;
380 }
381
382 if ( role == IsReferenceRole ) {
383 if ( ( value.toBool() == true ) && !member.isReference ) {
384 member.isReference = true;
385 }
386 if ( ( value.toBool() == false ) && member.isReference ) {
387 member.isReference = false;
388 member.data.setName( member.referencedContact.realName() );
389 member.data.setEmail( member.referencedContact.preferredEmail() );
390 }
391
392 return true;
393 }
394
395 return false;
396}
397
398QVariant ContactGroupModel::headerData( int section, Qt::Orientation orientation, int role ) const
399{
400 if ( section < 0 || section > 1 ) {
401 return QVariant();
402 }
403
404 if ( orientation != Qt::Horizontal ) {
405 return QVariant();
406 }
407
408 if ( role != Qt::DisplayRole ) {
409 return QVariant();
410 }
411
412 if ( section == 0 ) {
413 return i18nc( "contact's name", "Name" );
414 } else {
415 return i18nc( "contact's email address", "EMail" );
416 }
417}
418
419Qt::ItemFlags ContactGroupModel::flags( const QModelIndex &index ) const
420{
421 if ( !index.isValid() || index.row() < 0 || index.row() >= d->mMembers.count() ) {
422 return Qt::ItemIsEnabled;
423 }
424
425 if ( d->mMembers[ index.row() ].loadingError ) {
426 return Qt::ItemFlags( Qt::ItemIsEnabled );
427 }
428
429 Qt::ItemFlags parentFlags = QAbstractItemModel::flags( index );
430 return ( parentFlags | Qt::ItemIsEnabled | Qt::ItemIsEditable );
431}
432
433int ContactGroupModel::columnCount( const QModelIndex &parent ) const
434{
435 if ( !parent.isValid() ) {
436 return 2;
437 } else {
438 return 0;
439 }
440}
441
442int ContactGroupModel::rowCount( const QModelIndex &parent ) const
443{
444 if ( !parent.isValid() ) {
445 return d->mMembers.count();
446 } else {
447 return 0;
448 }
449}
450
451bool ContactGroupModel::removeRows( int row, int count, const QModelIndex &parent )
452{
453 if ( parent.isValid() ) {
454 return false;
455 }
456
457 beginRemoveRows( QModelIndex(), row, row + count - 1 );
458 for ( int i = 0; i < count; ++i ) {
459 d->mMembers.remove( row );
460 }
461 endRemoveRows();
462
463 return true;
464}
465
466#include "moc_contactgroupmodel_p.cpp"
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Wed Jan 24 2024 00:00:00 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi/contact

Skip menu "akonadi/contact"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal