Akonadi Contacts

displaynameeditwidget.cpp
1/*
2 This file is part of Contact Editor.
3
4 SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "displaynameeditwidget.h"
10
11#include <QAbstractItemView>
12#include <QEvent>
13#include <QHBoxLayout>
14#include <QPainter>
15#include <QStyledItemDelegate>
16
17#include <KComboBox>
18#include <KLocalizedString>
19using namespace Akonadi;
20// Tries to guess the display type that is used for the passed contact
21static DisplayNameEditWidget::DisplayType guessedDisplayType(const KContacts::Addressee &contact)
22{
23 if (contact.formattedName() == (contact.givenName() + QLatin1Char(' ') + contact.familyName())) {
24 return DisplayNameEditWidget::SimpleName;
25 } else if (contact.formattedName() == contact.assembledName()) {
26 return DisplayNameEditWidget::FullName;
27 } else if (contact.formattedName() == (contact.familyName() + QLatin1StringView(", ") + contact.givenName())) {
28 return DisplayNameEditWidget::ReverseNameWithComma;
29 } else if (contact.formattedName() == (contact.familyName() + QLatin1Char(' ') + contact.givenName())) {
30 return DisplayNameEditWidget::ReverseName;
31 } else if (contact.formattedName() == contact.organization()) {
32 return DisplayNameEditWidget::Organization;
33 } else {
34 return DisplayNameEditWidget::CustomName;
35 }
36}
37
38class DisplayNameDelegate : public QStyledItemDelegate
39{
41public:
42 DisplayNameDelegate(QAbstractItemView *view, QObject *parent = nullptr)
44 {
45 mDescriptions.append(i18n("Short Name"));
46 mDescriptions.append(i18n("Full Name"));
47 mDescriptions.append(i18n("Reverse Name with Comma"));
48 mDescriptions.append(i18n("Reverse Name"));
49 mDescriptions.append(i18n("Organization"));
50 mDescriptions.append(i18nc("@item:inlistbox A custom name format", "Custom"));
51
52 QFont font = view->font();
54 QFontMetrics metrics(font);
55 for (const QString &description : std::as_const(mDescriptions)) {
56 mMaxDescriptionWidth = qMax(mMaxDescriptionWidth, metrics.boundingRect(description).width());
57 }
58
59 mMaxDescriptionWidth += 2;
60 }
61
62 int maximumDescriptionWidth() const
63 {
64 return mMaxDescriptionWidth;
65 }
66
67 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
68 {
69 QStyledItemDelegate::paint(painter, option, index);
70 const QRect rect(option.rect.width() - mMaxDescriptionWidth, option.rect.y(), mMaxDescriptionWidth, option.rect.height());
71 painter->save();
72 QFont font(painter->font());
74 painter->setFont(font);
75 if (option.state & QStyle::State_Selected) {
76 painter->setPen(option.palette.color(QPalette::Normal, QPalette::BrightText));
77 } else {
78 painter->setPen(option.palette.color(QPalette::Disabled, QPalette::Text));
79 }
80 painter->drawText(rect, Qt::AlignLeft, mDescriptions.at(index.row()));
81 painter->restore();
82 }
83
84 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
85 {
86 QSize size = QStyledItemDelegate::sizeHint(option, index);
87 size.setWidth(size.width() + mMaxDescriptionWidth);
88
89 return size;
90 }
91
92private:
93 QStringList mDescriptions;
94 int mMaxDescriptionWidth = 0;
95};
96
97DisplayNameEditWidget::DisplayNameEditWidget(QWidget *parent)
98 : QWidget(parent)
99 , mDisplayType(FullName)
100{
101 auto layout = new QHBoxLayout(this);
102 layout->setContentsMargins({});
103
104 mView = new KComboBox(this);
105 mView->addItems(QStringList() << QString() << QString() << QString() << QString() << QString() << QString());
106
107 layout->addWidget(mView);
108 setFocusProxy(mView);
109 setFocusPolicy(Qt::StrongFocus);
110 connect(mView, &KComboBox::activated, this, &DisplayNameEditWidget::displayTypeChanged);
111
112 auto delegate = new DisplayNameDelegate(mView->view(), this);
113 mView->view()->setItemDelegate(delegate);
114
115 mAdditionalPopupWidth = delegate->maximumDescriptionWidth();
116
117 mViewport = mView->view()->viewport();
118 mViewport->installEventFilter(this);
119}
120
121DisplayNameEditWidget::~DisplayNameEditWidget() = default;
122
123void DisplayNameEditWidget::setReadOnly(bool readOnly)
124{
125 mView->setEnabled(!readOnly);
126}
127
128void DisplayNameEditWidget::setDisplayType(DisplayType type)
129{
130 if ((int)type == -1) {
131 // guess the used display type
132 mDisplayType = guessedDisplayType(mContact);
133 } else {
134 mDisplayType = type;
135 }
136
137 updateView();
138}
139
140DisplayNameEditWidget::DisplayType DisplayNameEditWidget::displayType() const
141{
142 return mDisplayType;
143}
144
145void DisplayNameEditWidget::loadContact(const KContacts::Addressee &contact)
146{
147 mContact = contact;
148
149 mDisplayType = guessedDisplayType(mContact);
150
151 updateView();
152}
153
154void DisplayNameEditWidget::storeContact(KContacts::Addressee &contact) const
155{
156 contact.setFormattedName(mView->currentText());
157}
158
159void DisplayNameEditWidget::changeName(const KContacts::Addressee &contact)
160{
161 const QString organization = mContact.organization();
162 mContact = contact;
163 mContact.setOrganization(organization);
164 if (mDisplayType == CustomName) {
165 mContact.setFormattedName(mView->currentText());
166 }
167
168 updateView();
169}
170
171void DisplayNameEditWidget::changeOrganization(const QString &organization)
172{
173 mContact.setOrganization(organization);
174
175 updateView();
176}
177
178void DisplayNameEditWidget::displayTypeChanged(int type)
179{
180 mDisplayType = (DisplayType)type;
181
182 updateView();
183}
184
185bool DisplayNameEditWidget::eventFilter(QObject *object, QEvent *event)
186{
187 if (object == mViewport) {
188 if (event->type() == QEvent::Show) {
189 // retrieve the widget that contains the popup view
191
192 int maxWidth = 0;
193 QFontMetrics metrics(mView->font());
194 const int viewCount(mView->count());
195 for (int i = 0; i < viewCount; ++i) {
196 maxWidth = qMax(maxWidth, metrics.boundingRect(mView->itemText(i)).width());
197 }
198
199 // resize it to show the complete content
200 parentWidget->resize(maxWidth + mAdditionalPopupWidth + 20, parentWidget->height());
201 }
202 return false;
203 }
204
205 return QWidget::eventFilter(object, event);
206}
207
208void DisplayNameEditWidget::updateView()
209{
210 // SimpleName:
211 mView->setItemText(0, mContact.givenName() + QLatin1Char(' ') + mContact.familyName());
212
213 // FullName:
214 mView->setItemText(1, mContact.assembledName());
215
216 // ReverseNameWithComma:
217 mView->setItemText(2, mContact.familyName() + QStringLiteral(", ") + mContact.givenName());
218
219 // ReverseName:
220 mView->setItemText(3, mContact.familyName() + QLatin1Char(' ') + mContact.givenName());
221
222 // Organization:
223 mView->setItemText(4, mContact.organization());
224
225 // CustomName:
226 mView->setItemText(5, mContact.formattedName());
227
228 // delay the state change here, since we might have been called from mView via a signal
230 this,
231 [this]() {
232 setComboBoxEditable(mDisplayType == CustomName);
233 },
235
236 mView->setCurrentIndex((int)mDisplayType);
237}
238
239void DisplayNameEditWidget::setComboBoxEditable(bool value)
240{
241 mView->setEditable(value);
242}
243
244#include "displaynameeditwidget.moc"
245
246#include "moc_displaynameeditwidget.cpp"
void setEditable(bool editable)
QString familyName() const
void setOrganization(const QString &organization)
QString organization() const
QString assembledName() const
QString formattedName() const
QString givenName() const
void setFormattedName(const QString &formattedName)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
A widget for editing the display name of a contact.
void activated(int index)
void setCurrentIndex(int index)
QString itemText(int index) const const
void setItemText(int index, const QString &text)
void setStyle(Style style)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
int row() const const
Q_OBJECTQ_OBJECT
virtual bool eventFilter(QObject *watched, QEvent *event)
QObject * parent() const const
void drawText(const QPoint &position, const QString &text)
const QFont & font() const const
void restore()
void save()
void setFont(const QFont &font)
void setPen(Qt::PenStyle style)
void setWidth(int width)
int width() const const
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const const override
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const const override
AlignLeft
QueuedConnection
StrongFocus
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setEnabled(bool)
virtual bool event(QEvent *event) override
QWidget * parentWidget() const const
void resize(const QSize &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:08:08 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.