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

0001 /*
0002 * Copyright (C) 2012 David Edmundson <kde@davidedmundson.co.uk>
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 St, Fifth Floor, Boston, MA  02110-1301  USA
0017 */
0018 
0019 #include "contacts-list-model.h"
0020 
0021 #include <TelepathyQt/Account>
0022 #include <TelepathyQt/Contact>
0023 #include <TelepathyQt/ContactCapabilities>
0024 #include <TelepathyQt/Connection>
0025 #include <TelepathyQt/ContactManager>
0026 #include <TelepathyQt/AccountSet>
0027 #include "debug.h"
0028 #include <QPixmap>
0029 
0030 #include "contact.h"
0031 #include "presence.h"
0032 #include "types.h"
0033 
0034 class KTp::ContactsListModel::Private
0035 {
0036 public:
0037     Private():
0038         initialized(false)
0039     {
0040     }
0041 
0042     QList<Tp::ContactPtr> contacts;
0043     KTp::GlobalContactManager *contactManager;
0044     bool initialized;
0045 };
0046 
0047 
0048 KTp::ContactsListModel::ContactsListModel(QObject *parent) :
0049     QAbstractListModel(parent),
0050     d(new KTp::ContactsListModel::Private())
0051 {
0052     d->contactManager = nullptr;
0053 }
0054 
0055 KTp::ContactsListModel::~ContactsListModel()
0056 {
0057     delete d;
0058 }
0059 
0060 void KTp::ContactsListModel::setAccountManager(const Tp::AccountManagerPtr &accountManager)
0061 {
0062     d->contactManager = new KTp::GlobalContactManager(accountManager, this);
0063     connect(d->contactManager, SIGNAL(allKnownContactsChanged(Tp::Contacts,Tp::Contacts)), SLOT(onContactsChanged(Tp::Contacts,Tp::Contacts)));
0064 
0065     // If there are no enabled account or no account is online, emit the signal
0066     // directly, because onContactsChanged won't be called
0067     const QList<Tp::AccountPtr> accounts = accountManager->enabledAccounts()->accounts();
0068     if (accounts.isEmpty()) {
0069         d->initialized = true;
0070         Q_EMIT modelInitialized(true);
0071     } else {
0072         Q_FOREACH (const Tp::AccountPtr &account, accounts) {
0073             if (account->isOnline()) {
0074                 return;
0075             }
0076         }
0077 
0078         d->initialized = true;
0079         Q_EMIT modelInitialized(true);
0080     }
0081 }
0082 
0083 int KTp::ContactsListModel::rowCount(const QModelIndex &parent) const
0084 {
0085     if (!parent.isValid()) {
0086         return d->contacts.size();
0087     } else {
0088         return 0;
0089     }
0090 }
0091 
0092 QVariant KTp::ContactsListModel::data(const QModelIndex &index, int role) const
0093 {
0094     int row = index.row();
0095 
0096     if (row >=0 && row < d->contacts.size()) {
0097         const KTp::ContactPtr contact = KTp::ContactPtr::qObjectCast(d->contacts[row]);
0098         Q_ASSERT_X(!contact.isNull(), "KTp::ContactListModel::data()",
0099                    "Failed to cast Tp::ContactPtr to KTp::ContactPtr. Are you using KTp::ContactFactory?");
0100 
0101         switch (role) {
0102         case KTp::RowTypeRole:
0103             return KTp::ContactRowType;
0104         case Qt::DisplayRole:
0105             return contact->alias();
0106        case KTp::IdRole:
0107             return contact->id();
0108 
0109         case KTp::ContactRole:
0110             return QVariant::fromValue(contact);
0111         case KTp::AccountRole:
0112             return QVariant::fromValue(d->contactManager->accountForContact(contact));
0113 
0114         case KTp::ContactClientTypesRole:
0115             return contact->clientTypes();
0116         case KTp::ContactAvatarPathRole:
0117             return contact->avatarData().fileName;
0118         case KTp::ContactAvatarPixmapRole:
0119             return contact->avatarPixmap();
0120         case KTp::ContactGroupsRole:
0121             return contact->groups();
0122 
0123         case KTp::ContactPresenceNameRole:
0124             return contact->presence().displayString();
0125         case KTp::ContactPresenceMessageRole:
0126             return contact->presence().statusMessage();
0127         case KTp::ContactPresenceTypeRole:
0128             return contact->presence().type();
0129         case KTp::ContactPresenceIconRole:
0130             return contact->presence().iconName();
0131 
0132         case KTp::ContactSubscriptionStateRole:
0133             return contact->subscriptionState();
0134           case KTp::ContactPublishStateRole:
0135             return contact->publishState();
0136         case KTp::ContactIsBlockedRole:
0137             return contact->isBlocked();
0138 
0139         case KTp::ContactCanTextChatRole:
0140             return contact->textChatCapability();
0141           case KTp::ContactCanFileTransferRole:
0142             return contact->fileTransferCapability();
0143         case KTp::ContactCanAudioCallRole:
0144             return contact->audioCallCapability();
0145         case KTp::ContactCanVideoCallRole:
0146             return contact->videoCallCapability();
0147         case KTp::ContactTubesRole:
0148             return QStringList() << contact->streamTubeServicesCapability()
0149                                  << contact->dbusTubeServicesCapability();
0150         default:
0151             break;
0152         }
0153     }
0154     return QVariant();
0155 }
0156 
0157 void KTp::ContactsListModel::onContactsChanged(const Tp::Contacts &added, const Tp::Contacts &removed)
0158 {
0159     //add contacts.
0160 
0161     Q_FOREACH(const Tp::ContactPtr &contact_uncasted, added) {
0162         KTp::ContactPtr contact = KTp::ContactPtr::qObjectCast(contact_uncasted);
0163 
0164         connect(contact.data(),
0165                 SIGNAL(aliasChanged(QString)),
0166                 SLOT(onChanged()));
0167         connect(contact.data(),
0168                 SIGNAL(avatarTokenChanged(QString)),
0169                 SLOT(onChanged()));
0170         connect(contact.data(),
0171                 SIGNAL(avatarDataChanged(Tp::AvatarData)),
0172                 SLOT(onChanged()));
0173         connect(contact.data(),
0174                 SIGNAL(presenceChanged(Tp::Presence)),
0175                 SLOT(onChanged()));
0176         connect(contact->manager()->connection()->selfContact().data(),
0177                 SIGNAL(capabilitiesChanged(Tp::ContactCapabilities)),
0178                 SLOT(onChanged()));
0179         connect(contact.data(),
0180                 SIGNAL(capabilitiesChanged(Tp::ContactCapabilities)),
0181                 SLOT(onChanged()));
0182         connect(contact.data(),
0183                 SIGNAL(locationUpdated(Tp::LocationInfo)),
0184                 SLOT(onChanged()));
0185         connect(contact.data(),
0186                 SIGNAL(infoFieldsChanged(Tp::Contact::InfoFields)),
0187                 SLOT(onChanged()));
0188         connect(contact.data(),
0189                 SIGNAL(subscriptionStateChanged(Tp::Contact::PresenceState)),
0190                 SLOT(onChanged()));
0191         connect(contact.data(),
0192                 SIGNAL(publishStateChanged(Tp::Contact::PresenceState,QString)),
0193                 SLOT(onChanged()));
0194         connect(contact.data(),
0195                 SIGNAL(blockStatusChanged(bool)),
0196                 SLOT(onChanged()));
0197         connect(contact.data(),
0198                 SIGNAL(clientTypesChanged(QStringList)),
0199                 SLOT(onChanged()));
0200         connect(contact.data(),
0201                 SIGNAL(addedToGroup(QString)),
0202                 SLOT(onChanged()));
0203         connect(contact.data(),
0204                 SIGNAL(removedFromGroup(QString)),
0205                 SLOT(onChanged()));
0206 
0207         connect(contact.data(),
0208                 SIGNAL(invalidated()),
0209                 SLOT(onConnectionDropped()));
0210     }
0211 
0212     if (added.size() > 0) {
0213         beginInsertRows(QModelIndex(), d->contacts.size(), d->contacts.size() + added.size() -1);
0214         d->contacts.append(added.values());
0215         endInsertRows();
0216     }
0217 
0218     //remove contacts
0219     Q_FOREACH(const Tp::ContactPtr &contact, removed) {
0220         int row = d->contacts.indexOf(contact);
0221         if (row >= 0) { //if contact found in list
0222             beginRemoveRows(QModelIndex(), row, row);
0223             d->contacts.removeOne(contact);
0224             endRemoveRows();
0225         }
0226     }
0227 
0228     if (!d->initialized) {
0229         Q_EMIT modelInitialized(true);
0230         d->initialized = true;
0231     }
0232 }
0233 
0234 void KTp::ContactsListModel::onChanged()
0235 {
0236     KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
0237     int row = d->contacts.indexOf(contact);
0238     if (row > 0) {
0239         QModelIndex index = createIndex(row, 0);
0240         dataChanged(index, index);
0241     }
0242 }
0243 
0244 void KTp::ContactsListModel::onConnectionDropped()
0245 {
0246     KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
0247     onContactsChanged(Tp::Contacts(), Tp::Contacts() << contact);
0248 }
0249