Merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/rewriteDatePickerInternal into lp:ubuntu-ui-toolkit/staging
- rewriteDatePickerInternal
- Merge into staging
Proposed by
Cris Dywan
Status: | Work in progress | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/rewriteDatePickerInternal | ||||
Merge into: | lp:ubuntu-ui-toolkit/staging | ||||
Diff against target: |
1468 lines (+1057/-254) 12 files modified
examples/ubuntu-ui-toolkit-gallery/Pickers.qml (+2/-0) src/imports/Components/Pickers/1.3/DatePicker.qml (+335/-254) src/imports/Components/Pickers/1.3/DatePickerHeader.qml (+98/-0) src/imports/Components/Pickers/1.3/DatePickerMonthDays.qml (+115/-0) src/imports/Components/Pickers/1.3/DatePickerMonthDaysWorker.js (+61/-0) src/imports/Components/Pickers/1.3/DayNightPicker.qml (+50/-0) src/imports/Components/Pickers/1.3/DigitSeparator.qml (+10/-0) src/imports/Components/Pickers/1.3/HourPicker.qml (+114/-0) src/imports/Components/Pickers/1.3/YearListDropdown.qml (+131/-0) src/imports/Components/Pickers/1.3/calendar.js (+79/-0) src/imports/Components/Pickers/1.3/dateutils.js (+53/-0) src/imports/Components/Pickers/Pickers.pro (+9/-0) |
||||
To merge this branch: | bzr merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/rewriteDatePickerInternal | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu SDK team | Pending | ||
Review via email: mp+308624@code.launchpad.net |
Commit message
Rewrite DatePicker internals
Description of the change
✔️ Allow overriding individual day display for calendar events integr.
✅ show/hide month/year switcher in calendar view depending on mode
✅ week numbers yes/no
✅ minimum month doesn't work (no arrow, but year selector)
⚪ current day needs highlight
✅ time picker shows calendar
⚪ selected 'last month'-day disappears while pressed
To post a comment you must log in.
Unmerged revisions
- 2139. By Cris Dywan
-
WIP
- 2138. By Cris Dywan
-
WIP
- 2137. By Cris Dywan
-
Rewrite DatePicker internals
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'examples/ubuntu-ui-toolkit-gallery/Pickers.qml' | |||
2 | --- examples/ubuntu-ui-toolkit-gallery/Pickers.qml 2015-09-24 20:05:52 +0000 | |||
3 | +++ examples/ubuntu-ui-toolkit-gallery/Pickers.qml 2016-10-25 11:37:58 +0000 | |||
4 | @@ -23,6 +23,7 @@ | |||
5 | 23 | id: root | 23 | id: root |
6 | 24 | 24 | ||
7 | 25 | property var stringListModel: ["starred", "media-record", "like", "language-chooser", "go-home", "email", "contact-group", "notification", "active-call"] | 25 | property var stringListModel: ["starred", "media-record", "like", "language-chooser", "go-home", "email", "contact-group", "notification", "active-call"] |
8 | 26 | /* | ||
9 | 26 | TemplateSection { | 27 | TemplateSection { |
10 | 27 | className: "Picker" | 28 | className: "Picker" |
11 | 28 | documentation: "qml-ubuntu-components-pickers-picker.html" | 29 | documentation: "qml-ubuntu-components-pickers-picker.html" |
12 | @@ -205,6 +206,7 @@ | |||
13 | 205 | } | 206 | } |
14 | 206 | } | 207 | } |
15 | 207 | } | 208 | } |
16 | 209 | */ | ||
17 | 208 | TemplateSection { | 210 | TemplateSection { |
18 | 209 | className: "DatePicker" | 211 | className: "DatePicker" |
19 | 210 | documentation: "qml-ubuntu-components-pickers-datepicker.html" | 212 | documentation: "qml-ubuntu-components-pickers-datepicker.html" |
20 | 211 | 213 | ||
21 | === modified file 'src/imports/Components/Pickers/1.3/DatePicker.qml' | |||
22 | --- src/imports/Components/Pickers/1.3/DatePicker.qml 2016-03-15 18:16:01 +0000 | |||
23 | +++ src/imports/Components/Pickers/1.3/DatePicker.qml 2016-10-25 11:37:58 +0000 | |||
24 | @@ -16,6 +16,8 @@ | |||
25 | 16 | 16 | ||
26 | 17 | import QtQuick 2.4 | 17 | import QtQuick 2.4 |
27 | 18 | import Ubuntu.Components 1.3 | 18 | import Ubuntu.Components 1.3 |
28 | 19 | import Ubuntu.Components.Private 1.3 | ||
29 | 20 | import 'dateutils.js' as DU | ||
30 | 19 | 21 | ||
31 | 20 | /*! | 22 | /*! |
32 | 21 | \qmltype DatePicker | 23 | \qmltype DatePicker |
33 | @@ -167,7 +169,8 @@ | |||
34 | 167 | insensitive. If minimum and maximum are within the same month, the month picker | 169 | insensitive. If minimum and maximum are within the same month, the month picker |
35 | 168 | will also be insensitive. | 170 | will also be insensitive. |
36 | 169 | */ | 171 | */ |
38 | 170 | StyledItem { | 172 | Item { |
39 | 173 | // StyledItem { | ||
40 | 171 | id: datePicker | 174 | id: datePicker |
41 | 172 | 175 | ||
42 | 173 | /*! | 176 | /*! |
43 | @@ -237,7 +240,8 @@ | |||
44 | 237 | The default values are the current date for the minimum, and 50 year distance | 240 | The default values are the current date for the minimum, and 50 year distance |
45 | 238 | value for maximum. | 241 | value for maximum. |
46 | 239 | */ | 242 | */ |
48 | 240 | property date minimum: Date.prototype.midnight.call(new Date()) | 243 | //property date minimum: Date.prototype.midnight.call(new Date()) |
49 | 244 | property date minimum: DU.clone(null, 'setDate', 1) | ||
50 | 241 | /*! | 245 | /*! |
51 | 242 | \qmlproperty int maximum | 246 | \qmlproperty int maximum |
52 | 243 | 247 | ||
53 | @@ -246,11 +250,12 @@ | |||
54 | 246 | 250 | ||
55 | 247 | See \l minimum for more details. | 251 | See \l minimum for more details. |
56 | 248 | */ | 252 | */ |
58 | 249 | property date maximum: { | 253 | /*property date maximum: { |
59 | 250 | var d = Date.prototype.midnight.call(new Date()); | 254 | var d = Date.prototype.midnight.call(new Date()); |
60 | 251 | d.setFullYear(d.getFullYear() + 50); | 255 | d.setFullYear(d.getFullYear() + 50); |
61 | 252 | return d; | 256 | return d; |
63 | 253 | } | 257 | }*/ |
64 | 258 | property date maximum: DU.clone(minimum, 'setFullYear', minimum.getFullYear() + 50) | ||
65 | 254 | 259 | ||
66 | 255 | /*! | 260 | /*! |
67 | 256 | For convenience, the \b year value of the \l date property. | 261 | For convenience, the \b year value of the \l date property. |
68 | @@ -298,11 +303,49 @@ | |||
69 | 298 | The property holds whether the component's pickers are moving. | 303 | The property holds whether the component's pickers are moving. |
70 | 299 | \sa Picker::moving | 304 | \sa Picker::moving |
71 | 300 | */ | 305 | */ |
77 | 301 | readonly property alias moving: positioner.moving | 306 | readonly property alias moving: listView.moving |
78 | 302 | 307 | ||
79 | 303 | implicitWidth: units.gu(36) | 308 | implicitWidth: parent.width |
80 | 304 | implicitHeight: units.gu(20) | 309 | implicitHeight: content.visible ? content.height : timeContent.height |
81 | 305 | activeFocusOnPress: true | 310 | // activeFocusOnPress: true |
82 | 311 | |||
83 | 312 | /*! | ||
84 | 313 | \qmlproperty Component delegate | ||
85 | 314 | Individual days are rendered by the delegate, in the case of \l mode | ||
86 | 315 | containing "Months". This is useful to customize the colors, frame, or | ||
87 | 316 | add visuals for calendar events. | ||
88 | 317 | Roles: | ||
89 | 318 | date: the date of the rendered day | ||
90 | 319 | text: the day as a string | ||
91 | 320 | currentMonth: the date lies in the currently selected month | ||
92 | 321 | pressed: whether this day is being pressed | ||
93 | 322 | */ | ||
94 | 323 | property Component delegate: Label { | ||
95 | 324 | id: label | ||
96 | 325 | anchors.centerIn: parent | ||
97 | 326 | horizontalAlignment: Text.AlignHCenter | ||
98 | 327 | verticalAlignment: Text.AlignVCenter | ||
99 | 328 | property color dayColor: { | ||
100 | 329 | if (DU.sameDay(date, datePicker.date)) | ||
101 | 330 | return theme.palette.normal.activity; | ||
102 | 331 | if (currentMonth) | ||
103 | 332 | return theme.palette.normal.backgroundText; | ||
104 | 333 | // FIXME: Original color is too light for Qt.lighter | ||
105 | 334 | return Qt.darker(theme.palette.normal.base); | ||
106 | 335 | } | ||
107 | 336 | color: pressed ? Qt.lighter(dayColor) : dayColor | ||
108 | 337 | textSize: Label.Medium | ||
109 | 338 | text: modelData.text | ||
110 | 339 | |||
111 | 340 | Frame { | ||
112 | 341 | anchors.fill: parent | ||
113 | 342 | thickness: units.dp(2) | ||
114 | 343 | radius: units.gu(1.7) | ||
115 | 344 | color: theme.palette.normal.backgroundText | ||
116 | 345 | property date today: new Date() | ||
117 | 346 | visible: date.getFullYear() == today.getFullYear() && date.getMonth() == today.getMonth() && DU.sameDay(date, today) | ||
118 | 347 | } | ||
119 | 348 | } | ||
120 | 306 | 349 | ||
121 | 307 | /*! \internal */ | 350 | /*! \internal */ |
122 | 308 | onMinimumChanged: { | 351 | onMinimumChanged: { |
123 | @@ -323,21 +366,30 @@ | |||
124 | 323 | date = maximum; | 366 | date = maximum; |
125 | 324 | } | 367 | } |
126 | 325 | } | 368 | } |
138 | 326 | /*! \internal */ | 369 | |
139 | 327 | onWidthChanged: { | 370 | onDateChanged: { |
140 | 328 | // use dayPicker narrowFormatLimit even if the dayPicker is hidden | 371 | if (!moving) |
141 | 329 | // and clamp the width so it cannot have less width that the sum of | 372 | listView.positionViewAtIndex(DU.getMonthsRange(minimum, date), ListView.Visible) |
142 | 330 | // the three tumblers' narrowFormatLimit | 373 | } |
143 | 331 | var minWidth = 0.0; | 374 | |
144 | 332 | for (var i = 0; i < tumblerModel.count; i++) { | 375 | property int monthsRange: DU.getMonthsRange(minimum, maximum) |
145 | 333 | minWidth += tumblerModel.get(i).pickerModel.narrowFormatLimit; | 376 | // FIXME: Move to Style |
146 | 334 | } | 377 | property int scrollDirection: Qt.Horizontal |
147 | 335 | width = Math.max(width, minWidth); | 378 | property int snapMode: ListView.SnapToItem |
148 | 336 | } | 379 | state: '' |
149 | 380 | |||
150 | 381 | function cancelFlick() { | ||
151 | 382 | listView.cancelFlick() | ||
152 | 383 | } | ||
153 | 384 | |||
154 | 385 | function toggleYearList() { | ||
155 | 386 | datePicker.state = datePicker.state === 'years-months'? '' : 'years-months' | ||
156 | 387 | } | ||
157 | 388 | |||
158 | 337 | /*! \internal */ | 389 | /*! \internal */ |
159 | 338 | onModeChanged: internals.updatePickers() | 390 | onModeChanged: internals.updatePickers() |
160 | 339 | /*! \internal */ | 391 | /*! \internal */ |
162 | 340 | onLocaleChanged: internals.updatePickers() | 392 | // onLocaleChanged: internals.updatePickers() |
163 | 341 | 393 | ||
164 | 342 | Component.onCompleted: { | 394 | Component.onCompleted: { |
165 | 343 | if (minimum === undefined) { | 395 | if (minimum === undefined) { |
166 | @@ -347,79 +399,10 @@ | |||
167 | 347 | internals.updatePickers(); | 399 | internals.updatePickers(); |
168 | 348 | } | 400 | } |
169 | 349 | 401 | ||
242 | 350 | // models | 402 | width: parent.width |
243 | 351 | YearModel { | 403 | height: content.height |
172 | 352 | id: yearModel | ||
173 | 353 | mainComponent: datePicker | ||
174 | 354 | pickerCompleted: internals.completed && internals.showYearPicker | ||
175 | 355 | pickerWidth: (!pickerItem) ? 0 : narrowFormatLimit | ||
176 | 356 | function syncModels() { | ||
177 | 357 | dayModel.syncModels(); | ||
178 | 358 | } | ||
179 | 359 | } | ||
180 | 360 | MonthModel { | ||
181 | 361 | id: monthModel | ||
182 | 362 | mainComponent: datePicker | ||
183 | 363 | pickerCompleted: internals.completed && internals.showMonthPicker | ||
184 | 364 | pickerWidth: { | ||
185 | 365 | if (!pickerItem) { | ||
186 | 366 | return 0; | ||
187 | 367 | } | ||
188 | 368 | return MathUtils.clamp(datePicker.width - yearModel.pickerWidth - dayModel.pickerWidth, narrowFormatLimit, longFormatLimit); | ||
189 | 369 | } | ||
190 | 370 | function syncModels() { | ||
191 | 371 | dayModel.syncModels(); | ||
192 | 372 | } | ||
193 | 373 | } | ||
194 | 374 | DayModel { | ||
195 | 375 | id: dayModel | ||
196 | 376 | mainComponent: datePicker | ||
197 | 377 | pickerCompleted: internals.completed && internals.showDayPicker | ||
198 | 378 | pickerWidth: { | ||
199 | 379 | if (!pickerItem) { | ||
200 | 380 | return 0; | ||
201 | 381 | } | ||
202 | 382 | var w = Math.max(datePicker.width * internals.dayPickerRatio, narrowFormatLimit); | ||
203 | 383 | if (w < longFormatLimit && w >= shortFormatLimit) { | ||
204 | 384 | return shortFormatLimit; | ||
205 | 385 | } | ||
206 | 386 | return w; | ||
207 | 387 | } | ||
208 | 388 | } | ||
209 | 389 | HoursModel { | ||
210 | 390 | id: hoursModel | ||
211 | 391 | mainComponent: datePicker | ||
212 | 392 | pickerCompleted: internals.completed && internals.showHoursPicker | ||
213 | 393 | pickerWidth: { | ||
214 | 394 | if (!pickerItem) { | ||
215 | 395 | return 0; | ||
216 | 396 | } | ||
217 | 397 | return narrowFormatLimit; | ||
218 | 398 | } | ||
219 | 399 | } | ||
220 | 400 | MinutesModel { | ||
221 | 401 | id: minutesModel | ||
222 | 402 | mainComponent: datePicker | ||
223 | 403 | pickerCompleted: internals.completed && internals.showMinutesPicker | ||
224 | 404 | pickerWidth: { | ||
225 | 405 | if (!pickerItem) { | ||
226 | 406 | return 0; | ||
227 | 407 | } | ||
228 | 408 | return narrowFormatLimit; | ||
229 | 409 | } | ||
230 | 410 | } | ||
231 | 411 | SecondsModel { | ||
232 | 412 | id: secondsModel | ||
233 | 413 | mainComponent: datePicker | ||
234 | 414 | pickerCompleted: internals.completed && internals.showSecondsPicker | ||
235 | 415 | pickerWidth: { | ||
236 | 416 | if (!pickerItem) { | ||
237 | 417 | return 0; | ||
238 | 418 | } | ||
239 | 419 | return narrowFormatLimit; | ||
240 | 420 | } | ||
241 | 421 | } | ||
244 | 422 | 404 | ||
245 | 405 | /* | ||
246 | 423 | styleName: "DatePickerStyle" | 406 | styleName: "DatePickerStyle" |
247 | 424 | Binding { | 407 | Binding { |
248 | 425 | target: __styleInstance | 408 | target: __styleInstance |
249 | @@ -437,77 +420,12 @@ | |||
250 | 437 | value: (internals.showHoursPicker || internals.showMinutesPicker || internals.showSecondsPicker) ? | 420 | value: (internals.showHoursPicker || internals.showMinutesPicker || internals.showSecondsPicker) ? |
251 | 438 | ":" : "" | 421 | ":" : "" |
252 | 439 | } | 422 | } |
320 | 440 | 423 | */ | |
321 | 441 | // tumbler positioner | 424 | |
255 | 442 | PickerRow { | ||
256 | 443 | id: positioner | ||
257 | 444 | parent: (datePicker.__styleInstance && datePicker.__styleInstance.hasOwnProperty("tumblerHolder")) ? | ||
258 | 445 | datePicker.__styleInstance.tumblerHolder : datePicker | ||
259 | 446 | mainComponent: datePicker | ||
260 | 447 | model: tumblerModel | ||
261 | 448 | margins: internals.margin | ||
262 | 449 | anchors { | ||
263 | 450 | top: parent.top | ||
264 | 451 | bottom: parent.bottom | ||
265 | 452 | horizontalCenter: parent.horizontalCenter | ||
266 | 453 | } | ||
267 | 454 | } | ||
268 | 455 | // tumbler model | ||
269 | 456 | ListModel { | ||
270 | 457 | /* | ||
271 | 458 | Model to hold tumbler order for repeaters. | ||
272 | 459 | Roles: | ||
273 | 460 | - pickerModel | ||
274 | 461 | - pickerName | ||
275 | 462 | */ | ||
276 | 463 | id: tumblerModel | ||
277 | 464 | |||
278 | 465 | /* | ||
279 | 466 | Signal triggered when the model is about to remove a picker. We cannot rely on | ||
280 | 467 | rowAboutToBeRemoved, as by the time the signal is called the list element is | ||
281 | 468 | already removed from the model. | ||
282 | 469 | */ | ||
283 | 470 | signal pickerRemoved(int index) | ||
284 | 471 | |||
285 | 472 | // the function checks whether a pickerModel was added or not | ||
286 | 473 | // returns the index of the model object the pickerModel was found | ||
287 | 474 | // or -1 on error. | ||
288 | 475 | function pickerModelIndex(name) { | ||
289 | 476 | for (var i = 0; i < count; i++) { | ||
290 | 477 | if (get(i).pickerName === name) { | ||
291 | 478 | return i; | ||
292 | 479 | } | ||
293 | 480 | } | ||
294 | 481 | return -1; | ||
295 | 482 | } | ||
296 | 483 | |||
297 | 484 | // the function checks whether a pickerModel is present in the list; | ||
298 | 485 | // moves the existing one to the given index or inserts it if not present | ||
299 | 486 | function setPickerModel(model, name, index) { | ||
300 | 487 | var idx = pickerModelIndex(name); | ||
301 | 488 | if (idx >= 0) { | ||
302 | 489 | move(idx, index, 1); | ||
303 | 490 | } else { | ||
304 | 491 | append({"pickerModel": model, "pickerName": name}); | ||
305 | 492 | } | ||
306 | 493 | } | ||
307 | 494 | |||
308 | 495 | // removes the given picker | ||
309 | 496 | function removePicker(name) { | ||
310 | 497 | var idx = pickerModelIndex(name); | ||
311 | 498 | if (idx >= 0) { | ||
312 | 499 | pickerRemoved(idx); | ||
313 | 500 | remove(idx); | ||
314 | 501 | } | ||
315 | 502 | } | ||
316 | 503 | } | ||
317 | 504 | |||
318 | 505 | // component to calculate text fitting | ||
319 | 506 | Label { id: textSizer; visible: false } | ||
322 | 507 | QtObject { | 425 | QtObject { |
323 | 508 | id: internals | 426 | id: internals |
324 | 509 | property bool completed: false | 427 | property bool completed: false |
326 | 510 | property real margin: units.gu(1.5) | 428 | property real margin: units.gu(2) |
327 | 511 | property real dayPickerRatio: 0.1 | 429 | property real dayPickerRatio: 0.1 |
328 | 512 | 430 | ||
329 | 513 | property bool showYearPicker: true | 431 | property bool showYearPicker: true |
330 | @@ -517,6 +435,7 @@ | |||
331 | 517 | property bool showHoursPicker: false | 435 | property bool showHoursPicker: false |
332 | 518 | property bool showMinutesPicker: false | 436 | property bool showMinutesPicker: false |
333 | 519 | property bool showSecondsPicker: false | 437 | property bool showSecondsPicker: false |
334 | 438 | property bool showDayNightPicker: showHoursPicker || showMinutesPicker || showSecondsPicker | ||
335 | 520 | 439 | ||
336 | 521 | /* | 440 | /* |
337 | 522 | Update pickers. | 441 | Update pickers. |
338 | @@ -574,99 +493,261 @@ | |||
339 | 574 | console.warn("Date and Time picking not allowed at the same time."); | 493 | console.warn("Date and Time picking not allowed at the same time."); |
340 | 575 | return; | 494 | return; |
341 | 576 | } | 495 | } |
435 | 577 | 496 | } | |
436 | 578 | arrangeTumblers(); | 497 | } |
437 | 579 | resetPickers(); | 498 | } |
438 | 580 | } | 499 | |
439 | 581 | } | 500 | states: [ |
440 | 582 | 501 | State { name: '' }, | |
441 | 583 | /* | 502 | State { name: 'years-months' } |
442 | 584 | Resets the pickers. Pickers will update their models with the given date, | 503 | ] |
443 | 585 | minimum and maximum values. | 504 | |
444 | 586 | */ | 505 | property real dropdownAnimDuration: UbuntuAnimation.FastDuration |
445 | 587 | function resetPickers() { | 506 | |
446 | 588 | if (!completed) return; | 507 | transitions: [ |
447 | 589 | for (var i = 0; i < tumblerModel.count; i++) { | 508 | Transition { |
448 | 590 | var pickerItem = tumblerModel.get(i).pickerModel.pickerItem; | 509 | from: '' |
449 | 591 | pickerItem.resetPicker(); | 510 | to: 'years-months' |
450 | 592 | } | 511 | ParallelAnimation { |
451 | 593 | 512 | UbuntuNumberAnimation { | |
452 | 594 | // calculate the ratio for the dayPicker | 513 | target: headerShadow |
453 | 595 | var maxWidth = 0.0; | 514 | property: 'width' |
454 | 596 | maxWidth += showYearPicker ? yearModel.longFormatLimit : 0.0; | 515 | to: content.width |
455 | 597 | maxWidth += showMonthPicker ? monthModel.longFormatLimit : 0.0; | 516 | duration: datePicker.dropdownAnimDuration / 2 |
456 | 598 | maxWidth += showDayPicker ? dayModel.longFormatLimit : 0.0; | 517 | } |
457 | 599 | if (showDayPicker && maxWidth > 0.0) { | 518 | UbuntuNumberAnimation { |
458 | 600 | dayPickerRatio = (dayModel.longFormatLimit / maxWidth).toPrecision(3); | 519 | target: headerShadow |
459 | 601 | } | 520 | property: 'opacity' |
460 | 602 | } | 521 | to: 1 |
461 | 603 | 522 | duration: datePicker.dropdownAnimDuration / 2 | |
462 | 604 | /* | 523 | } |
463 | 605 | Detects the tumbler order from the date format of the locale | 524 | UbuntuNumberAnimation { |
464 | 606 | */ | 525 | target: yearsListDropdown |
465 | 607 | function arrangeTumblers() { | 526 | property: 'y' |
466 | 608 | // disable completion so avoid accidental date changes | 527 | to: 0 |
467 | 609 | completed = false; | 528 | duration: datePicker.dropdownAnimDuration |
468 | 610 | 529 | } | |
469 | 611 | // use short format to exclude any extra characters | 530 | SequentialAnimation { |
470 | 612 | // FIXME: The js split(/\W/g) terminates the process on armhf with Qt 5.3 (v4 js) (https://bugreports.qt-project.org/browse/QTBUG-39255) | 531 | PauseAnimation { |
471 | 613 | var format = datePicker.locale.dateFormat(Locale.ShortFormat).match(/\w+/g); | 532 | duration: datePicker.dropdownAnimDuration |
472 | 614 | // loop through the format to decide the position of the tumbler | 533 | } |
473 | 615 | var formatIndex = 0; | 534 | UbuntuNumberAnimation { |
474 | 616 | for (var i in format) { | 535 | target: headerShadow |
475 | 617 | if (!format[i].length) continue; | 536 | property: 'width' |
476 | 618 | // check the first two characters | 537 | to: 0 |
477 | 619 | switch (format[i].substr(0, 1).toLowerCase()) { | 538 | duration: datePicker.dropdownAnimDuration / 1.5 |
478 | 620 | case 'y': | 539 | } |
479 | 621 | if (showYearPicker) { | 540 | } |
480 | 622 | tumblerModel.setPickerModel(yearModel, "YearPicker", formatIndex); | 541 | } |
481 | 623 | formatIndex++; | 542 | }, |
482 | 624 | } else { | 543 | Transition { |
483 | 625 | tumblerModel.removePicker("YearPicker"); | 544 | from: 'years-months' |
484 | 626 | } | 545 | to: '' |
485 | 627 | 546 | ParallelAnimation { | |
486 | 628 | break; | 547 | property real duration: 300 |
487 | 629 | case 'm': | 548 | UbuntuNumberAnimation { |
488 | 630 | if (showMonthPicker) { | 549 | target: headerShadow |
489 | 631 | tumblerModel.setPickerModel(monthModel, "MonthPicker", formatIndex); | 550 | property: 'width' |
490 | 632 | formatIndex++; | 551 | to: content.width |
491 | 633 | } else { | 552 | duration: datePicker.dropdownAnimDuration / 2 |
492 | 634 | tumblerModel.removePicker("MonthPicker"); | 553 | } |
493 | 635 | } | 554 | UbuntuNumberAnimation { |
494 | 636 | 555 | target: headerShadow | |
495 | 637 | break; | 556 | property: 'opacity' |
496 | 638 | case 'd': | 557 | to: 1 |
497 | 639 | if (showDayPicker) { | 558 | duration: datePicker.dropdownAnimDuration / 2 |
498 | 640 | tumblerModel.setPickerModel(dayModel, "DayPicker", formatIndex); | 559 | } |
499 | 641 | formatIndex++; | 560 | UbuntuNumberAnimation { |
500 | 642 | } else { | 561 | target: yearsListDropdown |
501 | 643 | tumblerModel.removePicker("DayPicker"); | 562 | property: 'y' |
502 | 644 | } | 563 | to: -yearsListDropdown.height |
503 | 645 | break; | 564 | duration: datePicker.dropdownAnimDuration |
504 | 646 | } | 565 | } |
505 | 647 | } | 566 | SequentialAnimation { |
506 | 648 | // check hms | 567 | PauseAnimation { |
507 | 649 | if (showHoursPicker) { | 568 | duration: datePicker.dropdownAnimDuration |
508 | 650 | tumblerModel.setPickerModel(hoursModel, "HoursPicker", formatIndex); | 569 | } |
509 | 651 | formatIndex++; | 570 | UbuntuNumberAnimation { |
510 | 652 | } else { | 571 | target: headerShadow |
511 | 653 | tumblerModel.removePicker("HoursPicker"); | 572 | property: 'width' |
512 | 654 | } | 573 | to: 0 |
513 | 655 | if (showMinutesPicker) { | 574 | duration: datePicker.dropdownAnimDuration / 1.5 |
514 | 656 | tumblerModel.setPickerModel(minutesModel, "MinutesPicker", formatIndex); | 575 | } |
515 | 657 | formatIndex++; | 576 | UbuntuNumberAnimation { |
516 | 658 | } else { | 577 | target: headerShadow |
517 | 659 | tumblerModel.removePicker("MinutesPicker"); | 578 | property: 'opacity' |
518 | 660 | } | 579 | to: 0 |
519 | 661 | if (showSecondsPicker) { | 580 | duration: datePicker.dropdownAnimDuration / 3 |
520 | 662 | tumblerModel.setPickerModel(secondsModel, "SecondsPicker", formatIndex); | 581 | } |
521 | 663 | formatIndex++; | 582 | } |
522 | 664 | } else { | 583 | } |
523 | 665 | tumblerModel.removePicker("SecondsPicker"); | 584 | } |
524 | 666 | } | 585 | ] |
525 | 667 | 586 | ||
526 | 668 | // re-enable completion | 587 | Rectangle { |
527 | 669 | completed = true; | 588 | color: theme.palette.normal.background |
528 | 589 | anchors.fill: parent | ||
529 | 590 | } | ||
530 | 591 | |||
531 | 592 | // TimePicker | ||
532 | 593 | |||
533 | 594 | Item { | ||
534 | 595 | id: timeContent | ||
535 | 596 | height: container.itemHeight * 5 | ||
536 | 597 | anchors.leftMargin: root.margin | ||
537 | 598 | anchors.rightMargin: root.margin | ||
538 | 599 | visible: internals.showHoursPicker || internals.showMinutesPicker || internals.showSecondsPicker | ||
539 | 600 | |||
540 | 601 | Row { | ||
541 | 602 | id: container | ||
542 | 603 | anchors.fill: parent | ||
543 | 604 | property real itemHeight: units.gu(2) | ||
544 | 605 | property int pickerCount: 3 | ||
545 | 606 | property real pickerWidth: (container.width - internals.margin * container.pickerCount - 1) / container.pickerCount | ||
546 | 607 | |||
547 | 608 | HourPicker { | ||
548 | 609 | type: 'hours' | ||
549 | 610 | width: container.pickerWidth | ||
550 | 611 | height: container.height | ||
551 | 612 | ampm: internals.showDayPicker | ||
552 | 613 | } | ||
553 | 614 | |||
554 | 615 | HourPicker { | ||
555 | 616 | type: 'minutes' | ||
556 | 617 | width: container.pickerWidth | ||
557 | 618 | height: container.height | ||
558 | 619 | } | ||
559 | 620 | |||
560 | 621 | HourPicker { | ||
561 | 622 | type: 'seconds' | ||
562 | 623 | width: container.pickerWidth | ||
563 | 624 | height: container.height | ||
564 | 625 | } | ||
565 | 626 | |||
566 | 627 | DayNightPicker { | ||
567 | 628 | width: container.pickerWidth | ||
568 | 629 | height: container.height | ||
569 | 630 | itemHeight: container.itemHeight | ||
570 | 631 | } | ||
571 | 632 | |||
572 | 633 | DigitSeparator { | ||
573 | 634 | width: container.pickerWidth | ||
574 | 635 | height: container.height | ||
575 | 636 | } | ||
576 | 637 | } | ||
577 | 638 | } | ||
578 | 639 | |||
579 | 640 | Item { | ||
580 | 641 | id: selectedShape | ||
581 | 642 | width: parent.width | ||
582 | 643 | height: parent.height / 5 | ||
583 | 644 | y: parent.height / 2 - height / 2 | ||
584 | 645 | visible: internals.showHoursPicker || internals.showMinutesPicker || internals.showSecondsPicker | ||
585 | 646 | |||
586 | 647 | Rectangle { | ||
587 | 648 | width: parent.width | ||
588 | 649 | height: units.dp(1) | ||
589 | 650 | y: 0 | ||
590 | 651 | color: UbuntuColors.lightGrey | ||
591 | 652 | } | ||
592 | 653 | |||
593 | 654 | Rectangle { | ||
594 | 655 | width: parent.width | ||
595 | 656 | height: units.dp(1) | ||
596 | 657 | y: parent.height - height | ||
597 | 658 | color: UbuntuColors.lightGrey | ||
598 | 659 | } | ||
599 | 660 | } | ||
600 | 661 | |||
601 | 662 | // DatePicker | ||
602 | 663 | |||
603 | 664 | Column { | ||
604 | 665 | id: content | ||
605 | 666 | width: parent.width | ||
606 | 667 | visible: internals.showMonthPicker || internals.showYearPicker || internals.showDayPicker | ||
607 | 668 | |||
608 | 669 | DatePickerHeader { | ||
609 | 670 | id: header | ||
610 | 671 | anchors.left: parent.left | ||
611 | 672 | anchors.right: parent.right | ||
612 | 673 | fontSize: 'large' | ||
613 | 674 | color: theme.palette.normal.backgroundText | ||
614 | 675 | activeColor: UbuntuColors.darkGrey | ||
615 | 676 | date: DU.clone(datePicker.date, 'setDate', 1) | ||
616 | 677 | minimum: datePicker.minimum | ||
617 | 678 | maximum: datePicker.maximum | ||
618 | 679 | onRequestNextMonth: datePicker.date = DU.clone(datePicker.date, 'setMonth', datePicker.date.getMonth() + 1) | ||
619 | 680 | onRequestPreviousMonth: datePicker.date = DU.clone(datePicker.date, 'setMonth', datePicker.date.getMonth() - 1) | ||
620 | 681 | onRequestToggleYearList: datePicker.toggleYearList() | ||
621 | 682 | yearsListOpened: datePicker.state === 'years-months' | ||
622 | 683 | visible: internals.showYearPicker | ||
623 | 684 | } | ||
624 | 685 | |||
625 | 686 | Item { | ||
626 | 687 | width: parent.width | ||
627 | 688 | height: header.height * 0.5 | ||
628 | 689 | Rectangle { | ||
629 | 690 | id: headerShadow | ||
630 | 691 | y: parent.height | ||
631 | 692 | visible: false | ||
632 | 693 | opacity: 0 | ||
633 | 694 | color: theme.palette.normal.baseText | ||
634 | 695 | width: 0 | ||
635 | 696 | height: units.gu(1/16) | ||
636 | 697 | anchors.horizontalCenter: parent.horizontalCenter | ||
637 | 698 | } | ||
638 | 699 | visible: internals.showYearPicker || internals.showMonthPicker | ||
639 | 700 | } | ||
640 | 701 | |||
641 | 702 | Item { | ||
642 | 703 | width: parent.width | ||
643 | 704 | height: listView.height | ||
644 | 705 | visible: internals.showDayPicker | ||
645 | 706 | ListView { | ||
646 | 707 | id: listView | ||
647 | 708 | clip: true | ||
648 | 709 | width: parent.width | ||
649 | 710 | height: currentItem.height | ||
650 | 711 | model: datePicker.monthsRange | ||
651 | 712 | snapMode: datePicker.snapMode | ||
652 | 713 | orientation: datePicker.scrollDirection === Qt.Horizontal ? ListView.Horizontal : ListView.Vertical | ||
653 | 714 | highlightFollowsCurrentItem: true | ||
654 | 715 | highlightMoveDuration: 0 | ||
655 | 716 | highlightRangeMode: ListView.StrictlyEnforceRange | ||
656 | 717 | property bool indexInit: false | ||
657 | 718 | onCurrentIndexChanged: { | ||
658 | 719 | if (!indexInit && currentIndex === 0) { | ||
659 | 720 | indexInit = true; | ||
660 | 721 | return; | ||
661 | 722 | } | ||
662 | 723 | if (!listView.moving) { | ||
663 | 724 | return; | ||
664 | 725 | } | ||
665 | 726 | datePicker.date = DU.clone(minimum, 'setMonth', minimum.getMonth() + currentIndex); | ||
666 | 727 | } | ||
667 | 728 | |||
668 | 729 | delegate: DatePickerMonthDays { | ||
669 | 730 | id: panel | ||
670 | 731 | width: datePicker.width | ||
671 | 732 | displayedMonth: DU.clone(minimum, 'setMonth', minimum.getMonth() + index) | ||
672 | 733 | onRequestNextMonth: datePicker.date = DU.clone(displayedMonth, 'setMonth', displayedMonth.getMonth() + 1) | ||
673 | 734 | onRequestPreviousMonth: datePicker.date = DU.clone(displayedMonth, 'setMonth', displayedMonth.getMonth() - 1) | ||
674 | 735 | onRequestDateChange: datePicker.date = date | ||
675 | 736 | delegate: datePicker.delegate | ||
676 | 737 | } | ||
677 | 738 | } | ||
678 | 739 | |||
679 | 740 | Item { | ||
680 | 741 | clip: true | ||
681 | 742 | width: parent.width | ||
682 | 743 | height: parent.height | ||
683 | 744 | YearListDropdown { | ||
684 | 745 | id: yearsListDropdown | ||
685 | 746 | minimum: datePicker.minimum | ||
686 | 747 | maximum: datePicker.maximum | ||
687 | 748 | onRequestDateChange: datePicker.date = newDate | ||
688 | 749 | } | ||
689 | 750 | } | ||
690 | 670 | } | 751 | } |
691 | 671 | } | 752 | } |
692 | 672 | } | 753 | } |
693 | 673 | 754 | ||
694 | === added file 'src/imports/Components/Pickers/1.3/DatePickerHeader.qml' | |||
695 | --- src/imports/Components/Pickers/1.3/DatePickerHeader.qml 1970-01-01 00:00:00 +0000 | |||
696 | +++ src/imports/Components/Pickers/1.3/DatePickerHeader.qml 2016-10-25 11:37:58 +0000 | |||
697 | @@ -0,0 +1,98 @@ | |||
698 | 1 | import QtQuick 2.4 | ||
699 | 2 | import Ubuntu.Components 1.3 | ||
700 | 3 | import './calendar.js' as Calendar | ||
701 | 4 | import './dateutils.js' as DU | ||
702 | 5 | |||
703 | 6 | Item { | ||
704 | 7 | id: root | ||
705 | 8 | |||
706 | 9 | property string fontSize: 'large' | ||
707 | 10 | property color color: 'black' | ||
708 | 11 | property color activeColor: 'grey' | ||
709 | 12 | |||
710 | 13 | property date date: new Date() | ||
711 | 14 | property date minimum: DU.clone(null, 'setDate', 1) | ||
712 | 15 | property date maximum: DU.clone(minimum, 'setFullYear', minimum.getFullYear() + 50) | ||
713 | 16 | |||
714 | 17 | property bool yearsListOpened: false | ||
715 | 18 | |||
716 | 19 | signal requestPreviousMonth() | ||
717 | 20 | signal requestNextMonth() | ||
718 | 21 | signal requestToggleYearList() | ||
719 | 22 | |||
720 | 23 | width: parent.width | ||
721 | 24 | height: month.height | ||
722 | 25 | |||
723 | 26 | MouseArea { | ||
724 | 27 | id: yearDropDown | ||
725 | 28 | onReleased: if (containsMouse) requestToggleYearList() | ||
726 | 29 | anchors.fill: parent | ||
727 | 30 | Row { | ||
728 | 31 | spacing: 0 | ||
729 | 32 | anchors.horizontalCenter: parent.horizontalCenter | ||
730 | 33 | height: parent.height | ||
731 | 34 | Label { | ||
732 | 35 | id: month | ||
733 | 36 | textSize: root.fontSize === 'large' ? Label.Medium : Label.Large | ||
734 | 37 | text: DU.format(root.date, 'MMMM') | ||
735 | 38 | horizontalAlignment: Text.AlignHCenter | ||
736 | 39 | color: yearDropDown.containsPress? root.activeColor : root.color | ||
737 | 40 | } | ||
738 | 41 | Item { | ||
739 | 42 | width: units.gu(0.5) | ||
740 | 43 | height: 1 | ||
741 | 44 | } | ||
742 | 45 | Label { | ||
743 | 46 | id: year | ||
744 | 47 | textSize: root.fontSize === 'large' ? Label.Medium : Label.Large | ||
745 | 48 | text: DU.format(root.date, 'yyyy') | ||
746 | 49 | horizontalAlignment: Text.AlignHCenter | ||
747 | 50 | color: yearDropDown.containsPress? root.activeColor : root.color | ||
748 | 51 | } | ||
749 | 52 | Item { | ||
750 | 53 | width: units.gu(0.5) | ||
751 | 54 | height: 1 | ||
752 | 55 | } | ||
753 | 56 | Icon { | ||
754 | 57 | name: yearsListOpened? 'up' : 'down' | ||
755 | 58 | height: year.height / 1.5 | ||
756 | 59 | y: parent.height / 2 - height / 2 + height * 0.1 | ||
757 | 60 | color: yearDropDown.containsPress? root.activeColor : root.color | ||
758 | 61 | } | ||
759 | 62 | } | ||
760 | 63 | } | ||
761 | 64 | |||
762 | 65 | MouseArea { | ||
763 | 66 | visible: !DU.sameDay(root.date, minimum) | ||
764 | 67 | anchors.left: parent.left | ||
765 | 68 | anchors.leftMargin: units.gu(1.7) | ||
766 | 69 | width: parent.height | ||
767 | 70 | height: width | ||
768 | 71 | onReleased: if (containsMouse) requestPreviousMonth() | ||
769 | 72 | Icon { | ||
770 | 73 | anchors.left: parent.left | ||
771 | 74 | anchors.verticalCenter: parent.verticalCenter | ||
772 | 75 | width: parent.width | ||
773 | 76 | height: width | ||
774 | 77 | color: parent.containsPress? root.activeColor : root.color | ||
775 | 78 | name: 'previous' | ||
776 | 79 | } | ||
777 | 80 | } | ||
778 | 81 | |||
779 | 82 | MouseArea { | ||
780 | 83 | visible: !DU.sameDay(root.date, maximum) | ||
781 | 84 | anchors.right: parent.right | ||
782 | 85 | anchors.rightMargin: units.gu(1.7) | ||
783 | 86 | width: parent.height | ||
784 | 87 | height: width | ||
785 | 88 | onReleased: if (containsMouse) requestNextMonth() | ||
786 | 89 | Icon { | ||
787 | 90 | anchors.right: parent.right | ||
788 | 91 | anchors.verticalCenter: parent.verticalCenter | ||
789 | 92 | width: parent.width | ||
790 | 93 | height: width | ||
791 | 94 | color: parent.containsPress? root.activeColor : root.color | ||
792 | 95 | name: 'next' | ||
793 | 96 | } | ||
794 | 97 | } | ||
795 | 98 | } | ||
796 | 0 | 99 | ||
797 | === added file 'src/imports/Components/Pickers/1.3/DatePickerMonthDays.qml' | |||
798 | --- src/imports/Components/Pickers/1.3/DatePickerMonthDays.qml 1970-01-01 00:00:00 +0000 | |||
799 | +++ src/imports/Components/Pickers/1.3/DatePickerMonthDays.qml 2016-10-25 11:37:58 +0000 | |||
800 | @@ -0,0 +1,115 @@ | |||
801 | 1 | import QtQuick 2.4 | ||
802 | 2 | import Ubuntu.Components 1.3 | ||
803 | 3 | import './calendar.js' as Calendar | ||
804 | 4 | import './dateutils.js' as DU | ||
805 | 5 | |||
806 | 6 | MouseArea { | ||
807 | 7 | id: root | ||
808 | 8 | |||
809 | 9 | height: cellHeight * 7 | ||
810 | 10 | onPressed: lastPressedPosition = getPosition(mouse) | ||
811 | 11 | |||
812 | 12 | onReleased: { | ||
813 | 13 | lastPressedPosition = null | ||
814 | 14 | var pressedPosition = getPosition(mouse) | ||
815 | 15 | var index = pressedPosition[1] * 7 + pressedPosition[0] | ||
816 | 16 | var item = monthDaysRepeater.itemAt(index) | ||
817 | 17 | |||
818 | 18 | var currDay = root.monthDays[index] | ||
819 | 19 | var currDate = currDay.date | ||
820 | 20 | var dispDate = root.displayedMonth | ||
821 | 21 | if (currDay.surrounding) { | ||
822 | 22 | if (DU.compareDates(currDate, dispDate) < 0) { | ||
823 | 23 | requestPreviousMonth() | ||
824 | 24 | } else { | ||
825 | 25 | requestNextMonth() | ||
826 | 26 | } | ||
827 | 27 | } else if (root.date.getTime() !== currDate.getTime()) { | ||
828 | 28 | requestDateChange(currDate) | ||
829 | 29 | } | ||
830 | 30 | } | ||
831 | 31 | |||
832 | 32 | property date date: new Date() | ||
833 | 33 | property date displayedMonth: new Date(date.getTime()) | ||
834 | 34 | property int firstDayOfWeek: 1 | ||
835 | 35 | property var monthDays: [] | ||
836 | 36 | property Component delegate | ||
837 | 37 | |||
838 | 38 | readonly property real cellWidth: width / 7 | ||
839 | 39 | readonly property real cellHeight: cellWidth * 0.62 | ||
840 | 40 | |||
841 | 41 | property var lastPressedPosition: null | ||
842 | 42 | |||
843 | 43 | property Item pressedItem: { | ||
844 | 44 | if (!(root.containsPress && root.lastPressedPosition)) { | ||
845 | 45 | return null | ||
846 | 46 | } | ||
847 | 47 | var index = lastPressedPosition[1] * 7 + lastPressedPosition[0] | ||
848 | 48 | return monthDaysRepeater.itemAt(index) | ||
849 | 49 | } | ||
850 | 50 | |||
851 | 51 | function getPosition(mouse) { | ||
852 | 52 | return [ | ||
853 | 53 | Math.floor(mouse.x / cellWidth), | ||
854 | 54 | Math.floor((mouse.y - cellHeight) / cellHeight), | ||
855 | 55 | ] | ||
856 | 56 | } | ||
857 | 57 | |||
858 | 58 | WorkerScript { | ||
859 | 59 | source: 'DatePickerMonthDaysWorker.js' | ||
860 | 60 | onMessage: { | ||
861 | 61 | if (messageObject.name === 'monthDays') { | ||
862 | 62 | root.monthDays = messageObject.monthDays | ||
863 | 63 | monthDaysRepeater.model = messageObject.monthDays.length | ||
864 | 64 | } | ||
865 | 65 | } | ||
866 | 66 | Component.onCompleted: { | ||
867 | 67 | this.sendMessage({ | ||
868 | 68 | name: 'requestMonthDays', | ||
869 | 69 | firstDayOfWeek: firstDayOfWeek, | ||
870 | 70 | displayedMonth: displayedMonth, | ||
871 | 71 | }) | ||
872 | 72 | } | ||
873 | 73 | } | ||
874 | 74 | |||
875 | 75 | signal requestPreviousMonth() | ||
876 | 76 | signal requestNextMonth() | ||
877 | 77 | signal requestDateChange(date date) | ||
878 | 78 | |||
879 | 79 | Repeater { | ||
880 | 80 | model: 7 | ||
881 | 81 | Label { | ||
882 | 82 | id: label | ||
883 | 83 | width: cellWidth | ||
884 | 84 | height: cellHeight | ||
885 | 85 | x: index * cellWidth | ||
886 | 86 | y: 0 | ||
887 | 87 | text: DU.shortDayName(index).toUpperCase() | ||
888 | 88 | horizontalAlignment: Text.AlignHCenter | ||
889 | 89 | verticalAlignment: Text.AlignVCenter | ||
890 | 90 | textSize: Label.XSmall | ||
891 | 91 | color: theme.palette.normal.backgroundTertiaryText | ||
892 | 92 | } | ||
893 | 93 | } | ||
894 | 94 | |||
895 | 95 | Repeater { | ||
896 | 96 | id: monthDaysRepeater | ||
897 | 97 | model: 0 | ||
898 | 98 | Item { | ||
899 | 99 | id: monthDayItem | ||
900 | 100 | width: cellWidth | ||
901 | 101 | height: cellHeight | ||
902 | 102 | x: (index % 7) * cellWidth | ||
903 | 103 | y: ((index - index % 7) / 7) * cellHeight + cellHeight | ||
904 | 104 | Loader { | ||
905 | 105 | property var modelData: root.monthDays[index] | ||
906 | 106 | property date date: modelData.date | ||
907 | 107 | property string text: modelData.text | ||
908 | 108 | property bool currentMonth: !modelData.surrounding | ||
909 | 109 | property bool pressed: monthDayItem === pressedItem | ||
910 | 110 | anchors.fill: parent | ||
911 | 111 | sourceComponent: delegate | ||
912 | 112 | } | ||
913 | 113 | } | ||
914 | 114 | } | ||
915 | 115 | } | ||
916 | 0 | 116 | ||
917 | === added file 'src/imports/Components/Pickers/1.3/DatePickerMonthDaysWorker.js' | |||
918 | --- src/imports/Components/Pickers/1.3/DatePickerMonthDaysWorker.js 1970-01-01 00:00:00 +0000 | |||
919 | +++ src/imports/Components/Pickers/1.3/DatePickerMonthDaysWorker.js 2016-10-25 11:37:58 +0000 | |||
920 | @@ -0,0 +1,61 @@ | |||
921 | 1 | function formatDay(d, month) { | ||
922 | 2 | var dateNum = d.getDate() | ||
923 | 3 | return { | ||
924 | 4 | dateNum: dateNum, | ||
925 | 5 | text: dateNum + '', | ||
926 | 6 | surrounding: d.getMonth() !== month, | ||
927 | 7 | date: d | ||
928 | 8 | } | ||
929 | 9 | } | ||
930 | 10 | |||
931 | 11 | function getMonthDays(Calendar, displayedMonth, firstDayOfWeek) { | ||
932 | 12 | |||
933 | 13 | var cal = new Calendar(firstDayOfWeek) | ||
934 | 14 | var month = displayedMonth.getMonth() | ||
935 | 15 | var year = displayedMonth.getFullYear() | ||
936 | 16 | |||
937 | 17 | function setTime(date) { | ||
938 | 18 | var d = new Date(displayedMonth.getTime()) | ||
939 | 19 | d.setFullYear(date.getFullYear()) | ||
940 | 20 | d.setMonth(date.getMonth()) | ||
941 | 21 | d.setDate(date.getDate()) | ||
942 | 22 | return d | ||
943 | 23 | } | ||
944 | 24 | |||
945 | 25 | var monthDates = [] | ||
946 | 26 | cal.monthDates(year, month, function(d) { | ||
947 | 27 | monthDates.push(formatDay(setTime(d), month)) | ||
948 | 28 | }) | ||
949 | 29 | |||
950 | 30 | if (monthDates.length / 7 > 5) { | ||
951 | 31 | return monthDates | ||
952 | 32 | } | ||
953 | 33 | |||
954 | 34 | // var lastDate = new Date(year, month, 1) | ||
955 | 35 | var lastDate = new Date(displayedMonth.getTime()) | ||
956 | 36 | lastDate.setFullYear(year) | ||
957 | 37 | lastDate.setMonth(month) | ||
958 | 38 | lastDate.setDate(1) | ||
959 | 39 | |||
960 | 40 | var lastDay = monthDates[monthDates.length - 1] | ||
961 | 41 | if (lastDay.surrounding) lastDate.setMonth(month + 1) | ||
962 | 42 | lastDate.setDate(lastDay.dateNum) | ||
963 | 43 | |||
964 | 44 | for (var i = monthDates.length; i < 7 * 6; i++) { | ||
965 | 45 | lastDate.setDate(lastDate.getDate() + 1) | ||
966 | 46 | monthDates.push(formatDay(lastDate, month)) | ||
967 | 47 | } | ||
968 | 48 | |||
969 | 49 | return monthDates | ||
970 | 50 | } | ||
971 | 51 | |||
972 | 52 | WorkerScript.onMessage = function(msg) { | ||
973 | 53 | if (msg.name === 'requestMonthDays') { | ||
974 | 54 | Qt.include('calendar.js', function(status) { | ||
975 | 55 | WorkerScript.sendMessage({ | ||
976 | 56 | name: 'monthDays', | ||
977 | 57 | monthDays: getMonthDays(Calendar, msg.displayedMonth, msg.firstDayOfWeek), | ||
978 | 58 | }) | ||
979 | 59 | }) | ||
980 | 60 | } | ||
981 | 61 | } | ||
982 | 0 | 62 | ||
983 | === added file 'src/imports/Components/Pickers/1.3/DayNightPicker.qml' | |||
984 | --- src/imports/Components/Pickers/1.3/DayNightPicker.qml 1970-01-01 00:00:00 +0000 | |||
985 | +++ src/imports/Components/Pickers/1.3/DayNightPicker.qml 2016-10-25 11:37:58 +0000 | |||
986 | @@ -0,0 +1,50 @@ | |||
987 | 1 | import Ubuntu.Components 1.3 | ||
988 | 2 | import QtQuick 2.4 | ||
989 | 3 | import 'dateutils.js' as DU | ||
990 | 4 | |||
991 | 5 | ListView { | ||
992 | 6 | id: ampmListView | ||
993 | 7 | clip: true | ||
994 | 8 | model: ['AM', 'PM'] | ||
995 | 9 | cacheBuffer: 0 | ||
996 | 10 | snapMode: ListView.SnapToItem | ||
997 | 11 | orientation: ListView.Vertical | ||
998 | 12 | property real itemHeight | ||
999 | 13 | |||
1000 | 14 | highlightFollowsCurrentItem: true | ||
1001 | 15 | highlightMoveDuration: UbuntuAnimation.FastDuration | ||
1002 | 16 | highlightRangeMode: ListView.StrictlyEnforceRange | ||
1003 | 17 | |||
1004 | 18 | preferredHighlightBegin: height / 2 - itemHeight / 2 | ||
1005 | 19 | preferredHighlightEnd: height / 2 + itemHeight / 2 | ||
1006 | 20 | |||
1007 | 21 | onCurrentIndexChanged: { | ||
1008 | 22 | var hour = date.getHours() | ||
1009 | 23 | |||
1010 | 24 | if (hour < 12 && currentIndex === 1) { | ||
1011 | 25 | hour += 12 | ||
1012 | 26 | } else if (hour > 12 && currentIndex === 0) { | ||
1013 | 27 | hour -= 12 | ||
1014 | 28 | } | ||
1015 | 29 | |||
1016 | 30 | datePicker.date = DU.clone(date, 'setHours', hour); | ||
1017 | 31 | } | ||
1018 | 32 | |||
1019 | 33 | delegate: MouseArea { | ||
1020 | 34 | property bool active: ListView.isCurrentItem | ||
1021 | 35 | width: parent.width | ||
1022 | 36 | height: itemHeight | ||
1023 | 37 | onReleased: ampmListView.currentIndex = index | ||
1024 | 38 | Label { | ||
1025 | 39 | id: item | ||
1026 | 40 | color: parent.active? UbuntuColors.darkGrey : UbuntuColors.lightGrey // FIXME: | ||
1027 | 41 | width: parent.width - units.gu(1) | ||
1028 | 42 | height: parent.height | ||
1029 | 43 | x: units.gu(1) | ||
1030 | 44 | text: modelData | ||
1031 | 45 | textSize: Label.Medium | ||
1032 | 46 | horizontalAlignment: Text.AlignLeft | ||
1033 | 47 | verticalAlignment: Text.AlignVCenter | ||
1034 | 48 | } | ||
1035 | 49 | } | ||
1036 | 50 | } | ||
1037 | 0 | 51 | ||
1038 | === added file 'src/imports/Components/Pickers/1.3/DigitSeparator.qml' | |||
1039 | --- src/imports/Components/Pickers/1.3/DigitSeparator.qml 1970-01-01 00:00:00 +0000 | |||
1040 | +++ src/imports/Components/Pickers/1.3/DigitSeparator.qml 2016-10-25 11:37:58 +0000 | |||
1041 | @@ -0,0 +1,10 @@ | |||
1042 | 1 | import QtQuick 2.4 | ||
1043 | 2 | import Ubuntu.Components 1.3 | ||
1044 | 3 | |||
1045 | 4 | Label { | ||
1046 | 5 | anchors.verticalCenter: parent.verticalCenter | ||
1047 | 6 | color: theme.palette.normal.backgroundText | ||
1048 | 7 | text: ':' | ||
1049 | 8 | textSize: Label.Medium | ||
1050 | 9 | Component.onCompleted: x -= width / 2 | ||
1051 | 10 | } | ||
1052 | 0 | 11 | ||
1053 | === added file 'src/imports/Components/Pickers/1.3/HourPicker.qml' | |||
1054 | --- src/imports/Components/Pickers/1.3/HourPicker.qml 1970-01-01 00:00:00 +0000 | |||
1055 | +++ src/imports/Components/Pickers/1.3/HourPicker.qml 2016-10-25 11:37:58 +0000 | |||
1056 | @@ -0,0 +1,114 @@ | |||
1057 | 1 | import Ubuntu.Components 1.3 | ||
1058 | 2 | import QtQuick 2.4 | ||
1059 | 3 | import 'dateutils.js' as DU | ||
1060 | 4 | |||
1061 | 5 | PathView { | ||
1062 | 6 | id: pathview | ||
1063 | 7 | property date date: datePicker.date // FIXME: | ||
1064 | 8 | property real itemAlign: Text.AlignHCenter | ||
1065 | 9 | property string type | ||
1066 | 10 | property bool ampm: true | ||
1067 | 11 | clip: true | ||
1068 | 12 | pathItemCount: 6 | ||
1069 | 13 | model: { | ||
1070 | 14 | if (type === 'hours') { | ||
1071 | 15 | return ampm? 12 : 24 | ||
1072 | 16 | } | ||
1073 | 17 | if (type === 'minutes' || type === 'seconds') { | ||
1074 | 18 | return 60 | ||
1075 | 19 | } | ||
1076 | 20 | return 0 | ||
1077 | 21 | } | ||
1078 | 22 | snapMode: PathView.SnapToItem | ||
1079 | 23 | preferredHighlightBegin: 0.5 | ||
1080 | 24 | preferredHighlightEnd: 0.5 | ||
1081 | 25 | |||
1082 | 26 | property bool indexInit: false | ||
1083 | 27 | Timer { | ||
1084 | 28 | id: afterCompleted | ||
1085 | 29 | interval: 0 | ||
1086 | 30 | onTriggered: indexInit = true | ||
1087 | 31 | } | ||
1088 | 32 | onCurrentIndexChanged: { | ||
1089 | 33 | if (!indexInit) return | ||
1090 | 34 | |||
1091 | 35 | var method = null | ||
1092 | 36 | var value = null | ||
1093 | 37 | var am = date.getHours() > 0 && date.getHours() < 13 | ||
1094 | 38 | |||
1095 | 39 | if (type === 'hours') { | ||
1096 | 40 | method = 'setHours' | ||
1097 | 41 | if (ampm) { | ||
1098 | 42 | value = am? currentIndex + 1 : ((currentIndex + 13) % 24) | ||
1099 | 43 | } else { | ||
1100 | 44 | value = (currentIndex + 1) % 24 | ||
1101 | 45 | } | ||
1102 | 46 | } else if (type === 'minutes') { | ||
1103 | 47 | method = 'setMinutes' | ||
1104 | 48 | value = currentIndex | ||
1105 | 49 | |||
1106 | 50 | } else if (type === 'seconds') { | ||
1107 | 51 | method = 'setSeconds' | ||
1108 | 52 | value = currentIndex | ||
1109 | 53 | } | ||
1110 | 54 | |||
1111 | 55 | if (method === null || value === null) { | ||
1112 | 56 | return | ||
1113 | 57 | } | ||
1114 | 58 | |||
1115 | 59 | datePicker.date = DU.clone(date, method, value) // FIXME: | ||
1116 | 60 | } | ||
1117 | 61 | delegate: Item { | ||
1118 | 62 | property bool active: PathView.isCurrentItem | ||
1119 | 63 | width: pathview.width | ||
1120 | 64 | height: datePicker.itemHeight // FIXME: | ||
1121 | 65 | Label { | ||
1122 | 66 | width: parent.width | ||
1123 | 67 | height: parent.height | ||
1124 | 68 | // FIXME: What color? | ||
1125 | 69 | color: parent.active? UbuntuColors.darkGrey : UbuntuColors.lightGrey | ||
1126 | 70 | text: { | ||
1127 | 71 | if (pathview.type === 'hours') { | ||
1128 | 72 | return DU.format(DU.clone(date, 'setHours', index + 1), 'HH') | ||
1129 | 73 | } | ||
1130 | 74 | if (pathview.type === 'minutes') { | ||
1131 | 75 | return DU.format(DU.clone(date, 'setMinutes', index), 'mm') | ||
1132 | 76 | } | ||
1133 | 77 | if (pathview.type === 'seconds') { | ||
1134 | 78 | return DU.format(DU.clone(date, 'setSeconds', index), 'ss') | ||
1135 | 79 | } | ||
1136 | 80 | return '' | ||
1137 | 81 | } | ||
1138 | 82 | // fontSize: 'x-large' | ||
1139 | 83 | textSize: Label.Medium | ||
1140 | 84 | horizontalAlignment: pathview.itemAlign | ||
1141 | 85 | verticalAlignment: Text.AlignVCenter | ||
1142 | 86 | } | ||
1143 | 87 | } | ||
1144 | 88 | path: Path { | ||
1145 | 89 | startX: pathview.width / 2 | ||
1146 | 90 | startY: - datePicker.itemHeight / 2 // FIXME: | ||
1147 | 91 | PathLine { | ||
1148 | 92 | x: pathview.width / 2 | ||
1149 | 93 | y: pathview.height + datePicker.itemHeight / 2 // FIXME: | ||
1150 | 94 | } | ||
1151 | 95 | } | ||
1152 | 96 | Component.onCompleted: { | ||
1153 | 97 | afterCompleted.start() | ||
1154 | 98 | switch (type) { | ||
1155 | 99 | case 'hours': | ||
1156 | 100 | if (ampm) { | ||
1157 | 101 | currentIndex = date.getHours() - 1 | ||
1158 | 102 | } else { | ||
1159 | 103 | currentIndex = date.getHours() % 24 - 1 | ||
1160 | 104 | } | ||
1161 | 105 | break | ||
1162 | 106 | case 'minutes': | ||
1163 | 107 | currentIndex = date.getMinutes() | ||
1164 | 108 | break | ||
1165 | 109 | case 'seconds': | ||
1166 | 110 | currentIndex = date.getSeconds() | ||
1167 | 111 | break | ||
1168 | 112 | } | ||
1169 | 113 | } | ||
1170 | 114 | } | ||
1171 | 0 | 115 | ||
1172 | === added file 'src/imports/Components/Pickers/1.3/YearListDropdown.qml' | |||
1173 | --- src/imports/Components/Pickers/1.3/YearListDropdown.qml 1970-01-01 00:00:00 +0000 | |||
1174 | +++ src/imports/Components/Pickers/1.3/YearListDropdown.qml 2016-10-25 11:37:58 +0000 | |||
1175 | @@ -0,0 +1,131 @@ | |||
1176 | 1 | import QtQuick 2.4 | ||
1177 | 2 | import Ubuntu.Components 1.3 | ||
1178 | 3 | import 'dateutils.js' as DU | ||
1179 | 4 | |||
1180 | 5 | Rectangle { | ||
1181 | 6 | id: root | ||
1182 | 7 | |||
1183 | 8 | property date minimum: DU.clone(null, 'setDate', 1) | ||
1184 | 9 | property date maximum: DU.clone(minimum, 'setFullYear', minimum.getFullYear() + 50) | ||
1185 | 10 | property real itemHeight: height / 5 | ||
1186 | 11 | property real itemWidth: width / 2 | ||
1187 | 12 | |||
1188 | 13 | property alias monthsPathView: monthsPathView | ||
1189 | 14 | property alias yearsListView: yearsListView | ||
1190 | 15 | |||
1191 | 16 | signal requestDateChange(date newDate) | ||
1192 | 17 | |||
1193 | 18 | width: parent.width | ||
1194 | 19 | height: parent.height | ||
1195 | 20 | y: -height | ||
1196 | 21 | color: 'white' | ||
1197 | 22 | |||
1198 | 23 | PathView { | ||
1199 | 24 | id: monthsPathView | ||
1200 | 25 | property var date: new Date(1970, 0, 1) | ||
1201 | 26 | width: root.itemWidth | ||
1202 | 27 | height: parent.height | ||
1203 | 28 | pathItemCount: 6 | ||
1204 | 29 | model: 12 | ||
1205 | 30 | snapMode: PathView.SnapToItem | ||
1206 | 31 | clip: true | ||
1207 | 32 | |||
1208 | 33 | preferredHighlightBegin: 0.5 | ||
1209 | 34 | preferredHighlightEnd: 0.5 | ||
1210 | 35 | |||
1211 | 36 | onCurrentIndexChanged: { | ||
1212 | 37 | var newDate = DU.clone(datePicker.date, 'setMonth', currentIndex) | ||
1213 | 38 | var newDisplayedDate = DU.clone(newDate) | ||
1214 | 39 | root.requestDateChange(newDate) | ||
1215 | 40 | } | ||
1216 | 41 | |||
1217 | 42 | delegate: Item { | ||
1218 | 43 | property bool active: PathView.isCurrentItem | ||
1219 | 44 | width: root.itemWidth | ||
1220 | 45 | height: root.itemHeight | ||
1221 | 46 | Rectangle { | ||
1222 | 47 | anchors.fill: parent | ||
1223 | 48 | color: 'transparent' | ||
1224 | 49 | Label { | ||
1225 | 50 | width: parent.width - units.gu(1) | ||
1226 | 51 | height: parent.height | ||
1227 | 52 | color: parent.parent.active? UbuntuColors.orange : UbuntuColors.darkGrey | ||
1228 | 53 | text: DU.format(DU.clone(monthsPathView.date, 'setMonth', index), 'MMMM') | ||
1229 | 54 | fontSize: 'x-large' | ||
1230 | 55 | horizontalAlignment: Text.AlignRight | ||
1231 | 56 | verticalAlignment: Text.AlignVCenter | ||
1232 | 57 | } | ||
1233 | 58 | } | ||
1234 | 59 | } | ||
1235 | 60 | |||
1236 | 61 | path: Path { | ||
1237 | 62 | startX: root.itemWidth / 2 | ||
1238 | 63 | startY: - root.itemHeight / 2 | ||
1239 | 64 | PathLine { | ||
1240 | 65 | x: root.itemWidth / 2 | ||
1241 | 66 | y: root.height + root.itemHeight / 2 | ||
1242 | 67 | } | ||
1243 | 68 | } | ||
1244 | 69 | |||
1245 | 70 | MouseArea { | ||
1246 | 71 | anchors.fill: parent | ||
1247 | 72 | } | ||
1248 | 73 | } | ||
1249 | 74 | |||
1250 | 75 | ListView { | ||
1251 | 76 | id: yearsListView | ||
1252 | 77 | |||
1253 | 78 | clip: true | ||
1254 | 79 | width: root.itemWidth | ||
1255 | 80 | height: parent.height | ||
1256 | 81 | x: width | ||
1257 | 82 | |||
1258 | 83 | model: root.maximum.getFullYear() - root.minimum.getFullYear() + 1 | ||
1259 | 84 | cacheBuffer: 10 | ||
1260 | 85 | snapMode: ListView.SnapToItem | ||
1261 | 86 | orientation: ListView.Vertical | ||
1262 | 87 | |||
1263 | 88 | highlightFollowsCurrentItem: true | ||
1264 | 89 | highlightMoveDuration: UbuntuAnimation.FastDuration | ||
1265 | 90 | highlightRangeMode: ListView.StrictlyEnforceRange | ||
1266 | 91 | |||
1267 | 92 | preferredHighlightBegin: height / 2 - root.itemHeight / 2 | ||
1268 | 93 | preferredHighlightEnd: height / 2 + root.itemHeight / 2 | ||
1269 | 94 | |||
1270 | 95 | property bool isCurrentIndexInit: false | ||
1271 | 96 | onCurrentIndexChanged: { | ||
1272 | 97 | if (!isCurrentIndexInit) { | ||
1273 | 98 | isCurrentIndexInit = true | ||
1274 | 99 | return | ||
1275 | 100 | } | ||
1276 | 101 | var newDate = DU.clone( | ||
1277 | 102 | minimum, 'setFullYear', | ||
1278 | 103 | minimum.getFullYear() + currentIndex | ||
1279 | 104 | ) | ||
1280 | 105 | root.requestDateChange(newDate) | ||
1281 | 106 | } | ||
1282 | 107 | |||
1283 | 108 | delegate: MouseArea { | ||
1284 | 109 | width: parent.width | ||
1285 | 110 | height: root.itemHeight | ||
1286 | 111 | property bool active: ListView.isCurrentItem | ||
1287 | 112 | onReleased: yearsListView.currentIndex = index | ||
1288 | 113 | Label { | ||
1289 | 114 | id: item | ||
1290 | 115 | color: parent.active? UbuntuColors.orange : UbuntuColors.darkGrey | ||
1291 | 116 | width: parent.width - units.gu(1) | ||
1292 | 117 | height: parent.height | ||
1293 | 118 | x: units.gu(1) | ||
1294 | 119 | text: root.minimum.getFullYear() + index | ||
1295 | 120 | fontSize: 'x-large' | ||
1296 | 121 | horizontalAlignment: Text.AlignLeft | ||
1297 | 122 | verticalAlignment: Text.AlignVCenter | ||
1298 | 123 | } | ||
1299 | 124 | } | ||
1300 | 125 | |||
1301 | 126 | Component.onCompleted: { | ||
1302 | 127 | // yearsListView.currentIndex = yearsListView.currentIndex | ||
1303 | 128 | yearsListView.positionViewAtIndex(yearsListView.currentIndex, ListView.SnapPosition) | ||
1304 | 129 | } | ||
1305 | 130 | } | ||
1306 | 131 | } | ||
1307 | 0 | 132 | ||
1308 | === added file 'src/imports/Components/Pickers/1.3/calendar.js' | |||
1309 | --- src/imports/Components/Pickers/1.3/calendar.js 1970-01-01 00:00:00 +0000 | |||
1310 | +++ src/imports/Components/Pickers/1.3/calendar.js 2016-10-25 11:37:58 +0000 | |||
1311 | @@ -0,0 +1,79 @@ | |||
1312 | 1 | .pragma library | ||
1313 | 2 | |||
1314 | 3 | /*! | ||
1315 | 4 | * calendar.js: inspired by the calendar module from Python | ||
1316 | 5 | * Copyright(c) 2011 Luciano Ramalho <luciano@ramalho.org> | ||
1317 | 6 | * MIT Licensed | ||
1318 | 7 | * | ||
1319 | 8 | * From https://github.com/ramalho/calendar.js | ||
1320 | 9 | */ | ||
1321 | 10 | |||
1322 | 11 | var CalendarException = function CalendarException(message) { | ||
1323 | 12 | this.message = message; | ||
1324 | 13 | this.toString = function() { | ||
1325 | 14 | return this.constructor.name + ": " + this.message | ||
1326 | 15 | }; | ||
1327 | 16 | } | ||
1328 | 17 | |||
1329 | 18 | var Calendar = function Calendar(firstWeekDay) { | ||
1330 | 19 | //properties | ||
1331 | 20 | this.firstWeekDay = firstWeekDay || 0; // 0 = Sunday | ||
1332 | 21 | }; | ||
1333 | 22 | |||
1334 | 23 | Calendar.prototype = { | ||
1335 | 24 | constructor : Calendar, | ||
1336 | 25 | weekStartDate : function weekStartDate(date) { | ||
1337 | 26 | var startDate = new Date(date.getTime()); | ||
1338 | 27 | while (startDate.getDay() !== this.firstWeekDay) { | ||
1339 | 28 | startDate.setDate(startDate.getDate() - 1); | ||
1340 | 29 | } | ||
1341 | 30 | return startDate; | ||
1342 | 31 | }, | ||
1343 | 32 | monthDates : function monthDates(year, month, dayFormatter, weekFormatter) { | ||
1344 | 33 | if ((typeof year !== "number") || (year < 1970)) { | ||
1345 | 34 | throw new CalendarException('year must be a number >= 1970'); | ||
1346 | 35 | }; | ||
1347 | 36 | if ((typeof month !== "number") || (month < 0) || (month > 11)) { | ||
1348 | 37 | throw new CalendarException('month must be a number (Jan is 0)'); | ||
1349 | 38 | }; | ||
1350 | 39 | var weeks = [], | ||
1351 | 40 | week = [], | ||
1352 | 41 | i = 0, | ||
1353 | 42 | date = this.weekStartDate(new Date(year, month, 1)); | ||
1354 | 43 | do { | ||
1355 | 44 | for (i=0; i<7; i++) { | ||
1356 | 45 | week.push(dayFormatter ? dayFormatter(date) : date); | ||
1357 | 46 | date = new Date(date.getTime()); | ||
1358 | 47 | date.setDate(date.getDate() + 1); | ||
1359 | 48 | } | ||
1360 | 49 | weeks.push(weekFormatter ? weekFormatter(week) : week); | ||
1361 | 50 | week = []; | ||
1362 | 51 | } while ((date.getMonth()<=month) && (date.getFullYear()===year)); | ||
1363 | 52 | return weeks; | ||
1364 | 53 | }, | ||
1365 | 54 | monthDays : function monthDays(year, month) { | ||
1366 | 55 | var getDayOrZero = function getDayOrZero(date) { | ||
1367 | 56 | return date.getMonth() === month ? date.getDate() : 0; | ||
1368 | 57 | }; | ||
1369 | 58 | return this.monthDates(year, month, getDayOrZero); | ||
1370 | 59 | }, | ||
1371 | 60 | monthText : function monthText(year, month) { | ||
1372 | 61 | if (typeof year === "undefined") { | ||
1373 | 62 | var now = new Date(); | ||
1374 | 63 | year = now.getFullYear(); | ||
1375 | 64 | month = now.getMonth(); | ||
1376 | 65 | }; | ||
1377 | 66 | var getDayOrBlank = function getDayOrBlank(date) { | ||
1378 | 67 | var s = date.getMonth() === month ? date.getDate().toString() : " "; | ||
1379 | 68 | while (s.length < 2) s = " "+s; | ||
1380 | 69 | return s; | ||
1381 | 70 | }; | ||
1382 | 71 | var weeks = this.monthDates(year, month, getDayOrBlank, | ||
1383 | 72 | function (week) { return week.join(" ") }); | ||
1384 | 73 | return weeks.join("\n"); | ||
1385 | 74 | } | ||
1386 | 75 | }; | ||
1387 | 76 | for (var i = 0; i < 11; i++) { | ||
1388 | 77 | var month = Qt.locale().monthName(i); // FIXME:, Locale.LongFormat); | ||
1389 | 78 | Calendar[month] = i; | ||
1390 | 79 | } | ||
1391 | 0 | 80 | ||
1392 | === added file 'src/imports/Components/Pickers/1.3/dateutils.js' | |||
1393 | --- src/imports/Components/Pickers/1.3/dateutils.js 1970-01-01 00:00:00 +0000 | |||
1394 | +++ src/imports/Components/Pickers/1.3/dateutils.js 2016-10-25 11:37:58 +0000 | |||
1395 | @@ -0,0 +1,53 @@ | |||
1396 | 1 | .pragma library | ||
1397 | 2 | |||
1398 | 3 | // Returns a formatted string from a date, using Qt Date.prototype.toLocaleString() | ||
1399 | 4 | function format(date, format, localeStr) { | ||
1400 | 5 | var locale = Qt.locale(localeStr || 'en_US') | ||
1401 | 6 | return date.toLocaleString(locale, format) | ||
1402 | 7 | } | ||
1403 | 8 | |||
1404 | 9 | // Clone a Date object, and optionally invokes methods on it | ||
1405 | 10 | function clone(date, calls) { | ||
1406 | 11 | var d = date? new Date(date.getTime()) : new Date() | ||
1407 | 12 | if (!calls) return d | ||
1408 | 13 | if (!Array.isArray(calls)) { | ||
1409 | 14 | calls = [[calls].concat([].slice.call(arguments, 2))] | ||
1410 | 15 | } | ||
1411 | 16 | for (var i = 0; i < calls.length; i++) { | ||
1412 | 17 | if (!calls[i]) continue | ||
1413 | 18 | d[calls[i][0]].apply(d, calls[i].slice(1)) | ||
1414 | 19 | } | ||
1415 | 20 | return d | ||
1416 | 21 | } | ||
1417 | 22 | |||
1418 | 23 | // Return true if date1 and date2 are the same day | ||
1419 | 24 | function sameDay(date1, date2) { | ||
1420 | 25 | return date1.getDate() === date2.getDate() && | ||
1421 | 26 | date1.getMonth() === date2.getMonth() && | ||
1422 | 27 | date1.getFullYear() === date2.getFullYear() | ||
1423 | 28 | } | ||
1424 | 29 | |||
1425 | 30 | // Compare two dates | ||
1426 | 31 | function compareDates(date1, date2) { | ||
1427 | 32 | var time1 = date1.getTime() | ||
1428 | 33 | var time2 = date2.getTime() | ||
1429 | 34 | if (time1 > time2) return 1 | ||
1430 | 35 | if (time1 < time2) return -1 | ||
1431 | 36 | return 0 | ||
1432 | 37 | } | ||
1433 | 38 | |||
1434 | 39 | var shortDayNames = 'Mon Tue Wed Thu Fri Sat Sun'.split(' ') | ||
1435 | 40 | |||
1436 | 41 | // Return a short day name based on a date object or a day number | ||
1437 | 42 | function shortDayName(date) { | ||
1438 | 43 | if (typeof date === 'number') { | ||
1439 | 44 | return shortDayNames[date] | ||
1440 | 45 | } | ||
1441 | 46 | return shortDayNames[date.getDay()] | ||
1442 | 47 | } | ||
1443 | 48 | |||
1444 | 49 | // Return the number of months between date1 and date2 (including both) | ||
1445 | 50 | function getMonthsRange(date1, date2) { | ||
1446 | 51 | return (date2.getFullYear() - date1.getFullYear()) * 12 + | ||
1447 | 52 | (date2.getMonth() - date1.getMonth()) | ||
1448 | 53 | } | ||
1449 | 0 | 54 | ||
1450 | === modified file 'src/imports/Components/Pickers/Pickers.pro' | |||
1451 | --- src/imports/Components/Pickers/Pickers.pro 2015-05-19 09:23:01 +0000 | |||
1452 | +++ src/imports/Components/Pickers/Pickers.pro 2016-10-25 11:37:58 +0000 | |||
1453 | @@ -29,6 +29,15 @@ | |||
1454 | 29 | 1.3/Picker.qml \ | 29 | 1.3/Picker.qml \ |
1455 | 30 | 1.3/PickerRow.qml \ | 30 | 1.3/PickerRow.qml \ |
1456 | 31 | 1.3/SecondsModel.qml \ | 31 | 1.3/SecondsModel.qml \ |
1457 | 32 | 1.3/dateutils.js \ | ||
1458 | 33 | 1.3/calendar.js \ | ||
1459 | 34 | 1.3/DatePickerMonthDays.qml \ | ||
1460 | 35 | 1.3/DatePickerMonthDaysWorker.js \ | ||
1461 | 36 | 1.3/YearListDropdown.qml \ | ||
1462 | 37 | 1.3/DatePickerHeader.qml \ | ||
1463 | 38 | 1.3/HourPicker.qml \ | ||
1464 | 39 | 1.3/DayNightPicker.qml \ | ||
1465 | 40 | 1.3/DigitSeparator.qml \ | ||
1466 | 32 | 1.3/YearModel.qml | 41 | 1.3/YearModel.qml |
1467 | 33 | 42 | ||
1468 | 34 | load(ubuntu_qml_module) | 43 | load(ubuntu_qml_module) |