• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.9.1 API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • akonadi
  • contact
  • editor
customfieldseditwidget.cpp
1 /*
2  This file is part of Akonadi Contact.
3 
4  Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>
5 
6  This library is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Library General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or (at your
9  option) any later version.
10 
11  This library is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14  License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  02110-1301, USA.
20 */
21 
22 #include "customfieldseditwidget.h"
23 
24 #include "customfieldeditordialog.h"
25 #include "customfieldmanager_p.h"
26 #include "customfieldsdelegate.h"
27 #include "customfieldsmodel.h"
28 
29 #include <kabc/addressee.h>
30 #include <klocale.h>
31 #include <kmessagebox.h>
32 
33 #include <QtCore/QPointer>
34 #include <QtCore/QUuid>
35 #include <QtGui/QGridLayout>
36 #include <QtGui/QPushButton>
37 #include <QtGui/QTreeView>
38 #include <QSortFilterProxyModel>
39 
40 void splitCustomField( const QString &str, QString &app, QString &name, QString &value )
41 {
42  const int colon = str.indexOf( QLatin1Char( ':' ) );
43  if ( colon != -1 ) {
44  const QString tmp = str.left( colon );
45  value = str.mid( colon + 1 );
46 
47  const int dash = tmp.indexOf( QLatin1Char( '-' ) );
48  if ( dash != -1 ) {
49  app = tmp.left( dash );
50  name = tmp.mid( dash + 1 );
51  }
52  }
53 }
54 
55 CustomFieldsEditWidget::CustomFieldsEditWidget( QWidget *parent )
56  : QWidget( parent ), mReadOnly( false )
57 {
58  QGridLayout *layout = new QGridLayout( this );
59  layout->setMargin( 0 );
60 
61 
62 
63  mView = new QTreeView;
64  mView->setSortingEnabled(true);
65  mView->setRootIsDecorated( false );
66  mView->setItemDelegate( new CustomFieldsDelegate( this ) );
67 
68  mAddButton = new QPushButton( i18n( "Add..." ) );
69  mEditButton = new QPushButton( i18n( "Edit..." ) );
70  mRemoveButton = new QPushButton( i18n( "Remove" ) );
71 
72  layout->addWidget( mView, 0, 0, 4, 1 );
73  layout->addWidget( mAddButton, 0, 1 );
74  layout->addWidget( mEditButton, 1, 1 );
75  layout->addWidget( mRemoveButton, 2, 1 );
76 
77  mModel = new CustomFieldsModel( this );
78  QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel;
79  proxyModel->setDynamicSortFilter(true);
80  proxyModel->setSourceModel(mModel);
81  mView->setModel( proxyModel );
82  mView->setColumnHidden( 2, true ); // hide the 'key' column
83 
84  connect( mView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
85  this, SLOT(slotUpdateButtons()) );
86  connect( mAddButton, SIGNAL(clicked()), this, SLOT(slotAdd()) );
87  connect( mEditButton, SIGNAL(clicked()), this, SLOT(slotEdit()) );
88  connect( mRemoveButton, SIGNAL(clicked()), this, SLOT(slotRemove()) );
89 }
90 
91 CustomFieldsEditWidget::~CustomFieldsEditWidget()
92 {
93 }
94 
95 void CustomFieldsEditWidget::loadContact( const KABC::Addressee &contact )
96 {
97  CustomField::List externalCustomFields;
98 
99  CustomField::List globalCustomFields = CustomFieldManager::globalCustomFieldDescriptions();
100 
101  const QStringList customs = contact.customs();
102  foreach ( const QString &custom, customs ) {
103 
104  QString app, name, value;
105  splitCustomField( custom, app, name, value );
106 
107  // skip all well-known fields that have separated editor widgets
108  if ( custom.startsWith( QLatin1String( "messaging/" ) ) ) // IM addresses
109  continue;
110 
111  if ( app == QLatin1String( "KADDRESSBOOK" ) ) {
112  static QSet<QString> blacklist;
113  if ( blacklist.isEmpty() ) {
114  blacklist << QLatin1String( "BlogFeed" )
115  << QLatin1String( "X-IMAddress" )
116  << QLatin1String( "X-Profession" )
117  << QLatin1String( "X-Office" )
118  << QLatin1String( "X-ManagersName" )
119  << QLatin1String( "X-AssistantsName" )
120  << QLatin1String( "X-Anniversary" )
121  << QLatin1String( "X-SpousesName" )
122  << QLatin1String( "X-Profession" )
123  << QLatin1String( "MailPreferedFormatting")
124  << QLatin1String( "MailAllowToRemoteContent")
125  << QLatin1String( "CRYPTOPROTOPREF" )
126  << QLatin1String( "OPENPGPFP" )
127  << QLatin1String( "SMIMEFP" )
128  << QLatin1String( "CRYPTOSIGNPREF" )
129  << QLatin1String( "CRYPTOENCRYPTPREF" );
130  }
131 
132  if ( blacklist.contains( name ) ) // several KAddressBook specific fields
133  continue;
134  }
135 
136  // check whether it correspond to a local custom field
137  bool isLocalCustomField = false;
138  for ( int i = 0; i < mLocalCustomFields.count(); ++i ) {
139  if ( mLocalCustomFields[ i ].key() == name ) {
140  mLocalCustomFields[ i ].setValue( value );
141  isLocalCustomField = true;
142  break;
143  }
144  }
145 
146  // check whether it correspond to a global custom field
147  bool isGlobalCustomField = false;
148  for ( int i = 0; i < globalCustomFields.count(); ++i ) {
149  if ( globalCustomFields[ i ].key() == name ) {
150  globalCustomFields[ i ].setValue( value );
151  isGlobalCustomField = true;
152  break;
153  }
154  }
155 
156  // if not local and not global it must be external
157  if ( !isLocalCustomField && !isGlobalCustomField ) {
158  if ( app == QLatin1String( "KADDRESSBOOK" ) ) {
159  // however if it starts with our prefix it might be that this is an outdated
160  // global custom field, in this case treat it as local field of type text
161  CustomField customField( name, name, CustomField::TextType, CustomField::LocalScope );
162  customField.setValue( value );
163 
164  mLocalCustomFields << customField;
165  } else {
166  // it is really an external custom field
167  const QString key = app + QLatin1Char( '-' ) + name;
168  CustomField customField( key, key, CustomField::TextType, CustomField::ExternalScope );
169  customField.setValue( value );
170 
171  externalCustomFields << customField;
172  }
173  }
174  }
175 
176  mModel->setCustomFields( CustomField::List() << mLocalCustomFields << globalCustomFields << externalCustomFields );
177 }
178 
179 void CustomFieldsEditWidget::storeContact( KABC::Addressee &contact ) const
180 {
181  const CustomField::List customFields = mModel->customFields();
182  foreach ( const CustomField &customField, customFields ) {
183  // write back values for local and global scope, leave external untouched
184  if ( customField.scope() != CustomField::ExternalScope ) {
185  if ( !customField.value().isEmpty() )
186  contact.insertCustom( QLatin1String( "KADDRESSBOOK" ), customField.key(), customField.value() );
187  else
188  contact.removeCustom( QLatin1String( "KADDRESSBOOK" ), customField.key() );
189  }
190  }
191 
192  // Now remove all fields that were available in loadContact (these are stored in mLocalCustomFields)
193  // but are not part of customFields now, which means they have been removed or renamed by the user
194  // in the editor dialog.
195  foreach ( const CustomField &oldCustomField, mLocalCustomFields ) {
196  if ( oldCustomField.scope() != CustomField::ExternalScope ) {
197 
198  bool fieldStillExists = false;
199  foreach ( const CustomField &newCustomField, customFields ) {
200  if ( newCustomField.scope() != CustomField::ExternalScope ) {
201  if ( newCustomField.key() == oldCustomField.key() ) {
202  fieldStillExists = true;
203  break;
204  }
205  }
206  }
207 
208  if ( !fieldStillExists )
209  contact.removeCustom( QLatin1String( "KADDRESSBOOK" ), oldCustomField.key() );
210  }
211  }
212 
213  // And store the global custom fields descriptions as well
214  CustomField::List globalCustomFields;
215  foreach ( const CustomField &customField, customFields ) {
216  if ( customField.scope() == CustomField::GlobalScope ) {
217  globalCustomFields << customField;
218  }
219  }
220 
221  CustomFieldManager::setGlobalCustomFieldDescriptions( globalCustomFields );
222 }
223 
224 void CustomFieldsEditWidget::setReadOnly( bool readOnly )
225 {
226  mReadOnly = readOnly;
227 
228  mView->setEnabled( !mReadOnly );
229 
230  slotUpdateButtons();
231 }
232 
233 void CustomFieldsEditWidget::setLocalCustomFieldDescriptions( const QVariantList &descriptions )
234 {
235  mLocalCustomFields.clear();
236 
237  foreach ( const QVariant &description, descriptions )
238  mLocalCustomFields.append( CustomField::fromVariantMap( description.toMap(), CustomField::LocalScope ) );
239 }
240 
241 QVariantList CustomFieldsEditWidget::localCustomFieldDescriptions() const
242 {
243  const CustomField::List customFields = mModel->customFields();
244 
245  QVariantList descriptions;
246  foreach ( const CustomField &field, customFields ) {
247  if ( field.scope() == CustomField::LocalScope )
248  descriptions.append( field.toVariantMap() );
249  }
250 
251  return descriptions;
252 }
253 
254 void CustomFieldsEditWidget::slotAdd()
255 {
256  CustomField field;
257 
258  // We use a Uuid as default key, so we won't have any duplicated keys,
259  // the user can still change it to something else in the editor dialog.
260  // Since the key only allows [A-Za-z0-9\-]*, we have to remove the curly
261  // braces as well.
262  QString key = QUuid::createUuid().toString();
263  key.remove( QLatin1Char( '{' ) );
264  key.remove( QLatin1Char( '}' ) );
265 
266  field.setKey( key );
267 
268  QPointer<CustomFieldEditorDialog> dlg = new CustomFieldEditorDialog( this );
269  dlg->setCustomField( field );
270 
271  if ( dlg->exec() == QDialog::Accepted ) {
272  const int lastRow = mModel->rowCount();
273  mModel->insertRow( lastRow );
274 
275  field = dlg->customField();
276  mModel->setData( mModel->index( lastRow, 2 ), field.key(), Qt::EditRole );
277  mModel->setData( mModel->index( lastRow, 0 ), field.title(), Qt::EditRole );
278  mModel->setData( mModel->index( lastRow, 0 ), field.type(), CustomFieldsModel::TypeRole );
279  mModel->setData( mModel->index( lastRow, 0 ), field.scope(), CustomFieldsModel::ScopeRole );
280  }
281 
282  delete dlg;
283 }
284 
285 void CustomFieldsEditWidget::slotEdit()
286 {
287  const QModelIndex currentIndex = mView->currentIndex();
288  if ( !currentIndex.isValid() )
289  return;
290 
291  CustomField field;
292  field.setKey( mModel->index( currentIndex.row(), 2 ).data( Qt::DisplayRole ).toString() );
293  field.setTitle( mModel->index( currentIndex.row(), 0 ).data( Qt::DisplayRole ).toString() );
294  field.setType( static_cast<CustomField::Type>( currentIndex.data( CustomFieldsModel::TypeRole ).toInt() ) );
295  field.setScope( static_cast<CustomField::Scope>( currentIndex.data( CustomFieldsModel::ScopeRole ).toInt() ) );
296 
297  QPointer<CustomFieldEditorDialog> dlg = new CustomFieldEditorDialog( this );
298  dlg->setCustomField( field );
299 
300  if ( dlg->exec() == QDialog::Accepted ) {
301  field = dlg->customField();
302  mModel->setData( mModel->index( currentIndex.row(), 2 ), field.key(), Qt::EditRole );
303  mModel->setData( mModel->index( currentIndex.row(), 0 ), field.title(), Qt::EditRole );
304  mModel->setData( currentIndex, field.type(), CustomFieldsModel::TypeRole );
305  mModel->setData( currentIndex, field.scope(), CustomFieldsModel::ScopeRole );
306  }
307 
308  delete dlg;
309 }
310 
311 void CustomFieldsEditWidget::slotRemove()
312 {
313  const QModelIndex currentIndex = mView->currentIndex();
314  if ( !currentIndex.isValid() )
315  return;
316 
317  if ( KMessageBox::warningContinueCancel( this,
318  i18nc( "Custom Fields", "Do you really want to delete the selected custom field?" ),
319  i18n( "Confirm Delete" ), KStandardGuiItem::del() ) != KMessageBox::Continue ) {
320  return;
321  }
322 
323  mModel->removeRow( currentIndex.row() );
324 }
325 
326 void CustomFieldsEditWidget::slotUpdateButtons()
327 {
328  const bool hasCurrent = mView->currentIndex().isValid();
329  const bool isExternal = (hasCurrent &&
330  (static_cast<CustomField::Scope>( mView->currentIndex().data( CustomFieldsModel::ScopeRole ).toInt() ) == CustomField::ExternalScope) );
331 
332  mAddButton->setEnabled( !mReadOnly );
333  mEditButton->setEnabled( !mReadOnly && hasCurrent && !isExternal );
334  mRemoveButton->setEnabled( !mReadOnly && hasCurrent && !isExternal );
335 }
336 
337 #include "customfieldseditwidget.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Sep 24 2012 09:06:25 by doxygen 1.8.1.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

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

kdepimlibs-4.9.1 API Reference

Skip menu "kdepimlibs-4.9.1 API Reference"
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal