Developing for Sailfish OS: notifications for example apps for taking notes

Hello! This article is a continuation of cycle of articles, dedicated to developing applications for the mobile platform Sailfish OS. This time we will talk about the app for taking notes, allowing the user to keep records, mark the tags, add images, photos, reminders, and sync with Evernote account.

Let's start the article with an extensive user interface applications, and then move on to technical details.

application Description


The main application screen is a list of user records, where each list item shows the title of the notes, a description (or part of it, if the description does not fit completely), and the image if it is added. List items also have a context menu allowing you to delete the note or to open a dialog to edit it. And by clicking on a list item opens a screen showing all the information about this article.
Talk details about the user interface of the application. The main application screen is a list of user records, where each list item shows the title of the notes, a description (or part of it, if the description does not fit completely), and the image if it is added. List items also have a context menu allowing you to delete the note or to open a dialog to edit it. And by clicking on a list item opens a screen showing all the information about this note.
the



The main application screen contains the PullDownMenu and PushUpMenu. In PullDownMenu is only one menu item that opens a dialog to add a new note. In PushUpMenu is two points: the first opens a window with a list of all tags, the second is the settings window.
the



Dialog to add/edit notes contain text boxes for entering tags, title and description, and buttons for adding images, photos and reminders. By clicking on the button "Add a picture" dialog that allows the user to draw or write anything on the screen to add this image to the note. And clicking on "Add a photo" opens the camera device by clicking on the picture is the same as the image is added to the note.
the



A button to add reminder opens a dialog that allows you to configure the date and time of the reminder using the standard components DatePickerDialog and TimePickerDialog.


The screen "Tags" is a list of all tags added to notes. By clicking on a tag in the list we get to a screen that contains only the records tagged with a given tag. All manipulations with notes (view details, edit, delete and add new) available to us and this screen.
the



The settings screen contains one item "Login via Evernote", which, after execution of authentication is changed to "Logout from Evernote" and "Synchronize data". The first allows you to get out of your Evernote account and disable the sync data and the second to start the synchronization process manually. Also, synchronization will start automatically when the data changes.
the


Nemo QML Plugin Notifications


In this article, we decided to focus on the work with notifications in Sailfish OS. To work with notifications Sailfish SDK provides a plug-in Nemo QML Plugin Notifications. The plugin contains two classes:

the
    the
  • QML class Notification to create a notification inside QML code;
  • the
  • C++ class Notification to create a notification inside C++ code.

Class Notification allows you to create instances of notifications that can be used to contact Lipstick Notification Manager using D-Bus. About what D-Bus and how to use it, we wrote from our article. Be sure to read it if you haven't already.

Notifications are generated with the help of some parameters. Here are the main:

the

    appIcon is the path to the application icon that will be displayed along with the notice;

    appName — the name of the application icon in addition to the notification can display it; the

  • summary is the title of the notification displayed in the notification panel;
  • previewSummary is the title of the notification displayed in the banner notification on top of the screen;

    body — the "body" of the notification, its description is displayed in the notification panel;

    previewBody — description of the notification displayed in the banner notification;

    itemCount — number of notifications to be displayed one element. For example, one notification may display up to 4 missed calls, if the parameter itemCount has a value 4;

    timestamp — the timestamp of the event, which is associated with the notification does not affect the creation of the notification itself and not the time when a notification is shown;

    remoteActions — list of objects with properties "name", "service", "path", "iface", "method", "displayName", "icon" and "arguments", defines possible actions by clicking on the notification. Read more about remoteActions discussed below.


All notification settings can be read in official documentation and the following is an example of creating a notification in QML.

the
Button {
Notification {
id: notification
appName: "Example App"
appIcon: "/usr/share/example-app/icon-l-application"
summary: "the Notification summary"
body: "Notification body"
previewSummary: "Notification preview summary"
previewBody: "Notification preview body"
itemCount: 5
timestamp: "2013-02-20 18:21:00"
remoteActions: [{
"name": "default",
"service": "com.example.service",
"path": "/com/example/service",
"iface": "com.example.service",
"method": "trigger"
"arguments": [ "argument 1" ]
}]
}
onClicked: notification.publish()
}

Code is easy to understand that by clicking on the button calls the method publish(). The method publish() publishes our notice in the Notification Manager appears on the screen of the device.

As mentioned above, we can configure the actions associated with the notification. Example, obvious — open the app by clicking on notification. Notifications are through the D-Bus, so the first thing we need to do is create your own D-Bus service. To do this, first, add the project root directory dbus and create there file with extension *.service with the following contents:

the
[D-BUS Service]
Interface=/com/example/service
Name=com.example.service
Exec=/usr/bin/invoker --type=silica-qt5 --desktop-file=example.desktop -s /usr/bin/example

Suggest to use the same name for the service name (the parameter Name) and the name of the file to avoid confusion in the future. Also note that the Exec used of the path to the *.desktop file of your project and the app itself on the device, here is "example" You should use the project name.
Next, you need to register the path to the D-Bus service *.pro the file.

the
...
dbus.files = dbus/com.example.service.service
dbus.path = /usr/share/dbus-1/services/
INSTALLS += dbus
...

And in *.spec file.

the
...
%files
%{_datadir}/dbus-1/services
...

To be able to link the action on a notification app, you need to create DBusAdaptor. DBusAdaptor object, providing the opportunity to interact with D-Bus service.

the
DBusAdaptor {
service: 'com.example.service'
iface: 'com.example.service'
path: '/com/example/service'
xml: '<interface name="com.example.service">\n' +
'<method name="trigger">\n' +
'<arg name="param" type="s" access="readwrite"/>\n"' +
'</method">\n' +
'</interface>\n'

function trigger(param) {
console.log('param:', param);
__silica_applicationwindow_instance.activate();
}
}

Properties service and iface are the name of the registered us D-Bus service and the property path — the path to the service object in the file system of the device. Of particular interest is the property of xml. It describes the contents of the service, namely the name of the method that can be invoked and its arguments. Here we use as a method of service the trigger(), which takes as input a string and outputs it to the console and opens the app to call the method activate() on the object ApplicationWindow.

Now we need to associate our actions with the created notification. This will help us a property remoteActions class Notification.

the
Button {
Notification {
...
remoteActions: [{
"name": "default",
"service": "com.example.service",
"path": "/com/example/service",
"iface": "com.example.service",
"method": "trigger"
"arguments": [ "argument 1" ]
}]
}
onClicked: notification.publish()
}

In remoteActions described the service, path and iface to contact D-Bus service. The parameter method is the name of the service method and in the property arguments pass the parameter list for the method. And that's it. Now clicking on the notification method will be called by D-Bus services with the application.

One feature of the work with notifications is that they appear when closed, the app will require an active daemon Manager service registered at D-Bus. Because after the closure of the service wasregistered. It is written in Sailfish FAQ.

Working with in-app notifications


To implement a notification in the app, we used C++ class Notification. Notifications in the app consist of the title and description of notes, to which is added the reminder, so we are only interested in the following class properties: summary, body, previewSummary and previewBody. Of course we are also interested in the method publish().
the



To manage notifications we created the class NotificationManager containing two methods publishNotification() and removeNotification(). First you need to create and display reminders, the second is to remove the reminder.

It should be noted that the Notification class does not provide functionality to set the display time of the notification, the method publish() displays a notification at exactly the moment when it (the method) has been called. This problem is solved by using a timer (class QTimer) to control the display time of the notification. As well as notes with reminders can be a few, and these timers must be several. Therefore, in the class NotificationManager was created by the hash (QHash) whose key is the id of notes in the database, and the value of QTimer.

the
class NotificationManager : public QObject {
Q_OBJECT
public:
explicit NotificationManager(QObject *parent = 0);
Q_INVOKABLE void publishNotification(const int noteId, const QString &summary,
const QString &body, QDateTime dateTime);
Q_INVOKABLE void removeNotification(const int noteId);
private:
QHash<int, QTimer* > timers;
};

Let us consider the implementation of the method publishNotification(). As arguments it takes the id of notes in the database, the title and description of the notification and the date and time when the notification should be shown.
First, the method creates a new timer and connects it with the signal timeout() with the slot described by a lambda function. In the lambda function is created and the notification setup, as well as calling the method publish(). After the notification was shown, we stop our timer. The same way the method publishNotification() checks whether a timer with this id entry already added in our hash, and if so, removes it from the hash. Next, start the timer and set how long (in milliseconds) it should stop and add a new timer into the hash.

the
void NotificationManager::publishNotification(const int noteId, const QString &summary,
const QString &body, QDateTime dateTime) {
QTimer *timer = new QTimer();
connect(timer, &QTimer::timeout, [summary, body, timer](){
Notification notification;
notification.setSummary(summary);
notification.setBody(body);
notification.setPreviewSummary(summary);
notification.setPreviewBody(body);
notification.the publish();
timer- > stop();
});
if (this->timers.contains(noteId)) removeNotification(noteId);
timer->start(QDateTime::currentDateTime().secsTo(dateTime) * 1000);
this->timers[noteId] = timer;
}

The method removeNotification() looks much easier. As a parameter it accepts only the id of the notes for which you want to remove the notification. The method checks that the timer with the given id already exists in the hash with timers, and if so, stops the timer and removes it from the hash.

the
void NotificationManager::removeNotification(const int noteId) {
if (this->timers.contains(noteId)) {
this->timers.value(noteId)->stop();
this->timers.remove(noteId);
}
}

Opinion


In the result the application was built with broad functionality that allows you to store notes with images, tags and reminders and sync them with Evernote. The app was published in app store, Jolla Harbour called SailNotes and is available for download to everyone. The source code of the application available on GitHub.

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

Комментарии

Популярные сообщения из этого блога

Briefly on how to make your Qt geoservice plugin

Database replication PostgreSQL-based SymmetricDS

Yandex.Widget + adjustIFrameHeight + MooTools