Making Sink(ed) contacts accessible to Plasma-Phonebook App

Plasma-phonebook is a contacts managing application for Plasma-Mobile. The app gets the data, i.e., contacts from the kpeople library. It acts as backend for the plasma-phonebook app.
The task is to reveal sink contacts, i.e., contacts synced using KDE sink API to kpeople. In other terms, we need to make sink’s contacts database as kpeople’s data-source. Sink is an offline-caching, synchronization and indexing system for calendars, contacts, mails, etc.

** “How contacts are synced using sink?” will be discussed in another blog. **

Here’s what happens. When Plasma-phonebook app is started, an instance of kpeople (the backend) is created, and following which all the datasources of kpeople are called upon to serve their master 😌.
In this case, KPeopleSinkDataSource.

class KPeopleSinkDataSource : public KPeople::BasePersonsDataSource
{
public:
    KPeopleSinkDataSource(QObject *parent, const QVariantList &data);
    virtual ~KPeopleSinkDataSource();
    QString sourcePluginId() const override;
    KPeople::AllContactsMonitor* createAllContactsMonitor() override;
};
QString KPeopleSinkDataSource::sourcePluginId() const
{
    return QStringLiteral("sink");
}
AllContactsMonitor* KPeopleSinkDataSource::createAllContactsMonitor()
{
    return new KPeopleSink();
}

All the logic of program the KPeople-Sink plugin lies in class KPeopleSink, whose temporary instance is returned in function createAllContactsMonitor [line number 14]. This class is inherited from KPeople::AllContactsMonitor. AllContactsMonitor needs to be subclassed by each datasource of kpeople.

All that is to be done is :
1. Fetch the list of addressbooks synced by sink.
2. Get resource-id of these address-books.
3. Fetch the list of contacts for that addressbook
4. Assign a unique URI to every contact
5. Create an object of a class inherited from AbstractContact. AbstractContact is the class to provide the data from a given contact by the backends. It’s virtual function customProperty, a generic method to access a random contact property needs to be defined in the subclass.
6. Emit contactAdded signal.
Contacts are now aadded to kpeople and hence, accessible to plasma-phonebook! Simple \o/

This is what code looks like:

void KPeopleSink::initialSinkContactstoKpeople(){
    //fetch all the addressbooks synced by sink
    const QList<Addressbook&gt; sinkAdressbooks = Sink::Store::read<Addressbook&gt;(Sink::Query());
    Q_FOREACH(const Addressbook sinkAddressbook, sinkAdressbooks){
        //to get resourceId
        QByteArray resourceId = sinkAddressbook.resourceInstanceIdentifier();

        //fetch all the contacts synced by sink
        const QList<Contact&gt; sinkContacts = Sink::Store::read<Contact&gt;(Sink::Query().resourceFilter(resourceId));
        Q_FOREACH (const Contact sinkContact, sinkContacts){
            //get uri
            const QString uri = getUri(sinkContact, resourceId);

            //add uri of contact to set
            m_contactUriHash.insert(uri, sinkContact);

            KPeople::AbstractContact::Ptr contact(new SinkContact(sinkContact));
            Q_EMIT contactAdded(uri,contact);
        }
    }
}

Now, suppose plasma-phonebook app is running and in the meanwhile sink syncs the updated addressbook from server. In that case, next task becomes to make the changes visible in phonebook. We set up a notifier for each resource-id that notifies everytime a contact/addressbook with that resource-id is updated.

m_notifier = new Notifier(resourceId);
m_notifier->registerHandler([=] (const Sink::Notification &notification) {
    if (notification.type == Notification::Info && notification.code == SyncStatus::SyncSuccess) {
        //Add program logic for updated addressbook/contact
    }
});

A hash-table can be maintained to keep track of new contacts being added. Fetch the list of contacts synced by sink. Each time a contact in the list is not present in hash-table, it means a new contact has been added on the server and hence, emit contactAdded signal. New contact will be added to kpeople and hence accessible in plasma-phonebook.

const QList<Contact&gt; sinkContacts = Sink::Store::read<Contact&gt;(Sink::Query().resourceFilter(resourceId));
Q_FOREACH (const Contact sinkContact, sinkContacts){
    const QString uri = getUri(sinkContact, resourceId);
    if(!m_contactUriHash.contains(uri)){
        m_contactUriHash.insert(uri, sinkContact);
        KPeople::AbstractContact::Ptr contact(new SinkContact(sinkContact));
        Q_EMIT contactAdded(uri,contact);
    }
}

Similarly, we can code for cases where a contact is updated or deleted.

And with this, Tada!
Our system for Nextcloud CardDav Integration on Plasma Mobile is here \o/

You can follow the similar procedure if you want to create your own contact datasource for KPeople 🙂

KPeople-Sink plugin’s code is available at: https://invent.kde.org/rpatwal/kpeople-sink
Contributions to the project are welcomed 😀

Advertisements

Nextcloud Login Plugin for PlaMo

With the completion of my first milestone for my GSoC project: Nextcloud Integration on Plasma Mobile, plasma mobile accounts settings now enables the users to add their nextcloud accounts via webview.

Well! didn’t accounts setting already provide the method to add nextcloud/owncloud accounts? Yes, this functionality was already implemented by the owncloud plugin in kaccounts-providers project. Then, why did I re-implement the same thing?
As I mentioned, now accounts can be added via webview.

Why using WebView approach for login is better?
This approach is not only more convenient to implement but, it also makes sure that the application never stores the user’s password. The users can be ensured that their credentials can’t be misused.

Work Flow
Clicking on Add new Account button shows all the accounts plugin options declared by .provider.in files in providers folder of kaccounts-providers.


On choosing nextcloud option, Nextcloud Wizard shows up. On clicking the login option, the server address entered by user is checked and then the WebView is initiated.


On the final login the server redirects to a url of the following format:
nc://login/server:<server>&user:<loginname>&password:<password>
From this URL login name and password that the application must use to login and store securely is fetched. The control is passed back to the wizard. The user is given option to choose whether or not (s)he wants to synchronize the contacts from the server. This is further facilitated and managed by kaccounts-mobile. Once the login is complete, the username, the password and the other data stored in json object is passed to kaccounts-integration. It manages storing all the accounts and displaying saved accounts on plasma-settings Accounts.

My First impression at PlaMo

How Plasma Mobile got my attention?
I remember how my admiration for android turned into disappointment when I got into android development. The realisation, with every new release the patches are built on the broken pieces of android was disheartening. And the water crossed the line when the whole system started disrespecting the users privacy!
Then, I fine day (mid-January 2019) I came to know about Plasma Mobile. When every other attempt at creating an open source mobile platform on the horizon failed, KDE came along with Plasma Mobile. So how could have I resisted to not to using it!
I purchased refurbished Nexus 5X, and here we are today:D

Installation
Currently Plasma Mobile is supported by very small number of devices. It works quite well on Nexus 5x (Bullhead). For installing PlaMo on Bullhead you can follow instructions at docs.plasma-mobile.org/Installation.html.

My asseveration
Operating Plasma Mobile at console level is just like working on Ubuntu/Kubuntu terminal on desktop, and I usually prefer using my PlaMo using Command-line Interface (CLI) because most of the functions work well when controlling via CLI.
Either you can use ‘Konsole’ app for that or control your phone remotely from the computer.Since the Konsole app isn’t very handy as for now, I prefer the second option.
ssh phablet@10.15.19.82
Plasma Mobile is very much an alpha-level product. It can’t be used for daily purpose as of now. But, it is really appreciable that the KDE developers have managed to take a Linux desktop, re-frame it around mobile hardware, and make it work quite well.
This could be something special!

PS: I do not intend to say Plasma Mobile is a full operating system itself (just like Plasma on desktop is not a complete distro). It needs an underlying OS.