00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00107
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 );
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"