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

akonadi/contact

  • 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  slotUpdateButtons();
90 }
91 
92 CustomFieldsEditWidget::~CustomFieldsEditWidget()
93 {
94 }
95 
96 void CustomFieldsEditWidget::loadContact( const KABC::Addressee &contact )
97 {
98  CustomField::List externalCustomFields;
99 
100  CustomField::List globalCustomFields = CustomFieldManager::globalCustomFieldDescriptions();
101 
102  const QStringList customs = contact.customs();
103  foreach ( const QString &custom, customs ) {
104 
105  QString app, name, value;
106  splitCustomField( custom, app, name, value );
107 
108  // skip all well-known fields that have separated editor widgets
109  if ( custom.startsWith( QLatin1String( "messaging/" ) ) ) // IM addresses
110  continue;
111 
112  if ( app == QLatin1String( "KADDRESSBOOK" ) ) {
113  static QSet<QString> blacklist;
114  if ( blacklist.isEmpty() ) {
115  blacklist << QLatin1String( "BlogFeed" )
116  << QLatin1String( "X-IMAddress" )
117  << QLatin1String( "X-Profession" )
118  << QLatin1String( "X-Office" )
119  << QLatin1String( "X-ManagersName" )
120  << QLatin1String( "X-AssistantsName" )
121  << QLatin1String( "X-Anniversary" )
122  << QLatin1String( "X-ANNIVERSARY" )
123  << QLatin1String( "X-SpousesName" )
124  << QLatin1String( "X-Profession" )
125  << QLatin1String( "MailPreferedFormatting")
126  << QLatin1String( "MailAllowToRemoteContent")
127  << QLatin1String( "CRYPTOPROTOPREF" )
128  << QLatin1String( "OPENPGPFP" )
129  << QLatin1String( "SMIMEFP" )
130  << QLatin1String( "CRYPTOSIGNPREF" )
131  << QLatin1String( "CRYPTOENCRYPTPREF" );
132  }
133 
134  if ( blacklist.contains( name ) ) // several KAddressBook specific fields
135  continue;
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  // Now remove all fields that were available in loadContact (these are stored in mLocalCustomFields)
195  // but are not part of customFields now, which means they have been removed or renamed by the user
196  // in the editor dialog.
197  foreach ( const CustomField &oldCustomField, mLocalCustomFields ) {
198  if ( oldCustomField.scope() != CustomField::ExternalScope ) {
199 
200  bool fieldStillExists = false;
201  foreach ( const CustomField &newCustomField, customFields ) {
202  if ( newCustomField.scope() != CustomField::ExternalScope ) {
203  if ( newCustomField.key() == oldCustomField.key() ) {
204  fieldStillExists = true;
205  break;
206  }
207  }
208  }
209 
210  if ( !fieldStillExists )
211  contact.removeCustom( QLatin1String( "KADDRESSBOOK" ), oldCustomField.key() );
212  }
213  }
214 
215  // And store the global custom fields descriptions as well
216  CustomField::List globalCustomFields;
217  foreach ( const CustomField &customField, customFields ) {
218  if ( customField.scope() == CustomField::GlobalScope ) {
219  globalCustomFields << customField;
220  }
221  }
222 
223  CustomFieldManager::setGlobalCustomFieldDescriptions( globalCustomFields );
224 }
225 
226 void CustomFieldsEditWidget::setReadOnly( bool readOnly )
227 {
228  mReadOnly = readOnly;
229 
230  mView->setEnabled( !mReadOnly );
231 
232  slotUpdateButtons();
233 }
234 
235 void CustomFieldsEditWidget::setLocalCustomFieldDescriptions( const QVariantList &descriptions )
236 {
237  mLocalCustomFields.clear();
238 
239  foreach ( const QVariant &description, descriptions )
240  mLocalCustomFields.append( CustomField::fromVariantMap( description.toMap(), CustomField::LocalScope ) );
241 }
242 
243 QVariantList CustomFieldsEditWidget::localCustomFieldDescriptions() const
244 {
245  const CustomField::List customFields = mModel->customFields();
246 
247  QVariantList descriptions;
248  foreach ( const CustomField &field, customFields ) {
249  if ( field.scope() == CustomField::LocalScope )
250  descriptions.append( field.toVariantMap() );
251  }
252 
253  return descriptions;
254 }
255 
256 void CustomFieldsEditWidget::slotAdd()
257 {
258  CustomField field;
259 
260  // We use a Uuid as default key, so we won't have any duplicated keys,
261  // the user can still change it to something else in the editor dialog.
262  // Since the key only allows [A-Za-z0-9\-]*, we have to remove the curly
263  // braces as well.
264  QString key = QUuid::createUuid().toString();
265  key.remove( QLatin1Char( '{' ) );
266  key.remove( QLatin1Char( '}' ) );
267 
268  field.setKey( key );
269 
270  QPointer<CustomFieldEditorDialog> dlg = new CustomFieldEditorDialog( this );
271  dlg->setCustomField( field );
272 
273  if ( dlg->exec() == QDialog::Accepted ) {
274  const int lastRow = mModel->rowCount();
275  mModel->insertRow( lastRow );
276 
277  field = dlg->customField();
278  mModel->setData( mModel->index( lastRow, 2 ), field.key(), Qt::EditRole );
279  mModel->setData( mModel->index( lastRow, 0 ), field.title(), Qt::EditRole );
280  mModel->setData( mModel->index( lastRow, 0 ), field.type(), CustomFieldsModel::TypeRole );
281  mModel->setData( mModel->index( lastRow, 0 ), field.scope(), CustomFieldsModel::ScopeRole );
282  }
283 
284  delete dlg;
285 }
286 
287 void CustomFieldsEditWidget::slotEdit()
288 {
289  const QModelIndex currentIndex = mView->currentIndex();
290  if ( !currentIndex.isValid() )
291  return;
292 
293  CustomField field;
294  field.setKey( mModel->index( currentIndex.row(), 2 ).data( Qt::DisplayRole ).toString() );
295  field.setTitle( mModel->index( currentIndex.row(), 0 ).data( Qt::DisplayRole ).toString() );
296  field.setType( static_cast<CustomField::Type>( currentIndex.data( CustomFieldsModel::TypeRole ).toInt() ) );
297  field.setScope( static_cast<CustomField::Scope>( currentIndex.data( CustomFieldsModel::ScopeRole ).toInt() ) );
298 
299  QPointer<CustomFieldEditorDialog> dlg = new CustomFieldEditorDialog( this );
300  dlg->setCustomField( field );
301 
302  if ( dlg->exec() == QDialog::Accepted ) {
303  field = dlg->customField();
304  mModel->setData( mModel->index( currentIndex.row(), 2 ), field.key(), Qt::EditRole );
305  mModel->setData( mModel->index( currentIndex.row(), 0 ), field.title(), Qt::EditRole );
306  mModel->setData( currentIndex, field.type(), CustomFieldsModel::TypeRole );
307  mModel->setData( currentIndex, field.scope(), CustomFieldsModel::ScopeRole );
308  }
309 
310  delete dlg;
311 }
312 
313 void CustomFieldsEditWidget::slotRemove()
314 {
315  const QModelIndex currentIndex = mView->currentIndex();
316  if ( !currentIndex.isValid() )
317  return;
318 
319  if ( KMessageBox::warningContinueCancel( this,
320  i18nc( "Custom Fields", "Do you really want to delete the selected custom field?" ),
321  i18n( "Confirm Delete" ), KStandardGuiItem::del() ) != KMessageBox::Continue ) {
322  return;
323  }
324 
325  mModel->removeRow( currentIndex.row() );
326 }
327 
328 void CustomFieldsEditWidget::slotUpdateButtons()
329 {
330  const bool hasCurrent = mView->currentIndex().isValid();
331  const bool isExternal = (hasCurrent &&
332  (static_cast<CustomField::Scope>( mView->currentIndex().data( CustomFieldsModel::ScopeRole ).toInt() ) == CustomField::ExternalScope) );
333 
334  mAddButton->setEnabled( !mReadOnly );
335  mEditButton->setEnabled( !mReadOnly && hasCurrent && !isExternal );
336  mRemoveButton->setEnabled( !mReadOnly && hasCurrent && !isExternal );
337 }
338 
339 #include "customfieldseditwidget.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Nov 26 2012 16:49:09 by doxygen 1.8.1.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi/contact

Skip menu "akonadi/contact"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.9.3 API Reference

Skip menu "kdepimlibs-4.9.3 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