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

akonadi/contact

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

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

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