File indexing completed on 2024-05-05 03:57:10
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"