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

0001 /*
0002     Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Lesser General Public
0006     License as published by the Free Software Foundation; either
0007     version 2.1 of the License, or (at your option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful,
0010     but WITHOUT ANY WARRANTY; without even the implied warranty of
0011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012     Lesser General Public License for more details.
0013 
0014     You should have received a copy of the GNU Lesser General Public
0015     License along with this library; if not, write to the Free Software
0016     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0017 */
0018 
0019 
0020 #include "kpeopletranslationproxy.h"
0021 #include "KTp/types.h"
0022 #include "KTp/global-contact-manager.h"
0023 
0024 #include <KPeople/PersonsModel>
0025 #include <KPeopleBackend/AbstractContact>
0026 
0027 #include <KIconLoader>
0028 
0029 #include <QPixmapCache>
0030 
0031 using namespace KPeople;
0032 
0033 
0034 KPeopleTranslationProxy::KPeopleTranslationProxy(QObject *parent)
0035     : QSortFilterProxyModel(parent)
0036 {
0037     setDynamicSortFilter(true);
0038 }
0039 
0040 KPeopleTranslationProxy::~KPeopleTranslationProxy()
0041 {
0042 }
0043 
0044 QVariant KPeopleTranslationProxy::data(const QModelIndex &proxyIndex, int role) const
0045 {
0046     if (!proxyIndex.isValid()) {
0047         return QVariant();
0048     }
0049 
0050 //     IMPersonsDataSource *imPlugin = qobject_cast<IMPersonsDataSource*>(PersonPluginManager::presencePlugin());
0051 //
0052 //     if (!imPlugin) {
0053 //         qCWarning(KTP_MODELS) << "No imPlugin";
0054 //         return QVariant();
0055 //     }
0056 //
0057     const QModelIndex sourceIndex = mapToSource(proxyIndex);
0058     AbstractContact::Ptr contact = sourceIndex.data(KPeople::PersonsModel::PersonVCardRole).value<AbstractContact::Ptr>();
0059 
0060     switch (role) {
0061         case KTp::ContactPresenceTypeRole:
0062             return s_presenceStrings.key(contact->customProperty(S_KPEOPLE_PROPERTY_PRESENCE).toString());
0063         case KTp::ContactPresenceIconRole:
0064             return KPeople::iconNameForPresenceString(contact->customProperty(S_KPEOPLE_PROPERTY_PRESENCE).toString());
0065 //         case KTp::ContactPresenceNameRole:
0066 //             return sourceIndex.data(PersonsModel::PresenceDisplayRole);
0067         case Qt::DisplayRole:
0068             return sourceIndex.data(KPeople::PersonsModel::FormattedNameRole);
0069         case KTp::RowTypeRole:
0070             if (proxyIndex.parent().isValid() || sourceModel()->rowCount(sourceIndex) <= 1) {
0071                 return KTp::ContactRowType;
0072             } else {
0073                 return KTp::PersonRowType;
0074             }
0075 //             //if the person has max 1 child, it's a fake person, so treat it as contact row
0076 //             if (sourceIndex.parent().isValid() || sourceModel()->rowCount(sourceIndex) <= 1) {
0077 //                 return KTp::ContactRowType;
0078 //             } else {
0079 //                 return KTp::PersonRowType;
0080 //             }
0081 //         case KTp::ContactAvatarPathRole:
0082 //             return sourceIndex.data(PersonsModel::PhotosRole);
0083         case KTp::ContactAvatarPixmapRole:
0084             return sourceIndex.data(KPeople::PersonsModel::PhotoRole);
0085         case KTp::ContactUriRole:
0086             return contact->customProperty(S_KPEOPLE_PROPERTY_CONTACT_URI);
0087         case KTp::IdRole:
0088             return contact->customProperty(S_KPEOPLE_PROPERTY_CONTACT_ID);
0089         case KTp::ContactIsBlockedRole:
0090             return contact->customProperty(S_KPEOPLE_PROPERTY_IS_BLOCKED);
0091 //         case KTp::HeaderTotalUsersRole:
0092 //             return sourceModel()->rowCount(sourceIndex);
0093         case KTp::ContactGroupsRole:
0094             return sourceIndex.data(PersonsModel::GroupsRole);
0095         case KTp::PersonIdRole:
0096             return sourceIndex.data(PersonsModel::PersonUriRole);
0097         case KTp::ContactVCardRole:
0098             return sourceIndex.data(KPeople::PersonsModel::PersonVCardRole);
0099     }
0100 
0101     AbstractContact::List contacts = sourceIndex.data(PersonsModel::ContactsVCardRole).value<AbstractContact::List>();
0102 
0103     int mostOnlineIndex = 0;
0104 
0105     for (int i = 0; i < contacts.size(); i++) {
0106         if (KPeople::presenceSortPriority(contact->customProperty(S_KPEOPLE_PROPERTY_PRESENCE).toString())
0107             < KPeople::presenceSortPriority(contacts.at(mostOnlineIndex)->customProperty(S_KPEOPLE_PROPERTY_PRESENCE).toString())) {
0108 
0109             mostOnlineIndex = i;
0110         }
0111     }
0112 
0113     AbstractContact::Ptr informationContact = contacts.isEmpty() ? contact : contacts.at(mostOnlineIndex);
0114     QVariant rValue = dataForKTpContact(informationContact->customProperty(S_KPEOPLE_PROPERTY_ACCOUNT_PATH).toString(),
0115                                informationContact->customProperty(S_KPEOPLE_PROPERTY_CONTACT_ID).toString(),
0116                                role);
0117 
0118     if (rValue.isNull()) {
0119         return sourceIndex.data(role);
0120     } else {
0121         return rValue;
0122     }
0123 }
0124 
0125 QVariant KPeopleTranslationProxy::dataForKTpContact(const QString &accountPath, const QString &contactId, int role) const
0126 {
0127     if (accountPath.isEmpty()) {
0128         return QVariant();
0129     }
0130     if (role == KTp::AccountRole) {
0131         return QVariant::fromValue<Tp::AccountPtr>(KTp::contactManager()->accountForAccountPath(accountPath));
0132     }
0133 
0134     KTp::ContactPtr ktpContact = KTp::contactManager()->contactForContactId(accountPath, contactId);
0135     if (!ktpContact.isNull()) {
0136         switch (role) {
0137         case KTp::ContactRole:
0138             return QVariant::fromValue<KTp::ContactPtr>(ktpContact);
0139             break;
0140         case KTp::ContactPresenceMessageRole:
0141             return ktpContact->presence().statusMessage();
0142             break;
0143         case KTp::ContactIsBlockedRole:
0144             return ktpContact->isBlocked();
0145             break;
0146         case KTp::ContactCanTextChatRole:
0147             return true;
0148             break;
0149         case KTp::ContactCanAudioCallRole:
0150             return ktpContact->audioCallCapability();
0151             break;
0152         case KTp::ContactCanVideoCallRole:
0153             return ktpContact->videoCallCapability();
0154             break;
0155         case KTp::ContactCanFileTransferRole:
0156             return ktpContact->fileTransferCapability();
0157             break;
0158         case KTp::ContactClientTypesRole:
0159             return ktpContact->clientTypes();
0160             break;
0161         }
0162     }
0163 
0164     return QVariant();
0165 }
0166 
0167 bool KPeopleTranslationProxy::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
0168 {
0169     QModelIndex sourceIndex = sourceModel()->index(source_row, 0, source_parent);
0170 
0171     //if no valid presence (not even "offline") .. reject the contact
0172     return !sourceIndex.data(KPeople::PersonsModel::PersonVCardRole).value<KPeople::AbstractContact::Ptr>()->customProperty(S_KPEOPLE_PROPERTY_PRESENCE).isNull();
0173 }
0174 
0175 QVariant KPeopleTranslationProxy::translatePresence(const QVariant &/*presenceName*/) const
0176 {
0177     return Tp::ConnectionPresenceTypeOffline;
0178 }
0179 
0180 QPixmap KPeopleTranslationProxy::contactPixmap(const QModelIndex &index) const
0181 {
0182     QPixmap avatar;
0183 
0184     int presenceType = index.data(KTp::ContactPresenceTypeRole).toInt();
0185     //we need some ID to generate proper cache key for this contact
0186     //so we'll use the contact's uri
0187     const QString id = index.data(KTp::IdRole).toString();
0188 
0189     //key for the pixmap cache, so we can look up the avatar
0190     const QString keyCache = id + (presenceType == Tp::ConnectionPresenceTypeOffline ? QLatin1String("-offline") : QLatin1String("-online"));
0191 
0192     //check pixmap cache for the avatar, if not present, load the avatar
0193     if (!QPixmapCache::find(keyCache, avatar)){
0194         const QVariantList files = index.data(KTp::ContactAvatarPathRole).toList();
0195         QString file;
0196         if (!files.isEmpty()) {
0197             file = files.first().toUrl().toLocalFile();
0198         }
0199 
0200         //QPixmap::load() checks for empty path
0201         avatar.load(file);
0202 
0203         //if the above didn't succeed, we need to load the generic icon
0204         if (avatar.isNull()) {
0205             avatar = KIconLoader::global()->loadIcon(QLatin1String("im-user"), KIconLoader::NoGroup, 96);
0206         }
0207 
0208         //if the contact is offline, gray it out
0209         if (presenceType == Tp::ConnectionPresenceTypeOffline) {
0210             QImage image = avatar.toImage();
0211             const QImage alpha = image.alphaChannel();
0212             for (int i = 0; i < image.width(); ++i) {
0213                 for (int j = 0; j < image.height(); ++j) {
0214                     int colour = qGray(image.pixel(i, j));
0215                     image.setPixel(i, j, qRgb(colour, colour, colour));
0216                 }
0217             }
0218             image.setAlphaChannel(alpha);
0219             avatar = avatar.fromImage(image);
0220         }
0221 
0222         //insert the contact into pixmap cache for faster lookup
0223         QPixmapCache::insert(keyCache, avatar);
0224     }
0225 
0226     return avatar;
0227 }