Разработка для SailfishOS: таймеры и реализация экспорта в файл
Описание приложения
Приложение, естественно, должно уметь вести журнал задач с возможность сохранения времени, потраченного на них. Желательно было, чтобы время можно было засекать с помощью встроенного таймера, а не только прописывать руками. Кроме этого, планировалась возможность создание текстовых отчетов о проделанной работе, в виде таблиц, с последующей отправкой их работодателю.
Так как разработка самой структуры приложения и его интерфейса уже была описана в предыдущих статьях цикла разработки для Sailfish OS (путь от начала разработки до создания первого приложения вы можете отследить здесь и тут), то в этой статье будет описан только функционал, который отличается от реализованного ранее и наиболее интересен с точки зрения его реализации. В нашем приложении — это таймеры задач и экспорт списка задач.
Таймер
Для измерения длительности работ в приложении используется механизм таймера. Процесс отсчета времени осуществляется с помощью стандартного элемента Qt Timer, у которого выставлен интервал обновления 1000 миллисекунд.
Timer {
id: stopwatch
interval: 1000
repeat: true
running: true
triggeredOnStart: true
onTriggered: {
if (timerActive) {
var currentTime = new Date ();
var differeceInTime = (currentTime.getTime() - previousTime.getTime());
previousTime = currentTime;
updateData(differentInTime);
}
}
}
function updateData(usec) {
elapsedTime += usec;
taskTimerString = getTimeString(elapsedTime);
}
При каждом срабатывании события onTriggered у Timer происходит вычисление времени таймера: из текущего времени вычитается время предыдущего срабатывания. Такая реализация удобна тем, что при выходе устройства из неактивного режима, время корректно будет обновлятся.
Для управления таймером сделаны кнопки Старт и Сбросить. Так же есть возможность поставить активный таймер на паузу. Чтобы сохранить замеренное время достаточно нажать на кнопку Сохранить время, доступную в выпадающем меню. Замер таймера автоматически добавится к текущему времени, потраченному на задачу.
Если пользователь пытается запустить новый таймер, пока активен старый, то будет выведен диалог с возможностью выбрать, как поступить со старым таймером: сбросить данные старого таймера и начать новый, сохранить данные старого таймера и начать новый, перейти к старому таймеру.
Также, если таймер активен, то он отображается на обложке приложения.
Экспорт отчетов
В приложении также реализована функция создания отчетов. Отчет представляет из себя таблицу, содержащую информацию о всех хранящихся в приложении задачах. В таблицу записываются даты начала и окончания задачи, ее название и описание, статус задачи, а также время, потраченное на нее. Список задач берется напрямую из базы данных, при этом задачи выбираются из промежутка, который пользователь сам указывает на экране создания отчетов.
function selectByPeriod(beginning, end) {
var database = getDatabase();
queryResult.clear();
database.transaction(function(transaction) {
var tasks = transaction.executeSql('SELECT * FROM tasks WHERE startDate >= ? AND finishDate <= ?', [beginning, end]);
for (var i = 0; i < tasks.rows.length; i++) {
var element = tasks.rows.item(i);
var startDate = new Date (element.startDate);
var finishDate = new Date (element.finishDate);
convertDateToUTC(startDate);
convertDateToUTC(finishDate);
var idDone = element.taskDone === 0 ? false : true
queryResult.append({"startDate": startDate, "finishDate": finishDate, "taskName": element.taskName, "taskDescription": element.taskDescription, "taskDone": isDone, "spentTime": element.spentTime});
}
})
}
Есть возможность записывать отчеты в файлы двух типов: csv и html. Выбор формата исходного файла происходит также на экране создания отчетов. Для каждого из типов реализован c++ класс, отвечающий за создание соответствующего файла. Запись в csv файлы осуществляется с помощью текстового потока QTextStream. Для корректного отображения кириллицы используется кодировка Windows-1251.
Q_INVOKABLE void writeLine(QVariantList taskInfo) {
QTextCodec *utf8 = QTextCodec::codecForName("Windows-1251");
QTextStream stream(&csvFile);
QStringList line;
stream.setCodec(utf8);
for(int i = 0; i < taskInfo.size(); i++) {
line << taskInfo[i].toString();
}
stream << line.join(",") << endl;
}
HTML отчеты создаются с помощью класса QTextDocument. Для создания таблицы с информацией по задачам используется класс QTextTable. Он позволяет задать стиль таблицы и текста в ней.
Q_INVOKABLE void createDocument(int rows, QVariantList columns) {
report = new QTextDocument();
QTextCursor cursor(report);
table = cursor.insertTable(rows + 1, columns.length());
QTextCharFormat format;
format.setFontWeight(QFont::Bold);
QTextCharFormat cellFormat;
cellFormat.setBackground(QBrush(Qt::cyan));
for(int col = 0; col < table->columns(); col++) {
QTextTableCell cell = table->cellAt(0, col);
QTextCursor cellCursor = cell.firstCursorPosition();
cell.setFormat(cellFormat);
cellCursor.mergeCharFormat(format);
cellCursor.insertText(columns[col].toString());
}
QTextTableFormat tableFormat = cursor.currentTable()->format();
tableFormat.setCellSpacing(0);
table->setFormat(tableFormat);
}
Q_INVOKABLE void addRow(int row, QVariantList taskInfo) {
QTextCharFormat cellFormat;
cellFormat.setBackground(QBrush(Qt::darkCyan));
for(int col = 0; col < table->columns(); col++) {
QTextTableCell cell = table->cellAt(row, col);
QTextCursor cellCursor = cell.firstCursorPosition();
cellCursor.insertText(taskInfo[col].toString());
}
QTextTableCell indexCell = table->cellAt(row, 0);
indexCell.setFormat(cellFormat);
}
Заключение
В результате было создано приложение с понятным и простым интерфейсом, которое позволяет легко вести и отслеживать список дел. Из ранее не планируемого функционала была добавлена возможность фильтровать задачи по статусу выполнения, чтобы можно было отсеивать выполненные. Приложение было опубликовано в магазине приложений Jolla Harbour под названием Report Card и доступно для скачивания всем желающим. Исходники приложения доступны на GitHub.
Автор: Максим Костерин