00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
00115 if ( !needsNormalization )
00116 return;
00117
00118 bool foundEmpty = false;
00119
00120
00121 mParent->beginInsertRows( QModelIndex(), mMembers.count(), mMembers.count() );
00122 GroupMember member;
00123 member.isReference = false;
00124 mMembers.append( member );
00125 mParent->endInsertRows();
00126
00127
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"