Здравствуйте! Данная статья является продолжением цикла статей, посвященных разработке приложений для мобильной платформы Sailfish OS. В данной статье речь пойдет об управлении контактами и событиями календаря устройства.

Управление контактами


Все распространенные мобильные операционные системы предоставляют API для управления контактами, хранящимися на устройстве. И Sailfish OS не является исключением. Sailfsh OS предоставляет возможность хранения и управления данными контактов, а также возможность переноса контактов между устройствами.

Мы, как разработчики, можем получить доступ к данным контактов с помощью плагина Nemo QML Plugin Contacts. Данный плагин позволяет получать данные о контактах и редактировать их. Стоит отметить, что плагин не имеет текстовой документации, поэтому разбираться с тем, как он работает, пришлось непосредственно на основании исходного кода.

Плагины Nemo предоставляют доступ к различным службам Sailfish OS. Мы уже рассказывали о таких плагинах как Nemo QML Plugin Notification и Nemo QML Plugin D-Bus в наших предыдущих статьях о работе с уведомлениями и системой D-Bus.

Nemo QML Plugin Contacts предоставляет четыре QML-компонента:

  • PeopleModel;
  • PeopleNameGroupModel;
  • PeopleVCardModel;
  • Person.

Первые три компонента из списка являются моделями, которые могут быть использованы для отображения списков контактов с помощью SilicaListView, например.

PeopleModel содержит информацию о каждом контакте: имя, фамилию, номер телефона, e-mail, дату рождения или еще какие-нибудь данные, указанные пользователем при добавлении контакта в записную книжку устройства. PeopleNameGroupModel содержит информацию лишь об именах контактов и о том, сколько контактов с данным именем содержится в записной книжке. А каждый объект в PeopleVCardModel является своего рода «визитной карточкой» формата vCard.

Компонент Person же просто содержит в себе информацию о контакте.

Давайте подробнее остановимся на том, какие данные можно извлечь с помощью PeopleModel и Person. Компоненты PeopleNameGroupModel и PeopleVCardModel не предоставляют так же много полезной информации, поэтому далее мы их рассматривать не будем. Но Вы всегда можете ознакомиться с ними самостоятельно.

Каждый объект модели PeopleModel предоставляет следующие данные о контакте:

  • firstName — имя контакта;
  • lastName — фамилия контакта;
  • favorite — true, если контакт помечен как «избранный», false — в противном случае;
  • avatar — путь до изображения с аватаром контакта на устройстве;
  • contactId — идентификатор контакта в базе данных устройства;
  • phoneNumbers — список номеров телефонов контакта;
  • emailDetails — информация об электронных адресах;
  • person — объект типа Person, содержащий больше информации о контакте.

Возможно, Вы заметили, что PeopleModel содержит не все поля, которые может содержать контакт в записной книжке устройства. Зачастую для контакта можно указать дату рождения, адрес проживания и другие данные. Полный набор таких полей содержит компонент Person:

  • id — идентификатор записи в базе данных;
  • firstName — имя контакта;
  • lastName — фамилия контакта;
  • middleName — отчество контакта;
  • companyName — название компании, где работает контакт;
  • role — должность контакта в компании;
  • department — отдел компании, где работает контакт;
  • favorite — true, если контакт помечен как «избранный», false — в противном случае;
  • avatar — путь до изображения с аватаром контакта на устройстве;
  • phoneNumbers — список номеров телефонов контакта;
  • emailDetails — информация об электронных адресах;
  • addressDetails — информация об адресе проживания;
  • birthday — дата рождения контакта.

Рассмотрим теперь подробнее как использовать плагин Nemo QML Plugin Contacts непосредственно в проекте.

Первое, что необходимо сделать – это добавить плагин в зависимости проекта. Для этого необходимо в yaml-файл в раздел Requires добавить плагин nemo-qml-plugin-contacts-qt5 следующим образом:

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

Напомним, что yaml-файл располагается в директории rpm/ в корне проекта.

Для использования плагина внутри QML-кода необходимо импортировать модуль org.nemomobile.contacts.

import org.nemomobile.contacts 1.0

И теперь мы можем объявлять и использовать компоненты, описанные выше.

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(", ")}
        }
    }
}

Данный пример демонстрирует создание компонента PeopleModel и использование его в качестве модели для списка SilicaListView. Для PeopleModel мы настраиваем свойство requiredProperty где указываем, что необходимо получить информацию о телефонных номерах. Также requiredProperty может принимать значение EmailAddressRequired для получения информации об электронных адресах контакта. С помощью значения FilterAll, переданного в свойство filterType, мы извлекаем список всех контактов. Свойство filterType также может принимать FilterFavorites и FilterOnline для извлечения только «избранных» контактов или только тех, которые сейчас онлайн.

Внутри делегата списка мы показанным выше образом можем использовать поля модели, такие как firstName, lastName и phoneNumbers. Поле phoneNumbers является списком строк, поэтому здесь используется метод join(), для объединения всех номеров телефонов в одну строку.


Для редактирования контакта необходимо внести изменения в поле person типа Person элемента модели PeopleModel. Затем, вызвать на объекте модели метод savePerson(Person person), куда в качестве аргумента необходимо передать измененный контакт person. В итоге, изменения данных контакта будут внесены в базу данных устройства. Новый контакт при этом создан не будет. Для добавления нового контакта в записную книжку устройства нужно создать новый объект типа Person и сохранить его данные аналогичным образом.

Управление событиями календаря


Помимо работы с контактами, Sailfish OS предоставляет разработчикам возможность создавать и просматривать события календаря, делиться ими с друзьями, устанавливать напоминания для событий.

Для работы с событиями календаря используется плагин Nemo QML Plugin Calendar. Он позволяет получать данные о событиях календаря и редактировать их внутри своих приложений. Данный плагин, так же как и Nemo QML Plugin Contacts, не имеет никакой текстовой документации, и разбираться с тем как он работает, тоже придется на основании исходного кода.

Плагин Nemo QML Plugin Calendar предоставляет несколько компонентов. В данной статье мы поговорим об основных из них, тех, что позволяют получить доступ к событиям календаря, а также редактировать их:

  • AgendaModel;
  • CalendarEvent;
  • CalendarEventModification;
  • Calendar.

AgendaModel — компонент для представления данных событий календаря. Обычно он используется в качестве модели для списка SilicaListView. AgendaModel имеет всего два свойства: startDate и endDate. Они служат для выбора событий из определенного временного диапазона, т.е. при установке данных свойств модель будет содержать данные именно за указанный период.

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

Модель, созданная в примере выше, будет содержать информацию о событиях календаря, начиная с текущего дня и заканчивая 1-м января 2018-ого года.

Элементами модели AgendaModel являются объекты CalendarEvent, каждый из которых содержит информацию об одном отдельно взятом событии. CalendarEvent содержит следующие свойства:

  • displayLabel — название события;
  • description — описание события;
  • startTime — время начала события;
  • endTime — время окончания события;
  • allDay — true, если событие помечено как событие на «весь день»;
  • location — место проведения мероприятия;
  • color — цвет, которым помечается событие в календаре;
  • uniqueId — уникальный идентификатор события в базе данных.

Все перечисленные свойства являются свойствами только для чтения. Для изменения же события используется компонент CalendarEventModification. Он содержит ровно те же свойства, что и CalendarEvent, но здесь все свойства могут быть отредактированы. Также CalendarEventModification обладает методом save(), который сохраняет изменения в базе данных.

Calendar — компонент-синглтон, позволяющий создавать, редактировать и удалять события календаря. Calendar имеет три функции:

  • CalendarEventModification createNewEvent();
  • CalendarEventModification createModification(CalendarEvent event);
  • void remove(string uniqueId).

Функция createNewEvent() создает новый объект типа CalendarEventModification, позволяющий заполнять данные о событии календаря. После вызова метода save() на созданном объекте будет добавлена новая запись в базу данных устройства. Таким образом может быть добавлено новое событие календаря.

Функция createModification() позволяет создать объект CalendarEventModification на основе уже существующего события календаря — объекта CalendarEvent. Как мы писали выше, объект типа CalendarEvent не может быть отредактирован, т.к. все его свойства исключительно для чтения. Именно поэтому к нему и применяется функция createModification(), чтобы получить возможность отредактировать событие. После вызова метода save() изменения события будут сохранены в базе данных устройства. Новое событие создано не будет, но будет изменено то, из которого сделали модификацию.

Функция remove() позволяет удалить существующее событие календаря из базы данных, используя его уникальный id.

Так как Calendar является синглтоном, то и создавать объект нет необходимости. Вызывать методы можно напрямую, используя лишь имя компонента.

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

Для добавления плагина Nemo QML Plugin Calendar в зависимости проекта необходимо прописать его в yaml-файле, так же как и плагин для работы с контактами.

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

Для использования плагина внутри QML-кода необходимо импортировать модуль org.nemomobile.calendar.

import org.nemomobile.calendar 1.0

Рассмотрим теперь пример реализации отображения списка событий календаря.

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 }
        }
    }
}
function eventDateTimeToString(event) {
    return Qt.formatTime(event.startTime, "HH:mm") + " – " 
           + Qt.formatTime(event.endTime, "HH:mm") + "\t" 
           + Qt.formatDate(event.startTime, Qt.SystemLocaleShortDate);
}

Данный пример похож на описанный выше с отображением списка контактов. Здесь так же создается объект-модель, и описывается список SilicaListView. Каждый элемент списка отображает время и дату события календаря, его название и местоположение проведения мероприятия. Для форматирования и корректного отображения даты и времени здесь создана JavaScript-функция eventDateTimeToString(), которая принимает на вход объект события CalendarEvent, и с помощью функций formatTime() и formatDate() формирует строку для отображения.


Отображать список событий календаря мы научились. Но помимо этого необходимо иметь возможность добавлять новые события и редактировать существующие. Для этого создадим диалог для добавления и редактирования событий.

Dialog {
    property var eventModification
    SilicaFlickable {
        // Компоненты ValueButton для установки даты, времени начала и времени конца события.           
        TextField {
            id: eventLabelTextField
            label: qsTr("Event")
            text: eventModification.displayLabel
        } 
        // Компонент TextField с id=locationTextField для установки места проведения мероприятия. 
    }
    onAccepted: {
        eventModification.displayLabel = eventLabelTextField.text;
        eventModification.location = locationTextField.text;
        eventModification.save();
    }
}

Свойство eventModification представляет собой объект типа CalendarEventModification. Это будет абсолютно пустой объект, если мы создаем новое событие, либо это будет объект с данными уже существующего события. Для изменения свойств данного объекта будет использоваться диалог. Далее мы описываем компоненты для редактирования информации о событии. Здесь мы используем три компонента ValueButton для редактирования значений даты, времени начала и времени окончания события, а также два компонента TextField для редактирования названия события и местоположения его проведения. В обработчике сигнала onAccepted вызываем метод save(), сохраняющий все изменения события в базу данных устройства. Таким образом мы создали диалоговое окно, позволяющее редактировать события и создавать новые.


Теперь необходимо добавить возможность открывать наш диалог. Открывать диалог для создания нового события мы будем при помощи компонента PullDownMenu, а для редактирования при помощи контекстного меню.

Компонент PullDownMenu представляет собой вытягиваемое сверху меню и подробнее о нем говорилось в одной из наших предыдущих статей. Меню будет, конечно же, помещено на экран со списком событий и будет содержать лишь один пункт «Add new event», по нажатию на который откроется наш диалог.

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

При нажатии на элемент меню вызывается обработчик сигнала onClicked, где описан вызов, открывающий диалог для редактирования события, куда в качестве свойства eventModification передается новый объект созданный с помощью Calendar.createNewEvent(). В итоге будет создано новое событие и передано в диалог, где оно и будет редактироваться.


Для редактирования событий воспользуемся контекстным меню элементов списка SilicaListView. Создадим компонент ContextMenu и добавим к нему пункт «Edit».

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

По нажатию на пункт «Edit» будет открываться диалог для редактирования события. В качестве свойства eventModification передается объект CalendarEventModifiation, созданный с помощью метода createModification() объекта Calendar. В качестве параметра функции createModification() здесь используется объект event, полученный из модели AgendaModel и все его данные будут содержаться в новом объекте для редактирования, который передается в диалог.

Также добавим возможность удаления события календаря. Для этого необходимо создать еще один пункт меню.

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

По нажатию на пункт меню «Delete» мы удаляем запись события из базы данных с помощью вызова Calendar.remove(), куда в качестве параметра передается уникальный идентификатор события, содержащийся в поле uniqueId. Таким образом мы реализовали возможность создания, редактирования и удаления событий календаря.


Заключение


На этом все. Данная статья демонстрирует пример работы с контактами и событиями календаря в Sailfish OS. Несмотря на то, что для описанных выше плагинов и компонентов нет никакой текстовой документации, разобраться с тем как их использовать не составит большого труда. В ходе написания статьи были созданы два готовых примера доступных на GitHub: пример управления контактами и пример управления событиями календаря.

Технические вопросы можно также обсудить на канале русскоязычного сообщества Sailfish OS в Telegram или группе ВКонтакте.

Автор: Иван Щитов
Поделиться с друзьями
-->

Комментарии (0)