akonadi
contacteditor.cpp
00001 /* 00002 This file is part of Akonadi Contact. 00003 00004 Copyright (c) 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 "contacteditor.h" 00023 00024 #include "abstractcontacteditorwidget_p.h" 00025 #include "autoqpointer_p.h" 00026 #include "contactmetadata_p.h" 00027 #include "contactmetadataattribute_p.h" 00028 #include "editor/contacteditorwidget.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/addressee.h> 00039 #include <klocale.h> 00040 00041 #include <QtCore/QPointer> 00042 #include <QtGui/QVBoxLayout> 00043 #include <QtGui/QMessageBox> 00044 00045 using namespace Akonadi; 00046 00047 class ContactEditor::Private 00048 { 00049 public: 00050 Private( ContactEditor::Mode mode, AbstractContactEditorWidget *editorWidget, ContactEditor *parent ) 00051 : mParent( parent ), mMode( mode ), mMonitor( 0 ), mReadOnly( false ) 00052 { 00053 if ( editorWidget ) 00054 mEditorWidget = editorWidget; 00055 #ifndef DISABLE_EDITOR_WIDGETS 00056 else 00057 mEditorWidget = new ContactEditorWidget(); 00058 #endif 00059 00060 QVBoxLayout *layout = new QVBoxLayout( mParent ); 00061 layout->setMargin( 0 ); 00062 layout->setSpacing( 0 ); 00063 layout->addWidget( mEditorWidget ); 00064 } 00065 00066 ~Private() 00067 { 00068 delete mMonitor; 00069 } 00070 00071 void itemFetchDone( KJob* ); 00072 void parentCollectionFetchDone( KJob* ); 00073 void storeDone( KJob* ); 00074 void itemChanged( const Akonadi::Item &item, const QSet<QByteArray>& ); 00075 00076 void loadContact( const KABC::Addressee &addr, const ContactMetaData &metaData ); 00077 void storeContact( KABC::Addressee &addr, ContactMetaData &metaData ); 00078 void setupMonitor(); 00079 00080 ContactEditor *mParent; 00081 ContactEditor::Mode mMode; 00082 Akonadi::Item mItem; 00083 Akonadi::ContactMetaData mContactMetaData; 00084 Akonadi::Monitor *mMonitor; 00085 Akonadi::Collection mDefaultCollection; 00086 AbstractContactEditorWidget *mEditorWidget; 00087 bool mReadOnly; 00088 }; 00089 00090 void ContactEditor::Private::itemFetchDone( KJob *job ) 00091 { 00092 if ( job->error() != KJob::NoError ) 00093 return; 00094 00095 Akonadi::ItemFetchJob *fetchJob = qobject_cast<Akonadi::ItemFetchJob*>( job ); 00096 if ( !fetchJob ) 00097 return; 00098 00099 if ( fetchJob->items().isEmpty() ) 00100 return; 00101 00102 mItem = fetchJob->items().first(); 00103 00104 mReadOnly = false; 00105 if ( mMode == ContactEditor::EditMode ) { 00106 // if in edit mode we have to fetch the parent collection to find out 00107 // about the modify rights of the item 00108 00109 Akonadi::CollectionFetchJob *collectionFetchJob = new Akonadi::CollectionFetchJob( mItem.parentCollection(), 00110 Akonadi::CollectionFetchJob::Base ); 00111 mParent->connect( collectionFetchJob, SIGNAL( result( KJob* ) ), 00112 SLOT( parentCollectionFetchDone( KJob* ) ) ); 00113 } else { 00114 const KABC::Addressee addr = mItem.payload<KABC::Addressee>(); 00115 mContactMetaData.load( mItem ); 00116 loadContact( addr, mContactMetaData ); 00117 mEditorWidget->setReadOnly( mReadOnly ); 00118 } 00119 } 00120 00121 void ContactEditor::Private::parentCollectionFetchDone( KJob *job ) 00122 { 00123 if ( job->error() ) 00124 return; 00125 00126 Akonadi::CollectionFetchJob *fetchJob = qobject_cast<Akonadi::CollectionFetchJob*>( job ); 00127 if ( !fetchJob ) 00128 return; 00129 00130 const Akonadi::Collection parentCollection = fetchJob->collections().first(); 00131 if ( parentCollection.isValid() ) 00132 mReadOnly = !(parentCollection.rights() & Collection::CanChangeItem); 00133 00134 mEditorWidget->setReadOnly( mReadOnly ); 00135 00136 const KABC::Addressee addr = mItem.payload<KABC::Addressee>(); 00137 mContactMetaData.load( mItem ); 00138 loadContact( addr, mContactMetaData ); 00139 } 00140 00141 void ContactEditor::Private::storeDone( KJob *job ) 00142 { 00143 if ( job->error() != KJob::NoError ) { 00144 emit mParent->error( job->errorString() ); 00145 return; 00146 } 00147 00148 if ( mMode == EditMode ) 00149 emit mParent->contactStored( mItem ); 00150 else if ( mMode == CreateMode ) 00151 emit mParent->contactStored( static_cast<Akonadi::ItemCreateJob*>( job )->item() ); 00152 } 00153 00154 void ContactEditor::Private::itemChanged( const Akonadi::Item&, const QSet<QByteArray>& ) 00155 { 00156 QPointer<QMessageBox> dlg = new QMessageBox( mParent ); //krazy:exclude=qclasses 00157 00158 dlg->setInformativeText( i18n( "The contact has been changed by someone else.\nWhat should be done?" ) ); 00159 dlg->addButton( i18n( "Take over changes" ), QMessageBox::AcceptRole ); 00160 dlg->addButton( i18n( "Ignore and Overwrite changes" ), QMessageBox::RejectRole ); 00161 00162 if ( dlg->exec() == QMessageBox::AcceptRole ) { 00163 Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( mItem ); 00164 job->fetchScope().fetchFullPayload(); 00165 job->fetchScope().fetchAttribute<ContactMetaDataAttribute>(); 00166 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent ); 00167 00168 mParent->connect( job, SIGNAL( result( KJob* ) ), mParent, SLOT( itemFetchDone( KJob* ) ) ); 00169 } 00170 00171 delete dlg; 00172 } 00173 00174 void ContactEditor::Private::loadContact( const KABC::Addressee &addr, const ContactMetaData &metaData ) 00175 { 00176 mEditorWidget->loadContact( addr, metaData ); 00177 } 00178 00179 void ContactEditor::Private::storeContact( KABC::Addressee &addr, ContactMetaData &metaData ) 00180 { 00181 mEditorWidget->storeContact( addr, metaData ); 00182 } 00183 00184 void ContactEditor::Private::setupMonitor() 00185 { 00186 delete mMonitor; 00187 mMonitor = new Akonadi::Monitor; 00188 mMonitor->ignoreSession( Akonadi::Session::defaultSession() ); 00189 00190 connect( mMonitor, SIGNAL( itemChanged( const Akonadi::Item&, const QSet<QByteArray>& ) ), 00191 mParent, SLOT( itemChanged( const Akonadi::Item&, const QSet<QByteArray>& ) ) ); 00192 } 00193 00194 00195 ContactEditor::ContactEditor( Mode mode, QWidget *parent ) 00196 : QWidget( parent ), d( new Private( mode, 0, this ) ) 00197 { 00198 } 00199 00200 ContactEditor::ContactEditor( Mode mode, AbstractContactEditorWidget *editorWidget, QWidget *parent ) 00201 : QWidget( parent ), d( new Private( mode, editorWidget, this ) ) 00202 { 00203 } 00204 00205 ContactEditor::~ContactEditor() 00206 { 00207 delete d; 00208 } 00209 00210 void ContactEditor::loadContact( const Akonadi::Item &item ) 00211 { 00212 if ( d->mMode == CreateMode ) 00213 Q_ASSERT_X( false, "ContactEditor::loadContact", "You are calling loadContact in CreateMode!" ); 00214 00215 Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( item ); 00216 job->fetchScope().fetchFullPayload(); 00217 job->fetchScope().fetchAttribute<ContactMetaDataAttribute>(); 00218 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent ); 00219 00220 connect( job, SIGNAL( result( KJob* ) ), SLOT( itemFetchDone( KJob* ) ) ); 00221 00222 d->setupMonitor(); 00223 d->mMonitor->setItemMonitored( item ); 00224 } 00225 00226 bool ContactEditor::saveContact() 00227 { 00228 if ( d->mMode == EditMode ) { 00229 if ( !d->mItem.isValid() ) 00230 return true; 00231 00232 if ( d->mReadOnly ) 00233 return true; 00234 00235 KABC::Addressee addr = d->mItem.payload<KABC::Addressee>(); 00236 00237 d->storeContact( addr, d->mContactMetaData ); 00238 00239 d->mContactMetaData.store( d->mItem ); 00240 00241 d->mItem.setPayload<KABC::Addressee>( addr ); 00242 00243 Akonadi::ItemModifyJob *job = new Akonadi::ItemModifyJob( d->mItem ); 00244 connect( job, SIGNAL( result( KJob* ) ), SLOT( storeDone( KJob* ) ) ); 00245 } else if ( d->mMode == CreateMode ) { 00246 if ( !d->mDefaultCollection.isValid() ) { 00247 const QStringList mimeTypeFilter( KABC::Addressee::mimeType() ); 00248 00249 AutoQPointer<CollectionDialog> dlg = new CollectionDialog( this ); 00250 dlg->setMimeTypeFilter( mimeTypeFilter ); 00251 dlg->setAccessRightsFilter( Collection::CanCreateItem ); 00252 dlg->setCaption( i18n( "Select Address Book" ) ); 00253 dlg->setDescription( i18n( "Select the address book the new contact shall be saved in:" ) ); 00254 if ( dlg->exec() == KDialog::Accepted ) 00255 setDefaultAddressBook( dlg->selectedCollection() ); 00256 else 00257 return false; 00258 } 00259 00260 KABC::Addressee addr; 00261 d->storeContact( addr, d->mContactMetaData ); 00262 00263 Akonadi::Item item; 00264 item.setPayload<KABC::Addressee>( addr ); 00265 item.setMimeType( KABC::Addressee::mimeType() ); 00266 00267 d->mContactMetaData.store( item ); 00268 00269 Akonadi::ItemCreateJob *job = new Akonadi::ItemCreateJob( item, d->mDefaultCollection ); 00270 connect( job, SIGNAL( result( KJob* ) ), SLOT( storeDone( KJob* ) ) ); 00271 } 00272 00273 return true; 00274 } 00275 00276 void ContactEditor::setContactTemplate( const KABC::Addressee &contact ) 00277 { 00278 d->loadContact( contact, d->mContactMetaData ); 00279 } 00280 00281 void ContactEditor::setDefaultAddressBook( const Akonadi::Collection &collection ) 00282 { 00283 d->mDefaultCollection = collection; 00284 } 00285 00286 #include "contacteditor.moc"