~ci-train-bot/ubuntu-settings-components/ubuntu-settings-components-ubuntu-zesty-2202

« back to all changes in this revision

Viewing changes to plugins/Ubuntu/Settings/Components/Calendar.qml

Merging with trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
import QtQuick 2.4
18
18
import Ubuntu.Components 1.3
19
19
import "dateExt.js" as DateExt
 
20
import "Calendar.js" as Cal
20
21
 
21
22
ListView {
22
23
    id: monthView
23
24
 
24
25
    property bool collapsed: false
25
 
    property var currentDate: selectedDate.monthStart().addDays(15)
 
26
    property var currentDate: new Date(priv.selectedDay.year, priv.selectedDay.month, 1)
26
27
    property var firstDayOfWeek: Qt.locale(i18n.language).firstDayOfWeek
27
28
    property var maximumDate
28
29
    property var minimumDate
29
 
    property var selectedDate: priv.today
 
30
    property var selectedDate: new Date(priv.today.year, priv.today.month, priv.today.day)
 
31
 
 
32
    function reset() {
 
33
        if (!priv.ready) return;
 
34
        currentDate = new Date(priv.today.year, priv.today.month, 1)
 
35
    }
30
36
 
31
37
    Component.onCompleted: {
32
 
        priv.__populateModel()
33
 
        timer.start()
 
38
        priv.__populateModel();
34
39
    }
35
40
 
36
41
    onCurrentIndexChanged: {
37
 
        if (!priv.ready) return
38
 
 
39
 
        currentDate = currentItem.monthStart
40
 
    }
41
 
 
42
 
    onCurrentDateChanged: {
43
 
        if (!priv.ready) return
44
 
 
45
 
        priv.__populateModel();
46
 
    }
47
 
 
48
 
    onMaximumDateChanged: {
49
 
        if (!priv.ready) return
50
 
 
51
 
        priv.__populateModel()
52
 
    }
53
 
 
54
 
    onMinimumDateChanged: {
55
 
        if (!priv.ready) return
56
 
 
57
 
        priv.__populateModel()
 
42
        if (!priv.ready) return;
 
43
 
 
44
        currentDate = new Date(currentItem.month.year, currentItem.month.month, 1);
58
45
    }
59
46
 
60
47
    ListModel {
67
54
        property bool ready: false
68
55
        property int squareUnit: monthView.width / 7
69
56
        property int verticalMargin: units.gu(1)
70
 
        property var today: (new Date()).midnight()
71
 
 
72
 
        function __withinLowerMonthBound(date) {
73
 
            return minimumDate == undefined || date.monthStart() >= minimumDate.monthStart()
74
 
        }
75
 
 
76
 
        function __withinUpperMonthBound(date) {
77
 
            return maximumDate == undefined || date.monthStart() <= maximumDate.monthStart()
78
 
        }
79
 
 
80
 
        function __getRealMinimumDate(date) {
81
 
            if (minimumDate != undefined && minimumDate > date) {
82
 
                return minimumDate;
83
 
            }
84
 
            return date;
85
 
        }
86
 
 
87
 
        function __getRealMaximumDate(date) {
88
 
            if (maximumDate != undefined && maximumDate < date) {
89
 
                return maximumDate;
90
 
            }
91
 
            return date;
 
57
        property var today: new Cal.Day().fromDate((new Date()))
 
58
 
 
59
        property var currentMonth: new Cal.Month().fromDate(currentDate)
 
60
        property var selectedDay: new Cal.Day().fromDate(selectedDate)
 
61
        property var minimumMonth: minimumDate ? new Cal.Month().fromDate(minimumDate) : undefined
 
62
        property var maximumMonth: maximumDate ? new Cal.Month().fromDate(maximumDate) : undefined
 
63
 
 
64
        property var minimumDay: minimumDate ? new Cal.Day().fromDate(minimumDate) : undefined
 
65
        property var maximumDay: maximumDate ? new Cal.Day().fromDate(maximumDate) : undefined
 
66
 
 
67
        onCurrentMonthChanged: {
 
68
            if (!ready) return
 
69
            __populateModel();
 
70
        }
 
71
        onSelectedDayChanged: {
 
72
            if (!ready) return
 
73
            __populateModel();
 
74
        }
 
75
        onMinimumMonthChanged: {
 
76
            if (!ready) return
 
77
            __populateModel();
 
78
        }
 
79
        onMaximumMonthChanged: {
 
80
            if (!ready) return
 
81
            __populateModel();
 
82
        }
 
83
 
 
84
        function __getRealMinimumMonth(month) {
 
85
            if (minimumMonth !== undefined && minimumMonth > month) {
 
86
                return minimumMonth;
 
87
            }
 
88
            return month;
 
89
        }
 
90
 
 
91
        function __getRealMaximumMonth(month) {
 
92
            if (maximumMonth !== undefined && maximumMonth < month) {
 
93
                return maximumMonth;
 
94
            }
 
95
            return month;
92
96
        }
93
97
 
94
98
        function __populateModel() {
95
99
            //  disable the onCurrentIndexChanged logic
96
 
            priv.ready = false
 
100
            priv.ready = false;
97
101
 
98
 
            var minimumAddedDate = priv.__getRealMinimumDate(currentDate.addMonths(-2)).monthStart();
99
 
            var maximumAddedDate = priv.__getRealMaximumDate(currentDate.addMonths(2)).monthStart();
 
102
            var minimumMonth = __getRealMinimumMonth(currentMonth.addMonths(-2));
 
103
            var maximumMonth = __getRealMaximumMonth(currentMonth.addMonths(2));
100
104
 
101
105
            // Remove old minimum months
102
 
            while (calendarModel.count > 0 && calendarModel.get(0).monthStart < minimumAddedDate) {
 
106
            while (calendarModel.count > 0 && new Cal.Month(calendarModel.get(0).month) < minimumMonth) {
103
107
                calendarModel.remove(0);
104
108
            }
105
109
            // Remove old maximum months
106
 
            while (calendarModel.count > 0 && calendarModel.get(calendarModel.count - 1).monthStart > maximumAddedDate) {
 
110
            while (calendarModel.count > 0 && new Cal.Month(calendarModel.get(calendarModel.count - 1).month) > maximumMonth) {
107
111
                calendarModel.remove(calendarModel.count - 1);
108
112
            }
109
113
 
110
 
            // Add new months
111
 
            var i = 0;
112
 
            while (calendarModel.count > 0 && calendarModel.get(0).monthStart > minimumAddedDate) {
113
 
                calendarModel.insert(0, { "monthStart": calendarModel.get(0).monthStart.addMonths(-1) });
114
 
                ++i;
115
 
            }
116
 
 
117
114
            if (calendarModel.count > 0) {
118
 
                i = 0;
119
 
                while (calendarModel.count > 0 && calendarModel.get(calendarModel.count - 1).monthStart < maximumAddedDate) {
120
 
                    calendarModel.append({ "monthStart": calendarModel.get(calendarModel.count - 1).monthStart.addMonths(1) });
121
 
                    ++i;
 
115
                // Add new months
 
116
                var firstMonth = new Cal.Month(calendarModel.get(0).month);
 
117
                while (firstMonth > minimumMonth) {
 
118
                    calendarModel.insert(0, { "month": firstMonth.addMonths(-1) });
 
119
                    firstMonth = new Cal.Month(calendarModel.get(0).month);
 
120
                }
 
121
 
 
122
                var lastMonth = new Cal.Month(calendarModel.get(calendarModel.count - 1).month);
 
123
                while (lastMonth < maximumMonth) {
 
124
                    calendarModel.append({ "month": lastMonth.addMonths(1) });
 
125
                    lastMonth = new Cal.Month(calendarModel.get(calendarModel.count - 1).month);
122
126
                }
123
127
            } else {
124
 
                i = 0;
 
128
                var i = 0;
125
129
                do {
126
 
                    calendarModel.append({ "monthStart": minimumAddedDate.addMonths(i) });
 
130
                    calendarModel.append({ "month": minimumMonth.addMonths(i) });
127
131
                    ++i;
128
 
                } while (calendarModel.get(i-1).monthStart < maximumAddedDate)
 
132
                } while (minimumMonth.addMonths(i) <= maximumMonth)
129
133
            }
130
134
 
131
 
            currentIndex = DateExt.diffMonths(minimumAddedDate, currentDate);
 
135
            currentIndex = currentMonth - minimumMonth;
132
136
 
133
137
            // Ok, we're all set up. enable the onCurrentIndexChanged logic
134
138
            priv.ready = true
135
139
        }
136
140
    }
137
141
 
138
 
    Timer {
139
 
        id: timer
140
 
        interval: 60000
141
 
        repeat: true
142
 
        running: true
143
 
        triggeredOnStart: true
144
 
 
145
 
        onTriggered: priv.today = (new Date()).midnight()
 
142
    LiveTimer {
 
143
        frequency: monthView.visible ? LiveTimer.Minute : LiveTimer.Disabled
 
144
        onFrequencyChanged: trigger()
 
145
        onTrigger: {
 
146
            Date.timeZoneUpdated(); // FIXME remove when fixed in UITK
 
147
            var today = new Cal.Day().fromDate((new Date()));
 
148
            if (!priv.today.equals(today)) {
 
149
                priv.today = today;
 
150
                reset();
 
151
            }
 
152
        }
146
153
    }
147
154
 
148
155
    width: parent.width
149
156
    height: priv.squareUnit * (collapsed ? 1 : 6) + priv.verticalMargin * 2
150
157
    interactive: !collapsed
151
158
    clip: true
152
 
    cacheBuffer: Math.max(width + 1, 0)
 
159
    cacheBuffer: Math.max((width+1) * 3, 0) // one page left, one page right
153
160
    highlightRangeMode: ListView.StrictlyEnforceRange
154
161
    preferredHighlightBegin: 0
155
162
    preferredHighlightEnd: width
157
164
    orientation: ListView.Horizontal
158
165
    snapMode: ListView.SnapOneItem
159
166
    focus: true
 
167
    highlightFollowsCurrentItem: true
160
168
 
161
169
    Keys.onLeftPressed: selectedDate.addDays(-1)
162
170
    Keys.onRightPressed: selectedDate.addDays(1)
164
172
    delegate: Item {
165
173
        id: monthItem
166
174
 
167
 
        property int currentWeekRow: Math.floor((selectedDate.getTime() - gridStart.getTime()) / Date.msPerWeek)
 
175
        property int currentWeekRow: Math.floor((priv.selectedDay - gridStart) / 7)
168
176
        property var gridStart: monthStart.weekStart(firstDayOfWeek)
169
177
        property var monthEnd: monthStart.addMonths(1)
170
 
        property var monthStart: model.monthStart
 
178
        property var monthStart: new Cal.Day(model.month.year, model.month.month, 1)
 
179
 
 
180
        property var month: new Cal.Month(model.month)
171
181
 
172
182
        width: monthView.width
173
183
        height: monthView.height
187
197
                    id: dayItem
188
198
                    objectName: "dayItem" + index
189
199
 
190
 
                    property bool isCurrent: (dayStart.getFullYear() == selectedDate.getFullYear() &&
191
 
                                              dayStart.getMonth() == selectedDate.getMonth() &&
192
 
                                              dayStart.getDate() == selectedDate.getDate())
193
 
                    property bool isCurrentMonth: monthStart <= dayStart && dayStart < monthEnd
 
200
                    property bool isCurrent: dayStart.equals(priv.selectedDay)
 
201
                    property bool isCurrentMonth: (monthStart < dayStart || monthStart.equals(dayStart))  && dayStart < monthEnd
194
202
                    property bool isCurrentWeek: row == currentWeekRow
195
203
                    property bool isSunday: weekday == 0
196
 
                    property bool isToday: dayStart.getTime() == priv.today.getTime()
197
 
                    property bool isWithinBounds: (minimumDate == undefined || dayStart >= minimumDate) &&
198
 
                                                  (maximumDate == undefined || dayStart <= maximumDate)
 
204
                    property bool isToday: dayStart.equals(priv.today)
 
205
                    property bool isWithinBounds: (priv.minimumDay === undefined || dayStart >= priv.minimumDay) &&
 
206
                                                  (priv.maximumDay === undefined || dayStart <= priv.maximumDay)
199
207
                    property int row: Math.floor(index / 7)
200
208
                    property int weekday: (index % 7 + firstDayOfWeek) % 7
201
209
                    property real bottomMargin: (row == 5 || (collapsed && isCurrentWeek)) ? -priv.verticalMargin : 0
202
210
                    property real topMargin: (row == 0 || (collapsed && isCurrentWeek)) ? -priv.verticalMargin : 0
203
211
                    property var dayStart: gridStart.addDays(index)
204
212
 
205
 
                    // Styling properties
206
 
                    property color color: theme.palette.normal.backgroundText
207
 
                    property color todayColor: theme.palette.normal.positive
208
 
                    property string fontSize: "large"
209
 
                    property var backgroundColor: "transparent" // FIXME use color instead var when Qt will fix the bug with the binding (loses alpha)
210
 
                    property var sundayBackgroundColor: "#19AEA79F" // FIXME use color instead var when Qt will fix the bug with the binding (loses alpha)
211
 
 
212
213
                    visible: collapsed ? isCurrentWeek : true
213
214
                    width: priv.squareUnit
214
215
                    height: priv.squareUnit
215
216
 
216
 
//                    ItemStyle.class: "day"
217
217
                    Item {
218
218
                        anchors {
219
219
                            fill: parent
223
223
 
224
224
                        Rectangle {
225
225
                            anchors.fill: parent
226
 
                            visible: color.a > 0
227
 
                            color: isSunday ? dayItem.sundayBackgroundColor : dayItem.backgroundColor
 
226
                            visible: isSunday
 
227
                            opacity: 0.1
 
228
                            color: UbuntuColors.warmGrey
228
229
                        }
229
230
 
230
231
                        Label {
231
232
                            anchors.centerIn: parent
232
 
                            text: dayStart.getDate()
233
 
                            fontSize: dayItem.fontSize
234
 
                            color: isToday ? dayItem.todayColor : dayItem.color
235
 
                            scale: isCurrent ? 1.8 : 1.
236
 
                            opacity: isWithinBounds ? isCurrentMonth ? 1. : 0.3 : 0.1
 
233
                            text: dayStart.day
 
234
                            font.pixelSize: units.dp(isCurrent ? 36 : 20)
 
235
                            color: isCurrentMonth && isWithinBounds ? isToday ? UbuntuColors.green :
 
236
                                                                                theme.palette.normal.backgroundText :
 
237
                                                                      theme.palette.disabled.backgroundText
 
238
                            opacity: isWithinBounds ? 1. : 0.33
237
239
 
238
 
                            Behavior on scale {
 
240
                            Behavior on font.pixelSize {
239
241
                                NumberAnimation { duration: 50 }
240
242
                            }
241
243
                        }
248
250
                            bottomMargin: dayItem.bottomMargin
249
251
                        }
250
252
 
251
 
                        onReleased: if (isWithinBounds) monthView.selectedDate = dayStart
 
253
                        onClicked: {
 
254
                            if (isWithinBounds) monthView.selectedDate = new Date(dayStart.year, dayStart.month, dayStart.day)
 
255
                        }
252
256
                    }
253
257
                }
254
258
            }