Developing for Sailfish OS: Work with calendar and contacts list

Hello! This article is a continuation of cycle of articles, dedicated to developing applications for the mobile platform Sailfish OS. In this article we will talk about managing contacts and calendar events on the device.

Manage contacts


All common mobile operating systems provide APIs to manage contacts stored on the device. And Sailfish OS is no exception. Sailfsh OS provides the ability to store and manage contact data as well as the possibility of transferring contacts between devices.

We, as developers, can access the data contacts using the plugin Nemo QML Plugin Contacts. This plugin allows you to get contacts and edit them. It is worth noting that the plugin does not have a text documentation, therefore, to understand how it works, went directly to the base source code.

Nemo plugins provide access to different services and Sailfish OS. We have already talked about such plugins as Nemo QML Plugin Notification and Nemo QML Plugin D-Bus in our previous articles about job notifications and D-Bus.

Nemo QML Plugin provides four Contacts QML-components:

the

    PeopleModel;

    PeopleNameGroupModel;

    PeopleVCardModel;

    Person.


The first three components from the list are models that can be used to display lists of contacts using the SilicaListViewfor example.

PeopleModel contains information about each contact: name, surname, telephone number, e-mail, date of birth or any information supplied by the user when adding a contact to notebook device. PeopleNameGroupModel contains information only about the names of contacts and how many contacts with a given name is contained in the notebook. And each object in PeopleVCardModel is a kind of "calling card" of the vCard format.

Component Person simply contains contact information.

Let's take a closer look at what data can be retrieved using PeopleModel and Person. Components PeopleNameGroupModel and PeopleVCardModel not provide as much useful information, so we shall not survey them. But You can always read them yourself.

Each model object PeopleModel provides the following information about the contact:

the

    firstName — the contact's name;

    lastName — the name of the contact; the

  • favorite — true if the contact is marked as "chosen", false otherwise;
  • avatar — the path to the image with the avatar of the contact on the device;

    contactId — the contact ID to the database device;

    phoneNumbers — list of telephone numbers for contact;

    emailDetails — information about email addresses.

    person object of type Person containing more information about the contact.


You may have noticed that PeopleModel contains all the fields that may contain contact in the address book of the device. Often for contact, you can specify the date of birth, address and other data. A complete set of these fields contains a component Person:

the
    the
  • id — the ID of the database record;
  • firstName — the contact's name;

    lastName — the name of the contact;

    middleName — the contact's middle name;

    companyName — the name of the company where the contact works;

    role — the contact's position in the company;

    department Department where the contact works; the

  • favorite — true if the contact is marked as "chosen", false otherwise;
  • avatar — the path to the image with the avatar of the contact on the device;

    phoneNumbers — list of telephone numbers for contact;

    emailDetails — information about email addresses.

    birthday — the date of birth of the contact.


We now consider the details how to use the plugin Nemo QML Plugin Contacts directly in the project.

The first thing you need to do is add the plugin to the project dependencies. To do this in the yaml-file in the section Requires add plugin nemo-qml-plugin-contacts-qt5 as follows:

the
...
# Runtime dependencies which are not automatically detected
Requires:
- sailfishsilica-qt5 > = 0.10.9
- nemo-qml-plugin-contacts-qt5
...

Recall that the yaml file is located in the directory rpm/ in the project root.

To use the plugin inside QML code, you must import the module org.nemomobile.contacts.

the
import org.nemomobile.contacts 1.0

And now we can declare and use the components described above.

the
PeopleModel {
id: peopleModel
filterType: PeopleModel.FilterAll
requiredProperty: PeopleModel.PhoneNumberRequired
}
SilicaListView {
anchors.fill: parent
header: PageHeader {title: qsTr("Contacts")}
model: peopleModel
delegate: ListItem {
width: parent.width
Column {
width: parent.width
Label {text: firstName + "" + lastName}
Label {text: qsTr("Phone numbers: ") + phoneNumbers.join(", ")}
}
}
}

This example demonstrates how to create a component PeopleModel and use it as a model for a list of SilicaListView. For PeopleModel we set the property requiredProperty where you specify that you want to obtain information about telephone numbers. Also requiredProperty can be EmailAddressRequired for information on electronic addresses contact. Using the values of FilterAll passed to the property filterType, we extract a list of all contacts. Property filterType can also take FilterFavorites and FilterOnline to retrieve only "favorite" contacts, or only those currently online.

Within the delegate list shown above we can use a model field, such as firstName, lastName and phoneNumbers. The field phoneNumbers is a list of strings, so here we use the method join(), to merge the phone numbers into one string.


To edit a contact you need to make changes in the field person Person model element PeopleModel. Then, call the model object method savePerson(Person person), where the argument you need to pass the modified contact person. In the end, change the contact data will be registered in the database of the device. New contact created in it will not. To add a new contact to the notebook, the device need to create a new object of type Person to save its data in the same way.

events calendar


In addition to the work with contacts, Sailfish OS gives developers the ability to create and view calendar events, share them with friends, set reminders for events.

To work with events calendar plugin is used Nemo QML Plugin Calendar. It allows you to receive information about calendar events and edit them inside their applications. This plugin, as well as the Nemo QML Plugin Contacts, has no textual documentation, and to understand how it works, too, will have based on the source code.

The Nemo QML plugin Calendar Plugin provides several components. In this article we will talk about the main ones, those that allow you to access calendar events and edit them:

the

    AgendaModel;

    CalendarEvent;

    CalendarEventModification; the

  • Calendar.

AgendaModel — component data to represent calendar events. It is commonly used as a model for a list of SilicaListView. AgendaModel has only two properties: startDate and endDate. They are used to select events from a specific time range, i.e. when you set these properties, the model will contain data for a specified period.

the
AgendaModel {
id: agendaModel
startDate: new Date()
endDate: new Date(2018, 0)
}


Elements of model AgendaModel objects are CalendarEvent, each of which contains information about one particular event. CalendarEvent contains the following properties:

the

    displayLabel — the name of the event;

    description — description of the event;

    startTime is the start time of the event;

    endTime — end time of the event;

    allDay — true if the event is marked as an event to "all day"; the

  • location is the event location;
  • the
  • color color, that marked the event in the calendar;
  • uniqueId — unique event ID in the database.


All of these properties are read-only properties. To change events using the CalendarEventModification. It contains exactly the same properties as CalendarEvent, but here all properties can be edited. Also CalendarEventModification has a method save(), which saves the changes to the database.

Calendar — component-singleton that allows you to create, edit, and delete calendar events. Calendar has three functions:

the

    CalendarEventModification createNewEvent();

    CalendarEventModification createModification(CalendarEvent event); the

  • void remove(string uniqueId).

The createNewEvent() creates a new object of type CalendarEventModification, to fill in information about the calendar event. After calling the method save() on the created object will be added a new record to the database device. Thus can be added a new calendar event.

The createModification() allows you to create an object CalendarEventModification based on an existing calendar event object CalendarEvent. As we wrote above, an object of type CalendarEvent cannot be edited, because all of its properties exclusively for reading. That is why to him, and applies the function createModification(), to be able to edit the event. After calling the method save() change events are stored in the database device. A new event will not be created, but will be changed so that made the modification.

The remove() allows you to delete an existing calendar event from the database using its unique id.

As Calendar is a singleton, and create the object there is no need. To invoke methods directly, using only the component name.

the
Calendar.createNewEvent();
Calendar.createModification(event);
Calendar.remove(event.uniqueId);

To add a plugin of the Nemo QML Plugin Calendar in the project dependencies need to specify it in the yaml file, as well as a plug-in for working with contacts.

the
...
# Runtime dependencies which are not automatically detected
Requires:
- sailfishsilica-qt5 > = 0.10.9
- nemo-qml-plugin-calendar-qt5
...

To use the plugin inside QML code, you must import the module org.nemomobile.calendar.

the
import org.nemomobile.calendar 1.0

Let us now consider an example of implementation of displaying a list of calendar events.

the
AgendaModel {
id: agendaModel
startDate: new Date() 
endDate: new Date(2018, 0)
}
SilicaListView {
anchors.fill: parent
header: PageHeader { title: qsTr("Calendar events") }
model: agendaModel
delegate: ListItem {
width: parent.width
contentHeight: column.height
Column {
id: column; 
width: parent.width
Label { text: eventDateTimeToString(event) }
Label { text: event.displayLabel }
Label { text: qsTr("Location: ") + event.location }
}
}
}
eventDateTimeToString function(event) {
return Qt.formatTime(event.startTime, "HH:mm") + " –" 
+ Qt.formatTime(event.endTime, "HH:mm") + "\t" 
+ Qt.formatDate(event.startTime, Qt.SystemLocaleShortDate);
}

This example is similar to that described above with the display of the contact list. Here the same object is created the model and describes the list of SilicaListView. Each list item displays the time and date of a calendar event, the name and location of the event. For formatting and correct displaying of date and time here created JavaScript function eventDateTimeToString(), which accepts the event object CalendarEvent, and using the functions formatTime() and formatDate() provides a string for display.



the
Dialog {
property var eventModification
SilicaFlickable {
// Components ValueButton to set the date, start time and end time of the event. 
TextField {
id: eventLabelTextField
label: qsTr("Event")
text: eventModification.displayLabel
} 
// The TextField component with the id=locationTextField to install the venue. 
}
onAccepted: {
eventModification.displayLabel = eventLabelTextField.text;
eventModification.location = locationTextField.text;
eventModification.save();
}
}

Property eventModification is an object of type CalendarEventModification. It will be a completely empty object, if we create a new event, or it will be the object with data already existing event. To change the properties of this object will be used in dialogue. Next, we introduce the components for editing the event information. Here we use three components ValueButton to edit date values, start time and end time of the event, as well as two components of the TextField to edit the name of event and location of its holding. In your signal handler onAccepted called method save(), retaining all the change events to the database device. Thus we have created a dialog box allowing you to edit events and create new ones.


Now you need to add the ability to open our dialogue. To open the dialog to create a new event we will be using the component PullDownMenu, and to edit the context menu.

Component PullDownMenu is a stretch from the top menu, and more talk about it our article. The menu will, of course, placed on the screen with the list of events will contain only one item "Add new event", clicking on which will open our dialogue.

the
PullDownMenu {
MenuItem {
text: "Add new event"
onClicked: pageStack.push(Qt.resolvedUrl("EditEventDialog.qml"), 
{eventModification: Calendar.createNewEvent()})
}
} 

When clicking on the menu item that invoked the signal handler onClicked, which describes the call that opens the dialog to edit an event, where as the properties eventModification is passed a new object created using the Calendar.createNewEvent(). This will create a new event and passed to the dialogue, where it will be edited.


To edit events, use the context menu of the list items SilicaListView. Create component ContextMenu and add the item "Edit".

the
SilicaListView {
// ...
model: agendaModel
delegate: ListItem {
// ...
menu: ContextMenu {
MenuItem {
text: "Edit"
onClicked: pageStack.push(Qt.resolvedUrl("EditEventDialog.qml"),
{eventMod: Calendar.createModification(event)})
}
}
}
}

By clicking on the "Edit" will open a dialog to edit the event. As a property eventModification pass the object CalendarEventModifiation, created by the method createModification() object Calendar. As a parameter of the function createModification() here we use object event, obtained from the model AgendaModel and all its data will be contained in the new object for editing, which is passed to the dialog.

Also add the ability to delete calendar events. To do this, create another menu item.

the
MenuItem {
text: qsTr("Delete")
onClicked: Calendar.remove(event.uniqueId)
}

By clicking on the menu item "Delete" we remove the event record from the database by calling Calendar.remove(), where as the parameter is passed on the unique event identifier that is contained in the uniqueId. Thus, we implemented the ability to create, edit, and delete calendar events.


Opinion


That's about it. This article demonstrates how to work with contacts and calendar events in Sailfish OS. Despite the fact that for the above-described plug-ins and components there is no textual documentation to understand how to use them will not be easy. In the course of writing the article was created two ready-made example available on GitHub: example contact management and management example events calendar.
Technical questions can be discussed on channel Russian-speaking community of Sailfish OS in Telegram or Facebook page.

Author: Ivan Shields
Article based on information from habrahabr.ru

Comments

Popular posts from this blog

Powershell and Cyrillic in the console (updated)

Active/Passive PostgreSQL Cluster, using Pacemaker, Corosync

Experience with the GPS logger Holux M-241. Working from under Windows, Mac OS X, Linux