Akonadi Contacts

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

KDE's Doxygen guidelines are available online.