File indexing completed on 2023-11-26 08:16:46

0001 /*
0002  * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
0003  * Copyright (C) 2012 Daniele E. Domenichelli <daniele.domenichelli@gmail.com>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public
0016  * License along with this library; if not, write to the Free Software
0017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
0018  */
0019 
0020 
0021 #include "contact-view-widget.h"
0022 
0023 #include <QLineEdit>
0024 #include <QTextOption>
0025 #include <QPainter>
0026 #include <QtWidgets/QApplication>
0027 #include <QtWidgets/QVBoxLayout>
0028 
0029 #include "types.h"
0030 #include <KTp/Models/contacts-list-model.h>
0031 #include <KTp/Models/contacts-filter-model.h>
0032 
0033 namespace KTp {
0034 
0035 class ContactViewDelegate : public QAbstractItemDelegate
0036 {
0037     Q_OBJECT
0038     Q_DISABLE_COPY(ContactViewDelegate)
0039 
0040 public:
0041     ContactViewDelegate(QObject *parent);
0042     ~ContactViewDelegate() override;
0043 
0044     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
0045     QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
0046 
0047 }; // class ContactViewDelegate
0048 
0049 } // namespace KTp
0050 
0051 
0052 KTp::ContactViewDelegate::ContactViewDelegate(QObject *parent)
0053     : QAbstractItemDelegate(parent)
0054 {
0055 }
0056 
0057 KTp::ContactViewDelegate::~ContactViewDelegate()
0058 {
0059 }
0060 
0061 void KTp::ContactViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
0062 {
0063     QStyle *style = QApplication::style();
0064     int textHeight = option.fontMetrics.height() * 2;
0065 
0066     style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter);
0067 
0068     QRect avatarRect = option.rect.adjusted(0, 0, 0, -textHeight);
0069     QRect textRect = option.rect.adjusted(0, option.rect.height() - textHeight, 0, -3);
0070 
0071     QPixmap avatar;
0072     avatar.load(index.data(KTp::ContactAvatarPathRole).toString());
0073     if (avatar.isNull()) {
0074         avatar = QIcon::fromTheme(QStringLiteral("im-user-online")).pixmap(option.decorationSize);
0075     } else if (avatar.width() > option.decorationSize.width() || avatar.height() > option.decorationSize.height()) {
0076         //resize larger avatars if required
0077         avatar = avatar.scaled(option.decorationSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
0078         //draw leaving paddings on smaller (or non square) avatars
0079     }
0080     style->drawItemPixmap(painter, avatarRect, Qt::AlignCenter, avatar);
0081 
0082 
0083     QTextOption textOption;
0084     textOption.setAlignment(Qt::AlignCenter);
0085     textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
0086     painter->drawText(textRect, index.data().toString(), textOption);
0087 
0088 }
0089 
0090 QSize KTp::ContactViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
0091 {
0092     Q_UNUSED(index);
0093     int textHeight = option.fontMetrics.height() * 2;
0094     return QSize(option.decorationSize.width() + 4, option.decorationSize.height() + textHeight + 3);
0095 }
0096 
0097 // -----------------------------------------------------------------------------
0098 
0099 class KTp::ContactViewWidget::Private
0100 {
0101 public:
0102     Private(KTp::ContactViewWidget *parent)
0103         : q(parent),
0104           layout(new QVBoxLayout(parent)),
0105           contactView(new QListView(parent)),
0106           contactFilterLineEdit(new QLineEdit(parent)),
0107           contactsModel(nullptr),
0108           filterModel(nullptr)
0109     {
0110     }
0111 
0112     ~Private()
0113     {
0114     }
0115 
0116     void _k_onSelectionChanged(const QItemSelection &newSelection, const QItemSelection &oldSelection);
0117     void _k_onDoubleClicked(const QModelIndex &index);
0118 
0119     KTp::ContactViewWidget *q;
0120     QVBoxLayout *layout;
0121     QListView *contactView;
0122     QLineEdit *contactFilterLineEdit;
0123     KTp::ContactsListModel *contactsModel;
0124     KTp::ContactsFilterModel *filterModel;
0125 };
0126 
0127 void KTp::ContactViewWidget::Private::_k_onSelectionChanged(const QItemSelection &newSelection,
0128                                                             const QItemSelection &oldSelection)
0129 {
0130     Q_UNUSED(oldSelection)
0131 
0132     if (newSelection.isEmpty()) {
0133         Q_EMIT q->selectionChanged(Tp::AccountPtr(), KTp::ContactPtr());
0134         return;
0135     }
0136 
0137     Q_EMIT q->selectionChanged(q->selectedAccount(), q->selectedContact());
0138 }
0139 
0140 void KTp::ContactViewWidget::Private::_k_onDoubleClicked(const QModelIndex& index)
0141 {
0142     if (!index.isValid()) {
0143         return;
0144     }
0145 
0146     Q_EMIT q->contactDoubleClicked(index.data(KTp::AccountRole).value<Tp::AccountPtr>(),
0147                                    index.data(KTp::ContactRole).value<KTp::ContactPtr>());
0148 }
0149 
0150 
0151 // -----------------------------------------------------------------------------
0152 
0153 KTp::ContactViewWidget::ContactViewWidget(KTp::ContactsListModel* model, QWidget *parent)
0154     : QWidget(parent),
0155       d(new Private(this))
0156 {
0157     d->filterModel = new KTp::ContactsFilterModel(this);
0158 
0159     d->contactsModel = model;
0160     d->filterModel->setSourceModel(d->contactsModel);
0161 
0162     d->contactView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0163     d->contactView->setResizeMode(QListView::Adjust);
0164     d->contactView->setSpacing(5);
0165     d->contactView->setViewMode(QListView::ListMode);
0166     d->contactView->setIconSize(QSize(80, 80));
0167 
0168     d->contactFilterLineEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
0169     d->contactFilterLineEdit->setClearButtonEnabled(true);
0170 
0171     d->layout->setMargin(0);
0172     d->layout->addWidget(d->contactView);
0173     d->layout->addWidget(d->contactFilterLineEdit);
0174     setLayout(d->layout);
0175 
0176     d->contactView->setModel(d->filterModel);
0177     d->contactView->setItemDelegate(new ContactViewDelegate(d->contactView));
0178 
0179     connect(d->contactView->selectionModel(),
0180             SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
0181             SLOT(_k_onSelectionChanged(QItemSelection,QItemSelection)));
0182     connect(d->contactView,
0183             SIGNAL(doubleClicked(QModelIndex)),
0184             SLOT(_k_onDoubleClicked(QModelIndex)));
0185 
0186     connect(d->contactFilterLineEdit,
0187             SIGNAL(textChanged(QString)),
0188             d->filterModel,
0189             SLOT(setDisplayNameFilterString(QString)));
0190 }
0191 
0192 KTp::ContactViewWidget::~ContactViewWidget()
0193 {
0194     delete d;
0195 }
0196 
0197 QString KTp::ContactViewWidget::displayNameFilter() const
0198 {
0199     return d->contactFilterLineEdit->text();
0200 }
0201 
0202 void KTp::ContactViewWidget::clearDisplayNameFilter()
0203 {
0204     setDisplayNameFilter(QString());
0205 }
0206 
0207 void KTp::ContactViewWidget::setDisplayNameFilter(const QString& displayNameFilter)
0208 {
0209     if (displayNameFilter != d->contactFilterLineEdit->text()) {
0210         d->contactFilterLineEdit->setText(displayNameFilter);
0211         Q_EMIT displayNameFilterChanged(displayNameFilter);
0212     }
0213 }
0214 
0215 QSize KTp::ContactViewWidget::iconSize() const
0216 {
0217     return d->contactView->iconSize();
0218 }
0219 
0220 void KTp::ContactViewWidget::setIconSize(const QSize& iconSize)
0221 {
0222     if (iconSize != d->contactView->iconSize()) {
0223         d->contactView->setIconSize(iconSize);
0224         Q_EMIT iconSizeChanged(iconSize);
0225     }
0226 }
0227 
0228 bool KTp::ContactViewWidget::hasSelection() const
0229 {
0230     return d->contactView->selectionModel()->hasSelection();
0231 }
0232 
0233 Tp::AccountPtr KTp::ContactViewWidget::selectedAccount() const
0234 {
0235     return d->contactView->currentIndex().data(KTp::AccountRole).value<Tp::AccountPtr>();
0236 }
0237 
0238 KTp::ContactPtr KTp::ContactViewWidget::selectedContact() const
0239 {
0240     return d->contactView->currentIndex().data(KTp::ContactRole).value<KTp::ContactPtr>();
0241 }
0242 
0243 QList<KTp::ContactPtr> KTp::ContactViewWidget::selectedContacts() const
0244 {
0245     QList<KTp::ContactPtr> selected;
0246 
0247     Q_FOREACH (const QModelIndex &index, d->contactView->selectionModel()->selectedIndexes()) {
0248         selected << index.data(KTp::ContactRole).value<KTp::ContactPtr>();
0249     }
0250     return selected;
0251 }
0252 
0253 void KTp::ContactViewWidget::setViewMode(QListView::ViewMode mode)
0254 {
0255     d->contactView->setViewMode(mode);
0256 }
0257 
0258 QListView::ViewMode KTp::ContactViewWidget::viewMode() const
0259 {
0260     return d->contactView->viewMode();
0261 }
0262 
0263 QAbstractItemView::SelectionMode KTp::ContactViewWidget::selectionMode()
0264 {
0265     return d->contactView->selectionMode();
0266 }
0267 
0268 void KTp::ContactViewWidget::setSelectionMode(QAbstractItemView::SelectionMode mode)
0269 {
0270     d->contactView->setSelectionMode(mode);
0271 }
0272 
0273 KTp::ContactsFilterModel* KTp::ContactViewWidget::filter() const
0274 {
0275     return d->filterModel;
0276 }
0277 
0278 QLineEdit* KTp::ContactViewWidget::contactFilterLineEdit() const
0279 {
0280     return d->contactFilterLineEdit;
0281 }
0282 
0283 #include "contact-view-widget.moc"
0284 #include "moc_contact-view-widget.cpp"