akonadi
customfieldseditwidget.cpp
00001 /* 00002 This file is part of Akonadi Contact. 00003 00004 Copyright (c) 2010 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 "customfieldseditwidget.h" 00023 00024 #include "customfieldeditordialog.h" 00025 #include "customfieldmanager_p.h" 00026 #include "customfieldsdelegate.h" 00027 #include "customfieldsmodel.h" 00028 00029 #include <kabc/addressee.h> 00030 #include <klocale.h> 00031 #include <kmessagebox.h> 00032 00033 #include <QtCore/QPointer> 00034 #include <QtCore/QUuid> 00035 #include <QtGui/QGridLayout> 00036 #include <QtGui/QPushButton> 00037 #include <QtGui/QTreeView> 00038 00039 void splitCustomField( const QString &str, QString &app, QString &name, QString &value ) 00040 { 00041 const int colon = str.indexOf( QLatin1Char( ':' ) ); 00042 if ( colon != -1 ) { 00043 const QString tmp = str.left( colon ); 00044 value = str.mid( colon + 1 ); 00045 00046 const int dash = tmp.indexOf( QLatin1Char( '-' ) ); 00047 if ( dash != -1 ) { 00048 app = tmp.left( dash ); 00049 name = tmp.mid( dash + 1 ); 00050 } 00051 } 00052 } 00053 00054 CustomFieldsEditWidget::CustomFieldsEditWidget( QWidget *parent ) 00055 : QWidget( parent ), mReadOnly( false ) 00056 { 00057 QGridLayout *layout = new QGridLayout( this ); 00058 layout->setMargin( 0 ); 00059 00060 mView = new QTreeView; 00061 mView->setRootIsDecorated( false ); 00062 mView->setItemDelegate( new CustomFieldsDelegate( this ) ); 00063 00064 mAddButton = new QPushButton( i18n( "Add..." ) ); 00065 mEditButton = new QPushButton( i18n( "Edit..." ) ); 00066 mRemoveButton = new QPushButton( i18n( "Remove" ) ); 00067 00068 layout->addWidget( mView, 0, 0, 4, 1 ); 00069 layout->addWidget( mAddButton, 0, 1 ); 00070 layout->addWidget( mEditButton, 1, 1 ); 00071 layout->addWidget( mRemoveButton, 2, 1 ); 00072 00073 mModel = new CustomFieldsModel( this ); 00074 mView->setModel( mModel ); 00075 mView->setColumnHidden( 2, true ); // hide the 'key' column 00076 00077 connect( mView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), 00078 this, SLOT(slotUpdateButtons()) ); 00079 connect( mAddButton, SIGNAL(clicked()), this, SLOT(slotAdd()) ); 00080 connect( mEditButton, SIGNAL(clicked()), this, SLOT(slotEdit()) ); 00081 connect( mRemoveButton, SIGNAL(clicked()), this, SLOT(slotRemove()) ); 00082 } 00083 00084 CustomFieldsEditWidget::~CustomFieldsEditWidget() 00085 { 00086 } 00087 00088 void CustomFieldsEditWidget::loadContact( const KABC::Addressee &contact ) 00089 { 00090 CustomField::List externalCustomFields; 00091 00092 CustomField::List globalCustomFields = CustomFieldManager::globalCustomFieldDescriptions(); 00093 00094 const QStringList customs = contact.customs(); 00095 foreach ( const QString &custom, customs ) { 00096 00097 QString app, name, value; 00098 splitCustomField( custom, app, name, value ); 00099 00100 // skip all well-known fields that have separated editor widgets 00101 if ( custom.startsWith( QLatin1String( "messaging/" ) ) ) // IM addresses 00102 continue; 00103 00104 if ( app == QLatin1String( "KADDRESSBOOK" ) ) { 00105 static QSet<QString> blacklist; 00106 if ( blacklist.isEmpty() ) { 00107 blacklist << QLatin1String( "BlogFeed" ) 00108 << QLatin1String( "X-IMAddress" ) 00109 << QLatin1String( "X-Profession" ) 00110 << QLatin1String( "X-Office" ) 00111 << QLatin1String( "X-ManagersName" ) 00112 << QLatin1String( "X-AssistantsName" ) 00113 << QLatin1String( "X-Anniversary" ) 00114 << QLatin1String( "X-SpousesName" ) 00115 << QLatin1String( "X-Profession" ); 00116 } 00117 00118 if ( blacklist.contains( name ) ) // several KAddressBook specific fields 00119 continue; 00120 } 00121 00122 // check whether it correspond to a local custom field 00123 bool isLocalCustomField = false; 00124 for ( int i = 0; i < mLocalCustomFields.count(); ++i ) { 00125 if ( mLocalCustomFields[ i ].key() == name ) { 00126 mLocalCustomFields[ i ].setValue( value ); 00127 isLocalCustomField = true; 00128 break; 00129 } 00130 } 00131 00132 // check whether it correspond to a global custom field 00133 bool isGlobalCustomField = false; 00134 for ( int i = 0; i < globalCustomFields.count(); ++i ) { 00135 if ( globalCustomFields[ i ].key() == name ) { 00136 globalCustomFields[ i ].setValue( value ); 00137 isGlobalCustomField = true; 00138 break; 00139 } 00140 } 00141 00142 // if not local and not global it must be external 00143 if ( !isLocalCustomField && !isGlobalCustomField ) { 00144 if ( app == QLatin1String( "KADDRESSBOOK" ) ) { 00145 // however if it starts with our prefix it might be that this is an outdated 00146 // global custom field, in this case treat it as local field of type text 00147 CustomField customField( name, name, CustomField::TextType, CustomField::LocalScope ); 00148 customField.setValue( value ); 00149 00150 mLocalCustomFields << customField; 00151 } else { 00152 // it is really an external custom field 00153 const QString key = app + QLatin1Char( '-' ) + name; 00154 CustomField customField( key, key, CustomField::TextType, CustomField::ExternalScope ); 00155 customField.setValue( value ); 00156 00157 externalCustomFields << customField; 00158 } 00159 } 00160 } 00161 00162 mModel->setCustomFields( CustomField::List() << mLocalCustomFields << globalCustomFields << externalCustomFields ); 00163 } 00164 00165 void CustomFieldsEditWidget::storeContact( KABC::Addressee &contact ) const 00166 { 00167 const CustomField::List customFields = mModel->customFields(); 00168 foreach ( const CustomField &customField, customFields ) { 00169 // write back values for local and global scope, leave external untouched 00170 if ( customField.scope() != CustomField::ExternalScope ) { 00171 if ( !customField.value().isEmpty() ) 00172 contact.insertCustom( QLatin1String( "KADDRESSBOOK" ), customField.key(), customField.value() ); 00173 else 00174 contact.removeCustom( QLatin1String( "KADDRESSBOOK" ), customField.key() ); 00175 } 00176 } 00177 00178 // Now remove all fields that were available in loadContact (these are stored in mLocalCustomFields) 00179 // but are not part of customFields now, which means they have been removed or renamed by the user 00180 // in the editor dialog. 00181 foreach ( const CustomField &oldCustomField, mLocalCustomFields ) { 00182 if ( oldCustomField.scope() != CustomField::ExternalScope ) { 00183 00184 bool fieldStillExists = false; 00185 foreach ( const CustomField &newCustomField, customFields ) { 00186 if ( newCustomField.scope() != CustomField::ExternalScope ) { 00187 if ( newCustomField.key() == oldCustomField.key() ) { 00188 fieldStillExists = true; 00189 break; 00190 } 00191 } 00192 } 00193 00194 if ( !fieldStillExists ) 00195 contact.removeCustom( QLatin1String( "KADDRESSBOOK" ), oldCustomField.key() ); 00196 } 00197 } 00198 00199 // And store the global custom fields descriptions as well 00200 CustomField::List globalCustomFields; 00201 foreach ( const CustomField &customField, customFields ) { 00202 if ( customField.scope() == CustomField::GlobalScope ) { 00203 globalCustomFields << customField; 00204 } 00205 } 00206 00207 CustomFieldManager::setGlobalCustomFieldDescriptions( globalCustomFields ); 00208 } 00209 00210 void CustomFieldsEditWidget::setReadOnly( bool readOnly ) 00211 { 00212 mReadOnly = readOnly; 00213 00214 mView->setEnabled( !mReadOnly ); 00215 00216 slotUpdateButtons(); 00217 } 00218 00219 void CustomFieldsEditWidget::setLocalCustomFieldDescriptions( const QVariantList &descriptions ) 00220 { 00221 mLocalCustomFields.clear(); 00222 00223 foreach ( const QVariant &description, descriptions ) 00224 mLocalCustomFields.append( CustomField::fromVariantMap( description.toMap(), CustomField::LocalScope ) ); 00225 } 00226 00227 QVariantList CustomFieldsEditWidget::localCustomFieldDescriptions() const 00228 { 00229 const CustomField::List customFields = mModel->customFields(); 00230 00231 QVariantList descriptions; 00232 foreach ( const CustomField &field, customFields ) { 00233 if ( field.scope() == CustomField::LocalScope ) 00234 descriptions.append( field.toVariantMap() ); 00235 } 00236 00237 return descriptions; 00238 } 00239 00240 void CustomFieldsEditWidget::slotAdd() 00241 { 00242 CustomField field; 00243 00244 // We use a Uuid as default key, so we won't have any duplicated keys, 00245 // the user can still change it to something else in the editor dialog. 00246 // Since the key only allows [A-Za-z0-9\-]*, we have to remove the curly 00247 // braces as well. 00248 QString key = QUuid::createUuid().toString(); 00249 key.remove( QLatin1Char( '{' ) ); 00250 key.remove( QLatin1Char( '}' ) ); 00251 00252 field.setKey( key ); 00253 00254 QPointer<CustomFieldEditorDialog> dlg = new CustomFieldEditorDialog( this ); 00255 dlg->setCustomField( field ); 00256 00257 if ( dlg->exec() == QDialog::Accepted ) { 00258 const int lastRow = mModel->rowCount(); 00259 mModel->insertRow( lastRow ); 00260 00261 field = dlg->customField(); 00262 mModel->setData( mModel->index( lastRow, 2 ), field.key(), Qt::EditRole ); 00263 mModel->setData( mModel->index( lastRow, 0 ), field.title(), Qt::EditRole ); 00264 mModel->setData( mModel->index( lastRow, 0 ), field.type(), CustomFieldsModel::TypeRole ); 00265 mModel->setData( mModel->index( lastRow, 0 ), field.scope(), CustomFieldsModel::ScopeRole ); 00266 } 00267 00268 delete dlg; 00269 } 00270 00271 void CustomFieldsEditWidget::slotEdit() 00272 { 00273 const QModelIndex currentIndex = mView->currentIndex(); 00274 if ( !currentIndex.isValid() ) 00275 return; 00276 00277 CustomField field; 00278 field.setKey( mModel->index( currentIndex.row(), 2 ).data( Qt::DisplayRole ).toString() ); 00279 field.setTitle( mModel->index( currentIndex.row(), 0 ).data( Qt::DisplayRole ).toString() ); 00280 field.setType( static_cast<CustomField::Type>( currentIndex.data( CustomFieldsModel::TypeRole ).toInt() ) ); 00281 field.setScope( static_cast<CustomField::Scope>( currentIndex.data( CustomFieldsModel::ScopeRole ).toInt() ) ); 00282 00283 QPointer<CustomFieldEditorDialog> dlg = new CustomFieldEditorDialog( this ); 00284 dlg->setCustomField( field ); 00285 00286 if ( dlg->exec() == QDialog::Accepted ) { 00287 field = dlg->customField(); 00288 mModel->setData( mModel->index( currentIndex.row(), 2 ), field.key(), Qt::EditRole ); 00289 mModel->setData( mModel->index( currentIndex.row(), 0 ), field.title(), Qt::EditRole ); 00290 mModel->setData( currentIndex, field.type(), CustomFieldsModel::TypeRole ); 00291 mModel->setData( currentIndex, field.scope(), CustomFieldsModel::ScopeRole ); 00292 } 00293 00294 delete dlg; 00295 } 00296 00297 void CustomFieldsEditWidget::slotRemove() 00298 { 00299 const QModelIndex currentIndex = mView->currentIndex(); 00300 if ( !currentIndex.isValid() ) 00301 return; 00302 00303 if ( KMessageBox::warningContinueCancel( this, 00304 i18nc( "Custom Fields", "Do you really want to delete the selected custom field?" ), 00305 i18n( "Confirm Delete" ), KStandardGuiItem::del() ) != KMessageBox::Continue ) { 00306 return; 00307 } 00308 00309 mModel->removeRow( currentIndex.row() ); 00310 } 00311 00312 void CustomFieldsEditWidget::slotUpdateButtons() 00313 { 00314 const bool hasCurrent = mView->currentIndex().isValid(); 00315 const bool isExternal = (hasCurrent && 00316 (static_cast<CustomField::Scope>( mView->currentIndex().data( CustomFieldsModel::ScopeRole ).toInt() ) == CustomField::ExternalScope) ); 00317 00318 mAddButton->setEnabled( !mReadOnly ); 00319 mEditButton->setEnabled( !mReadOnly && hasCurrent && !isExternal ); 00320 mRemoveButton->setEnabled( !mReadOnly && hasCurrent && !isExternal ); 00321 } 00322 00323 #include "customfieldseditwidget.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:09:21 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:09:21 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.