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