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

akonadi

  • sources
  • kde-4.12
  • kdepimlibs
  • 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 <klocalizedstring.h>
31 #include <kmessagebox.h>
32 
33 #include <QtCore/QPointer>
34 #include <QtCore/QUuid>
35 #include <QGridLayout>
36 #include <QPushButton>
37 #include <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  mView = new QTreeView;
62  mView->setSortingEnabled(true);
63  mView->setRootIsDecorated( false );
64  mView->setItemDelegate( new CustomFieldsDelegate( this ) );
65 
66  mAddButton = new QPushButton( i18n( "Add..." ) );
67  mEditButton = new QPushButton( i18n( "Edit..." ) );
68  mRemoveButton = new QPushButton( i18n( "Remove" ) );
69 
70  layout->addWidget( mView, 0, 0, 4, 1 );
71  layout->addWidget( mAddButton, 0, 1 );
72  layout->addWidget( mEditButton, 1, 1 );
73  layout->addWidget( mRemoveButton, 2, 1 );
74 
75  mModel = new CustomFieldsModel( this );
76  QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel;
77  proxyModel->setDynamicSortFilter(true);
78  proxyModel->setSourceModel(mModel);
79  mView->setModel( proxyModel );
80  mView->setColumnHidden( 2, true ); // hide the 'key' column
81 
82  connect( mView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
83  this, SLOT(slotUpdateButtons()) );
84  connect( mAddButton, SIGNAL(clicked()), this, SLOT(slotAdd()) );
85  connect( mEditButton, SIGNAL(clicked()), this, SLOT(slotEdit()) );
86  connect( mRemoveButton, SIGNAL(clicked()), this, SLOT(slotRemove()) );
87  slotUpdateButtons();
88 }
89 
90 CustomFieldsEditWidget::~CustomFieldsEditWidget()
91 {
92 }
93 
94 void CustomFieldsEditWidget::loadContact( const KABC::Addressee &contact )
95 {
96  CustomField::List externalCustomFields;
97 
98  CustomField::List globalCustomFields = CustomFieldManager::globalCustomFieldDescriptions();
99 
100  const QStringList customs = contact.customs();
101  foreach ( const QString &custom, customs ) {
102 
103  QString app, name, value;
104  splitCustomField( custom, app, name, value );
105 
106  // skip all well-known fields that have separated editor widgets
107  if ( custom.startsWith( QLatin1String( "messaging/" ) ) ) { // IM addresses
108  continue;
109  }
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-ANNIVERSARY" )
122  << QLatin1String( "X-SpousesName" )
123  << QLatin1String( "X-Profession" )
124  << QLatin1String( "MailPreferedFormatting")
125  << QLatin1String( "MailAllowToRemoteContent")
126  << QLatin1String( "CRYPTOPROTOPREF" )
127  << QLatin1String( "OPENPGPFP" )
128  << QLatin1String( "SMIMEFP" )
129  << QLatin1String( "CRYPTOSIGNPREF" )
130  << QLatin1String( "CRYPTOENCRYPTPREF" );
131  }
132 
133  if ( blacklist.contains( name ) ) { // several KAddressBook specific fields
134  continue;
135  }
136  }
137 
138  // check whether it correspond to a local custom field
139  bool isLocalCustomField = false;
140  for ( int i = 0; i < mLocalCustomFields.count(); ++i ) {
141  if ( mLocalCustomFields[ i ].key() == name ) {
142  mLocalCustomFields[ i ].setValue( value );
143  isLocalCustomField = true;
144  break;
145  }
146  }
147 
148  // check whether it correspond to a global custom field
149  bool isGlobalCustomField = false;
150  for ( int i = 0; i < globalCustomFields.count(); ++i ) {
151  if ( globalCustomFields[ i ].key() == name ) {
152  globalCustomFields[ i ].setValue( value );
153  isGlobalCustomField = true;
154  break;
155  }
156  }
157 
158  // if not local and not global it must be external
159  if ( !isLocalCustomField && !isGlobalCustomField ) {
160  if ( app == QLatin1String( "KADDRESSBOOK" ) ) {
161  // however if it starts with our prefix it might be that this is an outdated
162  // global custom field, in this case treat it as local field of type text
163  CustomField customField( name, name, CustomField::TextType, CustomField::LocalScope );
164  customField.setValue( value );
165 
166  mLocalCustomFields << customField;
167  } else {
168  // it is really an external custom field
169  const QString key = app + QLatin1Char( '-' ) + name;
170  CustomField customField( key, key, CustomField::TextType, CustomField::ExternalScope );
171  customField.setValue( value );
172 
173  externalCustomFields << customField;
174  }
175  }
176  }
177 
178  mModel->setCustomFields( CustomField::List() << mLocalCustomFields << globalCustomFields << externalCustomFields );
179 }
180 
181 void CustomFieldsEditWidget::storeContact( KABC::Addressee &contact ) const
182 {
183  const CustomField::List customFields = mModel->customFields();
184  foreach ( const CustomField &customField, customFields ) {
185  // write back values for local and global scope, leave external untouched
186  if ( customField.scope() != CustomField::ExternalScope ) {
187  if ( !customField.value().isEmpty() ) {
188  contact.insertCustom( QLatin1String( "KADDRESSBOOK" ), customField.key(), customField.value() );
189  } else {
190  contact.removeCustom( QLatin1String( "KADDRESSBOOK" ), customField.key() );
191  }
192  }
193  }
194 
195  // Now remove all fields that were available in loadContact (these are stored in mLocalCustomFields)
196  // but are not part of customFields now, which means they have been removed or renamed by the user
197  // in the editor dialog.
198  foreach ( const CustomField &oldCustomField, mLocalCustomFields ) {
199  if ( oldCustomField.scope() != CustomField::ExternalScope ) {
200 
201  bool fieldStillExists = false;
202  foreach ( const CustomField &newCustomField, customFields ) {
203  if ( newCustomField.scope() != CustomField::ExternalScope ) {
204  if ( newCustomField.key() == oldCustomField.key() ) {
205  fieldStillExists = true;
206  break;
207  }
208  }
209  }
210 
211  if ( !fieldStillExists ) {
212  contact.removeCustom( QLatin1String( "KADDRESSBOOK" ), oldCustomField.key() );
213  }
214  }
215  }
216 
217  // And store the global custom fields descriptions as well
218  CustomField::List globalCustomFields;
219  foreach ( const CustomField &customField, customFields ) {
220  if ( customField.scope() == CustomField::GlobalScope ) {
221  globalCustomFields << customField;
222  }
223  }
224 
225  CustomFieldManager::setGlobalCustomFieldDescriptions( globalCustomFields );
226 }
227 
228 void CustomFieldsEditWidget::setReadOnly( bool readOnly )
229 {
230  mReadOnly = readOnly;
231 
232  mView->setEnabled( !mReadOnly );
233 
234  slotUpdateButtons();
235 }
236 
237 void CustomFieldsEditWidget::setLocalCustomFieldDescriptions( const QVariantList &descriptions )
238 {
239  mLocalCustomFields.clear();
240 
241  foreach ( const QVariant &description, descriptions ) {
242  mLocalCustomFields.append( CustomField::fromVariantMap( description.toMap(), CustomField::LocalScope ) );
243  }
244 }
245 
246 QVariantList CustomFieldsEditWidget::localCustomFieldDescriptions() const
247 {
248  const CustomField::List customFields = mModel->customFields();
249 
250  QVariantList descriptions;
251  foreach ( const CustomField &field, customFields ) {
252  if ( field.scope() == CustomField::LocalScope ) {
253  descriptions.append( field.toVariantMap() );
254  }
255  }
256 
257  return descriptions;
258 }
259 
260 void CustomFieldsEditWidget::slotAdd()
261 {
262  CustomField field;
263 
264  // We use a Uuid as default key, so we won't have any duplicated keys,
265  // the user can still change it to something else in the editor dialog.
266  // Since the key only allows [A-Za-z0-9\-]*, we have to remove the curly
267  // braces as well.
268  QString key = QUuid::createUuid().toString();
269  key.remove( QLatin1Char( '{' ) );
270  key.remove( QLatin1Char( '}' ) );
271 
272  field.setKey( key );
273 
274  QPointer<CustomFieldEditorDialog> dlg = new CustomFieldEditorDialog( this );
275  dlg->setCustomField( field );
276 
277  if ( dlg->exec() == QDialog::Accepted ) {
278  const int lastRow = mModel->rowCount();
279  mModel->insertRow( lastRow );
280 
281  field = dlg->customField();
282  mModel->setData( mModel->index( lastRow, 2 ), field.key(), Qt::EditRole );
283  mModel->setData( mModel->index( lastRow, 0 ), field.title(), Qt::EditRole );
284  mModel->setData( mModel->index( lastRow, 0 ), field.type(), CustomFieldsModel::TypeRole );
285  mModel->setData( mModel->index( lastRow, 0 ), field.scope(), CustomFieldsModel::ScopeRole );
286  }
287 
288  delete dlg;
289 }
290 
291 void CustomFieldsEditWidget::slotEdit()
292 {
293  const QModelIndex currentIndex = mView->currentIndex();
294  if ( !currentIndex.isValid() ) {
295  return;
296  }
297 
298  CustomField field;
299  field.setKey( mModel->index( currentIndex.row(), 2 ).data( Qt::DisplayRole ).toString() );
300  field.setTitle( mModel->index( currentIndex.row(), 0 ).data( Qt::DisplayRole ).toString() );
301  field.setType( static_cast<CustomField::Type>( currentIndex.data( CustomFieldsModel::TypeRole ).toInt() ) );
302  field.setScope( static_cast<CustomField::Scope>( currentIndex.data( CustomFieldsModel::ScopeRole ).toInt() ) );
303 
304  QPointer<CustomFieldEditorDialog> dlg = new CustomFieldEditorDialog( this );
305  dlg->setCustomField( field );
306 
307  if ( dlg->exec() == QDialog::Accepted ) {
308  field = dlg->customField();
309  mModel->setData( mModel->index( currentIndex.row(), 2 ), field.key(), Qt::EditRole );
310  mModel->setData( mModel->index( currentIndex.row(), 0 ), field.title(), Qt::EditRole );
311  mModel->setData( currentIndex, field.type(), CustomFieldsModel::TypeRole );
312  mModel->setData( currentIndex, field.scope(), CustomFieldsModel::ScopeRole );
313  }
314 
315  delete dlg;
316 }
317 
318 void CustomFieldsEditWidget::slotRemove()
319 {
320  const QModelIndex currentIndex = mView->currentIndex();
321  if ( !currentIndex.isValid() ) {
322  return;
323  }
324 
325  if ( KMessageBox::warningContinueCancel( this,
326  i18nc( "Custom Fields", "Do you really want to delete the selected custom field?" ),
327  i18n( "Confirm Delete" ), KStandardGuiItem::del() ) != KMessageBox::Continue ) {
328  return;
329  }
330 
331  mModel->removeRow( currentIndex.row() );
332 }
333 
334 void CustomFieldsEditWidget::slotUpdateButtons()
335 {
336  const bool hasCurrent = mView->currentIndex().isValid();
337  const bool isExternal = ( hasCurrent &&
338  ( static_cast<CustomField::Scope>( mView->currentIndex().data( CustomFieldsModel::ScopeRole ).toInt() ) == CustomField::ExternalScope ) );
339 
340  mAddButton->setEnabled( !mReadOnly );
341  mEditButton->setEnabled( !mReadOnly && hasCurrent && !isExternal );
342  mRemoveButton->setEnabled( !mReadOnly && hasCurrent && !isExternal );
343 }
344 
CustomField
A class that represents non-standard contact fields.
Definition: customfields_p.h:47
CustomField::ExternalScope
Field has been defined by the external data source (e.g. vCard)
Definition: customfields_p.h:65
CustomField::GlobalScope
Field has been defined by user for all contacts.
Definition: customfields_p.h:64
CustomField::LocalScope
Field has been defined by user for one contact.
Definition: customfields_p.h:63
CustomField::Scope
Scope
Definition: customfields_p.h:62
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:00:27 by doxygen 1.8.7 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 API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

Search



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