akonadi/contact
contactgroupeditor.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "contactgroupeditor.h"
00023
00024 #include "autoqpointer_p.h"
00025 #include "contactgroupmodel_p.h"
00026 #include "contactgroupeditordelegate_p.h"
00027 #include "ui_contactgroupeditor.h"
00028 #include "waitingoverlay_p.h"
00029
00030 #include <akonadi/collectiondialog.h>
00031 #include <akonadi/collectionfetchjob.h>
00032 #include <akonadi/itemcreatejob.h>
00033 #include <akonadi/itemfetchjob.h>
00034 #include <akonadi/itemfetchscope.h>
00035 #include <akonadi/itemmodifyjob.h>
00036 #include <akonadi/monitor.h>
00037 #include <akonadi/session.h>
00038 #include <kabc/contactgroup.h>
00039 #include <klocale.h>
00040 #include <klineedit.h>
00041 #include <kmessagebox.h>
00042
00043 #include <QtCore/QTimer>
00044 #include <QtGui/QGridLayout>
00045 #include <QtGui/QMessageBox>
00046 #include <QtGui/QTableView>
00047
00048 namespace Akonadi
00049 {
00050
00051 class ContactGroupEditor::Private
00052 {
00053 public:
00054 Private( ContactGroupEditor *parent )
00055 : mParent( parent ), mMonitor( 0 ), mReadOnly( false )
00056 {
00057 }
00058
00059 ~Private()
00060 {
00061 delete mMonitor;
00062 }
00063
00064 void itemFetchDone( KJob* );
00065 void parentCollectionFetchDone( KJob* );
00066 void storeDone( KJob* );
00067 void itemChanged( const Akonadi::Item &item, const QSet<QByteArray>& );
00068 void memberChanged();
00069 void setReadOnly( bool );
00070
00071 void adaptHeaderSizes()
00072 {
00073 mGui.membersView->header()->setDefaultSectionSize( mGui.membersView->header()->width() / 2 );
00074 mGui.membersView->header()->resizeSections( QHeaderView::Interactive );
00075 }
00076
00077 void loadContactGroup( const KABC::ContactGroup &group );
00078 bool storeContactGroup( KABC::ContactGroup &group );
00079 void setupMonitor();
00080
00081 ContactGroupEditor *mParent;
00082 ContactGroupEditor::Mode mMode;
00083 Item mItem;
00084 Monitor *mMonitor;
00085 Collection mDefaultCollection;
00086 Ui::ContactGroupEditor mGui;
00087 bool mReadOnly;
00088 ContactGroupModel *mGroupModel;
00089 };
00090
00091 }
00092
00093 using namespace Akonadi;
00094
00095 void ContactGroupEditor::Private::itemFetchDone( KJob *job )
00096 {
00097 if ( job->error() )
00098 return;
00099
00100 ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob*>( job );
00101 if ( !fetchJob )
00102 return;
00103
00104 if ( fetchJob->items().isEmpty() )
00105 return;
00106
00107 mItem = fetchJob->items().first();
00108
00109 mReadOnly = false;
00110 if ( mMode == ContactGroupEditor::EditMode ) {
00111
00112
00113
00114 Akonadi::CollectionFetchJob *collectionFetchJob = new Akonadi::CollectionFetchJob( mItem.parentCollection(),
00115 Akonadi::CollectionFetchJob::Base );
00116 mParent->connect( collectionFetchJob, SIGNAL( result( KJob* ) ),
00117 SLOT( parentCollectionFetchDone( KJob* ) ) );
00118 } else {
00119 const KABC::ContactGroup group = mItem.payload<KABC::ContactGroup>();
00120 loadContactGroup( group );
00121
00122 setReadOnly( mReadOnly );
00123
00124 QTimer::singleShot( 0, mParent, SLOT( adaptHeaderSizes() ) );
00125 }
00126 }
00127
00128 void ContactGroupEditor::Private::parentCollectionFetchDone( KJob *job )
00129 {
00130 if ( job->error() )
00131 return;
00132
00133 Akonadi::CollectionFetchJob *fetchJob = qobject_cast<Akonadi::CollectionFetchJob*>( job );
00134 if ( !fetchJob )
00135 return;
00136
00137 const Akonadi::Collection parentCollection = fetchJob->collections().first();
00138 if ( parentCollection.isValid() )
00139 mReadOnly = !(parentCollection.rights() & Collection::CanChangeItem);
00140
00141 const KABC::ContactGroup group = mItem.payload<KABC::ContactGroup>();
00142 loadContactGroup( group );
00143
00144 setReadOnly( mReadOnly );
00145
00146 QTimer::singleShot( 0, mParent, SLOT( adaptHeaderSizes() ) );
00147 }
00148
00149 void ContactGroupEditor::Private::storeDone( KJob *job )
00150 {
00151 if ( job->error() ) {
00152 emit mParent->error( job->errorString() );
00153 return;
00154 }
00155
00156 if ( mMode == EditMode )
00157 emit mParent->contactGroupStored( mItem );
00158 else if ( mMode == CreateMode )
00159 emit mParent->contactGroupStored( static_cast<ItemCreateJob*>( job )->item() );
00160 }
00161
00162 void ContactGroupEditor::Private::itemChanged( const Item&, const QSet<QByteArray>& )
00163 {
00164 QMessageBox dlg( mParent );
00165
00166 dlg.setInformativeText( i18n( "The contact group has been changed by someone else.\nWhat should be done?" ) );
00167 dlg.addButton( i18n( "Take over changes" ), QMessageBox::AcceptRole );
00168 dlg.addButton( i18n( "Ignore and Overwrite changes" ), QMessageBox::RejectRole );
00169
00170 if ( dlg.exec() == QMessageBox::AcceptRole ) {
00171 ItemFetchJob *job = new ItemFetchJob( mItem );
00172 job->fetchScope().fetchFullPayload();
00173 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
00174
00175 mParent->connect( job, SIGNAL( result( KJob* ) ), mParent, SLOT( itemFetchDone( KJob* ) ) );
00176 new WaitingOverlay( job, mParent );
00177 }
00178 }
00179
00180 void ContactGroupEditor::Private::loadContactGroup( const KABC::ContactGroup &group )
00181 {
00182 mGui.groupName->setText( group.name() );
00183
00184 mGroupModel->loadContactGroup( group );
00185
00186 const QAbstractItemModel *model = mGui.membersView->model();
00187 mGui.membersView->setCurrentIndex( model->index( model->rowCount() - 1, 0 ) );
00188
00189 if ( mMode == EditMode )
00190 mGui.membersView->setFocus();
00191
00192 mGui.membersView->header()->resizeSections( QHeaderView::Stretch );
00193 }
00194
00195 bool ContactGroupEditor::Private::storeContactGroup( KABC::ContactGroup &group )
00196 {
00197 if ( mGui.groupName->text().isEmpty() ) {
00198 KMessageBox::error( mParent, i18n( "The name of the contact group must not be empty." ) );
00199 return false;
00200 }
00201
00202 group.setName( mGui.groupName->text() );
00203
00204 if ( !mGroupModel->storeContactGroup( group ) ) {
00205 KMessageBox::error( mParent, mGroupModel->lastErrorMessage() );
00206 return false;
00207 }
00208
00209 return true;
00210 }
00211
00212 void ContactGroupEditor::Private::setupMonitor()
00213 {
00214 delete mMonitor;
00215 mMonitor = new Monitor;
00216 mMonitor->ignoreSession( Session::defaultSession() );
00217
00218 connect( mMonitor, SIGNAL( itemChanged( const Akonadi::Item&, const QSet<QByteArray>& ) ),
00219 mParent, SLOT( itemChanged( const Akonadi::Item&, const QSet<QByteArray>& ) ) );
00220 }
00221
00222 void ContactGroupEditor::Private::setReadOnly( bool readOnly )
00223 {
00224 mGui.groupName->setReadOnly( readOnly );
00225 mGui.membersView->setEnabled( !readOnly );
00226 }
00227
00228
00229 ContactGroupEditor::ContactGroupEditor( Mode mode, QWidget *parent )
00230 : QWidget( parent ), d( new Private( this ) )
00231 {
00232 d->mMode = mode;
00233 d->mGui.setupUi( this );
00234
00235 d->mGui.membersView->setEditTriggers( QAbstractItemView::AllEditTriggers );
00236
00237 d->mGroupModel = new ContactGroupModel( this );
00238 d->mGui.membersView->setModel( d->mGroupModel );
00239 d->mGui.membersView->setItemDelegate( new ContactGroupEditorDelegate( d->mGui.membersView, this ) );
00240
00241 if ( mode == CreateMode ) {
00242 KABC::ContactGroup dummyGroup;
00243 d->mGroupModel->loadContactGroup( dummyGroup );
00244 d->mGui.groupName->setFocus();
00245
00246 QTimer::singleShot( 0, this, SLOT( adaptHeaderSizes() ) );
00247 }
00248
00249 d->mGui.membersView->header()->setStretchLastSection( true );
00250 }
00251
00252 ContactGroupEditor::~ContactGroupEditor()
00253 {
00254 delete d;
00255 }
00256
00257 void ContactGroupEditor::loadContactGroup( const Akonadi::Item &item )
00258 {
00259 if ( d->mMode == CreateMode )
00260 Q_ASSERT_X( false, "ContactGroupEditor::loadContactGroup", "You are calling loadContactGroup in CreateMode!" );
00261
00262 ItemFetchJob *job = new ItemFetchJob( item );
00263 job->fetchScope().fetchFullPayload();
00264 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
00265
00266 connect( job, SIGNAL( result( KJob* ) ), SLOT( itemFetchDone( KJob* ) ) );
00267
00268 d->setupMonitor();
00269 d->mMonitor->setItemMonitored( item );
00270
00271 new WaitingOverlay( job, this );
00272 }
00273
00274 bool ContactGroupEditor::saveContactGroup()
00275 {
00276 if ( d->mMode == EditMode ) {
00277 if ( !d->mItem.isValid() )
00278 return false;
00279
00280 if ( d->mReadOnly )
00281 return true;
00282
00283 KABC::ContactGroup group = d->mItem.payload<KABC::ContactGroup>();
00284
00285 if ( !d->storeContactGroup( group ) )
00286 return false;
00287
00288 d->mItem.setPayload<KABC::ContactGroup>( group );
00289
00290 ItemModifyJob *job = new ItemModifyJob( d->mItem );
00291 connect( job, SIGNAL( result( KJob* ) ), SLOT( storeDone( KJob* ) ) );
00292 } else if ( d->mMode == CreateMode ) {
00293 if ( !d->mDefaultCollection.isValid() ) {
00294 const QStringList mimeTypeFilter( KABC::ContactGroup::mimeType() );
00295
00296 AutoQPointer<CollectionDialog> dlg = new CollectionDialog( this );
00297 dlg->setMimeTypeFilter( mimeTypeFilter );
00298 dlg->setAccessRightsFilter( Collection::CanCreateItem );
00299 dlg->setCaption( i18n( "Select Address Book" ) );
00300 dlg->setDescription( i18n( "Select the address book the new contact group shall be saved in:" ) );
00301
00302 if ( dlg->exec() == KDialog::Accepted )
00303 setDefaultAddressBook( dlg->selectedCollection() );
00304 else
00305 return false;
00306 }
00307
00308 KABC::ContactGroup group;
00309 if ( !d->storeContactGroup( group ) )
00310 return false;
00311
00312 Item item;
00313 item.setPayload<KABC::ContactGroup>( group );
00314 item.setMimeType( KABC::ContactGroup::mimeType() );
00315
00316 ItemCreateJob *job = new ItemCreateJob( item, d->mDefaultCollection );
00317 connect( job, SIGNAL( result( KJob* ) ), SLOT( storeDone( KJob* ) ) );
00318 }
00319
00320 return true;
00321 }
00322
00323 void ContactGroupEditor::setContactGroupTemplate( const KABC::ContactGroup &group )
00324 {
00325 d->mGroupModel->loadContactGroup( group );
00326 d->mGui.membersView->header()->setDefaultSectionSize( d->mGui.membersView->header()->width() / 2 );
00327 d->mGui.membersView->header()->resizeSections( QHeaderView::Interactive );
00328 }
00329
00330 void ContactGroupEditor::setDefaultAddressBook( const Akonadi::Collection &collection )
00331 {
00332 d->mDefaultCollection = collection;
00333 }
00334
00335 #include "contactgroupeditor.moc"