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 <Akonadi/ChangeRecorder>
17 #include <Akonadi/ControlGui>
18 #include <Akonadi/EntityDisplayAttribute>
19 #include <Akonadi/EntityTreeView>
20 #include <Akonadi/ItemFetchScope>
21 #include <Akonadi/Session>
22 #include <KContacts/Addressee>
23 #include <KContacts/ContactGroup>
24 #include <KLocalizedString>
25 #include <contactsfilterproxymodel.h>
26 #include <contactstreemodel.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 Akonadi::EmailAddressSelectionWidgetPrivate
86 {
87 public:
88  EmailAddressSelectionWidgetPrivate(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 EmailAddressSelectionWidgetPrivate::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({});
118 
119  mDescriptionLabel = new QLabel;
120  mDescriptionLabel->hide();
121  layout->addWidget(mDescriptionLabel);
122 
123  auto searchLayout = new QHBoxLayout;
124  searchLayout->setContentsMargins({});
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  mSearchLine->setPlaceholderText(i18n("Search Contact..."));
133  label->setBuddy(mSearchLine);
134  searchLayout->addWidget(label);
135  searchLayout->addWidget(mSearchLine);
136 
137 #ifndef QT_NO_DRAGANDDROP
138  mView->setDragDropMode(QAbstractItemView::NoDragDrop);
139 #endif
140  layout->addWidget(mView);
141 
143  if (mShowOnlyContactWithEmail) {
144  filter->setFilterFlags(ContactsFilterProxyModel::HasEmail);
145  }
146  filter->setMatchFilterContactFlag(ContactsFilterProxyModel::MatchFilterContactFlag::OnlyNameAndEmailsAddresses);
147  filter->setExcludeVirtualCollections(true);
148  filter->setSourceModel(mModel);
149 
150  mSelectionModel = new EmailAddressSelectionProxyModel(q);
151  mSelectionModel->setSourceModel(filter);
152 
153  mView->setModel(mSelectionModel);
154  mView->header()->hide();
155 
156  q->connect(mSearchLine, &QLineEdit::textChanged, filter, &ContactsFilterProxyModel::setFilterString);
157 
158  q->connect(mView, qOverload<const Akonadi::Item &>(&Akonadi::EntityTreeView::doubleClicked), q, [this]() {
159  Q_EMIT q->doubleClicked();
160  });
162 
163  mSearchLine->setFocus();
164 
165  if (auto etm = qobject_cast<Akonadi::EntityTreeModel *>(mModel)) {
167  } else {
169  }
170 }
171 
173  : QWidget(parent)
174  , d(new EmailAddressSelectionWidgetPrivate(true, this, nullptr))
175 {
176 }
177 
179  : QWidget(parent)
180  , d(new EmailAddressSelectionWidgetPrivate(true, this, model))
181 {
182 }
183 
185  : QWidget(parent)
186  , d(new EmailAddressSelectionWidgetPrivate(showOnlyContactWithEmail, this, model))
187 {
188 }
189 
191 
193 {
194  EmailAddressSelection::List selections;
195 
196  if (!d->mView->selectionModel()) {
197  return selections;
198  }
199 
200  const QModelIndexList selectedRows = d->mView->selectionModel()->selectedRows(0);
201  for (const QModelIndex &index : selectedRows) {
202  EmailAddressSelection selection;
203  selection.d->mName = index.data(EmailAddressSelectionProxyModel::NameRole).toString();
204  selection.d->mEmailAddress = index.data(EmailAddressSelectionProxyModel::EmailAddressRole).toString();
205  selection.d->mItem = index.data(ContactsTreeModel::ItemRole).value<Akonadi::Item>();
206 
207  if (d->mShowOnlyContactWithEmail) {
208  if (!selection.d->mEmailAddress.isEmpty()) {
209  selections << selection;
210  }
211  } else {
212  selections << selection;
213  }
214  }
215 
216  return selections;
217 }
218 
220 {
221  return d->mSearchLine;
222 }
223 
225 {
226  return d->mView;
227 }
228 
229 #include "emailaddressselectionwidget.moc"
static void widgetNeedsAkonadi(QWidget *widget)
QTreeView * view() const
Returns the tree view that is used to list the items.
An selection of an email address and corresponding name.
virtual void keyPressEvent(QKeyEvent *event) override
NoButton
void collectionTreeFetched(const Akonadi::Collection::List &collections)
A widget to select email addresses from Akonadi.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void hide()
void setFilterString(const QString &filter)
Sets the filter that is used to filter for matching contacts and contact groups.
void expandAll()
virtual bool eventFilter(QObject *watched, QEvent *event)
A proxy model for ContactsTreeModel models.
QString i18n(const char *text, const TYPE &arg...)
void textChanged(const QString &text)
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
void init(KXmlGuiWindow *window, KgDifficulty *difficulty=nullptr)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
Key_Down
QString label(StandardShortcut id)
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)
EmailAddressSelectionWidget(QWidget *parent=nullptr)
Creates a new email address selection widget.
void setContentsMargins(int left, int top, int right, int bottom)
QLineEdit * searchLineEdit() const
Returns the line edit that is used for the search line.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void doubleClicked(const Akonadi::Collection &collection)
void setEditTriggers(QAbstractItemView::EditTriggers triggers)
KeypadModifier
~EmailAddressSelectionWidget() override
Destroys the email address selection widget.
EmailAddressSelection::List selectedAddresses() const
Returns the list of selected email addresses.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sat Apr 1 2023 04:09:05 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.