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

akonadi

  • sources
  • kde-4.12
  • kdepimlibs
  • 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 
31 using namespace Akonadi;
32 
33 struct GroupMember
34 {
35  GroupMember()
36  : isReference(false), loadingError( false )
37  {
38  }
39 
40  bool isReference;
41  KABC::ContactGroup::ContactReference reference;
42  KABC::ContactGroup::Data data;
43  KABC::Addressee referencedContact;
44  bool loadingError;
45 };
46 
47 class 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 
157 ContactGroupModel::ContactGroupModel( QObject *parent )
158  : QAbstractItemModel( parent ), d( new Private( this ) )
159 {
160 }
161 
162 ContactGroupModel::~ContactGroupModel()
163 {
164  delete d;
165 }
166 
167 void 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 
199 bool 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 
224 QString ContactGroupModel::lastErrorMessage() const
225 {
226  return d->mLastErrorMessage;
227 }
228 
229 QModelIndex ContactGroupModel::index( int row, int col, const QModelIndex& ) const
230 {
231  return createIndex( row, col);
232 }
233 
234 QModelIndex ContactGroupModel::parent( const QModelIndex& ) const
235 {
236  return QModelIndex();
237 }
238 
239 QVariant 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 
339 bool 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 
398 QVariant 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 
419 Qt::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 
433 int ContactGroupModel::columnCount( const QModelIndex &parent ) const
434 {
435  if ( !parent.isValid() ) {
436  return 2;
437  } else {
438  return 0;
439  }
440 }
441 
442 int ContactGroupModel::rowCount( const QModelIndex &parent ) const
443 {
444  if ( !parent.isValid() ) {
445  return d->mMembers.count();
446  } else {
447  return 0;
448  }
449 }
450 
451 bool 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"
Akonadi::ItemFetchScope::fetchFullPayload
void fetchFullPayload(bool fetch=true)
Sets whether the full payload shall be fetched.
Definition: itemfetchscope.cpp:68
Akonadi::ItemFetchJob::items
Item::List items() const
Returns the fetched items.
Definition: itemfetchjob.cpp:228
Akonadi::ItemFetchJob::fetchScope
ItemFetchScope & fetchScope()
Returns the item fetch scope.
Definition: itemfetchjob.cpp:256
Akonadi::ItemFetchJob
Job that fetches items from the Akonadi storage.
Definition: itemfetchjob.h:82
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:00:27 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

Search



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