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"