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.remove( i );
00136 mParent->endRemoveRows();
00137 foundEmpty = true;
00138 break;
00139 }
00140 }
00141 }
00142 } while ( foundEmpty );
00143 }
00144
00145 ContactGroupModel *mParent;
00146 QVector<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.email().isEmpty() ) {
00205 d->mLastErrorMessage =
00206 i18n( "The member with name <b>%1</b> is missing an email address",
00207 member.data.name() );
00208 return false;
00209 }
00210 group.append( member.data );
00211 }
00212 }
00213 }
00214
00215 return true;
00216 }
00217
00218 QString ContactGroupModel::lastErrorMessage() const
00219 {
00220 return d->mLastErrorMessage;
00221 }
00222
00223 QModelIndex ContactGroupModel::index( int row, int col, const QModelIndex& ) const
00224 {
00225 return createIndex( row, col, 0 );
00226 }
00227
00228 QModelIndex ContactGroupModel::parent( const QModelIndex& ) const
00229 {
00230 return QModelIndex();
00231 }
00232
00233 QVariant ContactGroupModel::data( const QModelIndex &index, int role ) const
00234 {
00235 if ( !index.isValid() )
00236 return QVariant();
00237
00238 if ( index.row() < 0 || index.row() >= d->mMembers.count() )
00239 return QVariant();
00240
00241 if ( index.column() < 0 || index.column() > 1 )
00242 return QVariant();
00243
00244 const GroupMember &member = d->mMembers[ index.row() ];
00245
00246 if ( role == Qt::DisplayRole ) {
00247 if ( member.loadingError ) {
00248 if ( index.column() == 0 )
00249 return i18n( "Contact does not exist any more" );
00250 else
00251 return QString();
00252 }
00253
00254 if ( member.isReference ) {
00255 if ( index.column() == 0 )
00256 return member.referencedContact.realName();
00257 else {
00258 if ( !member.reference.preferredEmail().isEmpty() )
00259 return member.reference.preferredEmail();
00260 else
00261 return member.referencedContact.preferredEmail();
00262 }
00263 } else {
00264 if ( index.column() == 0 )
00265 return member.data.name();
00266 else
00267 return member.data.email();
00268 }
00269 }
00270
00271 if ( role == Qt::DecorationRole ) {
00272 if ( index.column() == 1 )
00273 return QVariant();
00274
00275 if ( member.loadingError )
00276 return KIcon( QLatin1String( "emblem-important" ) );
00277
00278 if ( index.row() == (d->mMembers.count() - 1) )
00279 return KIcon( QLatin1String( "contact-new" ) );
00280
00281 if ( member.isReference ) {
00282 return KIcon( QLatin1String( "x-office-contact" ), KIconLoader::global(),
00283 QStringList() << QLatin1String( "emblem-symbolic-link" ) );
00284 } else {
00285 return KIcon( QLatin1String( "x-office-contact" ) );
00286 }
00287 }
00288
00289 if ( role == Qt::EditRole ) {
00290 if ( member.isReference ) {
00291 if ( index.column() == 0 )
00292 return member.referencedContact.realName();
00293 else {
00294 if ( !member.reference.preferredEmail().isEmpty() )
00295 return member.reference.preferredEmail();
00296 else
00297 return member.referencedContact.preferredEmail();
00298 }
00299 } else {
00300 if ( index.column() == 0 )
00301 return member.data.name();
00302 else
00303 return member.data.email();
00304 }
00305 }
00306
00307 if ( role == IsReferenceRole )
00308 return member.isReference;
00309
00310 if ( role == AllEmailsRole ) {
00311 if ( member.isReference )
00312 return member.referencedContact.emails();
00313 else
00314 return QStringList();
00315 }
00316
00317 return QVariant();
00318 }
00319
00320 bool ContactGroupModel::setData( const QModelIndex &index, const QVariant &value, int role )
00321 {
00322 if ( !index.isValid() )
00323 return false;
00324
00325 if ( index.row() < 0 || index.row() >= d->mMembers.count() )
00326 return false;
00327
00328 if ( index.column() < 0 || index.column() > 1 )
00329 return false;
00330
00331 GroupMember &member = d->mMembers[ index.row() ];
00332
00333 if ( role == Qt::EditRole ) {
00334 if ( member.isReference ) {
00335 if ( index.column() == 0 ) {
00336 member.reference.setUid( QString::number( value.toLongLong() ) );
00337 d->resolveContactReference( member.reference, index.row() );
00338 }
00339 if ( index.column() == 1 ) {
00340 const QString email = value.toString();
00341 if ( email != member.referencedContact.preferredEmail() ) {
00342 member.reference.setPreferredEmail( email );
00343 } else {
00344 member.reference.setPreferredEmail( QString() );
00345 }
00346 }
00347 } else {
00348 if ( index.column() == 0 )
00349 member.data.setName( value.toString() );
00350 else
00351 member.data.setEmail( value.toString() );
00352 }
00353
00354 d->normalizeMemberList();
00355
00356 return true;
00357 }
00358
00359 if ( role == IsReferenceRole ) {
00360 if ( (value.toBool() == true) && !member.isReference ) {
00361 member.isReference = true;
00362 }
00363 if ( (value.toBool() == false) && member.isReference ) {
00364 member.isReference = false;
00365 member.data.setName( member.referencedContact.realName() );
00366 member.data.setEmail( member.referencedContact.preferredEmail() );
00367 }
00368
00369 return true;
00370 }
00371
00372 return false;
00373 }
00374
00375 QVariant ContactGroupModel::headerData( int section, Qt::Orientation orientation, int role ) const
00376 {
00377 if ( section < 0 || section > 1 )
00378 return QVariant();
00379
00380 if ( orientation != Qt::Horizontal )
00381 return QVariant();
00382
00383 if ( role != Qt::DisplayRole )
00384 return QVariant();
00385
00386 if ( section == 0 )
00387 return i18nc( "contact's name", "Name" );
00388 else
00389 return i18nc( "contact's email address", "EMail" );
00390 }
00391
00392 Qt::ItemFlags ContactGroupModel::flags( const QModelIndex &index ) const
00393 {
00394 if ( !index.isValid() || index.row() < 0 || index.row() >= d->mMembers.count() )
00395 return Qt::ItemIsEnabled;
00396
00397 if ( d->mMembers[ index.row() ].loadingError )
00398 return Qt::ItemFlags( Qt::ItemIsEnabled );
00399
00400 Qt::ItemFlags parentFlags = QAbstractItemModel::flags( index );
00401 return (parentFlags | Qt::ItemIsEnabled | Qt::ItemIsEditable);
00402 }
00403
00404 int ContactGroupModel::columnCount( const QModelIndex &parent ) const
00405 {
00406 if ( !parent.isValid() )
00407 return 2;
00408 else
00409 return 0;
00410 }
00411
00412 int ContactGroupModel::rowCount( const QModelIndex &parent ) const
00413 {
00414 if ( !parent.isValid() )
00415 return d->mMembers.count();
00416 else
00417 return 0;
00418 }
00419
00420 bool ContactGroupModel::removeRows( int row, int count, const QModelIndex &parent )
00421 {
00422 if ( parent.isValid() )
00423 return false;
00424
00425 beginRemoveRows( QModelIndex(), row, row + count - 1 );
00426 for ( int i = 0; i < count; ++i )
00427 d->mMembers.remove( row );
00428 endRemoveRows();
00429
00430 return true;
00431 }
00432
00433 #include "contactgroupmodel_p.moc"