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

akonadi

  • 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  const Item item( reference.uid().toLongLong() );
58 
59  ItemFetchJob *job = new ItemFetchJob( item, mParent );
60  job->setProperty( "row", row );
61  job->fetchScope().fetchFullPayload();
62 
63  mParent->connect( job, SIGNAL(result(KJob*)), SLOT(itemFetched(KJob*)) );
64  }
65 
66  void itemFetched( KJob *job )
67  {
68  const int row = job->property( "row" ).toInt();
69 
70  if ( job->error() ) {
71  mMembers[ row ].loadingError = true;
72  emit mParent->dataChanged( mParent->index( row, 0, QModelIndex() ), mParent->index( row, 1, QModelIndex() ) );
73  return;
74  }
75 
76  ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
77 
78  if ( fetchJob->items().count() != 1 ) {
79  mMembers[ row ].loadingError = true;
80  emit mParent->dataChanged( mParent->index( row, 0, QModelIndex() ), mParent->index( row, 1, QModelIndex() ) );
81  return;
82  }
83 
84  const Item item = fetchJob->items().first();
85  const KABC::Addressee contact = item.payload<KABC::Addressee>();
86 
87  GroupMember &member = mMembers[ row ];
88  member.referencedContact = contact;
89  emit mParent->dataChanged( mParent->index( row, 0, QModelIndex() ), mParent->index( row, 1, QModelIndex() ) );
90  }
91 
92  void normalizeMemberList()
93  {
94  // check whether a normalization is needed or not
95  bool needsNormalization = false;
96  if ( mMembers.isEmpty() ) {
97  needsNormalization = true;
98  } else {
99  for ( int i = 0; i < mMembers.count(); ++i ) {
100  const GroupMember &member = mMembers[ i ];
101  if ( !member.isReference && !( i == mMembers.count() - 1 ) ) {
102  if ( member.data.name().isEmpty() && member.data.email().isEmpty() ) {
103  needsNormalization = true;
104  break;
105  }
106  }
107  }
108 
109  const GroupMember &member = mMembers.last();
110  if ( member.isReference || !( member.data.name().isEmpty() && member.data.email().isEmpty() ) ) {
111  needsNormalization = true;
112  }
113  }
114 
115  // if not, avoid to update the model and view
116  if ( !needsNormalization ) {
117  return;
118  }
119 
120  bool foundEmpty = false;
121 
122  // add an empty line at the end
123  mParent->beginInsertRows( QModelIndex(), mMembers.count(), mMembers.count() );
124  GroupMember member;
125  member.isReference = false;
126  mMembers.append( member );
127  mParent->endInsertRows();
128 
129  // remove all empty lines first except the last line
130  do {
131  foundEmpty = false;
132  for ( int i = 0; i < mMembers.count(); ++i ) {
133  const GroupMember &member = mMembers[ i ];
134  if ( !member.isReference && !( i == mMembers.count() - 1 ) ) {
135  if ( member.data.name().isEmpty() && member.data.email().isEmpty() ) {
136  mParent->beginRemoveRows( QModelIndex(), i, i );
137  mMembers.remove( i );
138  mParent->endRemoveRows();
139  foundEmpty = true;
140  break;
141  }
142  }
143  }
144  } while ( foundEmpty );
145  }
146 
147  ContactGroupModel *mParent;
148  QVector<GroupMember> mMembers;
149  KABC::ContactGroup mGroup;
150  QString mLastErrorMessage;
151 };
152 
153 ContactGroupModel::ContactGroupModel( QObject *parent )
154  : QAbstractItemModel( parent ), d( new Private( this ) )
155 {
156 }
157 
158 ContactGroupModel::~ContactGroupModel()
159 {
160  delete d;
161 }
162 
163 void ContactGroupModel::loadContactGroup( const KABC::ContactGroup &contactGroup )
164 {
165  emit layoutAboutToBeChanged();
166 
167  d->mMembers.clear();
168  d->mGroup = contactGroup;
169 
170  for ( uint i = 0; i < d->mGroup.dataCount(); ++i ) {
171  const KABC::ContactGroup::Data data = d->mGroup.data( i );
172  GroupMember member;
173  member.isReference = false;
174  member.data = data;
175 
176  d->mMembers.append( member );
177  }
178 
179  for ( uint i = 0; i < d->mGroup.contactReferenceCount(); ++i ) {
180  const KABC::ContactGroup::ContactReference reference = d->mGroup.contactReference( i );
181  GroupMember member;
182  member.isReference = true;
183  member.reference = reference;
184 
185  d->mMembers.append( member );
186 
187  d->resolveContactReference( reference, d->mMembers.count() - 1 );
188  }
189 
190  d->normalizeMemberList();
191 
192  emit layoutChanged();
193 }
194 
195 bool ContactGroupModel::storeContactGroup( KABC::ContactGroup &group ) const
196 {
197  group.removeAllContactReferences();
198  group.removeAllContactData();
199 
200  for ( int i = 0; i < d->mMembers.count(); ++i ) {
201  const GroupMember &member = d->mMembers[ i ];
202  if ( member.isReference ) {
203  group.append( member.reference );
204  } else {
205  if ( i != ( d->mMembers.count() - 1 ) ) {
206  if ( member.data.email().isEmpty() ) {
207  d->mLastErrorMessage =
208  i18n( "The member with name <b>%1</b> is missing an email address",
209  member.data.name() );
210  return false;
211  }
212  group.append( member.data );
213  }
214  }
215  }
216 
217  return true;
218 }
219 
220 QString ContactGroupModel::lastErrorMessage() const
221 {
222  return d->mLastErrorMessage;
223 }
224 
225 QModelIndex ContactGroupModel::index( int row, int col, const QModelIndex& ) const
226 {
227  return createIndex( row, col);
228 }
229 
230 QModelIndex ContactGroupModel::parent( const QModelIndex& ) const
231 {
232  return QModelIndex();
233 }
234 
235 QVariant ContactGroupModel::data( const QModelIndex &index, int role ) const
236 {
237  if ( !index.isValid() ) {
238  return QVariant();
239  }
240 
241  if ( index.row() < 0 || index.row() >= d->mMembers.count() ) {
242  return QVariant();
243  }
244 
245  if ( index.column() < 0 || index.column() > 1 ) {
246  return QVariant();
247  }
248 
249  const GroupMember &member = d->mMembers[ index.row() ];
250 
251  if ( role == Qt::DisplayRole ) {
252  if ( member.loadingError ) {
253  if ( index.column() == 0 ) {
254  return i18n( "Contact does not exist any more" );
255  } else {
256  return QString();
257  }
258  }
259 
260  if ( member.isReference ) {
261  if ( index.column() == 0 ) {
262  return member.referencedContact.realName();
263  } else {
264  if ( !member.reference.preferredEmail().isEmpty() ) {
265  return member.reference.preferredEmail();
266  } else {
267  return member.referencedContact.preferredEmail();
268  }
269  }
270  } else {
271  if ( index.column() == 0 ) {
272  return member.data.name();
273  } else {
274  return member.data.email();
275  }
276  }
277  }
278 
279  if ( role == Qt::DecorationRole ) {
280  if ( index.column() == 1 ) {
281  return QVariant();
282  }
283 
284  if ( member.loadingError ) {
285  return KIcon( QLatin1String( "emblem-important" ) );
286  }
287 
288  if ( index.row() == ( d->mMembers.count() - 1 ) ) {
289  return KIcon( QLatin1String( "contact-new" ) );
290  }
291 
292  if ( member.isReference ) {
293  return KIcon( QLatin1String( "x-office-contact" ), KIconLoader::global(),
294  QStringList() << QLatin1String( "emblem-symbolic-link" ) );
295  } else {
296  return KIcon( QLatin1String( "x-office-contact" ) );
297  }
298  }
299 
300  if ( role == Qt::EditRole ) {
301  if ( member.isReference ) {
302  if ( index.column() == 0 ) {
303  return member.referencedContact.realName();
304  } else {
305  if ( !member.reference.preferredEmail().isEmpty() ) {
306  return member.reference.preferredEmail();
307  } else {
308  return member.referencedContact.preferredEmail();
309  }
310  }
311  } else {
312  if ( index.column() == 0 ) {
313  return member.data.name();
314  } else {
315  return member.data.email();
316  }
317  }
318  }
319 
320  if ( role == IsReferenceRole ) {
321  return member.isReference;
322  }
323 
324  if ( role == AllEmailsRole ) {
325  if ( member.isReference ) {
326  return member.referencedContact.emails();
327  } else {
328  return QStringList();
329  }
330  }
331 
332  return QVariant();
333 }
334 
335 bool ContactGroupModel::setData( const QModelIndex &index, const QVariant &value, int role )
336 {
337  if ( !index.isValid() ) {
338  return false;
339  }
340 
341  if ( index.row() < 0 || index.row() >= d->mMembers.count() ) {
342  return false;
343  }
344 
345  if ( index.column() < 0 || index.column() > 1 ) {
346  return false;
347  }
348 
349  GroupMember &member = d->mMembers[ index.row() ];
350 
351  if ( role == Qt::EditRole ) {
352  if ( member.isReference ) {
353  if ( index.column() == 0 ) {
354  member.reference.setUid( QString::number( value.toLongLong() ) );
355  d->resolveContactReference( member.reference, index.row() );
356  }
357  if ( index.column() == 1 ) {
358  const QString email = value.toString();
359  if ( email != member.referencedContact.preferredEmail() ) {
360  member.reference.setPreferredEmail( email );
361  } else {
362  member.reference.setPreferredEmail( QString() );
363  }
364  }
365  } else {
366  if ( index.column() == 0 ) {
367  member.data.setName( value.toString() );
368  } else {
369  member.data.setEmail( value.toString() );
370  }
371  }
372 
373  d->normalizeMemberList();
374 
375  return true;
376  }
377 
378  if ( role == IsReferenceRole ) {
379  if ( ( value.toBool() == true ) && !member.isReference ) {
380  member.isReference = true;
381  }
382  if ( ( value.toBool() == false ) && member.isReference ) {
383  member.isReference = false;
384  member.data.setName( member.referencedContact.realName() );
385  member.data.setEmail( member.referencedContact.preferredEmail() );
386  }
387 
388  return true;
389  }
390 
391  return false;
392 }
393 
394 QVariant ContactGroupModel::headerData( int section, Qt::Orientation orientation, int role ) const
395 {
396  if ( section < 0 || section > 1 ) {
397  return QVariant();
398  }
399 
400  if ( orientation != Qt::Horizontal ) {
401  return QVariant();
402  }
403 
404  if ( role != Qt::DisplayRole ) {
405  return QVariant();
406  }
407 
408  if ( section == 0 ) {
409  return i18nc( "contact's name", "Name" );
410  } else {
411  return i18nc( "contact's email address", "EMail" );
412  }
413 }
414 
415 Qt::ItemFlags ContactGroupModel::flags( const QModelIndex &index ) const
416 {
417  if ( !index.isValid() || index.row() < 0 || index.row() >= d->mMembers.count() ) {
418  return Qt::ItemIsEnabled;
419  }
420 
421  if ( d->mMembers[ index.row() ].loadingError ) {
422  return Qt::ItemFlags( Qt::ItemIsEnabled );
423  }
424 
425  Qt::ItemFlags parentFlags = QAbstractItemModel::flags( index );
426  return ( parentFlags | Qt::ItemIsEnabled | Qt::ItemIsEditable );
427 }
428 
429 int ContactGroupModel::columnCount( const QModelIndex &parent ) const
430 {
431  if ( !parent.isValid() ) {
432  return 2;
433  } else {
434  return 0;
435  }
436 }
437 
438 int ContactGroupModel::rowCount( const QModelIndex &parent ) const
439 {
440  if ( !parent.isValid() ) {
441  return d->mMembers.count();
442  } else {
443  return 0;
444  }
445 }
446 
447 bool ContactGroupModel::removeRows( int row, int count, const QModelIndex &parent )
448 {
449  if ( parent.isValid() ) {
450  return false;
451  }
452 
453  beginRemoveRows( QModelIndex(), row, row + count - 1 );
454  for ( int i = 0; i < count; ++i ) {
455  d->mMembers.remove( row );
456  }
457  endRemoveRows();
458 
459  return true;
460 }
461 
462 #include "moc_contactgroupmodel_p.cpp"
Akonadi::ItemFetchJob::items
Item::List items() const
Returns the fetched item.
Definition: itemfetchjob.cpp:227
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-2013 The KDE developers.
Generated on Tue Nov 26 2013 09:03:16 by doxygen 1.8.5 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-4.11.3 API Reference

Skip menu "kdepimlibs-4.11.3 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