Akonadi Contacts

emailaddressselectionwidget.cpp
1 /*
2  This file is part of Akonadi Contact.
3 
4  SPDX-FileCopyrightText: 2010 KDAB
5  SPDX-FileContributor: Tobias Koenig <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "emailaddressselectionwidget.h"
11 
12 #include "emailaddressselection_p.h"
13 #include "emailaddressselectionmodel.h"
14 #include "emailaddressselectionproxymodel_p.h"
15 
16 #include <KLocalizedString>
17 #include <changerecorder.h>
18 #include <contactsfilterproxymodel.h>
19 #include <contactstreemodel.h>
20 #include <controlgui.h>
21 #include <entitydisplayattribute.h>
22 #include <entitytreeview.h>
23 #include <itemfetchscope.h>
24 #include <kcontacts/addressee.h>
25 #include <kcontacts/contactgroup.h>
26 #include <session.h>
27 
28 #include <QHBoxLayout>
29 #include <QHeaderView>
30 #include <QKeyEvent>
31 #include <QLabel>
32 #include <QLineEdit>
33 #include <QTimer>
34 #include <QVBoxLayout>
35 using namespace Akonadi;
36 
37 /**
38  * @internal
39  */
40 class SearchLineEdit : public QLineEdit
41 {
42  Q_OBJECT
43 public:
44  SearchLineEdit(QWidget *receiver, QWidget *parent = nullptr)
45  : QLineEdit(parent)
46  , mReceiver(receiver)
47  {
48  setClearButtonEnabled(true);
49  installEventFilter(this);
50  }
51 
52 protected:
53  void keyPressEvent(QKeyEvent *event) override
54  {
55  if (event->key() == Qt::Key_Down) {
56  QMetaObject::invokeMethod(mReceiver, "setFocus");
57  }
58 
60  }
61  bool eventFilter(QObject *obj, QEvent *event) override
62  {
63  if (obj == this) {
64  if (event->type() == QEvent::KeyPress) {
65  auto e = static_cast<QKeyEvent *>(event);
66  if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
67  const bool stopEvent = (e->modifiers() == Qt::NoButton || e->modifiers() == Qt::KeypadModifier);
68  if (stopEvent) {
69  Q_EMIT returnPressed();
70  }
71  return true;
72  }
73  }
74  }
75  return QObject::eventFilter(obj, event);
76  }
77 
78 private:
79  QWidget *const mReceiver;
80 };
81 
82 /**
83  * @internal
84  */
85 class Q_DECL_HIDDEN EmailAddressSelectionWidget::Private
86 {
87 public:
88  Private(bool showOnlyContactWithEmail, EmailAddressSelectionWidget *qq, QAbstractItemModel *model)
89  : q(qq)
90  , mModel(model)
91  , mShowOnlyContactWithEmail(showOnlyContactWithEmail)
92  {
93  init();
94  }
95 
96  void init();
97 
99  QAbstractItemModel *mModel = nullptr;
100  QLabel *mDescriptionLabel = nullptr;
101  SearchLineEdit *mSearchLine = nullptr;
102  Akonadi::EntityTreeView *mView = nullptr;
103  EmailAddressSelectionProxyModel *mSelectionModel = nullptr;
104  bool mShowOnlyContactWithEmail = false;
105 };
106 
107 void EmailAddressSelectionWidget::Private::init()
108 {
109  // setup internal model if needed
110  if (!mModel) {
111  auto model = new Akonadi::EmailAddressSelectionModel(q);
112  mModel = model->model();
113  }
114 
115  // setup ui
116  auto layout = new QVBoxLayout(q);
117  layout->setContentsMargins(0, 0, 0, 0);
118 
119  mDescriptionLabel = new QLabel;
120  mDescriptionLabel->hide();
121  layout->addWidget(mDescriptionLabel);
122 
123  auto searchLayout = new QHBoxLayout;
124  searchLayout->setContentsMargins(0, 0, 0, 0);
125  layout->addLayout(searchLayout);
126 
127  mView = new Akonadi::EntityTreeView;
129 
130  auto label = new QLabel(i18nc("@label Search in a list of contacts", "Search:"));
131  mSearchLine = new SearchLineEdit(mView);
132  label->setBuddy(mSearchLine);
133  searchLayout->addWidget(label);
134  searchLayout->addWidget(mSearchLine);
135 
136 #ifndef QT_NO_DRAGANDDROP
137  mView->setDragDropMode(QAbstractItemView::NoDragDrop);
138 #endif
139  layout->addWidget(mView);
140 
142  if (mShowOnlyContactWithEmail) {
143  filter->setFilterFlags(ContactsFilterProxyModel::HasEmail);
144  }
145  filter->setMatchFilterContactFlag(ContactsFilterProxyModel::MatchFilterContactFlag::OnlyNameAndEmailsAddresses);
146  filter->setExcludeVirtualCollections(true);
147  filter->setSourceModel(mModel);
148 
149  mSelectionModel = new EmailAddressSelectionProxyModel(q);
150  mSelectionModel->setSourceModel(filter);
151 
152  mView->setModel(mSelectionModel);
153  mView->header()->hide();
154 
155  q->connect(mSearchLine, &QLineEdit::textChanged, filter, &ContactsFilterProxyModel::setFilterString);
156 
157  q->connect(mView, QOverload<const Akonadi::Item &>::of(&Akonadi::EntityTreeView::doubleClicked), q, [this]() {
158  Q_EMIT q->doubleClicked();
159  });
161 
162  mSearchLine->setFocus();
163 
164  if (auto etm = qobject_cast<Akonadi::EntityTreeModel *>(mModel)) {
166  } else {
168  }
169 }
170 
172  : QWidget(parent)
173  , d(new Private(true, this, nullptr))
174 {
175 }
176 
178  : QWidget(parent)
179  , d(new Private(true, this, model))
180 {
181 }
182 
184  : QWidget(parent)
185  , d(new Private(showOnlyContactWithEmail, this, model))
186 {
187 }
188 
190 {
191  delete d;
192 }
193 
195 {
196  EmailAddressSelection::List selections;
197 
198  if (!d->mView->selectionModel()) {
199  return selections;
200  }
201 
202  const QModelIndexList selectedRows = d->mView->selectionModel()->selectedRows(0);
203  for (const QModelIndex &index : selectedRows) {
204  EmailAddressSelection selection;
205  selection.d->mName = index.data(EmailAddressSelectionProxyModel::NameRole).toString();
206  selection.d->mEmailAddress = index.data(EmailAddressSelectionProxyModel::EmailAddressRole).toString();
207  selection.d->mItem = index.data(ContactsTreeModel::ItemRole).value<Akonadi::Item>();
208 
209  if (d->mShowOnlyContactWithEmail) {
210  if (!selection.d->mEmailAddress.isEmpty()) {
211  selections << selection;
212  }
213  } else {
214  selections << selection;
215  }
216  }
217 
218  return selections;
219 }
220 
222 {
223  return d->mSearchLine;
224 }
225 
227 {
228  return d->mView;
229 }
230 
231 #include "emailaddressselectionwidget.moc"
void setFilterString(const QString &filter)
Sets the filter that is used to filter for matching contacts and contact groups.
A proxy model for ContactsTreeModel models.
KeypadModifier
QEvent::Type type() const const
void setContentsMargins(int left, int top, int right, int bottom)
void doubleClicked(const Akonadi::Collection &collection)
An selection of an email address and corresponding name.
NoButton
void textChanged(const QString &text)
EmailAddressSelectionWidget(QWidget *parent=nullptr)
Creates a new email address selection widget.
virtual void keyPressEvent(QKeyEvent *event) override
void collectionTreeFetched(const Akonadi::Collection::List &collections)
EmailAddressSelection::List selectedAddresses() const
Returns the list of selected email addresses.
static void widgetNeedsAkonadi(QWidget *widget)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString label(StandardShortcut id)
QTreeView * view() const
Returns the tree view that is used to list the items.
A widget to select email addresses from Akonadi.
void setEditTriggers(QAbstractItemView::EditTriggers triggers)
virtual bool eventFilter(QObject *watched, QEvent *event)
void hide()
int key() const const
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
void expandAll()
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
QCA_EXPORT void init()
QLineEdit * searchLineEdit() const
Returns the line edit that is used for the search line.
~EmailAddressSelectionWidget() override
Destroys the email address selection widget.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
Key_Down
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Fri Jun 18 2021 23:08:56 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.