EventEditor.qml 9.44 KB
Newer Older
1
/*
2
 * SPDX-FileCopyrightText: 2020 Dimitris Kardarakos <dimkard@posteo.net>
3
 *
4
 * SPDX-License-Identifier: GPL-3.0-or-later
5 6 7 8 9 10
 */

import QtQuick 2.0
import QtQuick.Controls 2.4 as Controls2
import QtQuick.Layouts 1.11
import org.kde.kirigami 2.4 as Kirigami
Nicolas Fella's avatar
Nicolas Fella committed
11
import org.kde.calindori 0.1 as Calindori
12 13 14 15 16 17 18

Kirigami.Page {
    id: root

    property string uid
    property alias summary: summary.text
    property alias description: description.text
19
    property alias startDt: startDateSelector.selectorDate
20 21 22
    property alias startHour: startTimeSelector.selectorHour
    property alias startMinute: startTimeSelector.selectorMinutes
    property alias startPm: startTimeSelector.selectorPm
23 24 25
    property alias allDay: allDaySelector.checked
    property alias location: location.text
    property var calendar
26
    property var incidenceData
27
    property alias endDt: endDateSelector.selectorDate
28 29 30
    property alias endHour: endTimeSelector.selectorHour
    property alias endMinute: endTimeSelector.selectorMinutes
    property alias endPm: endTimeSelector.selectorPm
Dimitris Kardarakos's avatar
Dimitris Kardarakos committed
31 32 33
    property alias repeatType: repeatSelector.repeatType
    property alias repeatEvery: repeatSelector.repeatEvery
    property alias repeatStopAfter: repeatSelector.stopAfter
34

35
    signal editcompleted(var vevent)
36

37 38 39 40 41 42 43 44 45
    /**
     * Function taht checks that the user input is valid
     *
     * Returns an object with success status and reason
     */
    function validate()
    {
        var result = { success: false, reason: "" };

46
        var endDtTime = new Date(root.endDt.getFullYear(), root.endDt.getMonth(), root.endDt.getDate(), root.endHour + (root.endPm ? 12 : 0), root.endMinute);
47

48
        var startDtTime = new Date(root.startDt.getFullYear(), root.startDt.getMonth(), root.startDt.getDate(), root.startHour + (root.startPm ? 12 : 0), root.startMinute);
49 50 51 52 53 54 55 56 57 58

        if(!(root.allDay) && (endDtTime < startDtTime)) {
            result.reason = "End date time should be after start date time";
            return result;
        }

        result.success = true;
        return result;
    }

59 60 61 62 63 64 65
    Component.onCompleted: {
        if(incidenceData == null && _calindoriConfig.alwaysRemind)
        {
            incidenceAlarmsModel.addAlarm(_calindoriConfig.preEventRemindTime * 60)
        }
    }

66
    title: uid == "" ? i18n("Add event") : i18n("Edit event")
67 68 69 70 71 72 73 74 75 76 77 78 79

    ColumnLayout {

        anchors.centerIn: parent

        Kirigami.FormLayout {
            id: eventCard

            enabled: !root.completed

            Controls2.Label {
                id: calendarName

80
                Kirigami.FormData.label: i18n("Calendar:")
81 82 83 84 85 86 87 88 89 90 91 92
                Layout.fillWidth: true
                text: root.calendar.name
            }

            Kirigami.Separator {
                Kirigami.FormData.isSection: true
            }

            Controls2.TextField {
                id: summary

                Layout.fillWidth: true
93
                Kirigami.FormData.label: i18n("Summary:")
94
                text: incidenceData ? incidenceData.summary : ""
95 96 97 98

            }

            RowLayout {
99
                Kirigami.FormData.label: i18n("Start:")
100 101
                spacing: 0

102
                DateSelectorButton {
103
                    id: startDateSelector
104
                }
105

106
                TimeSelectorButton {
107 108
                    id: startTimeSelector

109
                    selectorDate: root.startDt
110 111 112
                    selectorHour: (root.incidenceData ? root.incidenceData.dtstart.getHours() : root.startDt.getHours() ) % 12
                    selectorMinutes: root.incidenceData ? root.incidenceData.dtstart.getMinutes() : root.startDt.getMinutes()
                    selectorPm: root.incidenceData ? (root.incidenceData.dtstart.getHours() >=12) : (root.startDt.getHours() >=12)
113
                    enabled: !allDaySelector.checked
114 115 116 117
                }
            }

            RowLayout {
118
                Kirigami.FormData.label: i18n("End:")
119 120
                spacing: 0

121
                DateSelectorButton {
122 123 124 125
                    id: endDateSelector

                    enabled: !allDaySelector.checked

126
                    Component.onCompleted: selectorDate = root.incidenceData ? root.incidenceData.dtend : new Date(root.startDt.getTime() + _calindoriConfig.eventsDuration*60000);// Do not bind, just initialize
127
                }
128

129
                TimeSelectorButton {
130 131
                    id: endTimeSelector

132
                    selectorDate: root.endDt
133 134 135
                    selectorHour: root.endDt.getHours() % 12
                    selectorMinutes: root.endDt.getMinutes()
                    selectorPm: (root.endDt.getHours() >=12)
136
                    enabled: !allDaySelector.checked && (root.endDt != undefined && !isNaN(root.endDt))
137 138 139 140 141 142
                }
            }

            Controls2.CheckBox {
                id: allDaySelector

143
                enabled: !isNaN(root.startDt)
144
                checked: incidenceData ? incidenceData.allday: false
145
                text: i18n("All day")
146 147 148 149 150 151 152 153 154 155
            }

            Kirigami.Separator {
                Kirigami.FormData.isSection: true
            }

            Controls2.TextField {
                id: location

                Layout.fillWidth: true
156
                Kirigami.FormData.label: i18n("Location:")
157
                text: incidenceData ? incidenceData.location : ""
158
            }
Dimitris Kardarakos's avatar
Dimitris Kardarakos committed
159 160 161 162

            Controls2.ToolButton {
                id: repeatSelector

163 164
                property int repeatType: incidenceData != null && incidenceData.isRepeating ? incidenceData.repeatType : _repeatModel.noRepeat
                property int repeatEvery: incidenceData != null && incidenceData.isRepeating ? incidenceData.repeatEvery : 1
Dimitris Kardarakos's avatar
Dimitris Kardarakos committed
165
                property string repeatDescription: _repeatModel.periodDecription(repeatType)
166
                property int stopAfter: incidenceData != null && incidenceData.isRepeating ? incidenceData.repeatStopAfter: -1
Dimitris Kardarakos's avatar
Dimitris Kardarakos committed
167 168 169 170 171 172

                text: _repeatModel.repeatDescription(repeatType, repeatEvery, stopAfter)
                Kirigami.FormData.label: i18n("Repeat:")

                onClicked: recurPickerSheet.init(repeatType, repeatEvery, stopAfter )
            }
173 174 175 176 177 178 179 180 181 182 183 184
        }

        Kirigami.Separator {
            Layout.fillWidth: true
        }

        Controls2.TextArea {
            id: description

            Layout.fillWidth: true
            Layout.minimumWidth: Kirigami.Units.gridUnit * 4
            Layout.minimumHeight: Kirigami.Units.gridUnit * 4
185 186
            Layout.maximumWidth: eventCard.width
            wrapMode: Text.WrapAnywhere
187
            text: incidenceData ? incidenceData.description : ""
188
            placeholderText: i18n("Description")
189
        }
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217

        RowLayout {
            Controls2.Label {
                id: remindersLabel

                Layout.fillWidth: true
                text: i18n("Reminders")
            }

            Controls2.ToolButton {
                text: i18n("Add")

                onClicked: reminderEditor.open()
            }
        }

        Kirigami.Separator {
            Layout.fillWidth: true
        }

        Repeater {
            id: alarmsList

            model: incidenceAlarmsModel

            delegate: Kirigami.SwipeListItem {
                contentItem: Controls2.Label {
                    text: model.display
218
                    wrapMode: Text.WordWrap
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
                }

                Layout.fillWidth: true

                actions: [
                     Kirigami.Action {
                        id: deleteAlarm

                        iconName: "delete"
                        onTriggered: incidenceAlarmsModel.removeAlarm(model.index)
                    }
                ]
            }
        }

234 235 236 237 238 239 240
    }

    actions {

        left: Kirigami.Action {
            id: cancelAction

241
            text: i18n("Cancel")
242
            icon.name : "dialog-cancel"
243
            shortcut: "Esc"
244

245
            onTriggered: editcompleted(null)
246 247 248
        }

        main: Kirigami.Action {
249 250
            text: i18n("Save")
            icon.name: "dialog-ok"
251
            enabled: summary.text
252 253

            onTriggered: {
254 255 256
                var validation = validate();

                if(validation.success) {
257 258
                    console.log("Saving event, root.startDt:" + startDt);
                    var vevent = { "uid" : root.uid, "startDate": root.startDt, "summary": root.summary, "description": root.description, "startHour": root.startHour + (root.startPm ? 12 : 0), "startMinute": root.startMinute, "allDay": root.allDay, "location": root.location, "endDate": (root.allDay ? root.startDt : root.endDt), "endHour": root.endHour + (root.endPm ? 12 : 0), "endMinute": root.endMinute, "alarms": incidenceAlarmsModel.alarms(), "periodType": root.repeatType, "repeatEvery": root.repeatEvery, "stopAfter": root.repeatStopAfter};
Dimitris Kardarakos's avatar
Dimitris Kardarakos committed
259

260
                    _eventController.addEdit(root.calendar, vevent);
261
                    editcompleted(vevent);
262 263
                }
                else {
264
                    showPassiveNotification(validation.reason);
265 266 267 268 269
                }
            }
        }
    }

270 271 272
    Calindori.IncidenceAlarmsModel {

        id: incidenceAlarmsModel
Dimitris Kardarakos's avatar
Dimitris Kardarakos committed
273

274 275 276
        alarmProperties: { "calendar" : root.calendar, "uid": root.uid }
    }

Dimitris Kardarakos's avatar
Dimitris Kardarakos committed
277 278 279 280 281 282 283 284 285 286
    RecurrencePickerSheet {
        id: recurPickerSheet

        onRecurrencePicked: {
            repeatSelector.repeatType = recurPickerSheet.selectedRepeatType;
            repeatSelector.repeatEvery = recurPickerSheet.selectedRepeatEvery
            repeatSelector.stopAfter = recurPickerSheet.selectedStopAfter;
        }
    }

287 288 289 290 291
    ReminderEditor {
        id: reminderEditor

        onOffsetSelected: incidenceAlarmsModel.addAlarm(offset)
    }
292
}