File indexing completed on 2024-04-21 15:02:48

0001 /*
0002     SPDX-FileCopyrightText: 2013 David Edmundson (davidedmundson@kde.org)
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 #include "persondata.h"
0008 
0009 #include "backends/abstractcontact.h"
0010 #include "backends/abstracteditablecontact.h"
0011 #include "backends/basepersonsdatasource.h"
0012 #include "backends/contactmonitor.h"
0013 #include "metacontact_p.h"
0014 #include "personmanager_p.h"
0015 #include "personpluginmanager.h"
0016 
0017 #include "kpeople_debug.h"
0018 
0019 #include <QStandardPaths>
0020 #include <QUrl>
0021 
0022 namespace KPeople
0023 {
0024 class PersonDataPrivate
0025 {
0026 public:
0027     QStringList contactUris;
0028     MetaContact metaContact;
0029     QList<ContactMonitorPtr> watchers;
0030 };
0031 }
0032 
0033 using namespace KPeople;
0034 
0035 KPeople::PersonData::PersonData(const QString &id, QObject *parent)
0036     : QObject(parent)
0037     , d_ptr(new PersonDataPrivate)
0038 {
0039     Q_D(PersonData);
0040 
0041     if (id.isEmpty()) {
0042         return;
0043     }
0044 
0045     QString personUri;
0046     // query DB
0047     if (id.startsWith(QLatin1String("kpeople://"))) {
0048         personUri = id;
0049     } else {
0050         personUri = PersonManager::instance()->personUriForContact(id);
0051     }
0052 
0053     if (personUri.isEmpty()) {
0054         d->contactUris = QStringList() << id;
0055     } else {
0056         d->contactUris = PersonManager::instance()->contactsForPersonUri(personUri);
0057     }
0058 
0059     QMap<QString, AbstractContact::Ptr> contacts;
0060     for (const QString &contactUri : std::as_const(d->contactUris)) {
0061         // load the correct data source for this contact ID
0062         const QString sourceId = QUrl(contactUri).scheme();
0063         Q_ASSERT(!sourceId.isEmpty());
0064         BasePersonsDataSource *dataSource = PersonPluginManager::dataSource(sourceId);
0065         if (dataSource) {
0066             ContactMonitorPtr cw = dataSource->contactMonitor(contactUri);
0067             d->watchers << cw;
0068 
0069             // if the data source already has the contact set it already
0070             // if not it will be loaded when the contactChanged signal is emitted
0071             if (cw->contact()) {
0072                 contacts[contactUri] = cw->contact();
0073             }
0074             connect(cw.data(), SIGNAL(contactChanged()), SLOT(onContactChanged()));
0075         } else {
0076             qCWarning(KPEOPLE_LOG) << "error: creating PersonData for unknown contact" << contactUri << id;
0077         }
0078     }
0079 
0080     if (personUri.isEmpty() && contacts.size() == 1) {
0081         d->metaContact = MetaContact(id, contacts.first());
0082     } else {
0083         d->metaContact = MetaContact(personUri, contacts);
0084     }
0085 }
0086 
0087 PersonData::~PersonData()
0088 {
0089     delete d_ptr;
0090 }
0091 
0092 bool PersonData::isValid() const
0093 {
0094     Q_D(const PersonData);
0095     return !d->metaContact.id().isEmpty();
0096 }
0097 
0098 QString PersonData::personUri() const
0099 {
0100     Q_D(const PersonData);
0101     return d->metaContact.id();
0102 }
0103 
0104 QStringList PersonData::contactUris() const
0105 {
0106     Q_D(const PersonData);
0107     return d->metaContact.contactUris();
0108 }
0109 
0110 void PersonData::onContactChanged()
0111 {
0112     Q_D(PersonData);
0113 
0114     ContactMonitor *watcher = qobject_cast<ContactMonitor *>(sender());
0115     if (!watcher->contact()) {
0116         d->metaContact.removeContact(watcher->contactUri());
0117     } else if (d->metaContact.contactUris().contains(watcher->contactUri())) {
0118 #ifdef __GNUC__
0119 #warning probably not needed anymore
0120 #endif
0121         d->metaContact.updateContact(watcher->contactUri(), watcher->contact());
0122     } else {
0123         d->metaContact.insertContact(watcher->contactUri(), watcher->contact());
0124     }
0125     Q_EMIT dataChanged();
0126 }
0127 
0128 QPixmap PersonData::photo() const
0129 {
0130     QPixmap avatar;
0131 
0132     QVariant pic = contactCustomProperty(AbstractContact::PictureProperty);
0133     if (pic.canConvert<QImage>()) {
0134         avatar = QPixmap::fromImage(pic.value<QImage>());
0135     } else if (pic.canConvert<QUrl>()) {
0136         avatar = QPixmap(pic.toUrl().toLocalFile());
0137     }
0138 
0139     if (avatar.isNull()) {
0140         static QString defaultAvatar = QStringLiteral(":/org.kde.kpeople/pixmaps/dummy_avatar.png");
0141         avatar = QPixmap(defaultAvatar);
0142     }
0143     return avatar;
0144 }
0145 QVariant PersonData::contactCustomProperty(const QString &key) const
0146 {
0147     Q_D(const PersonData);
0148     return d->metaContact.personAddressee()->customProperty(key);
0149 }
0150 
0151 bool KPeople::PersonData::setContactCustomProperty(const QString &key, const QVariant &value)
0152 {
0153     Q_D(PersonData);
0154     auto contact = dynamic_cast<AbstractEditableContact *>(d->metaContact.personAddressee().data());
0155 
0156     return contact && contact->setCustomProperty(key, value);
0157 }
0158 
0159 QString PersonData::presenceIconName() const
0160 {
0161     QString contactPresence = contactCustomProperty(QStringLiteral("telepathy-presence")).toString();
0162     return KPeople::iconNameForPresenceString(contactPresence);
0163 }
0164 
0165 QString PersonData::name() const
0166 {
0167     return contactCustomProperty(AbstractContact::NameProperty).toString();
0168 }
0169 
0170 QString PersonData::presence() const
0171 {
0172     return contactCustomProperty(AbstractContact::PresenceProperty).toString();
0173 }
0174 
0175 QUrl PersonData::pictureUrl() const
0176 {
0177     return contactCustomProperty(AbstractContact::PictureProperty).toUrl();
0178 }
0179 
0180 QString PersonData::email() const
0181 {
0182     return contactCustomProperty(AbstractContact::EmailProperty).toString();
0183 }
0184 
0185 QStringList PersonData::groups() const
0186 {
0187     //     We might want to cache it eventually?
0188 
0189     const QVariantList groups = contactCustomProperty(AbstractContact::GroupsProperty).toList();
0190     QStringList ret;
0191     for (const QVariant &g : groups) {
0192         Q_ASSERT(g.canConvert<QString>());
0193         ret += g.toString();
0194     }
0195     ret.removeDuplicates();
0196     return ret;
0197 }
0198 
0199 QStringList PersonData::allEmails() const
0200 {
0201     const QVariantList emails = contactCustomProperty(AbstractContact::AllEmailsProperty).toList();
0202     QStringList ret;
0203     for (const QVariant &e : emails) {
0204         Q_ASSERT(e.canConvert<QString>());
0205         ret += e.toString();
0206     }
0207     ret.removeDuplicates();
0208     return ret;
0209 }
0210 
0211 bool KPeople::PersonData::isEditable() const
0212 {
0213     Q_D(const PersonData);
0214     return dynamic_cast<const AbstractEditableContact *>(d->metaContact.personAddressee().constData());
0215 }
0216 
0217 #include "moc_persondata.cpp"