• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi/contact

contactgroupmodel.cpp

00001 /*
00002     This file is part of Akonadi Contact.
00003 
00004     Copyright (c) 2009 Tobias Koenig <tokoe@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or modify it
00007     under the terms of the GNU Library General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or (at your
00009     option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful, but WITHOUT
00012     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00014     License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to the
00018     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00019     02110-1301, USA.
00020 */
00021 
00022 #include "contactgroupmodel_p.h"
00023 
00024 #include <akonadi/itemfetchjob.h>
00025 #include <akonadi/itemfetchscope.h>
00026 #include <kabc/addressee.h>
00027 #include <kicon.h>
00028 #include <kiconloader.h>
00029 #include <klocale.h>
00030 
00031 using namespace Akonadi;
00032 
00033 struct GroupMember
00034 {
00035   GroupMember()
00036     : loadingError( false )
00037   {
00038   }
00039 
00040   bool isReference;
00041   KABC::ContactGroup::ContactReference reference;
00042   KABC::ContactGroup::Data data;
00043   KABC::Addressee referencedContact;
00044   bool loadingError;
00045 };
00046 
00047 class ContactGroupModel::Private
00048 {
00049   public:
00050     Private( ContactGroupModel *parent )
00051       : mParent( parent )
00052     {
00053     }
00054 
00055     void resolveContactReference( const KABC::ContactGroup::ContactReference &reference, int row )
00056     {
00057       const Item item( reference.uid().toLongLong() );
00058 
00059       ItemFetchJob *job = new ItemFetchJob( item, mParent );
00060       job->setProperty( "row", row );
00061       job->fetchScope().fetchFullPayload();
00062 
00063       mParent->connect( job, SIGNAL( result( KJob* ) ), SLOT( itemFetched( KJob* ) ) );
00064     }
00065 
00066     void itemFetched( KJob *job )
00067     {
00068       const int row = job->property( "row" ).toInt();
00069 
00070       if ( job->error() ) {
00071         mMembers[ row ].loadingError = true;
00072         emit mParent->dataChanged( mParent->index( row, 0, QModelIndex() ), mParent->index( row, 1, QModelIndex() ) );
00073         return;
00074       }
00075 
00076       ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
00077 
00078       if ( fetchJob->items().count() != 1 ) {
00079         mMembers[ row ].loadingError = true;
00080         emit mParent->dataChanged( mParent->index( row, 0, QModelIndex() ), mParent->index( row, 1, QModelIndex() ) );
00081         return;
00082       }
00083 
00084       const Item item = fetchJob->items().first();
00085       const KABC::Addressee contact = item.payload<KABC::Addressee>();
00086 
00087       GroupMember &member = mMembers[ row ];
00088       member.referencedContact = contact;
00089       emit mParent->dataChanged( mParent->index( row, 0, QModelIndex() ), mParent->index( row, 1, QModelIndex() ) );
00090     }
00091 
00092     void normalizeMemberList()
00093     {
00094       // check whether a normalization is needed or not
00095       bool needsNormalization = false;
00096       if ( mMembers.isEmpty() ) {
00097         needsNormalization = true;
00098       } else {
00099         for ( int i = 0; i < mMembers.count(); ++i ) {
00100           const GroupMember &member = mMembers[ i ];
00101           if ( !member.isReference && !(i == mMembers.count() - 1) ) {
00102             if ( member.data.name().isEmpty() && member.data.email().isEmpty() ) {
00103               needsNormalization = true;
00104               break;
00105             }
00106           }
00107         }
00108 
00109         const GroupMember &member = mMembers.last();
00110         if ( member.isReference || !(member.data.name().isEmpty() && member.data.email().isEmpty()) )
00111           needsNormalization = true;
00112       }
00113 
00114       // if not, avoid to update the model and view
00115       if ( !needsNormalization )
00116         return;
00117 
00118       bool foundEmpty = false;
00119 
00120       // add an empty line at the end
00121       mParent->beginInsertRows( QModelIndex(), mMembers.count(), mMembers.count() );
00122       GroupMember member;
00123       member.isReference = false;
00124       mMembers.append( member );
00125       mParent->endInsertRows();
00126 
00127       // remove all empty lines first except the last line
00128       do {
00129         foundEmpty = false;
00130         for ( int i = 0; i < mMembers.count(); ++i ) {
00131           const GroupMember &member = mMembers[ i ];
00132           if ( !member.isReference && !(i == mMembers.count() - 1) ) {
00133             if ( member.data.name().isEmpty() && member.data.email().isEmpty() ) {
00134               mParent->beginRemoveRows( QModelIndex(), i, i );
00135               mMembers.removeAt( i );
00136               mParent->endRemoveRows();
00137               foundEmpty = true;
00138               break;
00139             }
00140           }
00141         }
00142       } while ( foundEmpty );
00143     }
00144 
00145     ContactGroupModel *mParent;
00146     QList<GroupMember> mMembers;
00147     KABC::ContactGroup mGroup;
00148     QString mLastErrorMessage;
00149 };
00150 
00151 ContactGroupModel::ContactGroupModel( QObject *parent )
00152   : QAbstractItemModel( parent ), d( new Private( this ) )
00153 {
00154 }
00155 
00156 ContactGroupModel::~ContactGroupModel()
00157 {
00158   delete d;
00159 }
00160 
00161 void ContactGroupModel::loadContactGroup( const KABC::ContactGroup &contactGroup )
00162 {
00163   emit layoutAboutToBeChanged();
00164 
00165   d->mMembers.clear();
00166   d->mGroup = contactGroup;
00167 
00168   for ( uint i = 0; i < d->mGroup.dataCount(); ++i ) {
00169     const KABC::ContactGroup::Data data = d->mGroup.data( i );
00170     GroupMember member;
00171     member.isReference = false;
00172     member.data = data;
00173 
00174     d->mMembers.append( member );
00175   }
00176 
00177   for ( uint i = 0; i < d->mGroup.contactReferenceCount(); ++i ) {
00178     const KABC::ContactGroup::ContactReference reference = d->mGroup.contactReference( i );
00179     GroupMember member;
00180     member.isReference = true;
00181     member.reference = reference;
00182 
00183     d->mMembers.append( member );
00184 
00185     d->resolveContactReference( reference, d->mMembers.count() - 1 );
00186   }
00187 
00188   d->normalizeMemberList();
00189 
00190   emit layoutChanged();
00191 }
00192 
00193 bool ContactGroupModel::storeContactGroup( KABC::ContactGroup &group ) const
00194 {
00195   group.removeAllContactReferences();
00196   group.removeAllContactData();
00197 
00198   for ( int i = 0; i < d->mMembers.count(); ++i ) {
00199     const GroupMember &member = d->mMembers[ i ];
00200     if ( member.isReference )
00201       group.append( member.reference );
00202     else {
00203       if ( i != (d->mMembers.count() - 1) ) {
00204         if ( member.data.name().isEmpty() ) {
00205           d->mLastErrorMessage =
00206             i18n( "The member with email address <b>%1</b> is missing a name",
00207                   member.data.email() );
00208           return false;
00209         } else if ( member.data.email().isEmpty() ) {
00210           d->mLastErrorMessage =
00211             i18n( "The member with name <b>%1</b> is missing an email address",
00212                   member.data.name() );
00213           return false;
00214         }
00215         group.append( member.data );
00216       }
00217     }
00218   }
00219 
00220   return true;
00221 }
00222 
00223 QString ContactGroupModel::lastErrorMessage() const
00224 {
00225   return d->mLastErrorMessage;
00226 }
00227 
00228 QModelIndex ContactGroupModel::index( int row, int col, const QModelIndex& ) const
00229 {
00230   return createIndex( row, col, 0 );
00231 }
00232 
00233 QModelIndex ContactGroupModel::parent( const QModelIndex& ) const
00234 {
00235   return QModelIndex();
00236 }
00237 
00238 QVariant ContactGroupModel::data( const QModelIndex &index, int role ) const
00239 {
00240   if ( !index.isValid() )
00241     return QVariant();
00242 
00243   if ( index.row() < 0 || index.row() >= d->mMembers.count() )
00244     return QVariant();
00245 
00246   if ( index.column() < 0 || index.column() > 1 )
00247     return QVariant();
00248 
00249   const GroupMember &member = d->mMembers[ index.row() ];
00250 
00251   if ( role == Qt::DisplayRole ) {
00252     if ( member.loadingError ) {
00253       if ( index.column() == 0 )
00254         return i18n( "Contact does not exist anymore" );
00255       else
00256         return QString();
00257     }
00258 
00259     if ( member.isReference ) {
00260       if ( index.column() == 0 )
00261         return member.referencedContact.realName();
00262       else {
00263         if ( !member.reference.preferredEmail().isEmpty() )
00264           return member.reference.preferredEmail();
00265         else
00266           return member.referencedContact.preferredEmail();
00267       }
00268     } else {
00269       if ( index.column() == 0 )
00270         return member.data.name();
00271       else
00272         return member.data.email();
00273     }
00274   }
00275 
00276   if ( role == Qt::DecorationRole ) {
00277     if ( index.column() == 1 )
00278       return QVariant();
00279 
00280     if ( member.loadingError )
00281       return KIcon( QLatin1String( "emblem-important" ) );
00282 
00283     if ( index.row() == (d->mMembers.count() - 1) )
00284       return KIcon( QLatin1String( "contact-new" ) );
00285 
00286     if ( member.isReference ) {
00287       return KIcon( QLatin1String( "x-office-contact" ), KIconLoader::global(),
00288                     QStringList() << QLatin1String( "emblem-symbolic-link" ) );
00289     } else {
00290       return KIcon( QLatin1String( "x-office-contact" ) );
00291     }
00292   }
00293 
00294   if ( role == Qt::EditRole ) {
00295     if ( member.isReference ) {
00296       if ( index.column() == 0 )
00297         return member.referencedContact.realName();
00298       else {
00299         if ( !member.reference.preferredEmail().isEmpty() )
00300           return member.reference.preferredEmail();
00301         else
00302           return member.referencedContact.preferredEmail();
00303       }
00304     } else {
00305       if ( index.column() == 0 )
00306         return member.data.name();
00307       else
00308         return member.data.email();
00309     }
00310   }
00311 
00312   if ( role == IsReferenceRole )
00313     return member.isReference;
00314 
00315   if ( role == AllEmailsRole ) {
00316     if ( member.isReference )
00317       return member.referencedContact.emails();
00318     else
00319       return QStringList();
00320   }
00321 
00322   return QVariant();
00323 }
00324 
00325 bool ContactGroupModel::setData( const QModelIndex &index, const QVariant &value, int role )
00326 {
00327   if ( !index.isValid() )
00328     return false;
00329 
00330   if ( index.row() < 0 || index.row() >= d->mMembers.count() )
00331     return false;
00332 
00333   if ( index.column() < 0 || index.column() > 1 )
00334     return false;
00335 
00336   GroupMember &member = d->mMembers[ index.row() ];
00337 
00338   if ( role == Qt::EditRole ) {
00339     if ( member.isReference ) {
00340       if ( index.column() == 0 ) {
00341         member.reference.setUid( QString::number( value.toLongLong() ) );
00342         d->resolveContactReference( member.reference, index.row() );
00343       }
00344       if ( index.column() == 1 ) {
00345         const QString email = value.toString();
00346         if ( email != member.referencedContact.preferredEmail() ) {
00347           member.reference.setPreferredEmail( email );
00348         } else {
00349           member.reference.setPreferredEmail( QString() );
00350         }
00351       }
00352     } else {
00353       if ( index.column() == 0 )
00354         member.data.setName( value.toString() );
00355       else
00356         member.data.setEmail( value.toString() );
00357     }
00358 
00359     d->normalizeMemberList();
00360 
00361     return true;
00362   }
00363 
00364   if ( role == IsReferenceRole ) {
00365     if ( (value.toBool() == true) && !member.isReference ) {
00366       member.isReference = true;
00367     }
00368     if ( (value.toBool() == false) && member.isReference ) {
00369       member.isReference = false;
00370       member.data.setName( member.referencedContact.realName() );
00371       member.data.setEmail( member.referencedContact.preferredEmail() );
00372     }
00373 
00374     return true;
00375   }
00376 
00377   return false;
00378 }
00379 
00380 QVariant ContactGroupModel::headerData( int section, Qt::Orientation orientation, int role ) const
00381 {
00382   if ( section < 0 || section > 1 )
00383     return QVariant();
00384 
00385   if ( orientation != Qt::Horizontal )
00386     return QVariant();
00387 
00388   if ( role != Qt::DisplayRole )
00389     return QVariant();
00390 
00391   if ( section == 0 )
00392     return i18nc( "contact's name", "Name" );
00393   else
00394     return i18nc( "contact's email address", "EMail" );
00395 }
00396 
00397 Qt::ItemFlags ContactGroupModel::flags( const QModelIndex &index ) const
00398 {
00399   if ( !index.isValid() || index.row() < 0 || index.row() >= d->mMembers.count() )
00400     return Qt::ItemIsEnabled;
00401 
00402   if ( d->mMembers[ index.row() ].loadingError )
00403     return Qt::ItemFlags( Qt::ItemIsEnabled );
00404 
00405   Qt::ItemFlags parentFlags = QAbstractItemModel::flags( index );
00406   return (parentFlags | Qt::ItemIsEnabled | Qt::ItemIsEditable);
00407 }
00408 
00409 int ContactGroupModel::columnCount( const QModelIndex &parent ) const
00410 {
00411   if ( !parent.isValid() )
00412     return 2;
00413   else
00414     return 0;
00415 }
00416 
00417 int ContactGroupModel::rowCount( const QModelIndex &parent ) const
00418 {
00419   if ( !parent.isValid() )
00420     return d->mMembers.count();
00421   else
00422     return 0;
00423 }
00424 
00425 bool ContactGroupModel::removeRows( int row, int count, const QModelIndex &parent )
00426 {
00427   if ( parent.isValid() )
00428     return false;
00429 
00430   beginRemoveRows( QModelIndex(), row, row + count - 1 );
00431   for ( int i = 0; i < count; ++i )
00432     d->mMembers.removeAt( row );
00433   endRemoveRows();
00434 
00435   return true;
00436 }
00437 
00438 #include "contactgroupmodel_p.moc"

akonadi/contact

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

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.2-20100208
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal