
Готовое_КР_Календарь
.pdf
Продолжение листинга 1
function hasEvents(date) { var result = false;
db.transaction(function(tx) {
var rs = tx.executeSql('SELECT 1 FROM events WHERE date=? LIMIT 1', [date]);
result = rs.rows.length > 0;
});
return result;
}
function addEvent(title, description, date, time) { db.transaction(function(tx) {
tx.executeSql('INSERT INTO events(title, description, date, time) VALUES(?, ?, ?, ?)',
[title, description, date, time]);
});
loadEventsForSelectedDate();
}
function deleteEvent(id) { db.transaction(function(tx) {
tx.executeSql('DELETE FROM events WHERE id=?', [id]);
});
loadEventsForSelectedDate();
}
Column { anchors {
top: header.bottom left: parent.left right: parent.right
margins: Theme.paddingLarge
}
spacing: Theme.paddingLarge}
Label {
id: monthYearLabel
anchors.horizontalCenter: parent.horizontalCenter
text: Qt.locale().monthName(selectedDate.getMonth()) + " " + selectedDate.getFullYear()
font.pixelSize: Theme.fontSizeLarge color: Theme.highlightColor
}
Grid {
id: calendarGrid
anchors.horizontalCenter: parent.horizontalCenter columns: 7
spacing: Theme.paddingSmall Repeater {
model: ["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"] Label { width: 40
height: 40
horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter
34

Продолжение листинга 1
Repeater { model: {
var firstDay = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1).getDay();
firstDay = firstDay === 0 ? 6 : firstDay - 1;
var daysInMonth = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, 0).getDate();
var daysInPrevMonth = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 0).getDate();
var cells = [];
for (var i = 0; i < firstDay; i++) {
cells.push({day: daysInPrevMonth - firstDay + i + 1,
month: -1});
}
for (i = 1; i <= daysInMonth; i++) { cells.push({day: i, month: 0});
}
var remaining = 42 - cells.length; for (i = 1; i <= remaining; i++) { cells.push({day: i, month: 1});
}
return cells;
}
Rectangle { width: 40 height: 40
radius: width / 2 color: {
if (modelData.day === selectedDate.getDate() &&
modelData.month === 0) {
return Theme.highlightColor;
}else if (modelData.month === 0) { return "transparent";
}else {
return Theme.rgba(Theme.secondaryColor, 0.1);
}
}
Label {
anchors.centerIn: parent text: modelData.day color: {
if (modelData.day === selectedDate.getDate() &&
modelData.month === 0) {
return Theme.primaryColor;
}else if (modelData.month === 0) { return Theme.primaryColor;
}else {
return Theme.secondaryColor;
}
}
}Rectangle { visible: {
if (modelData.month !== 0) return false;
var dateStr = selectedDate.getFullYear() + "-" + padNumber(selectedDate.getMonth() + 1, 2)
}
35

Продолжение листинга 1
return hasEvents(dateStr);
}
width: 6 height: 6 radius: 3
color: Theme.secondaryHighlightColor anchors {
horizontalCenter: parent.horizontalCenter bottom: parent.bottom
bottomMargin: 5
}
}
MouseArea { anchors.fill: parent onClicked: {
if (modelData.month === 0) { selectedDate = new
Date(selectedDate.getFullYear(), selectedDate.getMonth(), modelData.day); loadEventsForSelectedDate();
}
}
}
}
}
}
Row {
anchors.horizontalCenter: parent.horizontalCenter spacing: Theme.paddingLarge
Button {
text: "<" onClicked: {
selectedDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth() - 1, 1);
monthYearLabel.text = Qt.locale().monthName(selectedDate.getMonth()) + " " + selectedDate.getFullYear();
}
}
Button {
text: "Сегодня" onClicked: {
selectedDate = new Date(); monthYearLabel.text =
Qt.locale().monthName(selectedDate.getMonth()) + " " + selectedDate.getFullYear();
loadEventsForSelectedDate();
}
}
Button {
text: ">" onClicked: {
selectedDate = new Date(selectedDate.getFullYear(), selectedDate.getMonth() + 1, 1);
36

Продолжение листинга 1
}
}
SilicaListView { id: eventsList
width: parent.width height: 300
model: eventsModel clip: true
delegate: ListItem { width: parent.width
contentHeight: Theme.itemSizeMedium
Column {
width: parent.width - 2 * Theme.paddingLarge anchors.centerIn: parent
spacing: Theme.paddingSmall
Label {
width: parent.width text: title
font.pixelSize: Theme.fontSizeMedium color: Theme.primaryColor truncationMode: TruncationMode.Fade
}
Label {
width: parent.width
text: (time ? time : "00:00") + (description ? " • " +
description : "")
font.pixelSize: Theme.fontSizeSmall color: Theme.secondaryColor truncationMode: TruncationMode.Fade
}
}
onClicked: { pageStack.push(eventDialogComponent, {
eventId: id, eventTitle: title,
eventDescription: description, eventTime: time
});
}
menu: ContextMenu { MenuItem {
text: "Удалить" onClicked: deleteEvent(id)
}
}
}
Label {
anchors.centerIn: parent
text: "Нет событий на этот день" visible: eventsList.count === 0 color: Theme.secondaryColor
}
}
37

Продолжение листинга 1
Button {
anchors {
horizontalCenter: parent.horizontalCenter bottom: parent.bottom
bottomMargin: Theme.paddingLarge
}
text: "Добавить событие" onClicked: {
pageStack.push(eventDialogComponent);
}
}
Component {
id: eventDialogComponent
Dialog {
id: dialog
acceptDestination: calendarPage acceptDestinationAction: PageStackAction.Pop
property int eventId: -1 property string eventTitle: ""
property string eventDescription: ""
property string eventTime: Qt.formatTime(new Date(), "hh:mm")
Column {
width: parent.width spacing: Theme.paddingLarge
DialogHeader {
title: eventId === -1 ? "Новое событие" : "Редактировать
событие"
acceptText: "Сохранить"
}
Label {
x: Theme.horizontalPageMargin
width: parent.width - 2 * Theme.horizontalPageMargin
text: Qt.formatDate(calendarPage.selectedDate, "dd MMMM yyyy") color: Theme.highlightColor
font.pixelSize: Theme.fontSizeMedium
}
TextField {
id: titleField width: parent.width
label: "Название события" placeholderText: label text: eventTitle
}
TextArea {
id: descriptionField width: parent.width
label: "Описание (необязательно)" placeholderText: label
text: eventDescription
}
38

Продолжение листинга 1
TextField {
id: timeField width: parent.width
label: "Время (HH:MM)" placeholderText: "12:00" text: eventTime inputMethodHints: Qt.ImhTime
validator: RegExpValidator { regExp: /^([0-1]?[0-9]|2[0-
3]):[0-5][0-9]$/ }
}
}
onAccepted: {
var title = titleField.text.trim(); if (title === "") return;
var time = timeField.text.trim(); if (time === "") time = "00:00";
if (eventId !== -1) {
// Обновление события calendarPage.db.transaction(function(tx) {
tx.executeSql('UPDATE events SET title=?, description=?,
time=? WHERE id=?',
[title, descriptionField.text, time,
eventId]);
});
}else {
//Добавление нового события
calendarPage.addEvent(title, descriptionField.text, calendarPage.selectedDateString, time);
}
calendarPage.loadEventsForSelectedDate();
}
}
}
}
39