diff --git a/src/backends/CMakeLists.txt b/src/backends/CMakeLists.txt --- a/src/backends/CMakeLists.txt +++ b/src/backends/CMakeLists.txt @@ -5,6 +5,7 @@ allcontactsmonitor.cpp defaultcontactmonitor.cpp abstractpersonaction.cpp + abstracteditablecontact.cpp ) add_library (KF5::PeopleBackend ALIAS KF5PeopleBackend) @@ -26,6 +27,7 @@ ecm_generate_headers(KPeopleBackend_CamelCase_HEADERS HEADER_NAMES AbstractContact + AbstractEditableContact AbstractPersonAction AllContactsMonitor BasePersonsDataSource diff --git a/src/backends/abstractcontact.h b/src/backends/abstractcontact.h --- a/src/backends/abstractcontact.h +++ b/src/backends/abstractcontact.h @@ -74,6 +74,9 @@ /** QVariantList property that lists the emails the contact has */ static const QString AllEmailsProperty; + /** QByteArray with the raw vcard information */ + static const QString VCardProperty; + /** * Generic method to access a random contact property * diff --git a/src/backends/abstractcontact.cpp b/src/backends/abstractcontact.cpp --- a/src/backends/abstractcontact.cpp +++ b/src/backends/abstractcontact.cpp @@ -27,6 +27,7 @@ const QString AbstractContact::PresenceProperty = QStringLiteral("presence"); const QString AbstractContact::AllEmailsProperty = QStringLiteral("all-email"); const QString AbstractContact::PictureProperty = QStringLiteral("picture"); +const QString AbstractContact::VCardProperty = QStringLiteral("vcard"); const QString AbstractContact::GroupsProperty = QStringLiteral("all-groups"); AbstractContact::AbstractContact() diff --git a/src/backends/abstracteditablecontact.h b/src/backends/abstracteditablecontact.h new file mode 100644 --- /dev/null +++ b/src/backends/abstracteditablecontact.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2019 Aleix Pol i Gonzalez + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KPEOPLE_ABSTRACT_EDITABLE_CONTACT_H +#define KPEOPLE_ABSTRACT_EDITABLE_CONTACT_H + +#include "abstractcontact.h" +#include + +namespace KPeople +{ +/** + * @brief Additionally to @class AbstractContact features, it will allow us + * to suggest the backend property values for a said key. + * + * @since 5.62 + * @internal + */ + +class KPEOPLEBACKEND_EXPORT AbstractEditableContact : public AbstractContact +{ +public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + AbstractEditableContact(); + virtual ~AbstractEditableContact(); + + /** + * @p key @see AbstractContact for key identifiers + * @p value suggested value + * + * @returns whether the change was successful + */ + virtual bool setCustomProperty(const QString &key, const QVariant &value) = 0; + +private: + Q_DISABLE_COPY(AbstractEditableContact) +}; + +} + +Q_DECLARE_METATYPE(KPeople::AbstractEditableContact::List) +Q_DECLARE_METATYPE(KPeople::AbstractEditableContact::Ptr) + +#endif diff --git a/src/backends/abstracteditablecontact.cpp b/src/backends/abstracteditablecontact.cpp new file mode 100644 --- /dev/null +++ b/src/backends/abstracteditablecontact.cpp @@ -0,0 +1,26 @@ +/* + Copyright (C) 2019 Aleix Pol i Gonzalez + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "abstracteditablecontact.h" + +using namespace KPeople; + +AbstractEditableContact::AbstractEditableContact() +{} + +AbstractEditableContact::~AbstractEditableContact() = default; diff --git a/src/backends/basepersonsdatasource.h b/src/backends/basepersonsdatasource.h --- a/src/backends/basepersonsdatasource.h +++ b/src/backends/basepersonsdatasource.h @@ -71,5 +71,14 @@ BasePersonsDataSourcePrivate *d_ptr; }; +class KPEOPLEBACKEND_EXPORT BasePersonsDataSourceV2 : public BasePersonsDataSource +{ + Q_OBJECT +public: + BasePersonsDataSourceV2(QObject *parent, const QVariantList &args = QVariantList()); + + virtual bool addContact(const QVariantMap &properties) = 0; +}; + } #endif // BASE_PERSONS_DATA_SOURCE_H diff --git a/src/backends/basepersonsdatasource.cpp b/src/backends/basepersonsdatasource.cpp --- a/src/backends/basepersonsdatasource.cpp +++ b/src/backends/basepersonsdatasource.cpp @@ -49,28 +49,33 @@ Q_D(BasePersonsDataSource); //if there is currently no watcher, create one - AllContactsMonitorPtr c; - if (!d->m_allContactsMonitor.toStrongRef()) { + AllContactsMonitorPtr c = d->m_allContactsMonitor.toStrongRef(); + if (!c) { c = AllContactsMonitorPtr(createAllContactsMonitor()); d->m_allContactsMonitor = c; } - return d->m_allContactsMonitor.toStrongRef(); + return c; } ContactMonitorPtr BasePersonsDataSource::contactMonitor(const QString &contactUri) { Q_D(BasePersonsDataSource); - ContactMonitorPtr c; - if (!d->m_contactMonitors[contactUri].toStrongRef()) { + ContactMonitorPtr c = d->m_contactMonitors[contactUri].toStrongRef(); + if (!c) { c = ContactMonitorPtr(createContactMonitor(contactUri)); d->m_contactMonitors[contactUri] = c; } - return d->m_contactMonitors[contactUri].toStrongRef(); + return c; } ContactMonitor *BasePersonsDataSource::createContactMonitor(const QString &contactUri) { return new DefaultContactMonitor(contactUri, allContactsMonitor()); } + +BasePersonsDataSourceV2::BasePersonsDataSourceV2(QObject* parent, const QVariantList& args) + : BasePersonsDataSource(parent, args) +{ +} diff --git a/src/declarative/peopleqmlplugin.cpp b/src/declarative/peopleqmlplugin.cpp --- a/src/declarative/peopleqmlplugin.cpp +++ b/src/declarative/peopleqmlplugin.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "declarativepersondata.h" @@ -43,14 +44,24 @@ Q_ENUM(ActionType) }; +class DeclarativePersonPluginManager : public QObject +{ + Q_OBJECT +public: + Q_SCRIPTABLE bool addContact(const QVariantMap &properties) { + return KPeople::PersonPluginManager::addContact(properties); + } +}; + void PeopleQMLPlugin::registerTypes(const char *uri) { qmlRegisterType(uri, 1, 0, "PersonsModel"); qmlRegisterType(uri, 1, 0, "PersonsSortFilterProxyModel"); qmlRegisterType(uri, 1, 0, "PersonActions"); qmlRegisterType(uri, 1, 0, "PersonData"); qmlRegisterType(); qmlRegisterUncreatableType(uri, 1, 0, "ActionType", QStringLiteral("You cannot create ActionType")); + qmlRegisterSingletonType(uri, 1, 0, "PersonPluginManager", [] (QQmlEngine*, QJSEngine*) -> QObject* { return new DeclarativePersonPluginManager; }); } #include "peopleqmlplugin.moc" diff --git a/src/global.h b/src/global.h --- a/src/global.h +++ b/src/global.h @@ -21,6 +21,7 @@ #include #include +#include #include diff --git a/src/persondata.h b/src/persondata.h --- a/src/persondata.h +++ b/src/persondata.h @@ -50,6 +50,13 @@ Q_PROPERTY(QPixmap photo READ photo NOTIFY dataChanged) Q_PROPERTY(QString presenceIconName READ presenceIconName NOTIFY dataChanged) + /** + * @returns whether setContactCustomProperty can be called on this contact + * + * @since 5.62 + */ + Q_PROPERTY(bool isEditable READ isEditable CONSTANT) + public: /** Creates a Person object from a given ID. * The ID can be either a local application specific ID (such as akonadi://?item=15) @@ -93,6 +100,17 @@ */ Q_SCRIPTABLE QVariant contactCustomProperty(const QString &key) const; + /** + * Sends a desired @p value for the contact according to the @p key. + * It's not necessarily implemented. The back-end gets to decide whether a property + * can be set or not. + * + * @returns whether the property value was changed + * + * @since 5.62 + */ + Q_SCRIPTABLE bool setContactCustomProperty(const QString &key, const QVariant &value); + /** * Returns the contact's online presence. */ @@ -114,6 +132,13 @@ /** Returns all e-mail addresses from the person. */ QStringList allEmails() const; + /** + * @returns whether the contact can be edited. + * + * @since 5.62 + */ + bool isEditable() const; + // struct PhoneNumber { // QString name; // QString number; diff --git a/src/persondata.cpp b/src/persondata.cpp --- a/src/persondata.cpp +++ b/src/persondata.cpp @@ -24,6 +24,7 @@ #include "backends/basepersonsdatasource.h" #include "backends/contactmonitor.h" #include "backends/abstractcontact.h" +#include "backends/abstracteditablecontact.h" #include #include "kpeople_debug.h" @@ -155,6 +156,14 @@ return d->metaContact.personAddressee()->customProperty(key); } +bool KPeople::PersonData::setContactCustomProperty(const QString& key, const QVariant& value) +{ + Q_D(PersonData); + auto contact = dynamic_cast(d->metaContact.personAddressee().data()); + + return contact && contact->setCustomProperty(key, value); +} + QString PersonData::presenceIconName() const { QString contactPresence = contactCustomProperty(QStringLiteral("telepathy-presence")).toString(); @@ -207,3 +216,8 @@ return ret; } +bool KPeople::PersonData::isEditable() const +{ + Q_D(const PersonData); + return dynamic_cast(d->metaContact.personAddressee().constData()); +} diff --git a/src/personmanager_p.h b/src/personmanager_p.h --- a/src/personmanager_p.h +++ b/src/personmanager_p.h @@ -66,6 +66,14 @@ */ QStringList contactsForPersonUri(const QString &personUri) const; + /** + * Creates a contact with the specified @p properties + * + * @since 5.62 + */ + + bool addContact(const QVariantMap &properties); + public Q_SLOTS: //merge all ids (person IDs and contactUris into a single person) //returns the ID that will be created diff --git a/src/personpluginmanager.h b/src/personpluginmanager.h --- a/src/personpluginmanager.h +++ b/src/personpluginmanager.h @@ -23,6 +23,7 @@ #include +#include #include namespace KPeople @@ -68,6 +69,14 @@ * This is for unit tests only */ static void setDataSourcePlugins(const QHash &dataSources); + + /** + * Creates a contact with the specified @p properties + * @returns if it could be done successfully + * + * @since 5.62 + */ + static bool addContact(const QVariantMap &properties); }; } diff --git a/src/personpluginmanager.cpp b/src/personpluginmanager.cpp --- a/src/personpluginmanager.cpp +++ b/src/personpluginmanager.cpp @@ -135,3 +135,16 @@ } return s_instance->dataSourcePlugins.value(sourceId); } + +bool KPeople::PersonPluginManager::addContact(const QVariantMap& properties) +{ + bool ret = false; + for (auto p : qAsConst(s_instance->dataSourcePlugins)) { + auto v2 = dynamic_cast(p); + if (!v2) + continue; + const bool added = v2->addContact(properties); + ret |= added; + } + return ret; +}