akonadi
contactgroupeditor.cpp
00001 /* 00002 This file is part of Akonadi Contact. 00003 00004 Copyright (c) 2007-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 "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 // if in edit mode we have to fetch the parent collection to find out 00083 // about the modify rights of the item 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 ); //krazy:exclude=qclasses 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"