• Skip to content
  • Skip to link menu
KDE 4.8 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • KDE Home
  • Contact Us
 

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"

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal