• 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
contactgroupeditordelegate.cpp
1 /*
2  This file is part of Akonadi Contact.
3 
4  Copyright (c) 2009 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 "contactgroupeditordelegate_p.h"
23 
24 #include "contactcompletionmodel_p.h"
25 #include "contactgroupmodel_p.h"
26 
27 #include <akonadi/entitytreemodel.h>
28 #include <kcombobox.h>
29 #include <kicon.h>
30 #include <klocalizedstring.h>
31 
32 #include <QtCore/QTimer>
33 #include <QAbstractItemView>
34 #include <QCompleter>
35 #include <QMouseEvent>
36 #include <QSortFilterProxyModel>
37 
38 using namespace Akonadi;
39 
43 class ContactsWithEmailFilterModel : public QSortFilterProxyModel
44 {
45  public:
46  ContactsWithEmailFilterModel( QObject *parent )
47  : QSortFilterProxyModel( parent )
48  {
49  // contact names should be sorted correctly
50  setSortLocaleAware( true );
51  }
52 
53  protected:
54  virtual bool filterAcceptsRow( int row, const QModelIndex &parent ) const
55  {
56  const QModelIndex index = sourceModel()->index( row, Akonadi::ContactCompletionModel::EmailColumn, parent );
57  if ( !index.isValid() ) {
58  return false;
59  }
60 
61  return !index.data().toString().isEmpty();
62  }
63 };
64 
65 ContactLineEdit::ContactLineEdit( bool isReference, QWidget *parent )
66  : KLineEdit( parent ), mIsReference( isReference )
67 {
68  setFrame( false );
69 
70  ContactsWithEmailFilterModel *filter = new ContactsWithEmailFilterModel( this );
71  filter->setSourceModel( Akonadi::ContactCompletionModel::self() );
72 
73  QCompleter *completer = new QCompleter( filter, this );
74  completer->setCompletionColumn( Akonadi::ContactCompletionModel::NameColumn );
75  completer->setCaseSensitivity( Qt::CaseInsensitive );
76  connect( completer, SIGNAL(activated(QModelIndex)), SLOT(completed(QModelIndex)) );
77 
78  setCompleter( completer );
79 
80  connect( this, SIGNAL(textEdited(QString)), SLOT(slotTextEdited()) );
81 }
82 
83 bool ContactLineEdit::isReference() const
84 {
85  return mIsReference;
86 }
87 
88 Akonadi::Item ContactLineEdit::completedItem() const
89 {
90  return mItem;
91 }
92 
93 void ContactLineEdit::completed( const QModelIndex &index )
94 {
95  if ( index.isValid() ) {
96  mItem = index.data( Akonadi::EntityTreeModel::ItemRole ).value<Akonadi::Item>();
97  mIsReference = true;
98  } else {
99  mItem = Item();
100  mIsReference = false;
101  }
102 
103  emit completed( this );
104 }
105 
106 void ContactLineEdit::slotTextEdited()
107 {
108  // if the user has edited the text, we break up the reference
109  mIsReference = false;
110 }
111 
112 class ContactGroupEditorDelegate::Private
113 {
114  public:
115  Private()
116  : mButtonSize( 16, 16 ), mIcon( QLatin1String( "list-remove" ) ), mItemView( 0 )
117  {
118  }
119 
120  QSize mButtonSize;
121  const KIcon mIcon;
122  QAbstractItemView *mItemView;
123 };
124 
125 ContactGroupEditorDelegate::ContactGroupEditorDelegate( QAbstractItemView *view, QObject *parent )
126  : QStyledItemDelegate( parent ), d( new Private )
127 {
128  d->mItemView = view;
129 }
130 
131 ContactGroupEditorDelegate::~ContactGroupEditorDelegate()
132 {
133  delete d;
134 }
135 
136 QWidget* ContactGroupEditorDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem&,
137  const QModelIndex &index ) const
138 {
139  if ( index.column() == 0 ) {
140  ContactLineEdit *edit = 0;
141  if ( index.data( ContactGroupModel::IsReferenceRole ).toBool() ) {
142  edit = new ContactLineEdit( true, parent );
143  } else {
144  edit = new ContactLineEdit( false, parent );
145  }
146 
147  connect( edit, SIGNAL(completed(QWidget*)), SLOT(completed(QWidget*)) );
148 
149  return edit;
150  } else {
151  if ( index.data( ContactGroupModel::IsReferenceRole ).toBool() ) {
152  KComboBox *comboBox = new KComboBox( parent );
153  comboBox->setFrame( false );
154  comboBox->setAutoFillBackground( true );
155  return comboBox;
156  } else {
157  KLineEdit *lineEdit = new KLineEdit( parent );
158  lineEdit->setFrame( false );
159  return lineEdit;
160  }
161  }
162 }
163 
164 void ContactGroupEditorDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
165 {
166  if ( index.data( ContactGroupModel::IsReferenceRole ).toBool() ) {
167  if ( index.column() == 0 ) {
168  KLineEdit *lineEdit = qobject_cast<KLineEdit*>( editor );
169  if ( !lineEdit ) {
170  return;
171  }
172 
173  lineEdit->setText( index.data( Qt::EditRole ).toString() );
174  } else {
175  KComboBox *comboBox = qobject_cast<KComboBox*>( editor );
176  if ( !comboBox ) {
177  return;
178  }
179 
180  const QStringList emails = index.data( ContactGroupModel::AllEmailsRole ).toStringList();
181  comboBox->clear();
182  comboBox->addItems( emails );
183  comboBox->setCurrentIndex( comboBox->findText( index.data( Qt::EditRole ).toString() ) );
184  }
185  } else {
186  KLineEdit *lineEdit = qobject_cast<KLineEdit*>( editor );
187  if ( !lineEdit ) {
188  return;
189  }
190 
191  lineEdit->setText( index.data( Qt::EditRole ).toString() );
192  }
193 }
194 
195 void ContactGroupEditorDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
196 {
197  if ( index.data( ContactGroupModel::IsReferenceRole ).toBool() ) {
198  if ( index.column() == 0 ) {
199  ContactLineEdit *lineEdit = static_cast<ContactLineEdit*>( editor );
200 
201  const bool isReference = lineEdit->isReference();
202  const Item item = lineEdit->completedItem();
203  model->setData( index, isReference, ContactGroupModel::IsReferenceRole );
204  if ( isReference ) {
205  if ( item.isValid() ) {
206  model->setData( index, item.id(), Qt::EditRole );
207  }
208  } else {
209  model->setData( index, lineEdit->text(), Qt::EditRole );
210  }
211  }
212 
213  if ( index.column() == 1 ) {
214  KComboBox *comboBox = qobject_cast<KComboBox*>( editor );
215  if ( !comboBox ) {
216  return;
217  }
218 
219  model->setData( index, comboBox->currentText(), Qt::EditRole );
220  }
221  } else {
222  if ( index.column() == 0 ) {
223  ContactLineEdit *lineEdit = static_cast<ContactLineEdit*>( editor );
224 
225  const bool isReference = lineEdit->isReference();
226  const Item item = lineEdit->completedItem();
227  model->setData( index, isReference, ContactGroupModel::IsReferenceRole );
228  if ( isReference ) {
229  if ( item.isValid() ) {
230  model->setData( index, item.id(), Qt::EditRole );
231  }
232  } else
233  model->setData( index, lineEdit->text(), Qt::EditRole );
234  }
235 
236  if ( index.column() == 1 ) {
237  KLineEdit *lineEdit = qobject_cast<KLineEdit*>( editor );
238  if ( !lineEdit ) {
239  return;
240  }
241 
242  model->setData( index, lineEdit->text(), Qt::EditRole );
243  }
244  }
245 }
246 
247 static bool isLastRow( const QModelIndex &index )
248 {
249  return ( index.row() == ( index.model()->rowCount() - 1 ) );
250 }
251 
252 void ContactGroupEditorDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
253 {
254  QStyledItemDelegate::paint( painter, option, index );
255 
256  if ( index.column() == 1 && !isLastRow( index ) ) {
257  d->mIcon.paint( painter, option.rect, Qt::AlignRight );
258  }
259 }
260 
261 QSize ContactGroupEditorDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
262 {
263  Q_UNUSED( option );
264 
265  QSize hint = QStyledItemDelegate::sizeHint( option, index );
266  hint.setHeight( qMax( hint.height(), d->mButtonSize.height() ) );
267 
268  if ( index.column() == 1 ) {
269  hint.setWidth( hint.width() + d->mButtonSize.width() );
270  }
271 
272  return hint;
273 }
274 
275 bool ContactGroupEditorDelegate::editorEvent( QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index )
276 {
277  if ( index.column() == 1 && !isLastRow( index ) ) {
278  if ( event->type() == QEvent::MouseButtonRelease ) {
279  const QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event );
280  QRect buttonRect = d->mItemView->visualRect( index );
281  buttonRect.setLeft( buttonRect.right() - d->mButtonSize.width() );
282 
283  if ( buttonRect.contains( mouseEvent->pos() ) ) {
284  model->removeRows( index.row(), 1 );
285  QTimer::singleShot( 0, this, SLOT(setFirstColumnAsCurrent()) );
286  return true;
287  }
288  }
289  }
290  return QStyledItemDelegate::editorEvent( event, model, option, index );
291 }
292 
293 void ContactGroupEditorDelegate::completed( QWidget *widget )
294 {
295  emit commitData( widget );
296  emit closeEditor( widget );
297 }
298 
299 void ContactGroupEditorDelegate::setFirstColumnAsCurrent()
300 {
301  d->mItemView->setCurrentIndex( d->mItemView->model()->index( d->mItemView->currentIndex().row(), 0 ) );
302 }
303 
304 #include "moc_contactgroupeditordelegate_p.cpp"
QList::clear
void clear()
QModelIndex
QCompleter::setCaseSensitivity
void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity)
QEvent
QWidget
QAbstractItemModel::rowCount
virtual int rowCount(const QModelIndex &parent) const =0
QSize::setHeight
void setHeight(int height)
QEvent::type
Type type() const
QSize::width
int width() const
QAbstractItemView
QRect::right
int right() const
QVariant::value
T value() const
QMouseEvent
QRect
QModelIndex::isValid
bool isValid() const
QCompleter::setCompletionColumn
void setCompletionColumn(int column)
QStyleOptionViewItem
QObject
QStyledItemDelegate::paint
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
QSize::setWidth
void setWidth(int width)
QPainter
QString::isEmpty
bool isEmpty() const
QModelIndex::row
int row() const
QStyledItemDelegate::sizeHint
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
QRect::contains
bool contains(const QPoint &point, bool proper) const
QString
QStringList
QSize
QSortFilterProxyModel
QStyledItemDelegate::editorEvent
virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
QAbstractItemModel::removeRows
virtual bool removeRows(int row, int count, const QModelIndex &parent)
QModelIndex::model
const QAbstractItemModel * model() const
QVariant::toStringList
QStringList toStringList() const
QModelIndex::data
QVariant data(int role) const
QLatin1String
QSize::height
int height() const
QModelIndex::column
int column() const
QVariant::toBool
bool toBool() const
QAbstractItemModel
QAbstractItemModel::setData
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
QtConcurrent::filter
QFuture< void > filter(Sequence &sequence, FilterFunction filterFunction)
QMouseEvent::pos
const QPoint & pos() const
QCompleter
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QVariant::toString
QString toString() const
QRect::setLeft
void setLeft(int x)
QTimer::singleShot
singleShot
QStyledItemDelegate
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