• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.9.4 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 <klocale.h>
30 
31 using namespace Akonadi;
32 
33 struct GroupMember
34 {
35  GroupMember()
36  : 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  // if not, avoid to update the model and view
115  if ( !needsNormalization )
116  return;
117 
118  bool foundEmpty = false;
119 
120  // add an empty line at the end
121  mParent->beginInsertRows( QModelIndex(), mMembers.count(), mMembers.count() );
122  GroupMember member;
123  member.isReference = false;
124  mMembers.append( member );
125  mParent->endInsertRows();
126 
127  // remove all empty lines first except the last line
128  do {
129  foundEmpty = false;
130  for ( int i = 0; i < mMembers.count(); ++i ) {
131  const GroupMember &member = mMembers[ i ];
132  if ( !member.isReference && !(i == mMembers.count() - 1) ) {
133  if ( member.data.name().isEmpty() && member.data.email().isEmpty() ) {
134  mParent->beginRemoveRows( QModelIndex(), i, i );
135  mMembers.remove( i );
136  mParent->endRemoveRows();
137  foundEmpty = true;
138  break;
139  }
140  }
141  }
142  } while ( foundEmpty );
143  }
144 
145  ContactGroupModel *mParent;
146  QVector<GroupMember> mMembers;
147  KABC::ContactGroup mGroup;
148  QString mLastErrorMessage;
149 };
150 
151 ContactGroupModel::ContactGroupModel( QObject *parent )
152  : QAbstractItemModel( parent ), d( new Private( this ) )
153 {
154 }
155 
156 ContactGroupModel::~ContactGroupModel()
157 {
158  delete d;
159 }
160 
161 void ContactGroupModel::loadContactGroup( const KABC::ContactGroup &contactGroup )
162 {
163  emit layoutAboutToBeChanged();
164 
165  d->mMembers.clear();
166  d->mGroup = contactGroup;
167 
168  for ( uint i = 0; i < d->mGroup.dataCount(); ++i ) {
169  const KABC::ContactGroup::Data data = d->mGroup.data( i );
170  GroupMember member;
171  member.isReference = false;
172  member.data = data;
173 
174  d->mMembers.append( member );
175  }
176 
177  for ( uint i = 0; i < d->mGroup.contactReferenceCount(); ++i ) {
178  const KABC::ContactGroup::ContactReference reference = d->mGroup.contactReference( i );
179  GroupMember member;
180  member.isReference = true;
181  member.reference = reference;
182 
183  d->mMembers.append( member );
184 
185  d->resolveContactReference( reference, d->mMembers.count() - 1 );
186  }
187 
188  d->normalizeMemberList();
189 
190  emit layoutChanged();
191 }
192 
193 bool ContactGroupModel::storeContactGroup( KABC::ContactGroup &group ) const
194 {
195  group.removeAllContactReferences();
196  group.removeAllContactData();
197 
198  for ( int i = 0; i < d->mMembers.count(); ++i ) {
199  const GroupMember &member = d->mMembers[ i ];
200  if ( member.isReference )
201  group.append( member.reference );
202  else {
203  if ( i != (d->mMembers.count() - 1) ) {
204  if ( member.data.email().isEmpty() ) {
205  d->mLastErrorMessage =
206  i18n( "The member with name <b>%1</b> is missing an email address",
207  member.data.name() );
208  return false;
209  }
210  group.append( member.data );
211  }
212  }
213  }
214 
215  return true;
216 }
217 
218 QString ContactGroupModel::lastErrorMessage() const
219 {
220  return d->mLastErrorMessage;
221 }
222 
223 QModelIndex ContactGroupModel::index( int row, int col, const QModelIndex& ) const
224 {
225  return createIndex( row, col, 0 );
226 }
227 
228 QModelIndex ContactGroupModel::parent( const QModelIndex& ) const
229 {
230  return QModelIndex();
231 }
232 
233 QVariant ContactGroupModel::data( const QModelIndex &index, int role ) const
234 {
235  if ( !index.isValid() )
236  return QVariant();
237 
238  if ( index.row() < 0 || index.row() >= d->mMembers.count() )
239  return QVariant();
240 
241  if ( index.column() < 0 || index.column() > 1 )
242  return QVariant();
243 
244  const GroupMember &member = d->mMembers[ index.row() ];
245 
246  if ( role == Qt::DisplayRole ) {
247  if ( member.loadingError ) {
248  if ( index.column() == 0 )
249  return i18n( "Contact does not exist any more" );
250  else
251  return QString();
252  }
253 
254  if ( member.isReference ) {
255  if ( index.column() == 0 )
256  return member.referencedContact.realName();
257  else {
258  if ( !member.reference.preferredEmail().isEmpty() )
259  return member.reference.preferredEmail();
260  else
261  return member.referencedContact.preferredEmail();
262  }
263  } else {
264  if ( index.column() == 0 )
265  return member.data.name();
266  else
267  return member.data.email();
268  }
269  }
270 
271  if ( role == Qt::DecorationRole ) {
272  if ( index.column() == 1 )
273  return QVariant();
274 
275  if ( member.loadingError )
276  return KIcon( QLatin1String( "emblem-important" ) );
277 
278  if ( index.row() == (d->mMembers.count() - 1) )
279  return KIcon( QLatin1String( "contact-new" ) );
280 
281  if ( member.isReference ) {
282  return KIcon( QLatin1String( "x-office-contact" ), KIconLoader::global(),
283  QStringList() << QLatin1String( "emblem-symbolic-link" ) );
284  } else {
285  return KIcon( QLatin1String( "x-office-contact" ) );
286  }
287  }
288 
289  if ( role == Qt::EditRole ) {
290  if ( member.isReference ) {
291  if ( index.column() == 0 )
292  return member.referencedContact.realName();
293  else {
294  if ( !member.reference.preferredEmail().isEmpty() )
295  return member.reference.preferredEmail();
296  else
297  return member.referencedContact.preferredEmail();
298  }
299  } else {
300  if ( index.column() == 0 )
301  return member.data.name();
302  else
303  return member.data.email();
304  }
305  }
306 
307  if ( role == IsReferenceRole )
308  return member.isReference;
309 
310  if ( role == AllEmailsRole ) {
311  if ( member.isReference )
312  return member.referencedContact.emails();
313  else
314  return QStringList();
315  }
316 
317  return QVariant();
318 }
319 
320 bool ContactGroupModel::setData( const QModelIndex &index, const QVariant &value, int role )
321 {
322  if ( !index.isValid() )
323  return false;
324 
325  if ( index.row() < 0 || index.row() >= d->mMembers.count() )
326  return false;
327 
328  if ( index.column() < 0 || index.column() > 1 )
329  return false;
330 
331  GroupMember &member = d->mMembers[ index.row() ];
332 
333  if ( role == Qt::EditRole ) {
334  if ( member.isReference ) {
335  if ( index.column() == 0 ) {
336  member.reference.setUid( QString::number( value.toLongLong() ) );
337  d->resolveContactReference( member.reference, index.row() );
338  }
339  if ( index.column() == 1 ) {
340  const QString email = value.toString();
341  if ( email != member.referencedContact.preferredEmail() ) {
342  member.reference.setPreferredEmail( email );
343  } else {
344  member.reference.setPreferredEmail( QString() );
345  }
346  }
347  } else {
348  if ( index.column() == 0 )
349  member.data.setName( value.toString() );
350  else
351  member.data.setEmail( value.toString() );
352  }
353 
354  d->normalizeMemberList();
355 
356  return true;
357  }
358 
359  if ( role == IsReferenceRole ) {
360  if ( (value.toBool() == true) && !member.isReference ) {
361  member.isReference = true;
362  }
363  if ( (value.toBool() == false) && member.isReference ) {
364  member.isReference = false;
365  member.data.setName( member.referencedContact.realName() );
366  member.data.setEmail( member.referencedContact.preferredEmail() );
367  }
368 
369  return true;
370  }
371 
372  return false;
373 }
374 
375 QVariant ContactGroupModel::headerData( int section, Qt::Orientation orientation, int role ) const
376 {
377  if ( section < 0 || section > 1 )
378  return QVariant();
379 
380  if ( orientation != Qt::Horizontal )
381  return QVariant();
382 
383  if ( role != Qt::DisplayRole )
384  return QVariant();
385 
386  if ( section == 0 )
387  return i18nc( "contact's name", "Name" );
388  else
389  return i18nc( "contact's email address", "EMail" );
390 }
391 
392 Qt::ItemFlags ContactGroupModel::flags( const QModelIndex &index ) const
393 {
394  if ( !index.isValid() || index.row() < 0 || index.row() >= d->mMembers.count() )
395  return Qt::ItemIsEnabled;
396 
397  if ( d->mMembers[ index.row() ].loadingError )
398  return Qt::ItemFlags( Qt::ItemIsEnabled );
399 
400  Qt::ItemFlags parentFlags = QAbstractItemModel::flags( index );
401  return (parentFlags | Qt::ItemIsEnabled | Qt::ItemIsEditable);
402 }
403 
404 int ContactGroupModel::columnCount( const QModelIndex &parent ) const
405 {
406  if ( !parent.isValid() )
407  return 2;
408  else
409  return 0;
410 }
411 
412 int ContactGroupModel::rowCount( const QModelIndex &parent ) const
413 {
414  if ( !parent.isValid() )
415  return d->mMembers.count();
416  else
417  return 0;
418 }
419 
420 bool ContactGroupModel::removeRows( int row, int count, const QModelIndex &parent )
421 {
422  if ( parent.isValid() )
423  return false;
424 
425  beginRemoveRows( QModelIndex(), row, row + count - 1 );
426  for ( int i = 0; i < count; ++i )
427  d->mMembers.remove( row );
428  endRemoveRows();
429 
430  return true;
431 }
432 
433 #include "contactgroupmodel_p.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue Dec 11 2012 12:14:31 by doxygen 1.8.1.2 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.9.4 API Reference

Skip menu "kdepimlibs-4.9.4 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • 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