Akonadi Contacts

emailaddressselectionwidget.cpp
1/*
2 This file is part of Akonadi Contact.
3
4 SPDX-FileCopyrightText: 2010 KDAB
5 SPDX-FileContributor: Tobias Koenig <tokoe@kde.org>
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 "contactsfilterproxymodel.h"
17#include "contactstreemodel.h"
18#include <Akonadi/ChangeRecorder>
19#include <Akonadi/ControlGui>
20#include <Akonadi/EntityDisplayAttribute>
21#include <Akonadi/EntityTreeView>
22#include <Akonadi/ItemFetchScope>
23#include <Akonadi/Session>
24#include <KLocalizedString>
25
26#include <QHBoxLayout>
27#include <QHeaderView>
28#include <QKeyEvent>
29#include <QLabel>
30#include <QLineEdit>
31#include <QTimer>
32#include <QVBoxLayout>
33using namespace Akonadi;
34using namespace Akonadi;
35/**
36 * @internal
37 */
38class SearchLineEdit : public QLineEdit
39{
41public:
42 SearchLineEdit(QWidget *receiver, QWidget *parent = nullptr)
44 , mReceiver(receiver)
45 {
48 }
49
50protected:
51 void keyPressEvent(QKeyEvent *event) override
52 {
53 if (event->key() == Qt::Key_Down) {
54 QMetaObject::invokeMethod(mReceiver, "setFocus");
55 }
56
58 }
59 bool eventFilter(QObject *obj, QEvent *event) override
60 {
61 if (obj == this) {
62 if (event->type() == QEvent::KeyPress) {
63 auto e = static_cast<QKeyEvent *>(event);
64 if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
65 const bool stopEvent = (e->modifiers() == Qt::NoButton || e->modifiers() == Qt::KeypadModifier);
66 if (stopEvent) {
68 }
69 return true;
70 }
71 }
72 }
73 return QObject::eventFilter(obj, event);
74 }
75
76private:
77 QWidget *const mReceiver;
78};
79
80/**
81 * @internal
82 */
83class Akonadi::EmailAddressSelectionWidgetPrivate
84{
85public:
86 EmailAddressSelectionWidgetPrivate(bool showOnlyContactWithEmail, EmailAddressSelectionWidget *qq, QAbstractItemModel *model)
87 : q(qq)
88 , mModel(model)
89 , mShowOnlyContactWithEmail(showOnlyContactWithEmail)
90 {
91 init();
92 }
93
94 void init();
95
96 EmailAddressSelectionWidget *const q;
97 QAbstractItemModel *mModel = nullptr;
98 QLabel *mDescriptionLabel = nullptr;
99 SearchLineEdit *mSearchLine = nullptr;
100 Akonadi::EntityTreeView *mView = nullptr;
101 EmailAddressSelectionProxyModel *mSelectionModel = nullptr;
102 bool mShowOnlyContactWithEmail = false;
103};
104
105void EmailAddressSelectionWidgetPrivate::init()
106{
107 // setup internal model if needed
108 if (!mModel) {
109 auto model = new Akonadi::EmailAddressSelectionModel(q);
110 mModel = model->model();
111 }
112
113 // setup ui
114 auto layout = new QVBoxLayout(q);
115 layout->setContentsMargins({});
116
117 mDescriptionLabel = new QLabel;
118 mDescriptionLabel->hide();
119 layout->addWidget(mDescriptionLabel);
120
121 auto searchLayout = new QHBoxLayout;
122 searchLayout->setContentsMargins({});
123 layout->addLayout(searchLayout);
124
125 mView = new Akonadi::EntityTreeView;
126 mView->setEditTriggers(Akonadi::EntityTreeView::NoEditTriggers);
127
128 auto label = new QLabel(i18nc("@label Search in a list of contacts", "Search:"));
129 mSearchLine = new SearchLineEdit(mView);
130 mSearchLine->setPlaceholderText(i18nc("@info:placeholder", "Search Contact..."));
131 label->setBuddy(mSearchLine);
132 searchLayout->addWidget(label);
133 searchLayout->addWidget(mSearchLine);
134
135#ifndef QT_NO_DRAGANDDROP
136 mView->setDragDropMode(QAbstractItemView::NoDragDrop);
137#endif
138 layout->addWidget(mView);
139
140 auto filter = new Akonadi::ContactsFilterProxyModel(q);
141 if (mShowOnlyContactWithEmail) {
142 filter->setFilterFlags(ContactsFilterProxyModel::HasEmail);
143 }
144 filter->setMatchFilterContactFlag(ContactsFilterProxyModel::MatchFilterContactFlag::OnlyNameAndEmailsAddresses);
145 filter->setExcludeVirtualCollections(true);
146 filter->setSourceModel(mModel);
147
148 mSelectionModel = new EmailAddressSelectionProxyModel(q);
149 mSelectionModel->setSourceModel(filter);
150
151 mView->setModel(mSelectionModel);
152 mView->header()->hide();
153
154 q->connect(mSearchLine, &QLineEdit::textChanged, filter, &ContactsFilterProxyModel::setFilterString);
155
156 q->connect(mView, qOverload<const Akonadi::Item &>(&Akonadi::EntityTreeView::doubleClicked), q, [this]() {
157 Q_EMIT q->doubleClicked();
158 });
160
161 mSearchLine->setFocus();
162
163 if (auto etm = qobject_cast<Akonadi::EntityTreeModel *>(mModel)) {
165 } else {
167 }
168}
169
171 : QWidget(parent)
172 , d(new EmailAddressSelectionWidgetPrivate(true, this, nullptr))
173{
174}
175
177 : QWidget(parent)
178 , d(new EmailAddressSelectionWidgetPrivate(true, this, model))
179{
180}
181
183 : QWidget(parent)
184 , d(new EmailAddressSelectionWidgetPrivate(showOnlyContactWithEmail, this, model))
185{
186}
187
189
191{
193
194 if (!d->mView->selectionModel()) {
195 return selections;
196 }
197
198 const QModelIndexList selectedRows = d->mView->selectionModel()->selectedRows(0);
199 for (const QModelIndex &index : selectedRows) {
200 EmailAddressSelection selection;
201 selection.setName(index.data(EmailAddressSelectionProxyModel::NameRole).toString());
202 selection.setEmail(index.data(EmailAddressSelectionProxyModel::EmailAddressRole).toString());
203 selection.setItem(index.data(ContactsTreeModel::ItemRole).value<Akonadi::Item>());
204
205 if (d->mShowOnlyContactWithEmail) {
206 if (!selection.email().isEmpty()) {
207 selections << selection;
208 }
209 } else {
210 selections << selection;
211 }
212 }
213
214 return selections;
215}
216
218{
219 return d->mSearchLine;
220}
221
223{
224 return d->mView;
225}
226
227#include "emailaddressselectionwidget.moc"
228
229#include "moc_emailaddressselectionwidget.cpp"
void setFilterString(const QString &filter)
Sets the filter that is used to filter for matching contacts and contact groups.
static void widgetNeedsAkonadi(QWidget *widget)
~EmailAddressSelectionWidget() override
Destroys the email address selection widget.
QLineEdit * searchLineEdit() const
Returns the line edit that is used for the search line.
EmailAddressSelectionWidget(QWidget *parent=nullptr)
Creates a new email address selection widget.
Akonadi::EmailAddressSelection::List selectedAddresses() const
Returns the list of selected email addresses.
QTreeView * view() const
Returns the tree view that is used to list the items.
An selection of an email address and corresponding name.
QList< EmailAddressSelection > List
A list of email address selection objects.
QString email() const
Returns the address part of the selected email address.
void collectionTreeFetched(const Akonadi::Collection::List &collections)
void doubleClicked(const Akonadi::Collection &collection)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
A widget for editing the display name of a contact.
QString label(StandardShortcut id)
QLineEdit(QWidget *parent)
void setClearButtonEnabled(bool enable)
virtual void keyPressEvent(QKeyEvent *event) override
void returnPressed()
void textChanged(const QString &text)
bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
QObject(QObject *parent)
Q_EMITQ_EMIT
Q_OBJECTQ_OBJECT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
virtual bool eventFilter(QObject *watched, QEvent *event)
void installEventFilter(QObject *filterObj)
QObject * parent() const const
bool isEmpty() const const
Key_Down
KeypadModifier
NoButton
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
void expandAll()
QWidget(QWidget *parent, Qt::WindowFlags f)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:55:33 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.