Merge lp:~3v1n0/ubuntu-settings-components/new-calendar-design into lp:ubuntu-settings-components
- new-calendar-design
- Merge into trunk
Status: | Merged | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Lukáš Tinkl | ||||||||||||||||||||||||
Approved revision: | 333 | ||||||||||||||||||||||||
Merged at revision: | 170 | ||||||||||||||||||||||||
Proposed branch: | lp:~3v1n0/ubuntu-settings-components/new-calendar-design | ||||||||||||||||||||||||
Merge into: | lp:ubuntu-settings-components | ||||||||||||||||||||||||
Prerequisite: | lp:~3v1n0/ubuntu-settings-components/touch+pointer-styles | ||||||||||||||||||||||||
Diff against target: |
1004 lines (+552/-198) 9 files modified
debian/bileto_pre_release_hook (+4/-0) examples/OtherComponents.qml (+7/-0) examples/SettingsComponents.qml (+13/-1) plugins/Ubuntu/Settings/Components/Calendar.js (+23/-0) plugins/Ubuntu/Settings/Components/Calendar.qml (+265/-117) plugins/Ubuntu/Settings/Components/plugin.cpp (+16/-0) plugins/Ubuntu/Settings/Menus/CalendarMenu.qml (+91/-35) tests/qmltests/Components/tst_Calendar.qml (+88/-32) tests/qmltests/Menus/tst_CalendarMenu.qml (+45/-13) |
||||||||||||||||||||||||
To merge this branch: | bzr merge lp:~3v1n0/ubuntu-settings-components/new-calendar-design | ||||||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lukáš Tinkl (community) | Approve | ||
Unity8 CI Bot | continuous-integration | Approve | |
Review via email: mp+307976@code.launchpad.net |
Commit message
Calendar: update to new style with weekdays header and Month selection
Description of the change
* Are there any related MPs required for this MP to build/function as expected? Please list.
N/A
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yep, ran in both laptop and phone
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
* If you changed the UI, has there been a design review?
Implemented new calendar look as defined in this doc:
I've not added the month selection dropdown since it would increase the complexity for something that is just an temporary solution (since new calendar SDK item should land soon, and thus this component should be dropped too).
* If you changed localized strings, has the POT file been updated?
N/A
- 300. By Marco Trevisan (Treviño)
-
CalendarMenu: correctly theme the icon
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:300
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Lukáš Tinkl (lukas-kde) wrote : | # |
A couple of inline comments
Lukáš Tinkl (lukas-kde) wrote : | # |
It's not possible to pick an arbitrary month/year. According to Patty, this should use some new date/time picker: https:/
Is this going to be implemented at this stage?
Lukáš Tinkl (lukas-kde) wrote : | # |
The month name in the calendar header should imho use some smaller font, it looks different than on the screenshots.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> It's not possible to pick an arbitrary month/year. According to Patty, this
> should use some new date/time picker: https:/
> FColFvHuBpUcXyp
> p
>
>
> Is this going to be implemented at this stage?
As I wrote in the description, since this component is something that is going to be replaced soon by default SDK one (which is in the works and that will be ready in some weeks), I didn't want to spend too much time for that...
So, I think for now this should be enough (as there's no regression anyway), while this will be then replaced.
> The month name in the calendar header should imho use some smaller font, it
> looks different than on the screenshots.
Mh, might be... But in the specs I have (see the linked doc above), it was marked as "Small" font. I've used XSmall instead since it looked more similar to the designs, but if you think it's better I can switch to XXSmall (it would be http://
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> It's not possible to pick an arbitrary month/year. According to Patty, this
> should use some new date/time picker: https:/
> FColFvHuBpUcXyp
> p
>
>
> Is this going to be implemented at this stage?
As I wrote in the description, since this component is something that is going to be replaced soon by default SDK one (which is in the works and that will be ready in some weeks), I didn't want to spend too much time for that...
So, I think for now this should be enough (as there's no regression anyway), while this will be then replaced.
> The month name in the calendar header should imho use some smaller font, it
> looks different than on the screenshots.
Mh, might be... But in the specs I have (see the linked doc above), it was marked as "Small" font. I've used XSmall instead since it looked more similar to the designs, but if you think it's better I can switch to XXSmall (it would be http://
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> A couple of inline comments
Replied to these too.
- 301. By Marco Trevisan (Treviño)
-
Calendar: use standaloneDayName instead of dayName
- 302. By Marco Trevisan (Treviño)
-
Calendar: set livetimer back to Minute frequency to avoid bugs
Lukáš Tinkl (lukas-kde) wrote : | # |
Found a bug: when you click around the days in the calendar, the view animates smoothly left/right if the date selection falls into previous/next month. However, if you use the arrows to switch the month, the whole animation breaks from this point on and the month isn't switched at all.
Lukáš Tinkl (lukas-kde) wrote : | # |
Also, the doubled binding on color, think it could be collapsed into one, without the "when" condition?
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:301
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:302
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 303. By Marco Trevisan (Treviño)
-
Calendar: ensure that currentDate is updated when selectedDate changes if they differs
There was an initial binding that might break once the user switch month
- 304. By Marco Trevisan (Treviño)
-
Calendar: toggle selection on selected days when re-clicking on them
- 305. By Marco Trevisan (Treviño)
-
testCalendar: verify that currentDate matches selectedDate when changed
- 306. By Marco Trevisan (Treviño)
-
CalendarMenu: update currentDate manually on icon clicks so we've proper animation
And update tests accordingly
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:305
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:306
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:306
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> Also, the doubled binding on color, think it could be collapsed into one,
> without the "when" condition?
I thought it was clearer to read... But as you prefer.
Lukáš Tinkl (lukas-kde) wrote : | # |
Waiting for the design to come up with week numbers and events highlight specification.
- 307. By Marco Trevisan (Treviño)
-
Merged touch+pointer-
styles into new-calendar- design. - 308. By Marco Trevisan (Treviño)
-
CalendarMenu: use proper color for layout title
- 309. By Marco Trevisan (Treviño)
-
Calendar: add marker to days that have planned events and expose eventDays
- 310. By Marco Trevisan (Treviño)
-
testCalendar: verify events marker visibility
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:310
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 311. By Marco Trevisan (Treviño)
-
Calendar: use relative positioning for the event shape
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:311
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Lukáš Tinkl (lukas-kde) wrote : | # |
In the light theme, the "overflowing" days (those that fall in the previous/next months) are not visible
- 312. By Marco Trevisan (Treviño)
-
Calendar: update the selectedDate if currentDate changed to ensure it will point to the first day of the month
- 313. By Marco Trevisan (Treviño)
-
Calendar: use better colors that work with both Ambiance and Suru
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:313
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 314. By Marco Trevisan (Treviño)
-
Calendar: use zeroDigit from locale
- 315. By Marco Trevisan (Treviño)
-
Calendar.js: add toDate method to Day object
- 316. By Marco Trevisan (Treviño)
-
Calendar: add support for showing week numbers
Week number has to be properly computed yet, though.
- 317. By Marco Trevisan (Treviño)
-
Components: expose QtDate::weekNumber function to QML
- 318. By Marco Trevisan (Treviño)
-
Calendar: use QtDateFunctions
.weekNumber to get the proper value for the current date - 319. By Marco Trevisan (Treviño)
-
Calendar: use toLocaleString to get proper day visualization
- 320. By Marco Trevisan (Treviño)
-
Calendar: add comment for translators
- 321. By Marco Trevisan (Treviño)
-
Calendar: make some local properties readonly
- 322. By Marco Trevisan (Treviño)
-
Calendar: use formattedWeekNumber to pad the week number with 0's
- 323. By Marco Trevisan (Treviño)
-
Calendar: properly translate the header text with comment
And don't keep a Day and Date instance, just do it once.
- 324. By Marco Trevisan (Treviño)
-
debian/
bileto_ pre_release_ hook: run po/update-usc-pot on release
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:319
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:324
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 325. By Marco Trevisan (Treviño)
-
testCalendarMenu: update test for currentDate setting
- 326. By Marco Trevisan (Treviño)
-
testCalendar: add tests for week numbers visibility
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:325
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:326
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 327. By Marco Trevisan (Treviño)
-
Calendar: add the weekNumber Column to a loader
So it will be loaded only when needed
- 328. By Marco Trevisan (Treviño)
-
Calendar: add the today shapes to a loader
Since there will be only one for list, it should save something
- 329. By Marco Trevisan (Treviño)
-
Calendar: put event markers into a loader
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:329
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 330. By Marco Trevisan (Treviño)
-
Merged touch+pointer-
styles into new-calendar- design.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:330
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 331. By Marco Trevisan (Treviño)
-
Calendar: use quicker animation to switch month
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:331
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 332. By Marco Trevisan (Treviño)
-
Calendar: use proper color for the eventMarker when selected
- 333. By Marco Trevisan (Treviño)
-
Calendar: reposition the eventMarker going more down that we can
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:333
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Lukáš Tinkl (lukas-kde) wrote : | # |
Yup, quite happy with this atm, thanks!
- 334. By Marco Trevisan (Treviño)
-
Calendar: don't try to update value if not ready, and set selectedDate to currentDate
- 335. By Marco Trevisan (Treviño)
-
Calendar: implement Month::firstDay and use it instead of relying on model valueOf
Model's month can be undefined in certain cases, but this will ensure that binding won't
be broken in case. - 336. By Marco Trevisan (Treviño)
-
Calendar: remove unused minimum, maximum date properties
They overcomplicate the logic without any actual need
- 337. By Marco Trevisan (Treviño)
-
CalendarMenu: remove unneded extra column as mainSlot
- 338. By Marco Trevisan (Treviño)
-
CalendarMenu: Qt 5.4 needs this extra item to correctly fill the width, so let's be conservative
- 339. By Marco Trevisan (Treviño)
-
Calendar: put the delegate inside a loader, it workarounds QTBUG-49224
- 340. By Marco Trevisan (Treviño)
-
Calendar: Binding doesn't work well with new Loader, use more complex binding instead
- 341. By Marco Trevisan (Treviño)
-
Calendar: only show the abstract button on current month view
This fixes possible edge clicks being recorded.
- 342. By Marco Trevisan (Treviño)
-
Calendar: make the AbstractButton to fill the dayNumber instead of the whole day box
- 343. By Marco Trevisan (Treviño)
-
CalendarMenu: tapping on month date updates the selected date to month start
- 344. By Marco Trevisan (Treviño)
-
Calendar: When changing months, always set the current date to first Day
- 345. By Marco Trevisan (Treviño)
-
Calendar: reset the selected date to today if we're on current month
- 346. By Marco Trevisan (Treviño)
-
Calendar: ensure we always set back currentDate to today when changing month
- 347. By Marco Trevisan (Treviño)
-
Calendar: add toDate method to Month
Preview Diff
1 | === added file 'debian/bileto_pre_release_hook' | |||
2 | --- debian/bileto_pre_release_hook 1970-01-01 00:00:00 +0000 | |||
3 | +++ debian/bileto_pre_release_hook 2016-11-15 18:02:52 +0000 | |||
4 | @@ -0,0 +1,4 @@ | |||
5 | 1 | #!/bin/sh | ||
6 | 2 | |||
7 | 3 | set -eux | ||
8 | 4 | sh ./po/update-usc-pot | ||
9 | 0 | 5 | ||
10 | === modified file 'examples/OtherComponents.qml' | |||
11 | --- examples/OtherComponents.qml 2016-11-15 18:02:52 +0000 | |||
12 | +++ examples/OtherComponents.qml 2016-11-15 18:02:52 +0000 | |||
13 | @@ -153,6 +153,13 @@ | |||
14 | 153 | 153 | ||
15 | 154 | CalendarMenu { | 154 | CalendarMenu { |
16 | 155 | id: calendar | 155 | id: calendar |
17 | 156 | eventDays: currentDate.getMonth() % 2 ? [5, 20] : [] | ||
18 | 157 | } | ||
19 | 158 | |||
20 | 159 | SwitchMenu { | ||
21 | 160 | text: i18n.tr("Show week numbers in calendar") | ||
22 | 161 | checked: calendar.showWeekNumbers | ||
23 | 162 | onCheckedChanged: calendar.showWeekNumbers = checked | ||
24 | 156 | } | 163 | } |
25 | 157 | 164 | ||
26 | 158 | UserSessionMenu { | 165 | UserSessionMenu { |
27 | 159 | 166 | ||
28 | === modified file 'examples/SettingsComponents.qml' | |||
29 | --- examples/SettingsComponents.qml 2016-11-15 18:02:52 +0000 | |||
30 | +++ examples/SettingsComponents.qml 2016-11-15 18:02:52 +0000 | |||
31 | @@ -48,11 +48,23 @@ | |||
32 | 48 | id: header | 48 | id: header |
33 | 49 | title: listView.currentItem ? listView.currentItem.item.title : "Components" | 49 | title: listView.currentItem ? listView.currentItem.item.title : "Components" |
34 | 50 | 50 | ||
36 | 51 | leadingActionBar.actions: [ | 51 | trailingActionBar.actions: [ |
37 | 52 | Action { | 52 | Action { |
38 | 53 | iconName: mainView.pointerMode ? "input-mouse-symbolic" : "input-touchpad-symbolic" | 53 | iconName: mainView.pointerMode ? "input-mouse-symbolic" : "input-touchpad-symbolic" |
39 | 54 | text: mainView.pointerMode ? "Pointer mode" : "Touch mode" | 54 | text: mainView.pointerMode ? "Pointer mode" : "Touch mode" |
40 | 55 | onTriggered: mainView.pointerMode = !mainView.pointerMode | 55 | onTriggered: mainView.pointerMode = !mainView.pointerMode |
41 | 56 | }, | ||
42 | 57 | Action { | ||
43 | 58 | text: i18n.tr('Use dark theme') | ||
44 | 59 | iconName: 'torch-on' | ||
45 | 60 | visible: theme.name == 'Ubuntu.Components.Themes.Ambiance' | ||
46 | 61 | onTriggered: theme.name = 'Ubuntu.Components.Themes.SuruDark' | ||
47 | 62 | }, | ||
48 | 63 | Action { | ||
49 | 64 | text: i18n.tr('Use light theme') | ||
50 | 65 | iconName: 'torch-off' | ||
51 | 66 | visible: theme.name == 'Ubuntu.Components.Themes.SuruDark' | ||
52 | 67 | onTriggered: theme.name = 'Ubuntu.Components.Themes.Ambiance' | ||
53 | 56 | } | 68 | } |
54 | 57 | ] | 69 | ] |
55 | 58 | } | 70 | } |
56 | 59 | 71 | ||
57 | === modified file 'plugins/Ubuntu/Settings/Components/Calendar.js' | |||
58 | --- plugins/Ubuntu/Settings/Components/Calendar.js 2016-09-06 13:54:51 +0000 | |||
59 | +++ plugins/Ubuntu/Settings/Components/Calendar.js 2016-11-15 18:02:52 +0000 | |||
60 | @@ -25,6 +25,10 @@ | |||
61 | 25 | return new Month(date.getFullYear(), date.getMonth()); | 25 | return new Month(date.getFullYear(), date.getMonth()); |
62 | 26 | } | 26 | } |
63 | 27 | 27 | ||
64 | 28 | Month.prototype.firstDay = function() { | ||
65 | 29 | return new Day(this.year, this.month, 1) | ||
66 | 30 | } | ||
67 | 31 | |||
68 | 28 | Month.prototype.toString = function() { | 32 | Month.prototype.toString = function() { |
69 | 29 | return JSON.stringify(this); | 33 | return JSON.stringify(this); |
70 | 30 | } | 34 | } |
71 | @@ -33,6 +37,17 @@ | |||
72 | 33 | return this.year * 12 + this.month; | 37 | return this.year * 12 + this.month; |
73 | 34 | } | 38 | } |
74 | 35 | 39 | ||
75 | 40 | Month.prototype.equals = function(other) { | ||
76 | 41 | if (other instanceof Month) { | ||
77 | 42 | return other.valueOf() == this.valueOf(); | ||
78 | 43 | } | ||
79 | 44 | return false; | ||
80 | 45 | } | ||
81 | 46 | |||
82 | 47 | Month.prototype.toDate = function() { | ||
83 | 48 | return new Date(this.year, this.month) | ||
84 | 49 | } | ||
85 | 50 | |||
86 | 36 | function Day(arg1, arg2, arg3) { | 51 | function Day(arg1, arg2, arg3) { |
87 | 37 | if (arg1 === undefined) { | 52 | if (arg1 === undefined) { |
88 | 38 | var date = new Date(); | 53 | var date = new Date(); |
89 | @@ -65,6 +80,10 @@ | |||
90 | 65 | return new Day(date.getFullYear(), date.getMonth(), date.getDate()); | 80 | return new Day(date.getFullYear(), date.getMonth(), date.getDate()); |
91 | 66 | } | 81 | } |
92 | 67 | 82 | ||
93 | 83 | Day.prototype.getMonth = function() { | ||
94 | 84 | return new Month(this.year, this.month) | ||
95 | 85 | } | ||
96 | 86 | |||
97 | 68 | Day.prototype.dayofweek = function () /* 1 <= m <= 12, y > 1752 (in the U.K.) */ | 87 | Day.prototype.dayofweek = function () /* 1 <= m <= 12, y > 1752 (in the U.K.) */ |
98 | 69 | { | 88 | { |
99 | 70 | var t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]; | 89 | var t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]; |
100 | @@ -99,3 +118,7 @@ | |||
101 | 99 | } | 118 | } |
102 | 100 | return false; | 119 | return false; |
103 | 101 | } | 120 | } |
104 | 121 | |||
105 | 122 | Day.prototype.toDate = function() { | ||
106 | 123 | return new Date(this.year, this.month, this.day) | ||
107 | 124 | } | ||
108 | 102 | 125 | ||
109 | === modified file 'plugins/Ubuntu/Settings/Components/Calendar.qml' | |||
110 | --- plugins/Ubuntu/Settings/Components/Calendar.qml 2016-09-06 13:48:32 +0000 | |||
111 | +++ plugins/Ubuntu/Settings/Components/Calendar.qml 2016-11-15 18:02:52 +0000 | |||
112 | @@ -1,5 +1,5 @@ | |||
113 | 1 | /* | 1 | /* |
115 | 2 | * Copyright 2013 Canonical Ltd. | 2 | * Copyright 2013-2016 Canonical Ltd. |
116 | 3 | * | 3 | * |
117 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
118 | 5 | * it under the terms of the GNU Lesser General Public License as published by | 5 | * it under the terms of the GNU Lesser General Public License as published by |
119 | @@ -12,26 +12,41 @@ | |||
120 | 12 | * | 12 | * |
121 | 13 | * You should have received a copy of the GNU Lesser General Public License | 13 | * You should have received a copy of the GNU Lesser General Public License |
122 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
123 | 15 | * | ||
124 | 16 | * Authors: | ||
125 | 17 | * Andrea Cimitan <andrea.cimitan@canonical.com> | ||
126 | 18 | * Marco Trevisan <marco.trevisan@canonical.com> | ||
127 | 15 | */ | 19 | */ |
128 | 16 | 20 | ||
129 | 17 | import QtQuick 2.4 | 21 | import QtQuick 2.4 |
130 | 18 | import Ubuntu.Components 1.3 | 22 | import Ubuntu.Components 1.3 |
131 | 23 | import Ubuntu.Settings.Components 0.1 | ||
132 | 19 | import "dateExt.js" as DateExt | 24 | import "dateExt.js" as DateExt |
133 | 20 | import "Calendar.js" as Cal | 25 | import "Calendar.js" as Cal |
134 | 21 | 26 | ||
135 | 22 | ListView { | 27 | ListView { |
137 | 23 | id: monthView | 28 | id: calendar |
138 | 24 | 29 | ||
141 | 25 | property bool collapsed: false | 30 | property var currentDate: priv.today.toDate() |
140 | 26 | property var currentDate: new Date(priv.selectedDay.year, priv.selectedDay.month, 1) | ||
142 | 27 | property int firstDayOfWeek: Qt.locale(i18n.language).firstDayOfWeek | 31 | property int firstDayOfWeek: Qt.locale(i18n.language).firstDayOfWeek |
146 | 28 | property var maximumDate | 32 | property var selectedDate: currentDate |
147 | 29 | property var minimumDate | 33 | property var eventDays: new Array() |
148 | 30 | property var selectedDate: new Date(priv.today.year, priv.today.month, priv.today.day) | 34 | property bool showWeekNumbers: false |
149 | 31 | 35 | ||
150 | 32 | function reset() { | 36 | function reset() { |
151 | 33 | if (!priv.ready) return; | 37 | if (!priv.ready) return; |
153 | 34 | currentDate = new Date(priv.today.year, priv.today.month, 1) | 38 | currentDate = priv.today.toDate() |
154 | 39 | } | ||
155 | 40 | |||
156 | 41 | function moveToMonth(delta) { | ||
157 | 42 | if (!priv.ready) return; | ||
158 | 43 | priv.__setCurrentDateFromMonth(priv.currentMonth.addMonths(delta)) | ||
159 | 44 | } | ||
160 | 45 | |||
161 | 46 | function selectFistDayOfTheMonth() { | ||
162 | 47 | if (!priv.ready) return; | ||
163 | 48 | priv.userSelected = false | ||
164 | 49 | selectedDate = currentItem.month.toDate() | ||
165 | 35 | } | 50 | } |
166 | 36 | 51 | ||
167 | 37 | Component.onCompleted: { | 52 | Component.onCompleted: { |
168 | @@ -40,8 +55,23 @@ | |||
169 | 40 | 55 | ||
170 | 41 | onCurrentIndexChanged: { | 56 | onCurrentIndexChanged: { |
171 | 42 | if (!priv.ready) return; | 57 | if (!priv.ready) return; |
174 | 43 | 58 | priv.__setCurrentDateFromMonth(currentItem.month) | |
175 | 44 | currentDate = new Date(currentItem.month.year, currentItem.month.month, 1); | 59 | } |
176 | 60 | |||
177 | 61 | onSelectedDateChanged: { | ||
178 | 62 | if (!priv.ready) return; | ||
179 | 63 | |||
180 | 64 | if (currentDate != selectedDate) | ||
181 | 65 | currentDate = selectedDate | ||
182 | 66 | } | ||
183 | 67 | |||
184 | 68 | onCurrentDateChanged: { | ||
185 | 69 | if (!priv.ready) return; | ||
186 | 70 | |||
187 | 71 | if (selectedDate != currentDate) { | ||
188 | 72 | priv.userSelected = false | ||
189 | 73 | selectedDate = currentDate | ||
190 | 74 | } | ||
191 | 45 | } | 75 | } |
192 | 46 | 76 | ||
193 | 47 | ListModel { | 77 | ListModel { |
194 | @@ -50,57 +80,39 @@ | |||
195 | 50 | 80 | ||
196 | 51 | QtObject { | 81 | QtObject { |
197 | 52 | id: priv | 82 | id: priv |
198 | 83 | objectName: "calendarPriv" | ||
199 | 53 | 84 | ||
200 | 54 | property bool ready: false | 85 | property bool ready: false |
203 | 55 | property int squareUnit: monthView.width / 7 | 86 | property bool userSelected: false |
202 | 56 | property int verticalMargin: units.gu(1) | ||
204 | 57 | property var today: new Cal.Day().fromDate((new Date())) | 87 | property var today: new Cal.Day().fromDate((new Date())) |
205 | 88 | property real weekDaysHeight: 0 | ||
206 | 89 | readonly property real squareUnit: units.gu(3) | ||
207 | 90 | readonly property real todayRingThickness: units.gu(.1) | ||
208 | 91 | readonly property int days: 7 | ||
209 | 92 | readonly property int weeks: 6 | ||
210 | 58 | 93 | ||
211 | 59 | property var currentMonth: new Cal.Month().fromDate(currentDate) | 94 | property var currentMonth: new Cal.Month().fromDate(currentDate) |
212 | 60 | property var selectedDay: new Cal.Day().fromDate(selectedDate) | 95 | property var selectedDay: new Cal.Day().fromDate(selectedDate) |
213 | 61 | property var minimumMonth: minimumDate ? new Cal.Month().fromDate(minimumDate) : undefined | ||
214 | 62 | property var maximumMonth: maximumDate ? new Cal.Month().fromDate(maximumDate) : undefined | ||
215 | 63 | |||
216 | 64 | property var minimumDay: minimumDate ? new Cal.Day().fromDate(minimumDate) : undefined | ||
217 | 65 | property var maximumDay: maximumDate ? new Cal.Day().fromDate(maximumDate) : undefined | ||
218 | 66 | 96 | ||
219 | 67 | onCurrentMonthChanged: { | 97 | onCurrentMonthChanged: { |
220 | 68 | if (!ready) return | 98 | if (!ready) return |
221 | 69 | __populateModel(); | 99 | __populateModel(); |
222 | 70 | } | 100 | } |
248 | 71 | onSelectedDayChanged: { | 101 | |
249 | 72 | if (!ready) return | 102 | function __setCurrentDateFromMonth(month) { |
250 | 73 | __populateModel(); | 103 | if (month.equals(priv.today.getMonth())) { |
251 | 74 | } | 104 | currentDate = priv.today.toDate() |
252 | 75 | onMinimumMonthChanged: { | 105 | } else { |
253 | 76 | if (!ready) return | 106 | currentDate = month.toDate() |
254 | 77 | __populateModel(); | 107 | } |
230 | 78 | } | ||
231 | 79 | onMaximumMonthChanged: { | ||
232 | 80 | if (!ready) return | ||
233 | 81 | __populateModel(); | ||
234 | 82 | } | ||
235 | 83 | |||
236 | 84 | function __getRealMinimumMonth(month) { | ||
237 | 85 | if (minimumMonth !== undefined && minimumMonth > month) { | ||
238 | 86 | return minimumMonth; | ||
239 | 87 | } | ||
240 | 88 | return month; | ||
241 | 89 | } | ||
242 | 90 | |||
243 | 91 | function __getRealMaximumMonth(month) { | ||
244 | 92 | if (maximumMonth !== undefined && maximumMonth < month) { | ||
245 | 93 | return maximumMonth; | ||
246 | 94 | } | ||
247 | 95 | return month; | ||
255 | 96 | } | 108 | } |
256 | 97 | 109 | ||
257 | 98 | function __populateModel() { | 110 | function __populateModel() { |
258 | 99 | // disable the onCurrentIndexChanged logic | 111 | // disable the onCurrentIndexChanged logic |
259 | 100 | priv.ready = false; | 112 | priv.ready = false; |
260 | 101 | 113 | ||
263 | 102 | var minimumMonth = __getRealMinimumMonth(currentMonth.addMonths(-2)); | 114 | var minimumMonth = currentMonth.addMonths(-2); |
264 | 103 | var maximumMonth = __getRealMaximumMonth(currentMonth.addMonths(2)); | 115 | var maximumMonth = currentMonth.addMonths(2); |
265 | 104 | 116 | ||
266 | 105 | // Remove old minimum months | 117 | // Remove old minimum months |
267 | 106 | while (calendarModel.count > 0 && new Cal.Month(calendarModel.get(0).month) < minimumMonth) { | 118 | while (calendarModel.count > 0 && new Cal.Month(calendarModel.get(0).month) < minimumMonth) { |
268 | @@ -140,7 +152,7 @@ | |||
269 | 140 | } | 152 | } |
270 | 141 | 153 | ||
271 | 142 | LiveTimer { | 154 | LiveTimer { |
273 | 143 | frequency: monthView.visible ? LiveTimer.Minute : LiveTimer.Disabled | 155 | frequency: calendar.visible ? LiveTimer.Minute : LiveTimer.Disabled |
274 | 144 | onFrequencyChanged: trigger() | 156 | onFrequencyChanged: trigger() |
275 | 145 | onTrigger: { | 157 | onTrigger: { |
276 | 146 | Date.timeZoneUpdated(); // FIXME remove when fixed in UITK | 158 | Date.timeZoneUpdated(); // FIXME remove when fixed in UITK |
277 | @@ -152,9 +164,9 @@ | |||
278 | 152 | } | 164 | } |
279 | 153 | } | 165 | } |
280 | 154 | 166 | ||
284 | 155 | width: parent.width | 167 | implicitWidth: priv.squareUnit * priv.days |
285 | 156 | height: priv.squareUnit * (collapsed ? 1 : 6) + priv.verticalMargin * 2 | 168 | implicitHeight: priv.squareUnit * priv.weeks + priv.weekDaysHeight |
286 | 157 | interactive: !collapsed | 169 | interactive: true |
287 | 158 | clip: true | 170 | clip: true |
288 | 159 | cacheBuffer: Math.max((width+1) * 3, 0) // one page left, one page right | 171 | cacheBuffer: Math.max((width+1) * 3, 0) // one page left, one page right |
289 | 160 | highlightRangeMode: ListView.StrictlyEnforceRange | 172 | highlightRangeMode: ListView.StrictlyEnforceRange |
290 | @@ -165,93 +177,227 @@ | |||
291 | 165 | snapMode: ListView.SnapOneItem | 177 | snapMode: ListView.SnapOneItem |
292 | 166 | focus: true | 178 | focus: true |
293 | 167 | highlightFollowsCurrentItem: true | 179 | highlightFollowsCurrentItem: true |
294 | 180 | highlightMoveDuration: UbuntuAnimation.FastDuration | ||
295 | 168 | 181 | ||
296 | 169 | Keys.onLeftPressed: selectedDate.addDays(-1) | 182 | Keys.onLeftPressed: selectedDate.addDays(-1) |
297 | 170 | Keys.onRightPressed: selectedDate.addDays(1) | 183 | Keys.onRightPressed: selectedDate.addDays(1) |
298 | 171 | 184 | ||
311 | 172 | delegate: Item { | 185 | // This is a workaround for bug https://bugreports.qt.io/browse/QTBUG-49224 |
312 | 173 | id: monthItem | 186 | delegate: Loader { |
313 | 174 | 187 | id: monthDelegateLoader | |
314 | 175 | property int currentWeekRow: Math.floor((priv.selectedDay - gridStart) / 7) | 188 | sourceComponent: monthComponent |
315 | 176 | property var gridStart: monthStart.weekStart(firstDayOfWeek) | 189 | |
316 | 177 | property var monthEnd: monthStart.addMonths(1) | 190 | readonly property var month: new Cal.Month(model.month) |
317 | 178 | property var monthStart: new Cal.Day(model.month.year, model.month.month, 1) | 191 | |
318 | 179 | 192 | Binding { | |
319 | 180 | property var month: new Cal.Month(model.month) | 193 | target: monthDelegateLoader.item |
320 | 181 | 194 | property: "monthIndex" | |
321 | 182 | width: monthView.width | 195 | value: index |
322 | 183 | height: monthView.height | 196 | when: monthDelegateLoader.status == Loader.Ready |
323 | 197 | } | ||
324 | 198 | |||
325 | 199 | Binding { | ||
326 | 200 | target: monthDelegateLoader.item | ||
327 | 201 | property: "month" | ||
328 | 202 | value: month | ||
329 | 203 | when: monthDelegateLoader.status == Loader.Ready | ||
330 | 204 | } | ||
331 | 205 | } | ||
332 | 206 | |||
333 | 207 | Component { | ||
334 | 208 | id: monthComponent | ||
335 | 209 | Row { | ||
336 | 210 | objectName: "monthRow" + monthIndex | ||
337 | 211 | property int monthIndex: 0 | ||
338 | 212 | property var month: new Cal.Month() | ||
339 | 213 | readonly property var monthStart: month.firstDay() | ||
340 | 214 | readonly property var monthEnd: monthStart.addMonths(1) | ||
341 | 215 | readonly property var gridStart: monthStart.weekStart(firstDayOfWeek) | ||
342 | 216 | |||
343 | 217 | Loader { | ||
344 | 218 | id: weekNumbersLoader | ||
345 | 219 | objectName: "weekNumbersLoader" + monthIndex | ||
346 | 220 | active: calendar.showWeekNumbers | ||
347 | 221 | visible: active | ||
348 | 222 | |||
349 | 223 | sourceComponent: Column { | ||
350 | 224 | id: weekNumbersColumn | ||
351 | 225 | objectName: "weekNumbersColumn" + monthIndex | ||
352 | 226 | spacing: monthGrid.rowSpacing | ||
353 | 227 | |||
354 | 228 | Row { | ||
355 | 229 | Column { | ||
356 | 230 | Label { | ||
357 | 231 | objectName: "weekDay" + monthIndex | ||
358 | 232 | text: i18n.ctr("Header text: keep it short and upper case", "WEEK") | ||
359 | 233 | textSize: Label.XSmall | ||
360 | 234 | // FIXME: There's no good palette that covers both | ||
361 | 235 | // Ambiance (Ash) and Suru (Silk) | ||
362 | 236 | color: theme.palette.disabled.base | ||
363 | 237 | } | ||
364 | 238 | |||
365 | 239 | Repeater { | ||
366 | 240 | id: weekNumbers | ||
367 | 241 | model: priv.weeks | ||
368 | 242 | delegate: Item { | ||
369 | 243 | readonly property var rowDate: monthStart.addDays(index * priv.days).toDate() | ||
370 | 244 | width: priv.squareUnit | ||
371 | 245 | height: priv.squareUnit | ||
372 | 246 | |||
373 | 247 | Label { | ||
374 | 248 | id: weekNumberLabel | ||
375 | 249 | anchors.centerIn: parent | ||
376 | 250 | text: QtDateFunctions.formattedWeekNumber(rowDate) | ||
377 | 251 | textSize: Label.Medium | ||
378 | 252 | color: theme.palette.normal.backgroundTertiaryText | ||
379 | 253 | } | ||
380 | 254 | } | ||
381 | 255 | } | ||
382 | 256 | } | ||
383 | 257 | |||
384 | 258 | Column { | ||
385 | 259 | Item { | ||
386 | 260 | width: units.gu(2) | ||
387 | 261 | height: weekNumbersColumn.height | ||
388 | 262 | |||
389 | 263 | Rectangle { | ||
390 | 264 | color: theme.palette.disabled.base | ||
391 | 265 | anchors.fill: parent | ||
392 | 266 | anchors.topMargin: units.gu(0.5) | ||
393 | 267 | anchors.bottomMargin: anchors.topMargin | ||
394 | 268 | anchors.leftMargin: units.gu(0.9) | ||
395 | 269 | anchors.rightMargin: anchors.leftMargin | ||
396 | 270 | } | ||
397 | 271 | } | ||
398 | 272 | } | ||
399 | 273 | } | ||
400 | 274 | } | ||
401 | 275 | } | ||
402 | 184 | 276 | ||
403 | 185 | Grid { | 277 | Grid { |
404 | 186 | id: monthGrid | 278 | id: monthGrid |
405 | 187 | 279 | ||
414 | 188 | rows: 6 | 280 | columns: priv.days |
415 | 189 | columns: 7 | 281 | columnSpacing: (calendar.width - calendar.implicitWidth - (weekNumbersLoader.visible ? weekNumbersLoader.width : 0)) / (columns - 1) |
416 | 190 | y: priv.verticalMargin | 282 | |
417 | 191 | width: priv.squareUnit * columns | 283 | rows: priv.weeks + 1 /* the weekDays header */ |
418 | 192 | height: priv.squareUnit * rows | 284 | rowSpacing: (calendar.height - calendar.implicitHeight) / (rows - 1) |
419 | 193 | 285 | ||
420 | 194 | Repeater { | 286 | verticalItemAlignment: Grid.AlignVCenter |
421 | 195 | model: monthGrid.rows * monthGrid.columns | 287 | horizontalItemAlignment: Grid.AlignHCenter |
422 | 288 | |||
423 | 289 | Repeater { | ||
424 | 290 | id: daysHeader | ||
425 | 291 | model: priv.days | ||
426 | 292 | |||
427 | 293 | delegate: Label { | ||
428 | 294 | objectName: "weekDay" + index | ||
429 | 295 | text: Qt.locale(i18n.language).standaloneDayName((index + firstDayOfWeek) % priv.days, Locale.ShortFormat).toUpperCase() | ||
430 | 296 | textSize: Label.XSmall | ||
431 | 297 | // FIXME: There's no good palette that covers both | ||
432 | 298 | // Ambiance (Ash) and Suru (Silk) | ||
433 | 299 | color: theme.palette.highlighted.base | ||
434 | 300 | onHeightChanged: priv.weekDaysHeight = Math.max(height, priv.weekDaysHeight) | ||
435 | 301 | } | ||
436 | 302 | } | ||
437 | 303 | |||
438 | 304 | Repeater { | ||
439 | 305 | model: priv.days * priv.weeks | ||
440 | 196 | delegate: Item { | 306 | delegate: Item { |
441 | 197 | id: dayItem | 307 | id: dayItem |
442 | 198 | objectName: "dayItem" + index | 308 | objectName: "dayItem" + index |
443 | 199 | 309 | ||
456 | 200 | property bool isCurrent: dayStart.equals(priv.selectedDay) | 310 | readonly property int weekday: (index % priv.days + firstDayOfWeek) % priv.days |
457 | 201 | property bool isCurrentMonth: (monthStart < dayStart || monthStart.equals(dayStart)) && dayStart < monthEnd | 311 | readonly property var dayStart: gridStart.addDays(index) |
458 | 202 | property bool isCurrentWeek: row == currentWeekRow | 312 | readonly property bool isSelected: priv.userSelected && dayStart.equals(priv.selectedDay) |
459 | 203 | property bool isSunday: weekday == 0 | 313 | readonly property bool isCurrentMonth: (monthStart < dayStart || monthStart.equals(dayStart)) && dayStart < monthEnd |
460 | 204 | property bool isToday: dayStart.equals(priv.today) | 314 | readonly property bool isWeekend: weekday == 0 || weekday == 6 |
461 | 205 | property bool isWithinBounds: (priv.minimumDay === undefined || dayStart >= priv.minimumDay) && | 315 | readonly property bool isToday: dayStart.equals(priv.today) |
462 | 206 | (priv.maximumDay === undefined || dayStart <= priv.maximumDay) | 316 | readonly property bool hasEvent: isCurrentMonth && eventDays.indexOf(dayStart.day) != -1 |
451 | 207 | property int row: Math.floor(index / 7) | ||
452 | 208 | property int weekday: (index % 7 + firstDayOfWeek) % 7 | ||
453 | 209 | property real bottomMargin: (row == 5 || (collapsed && isCurrentWeek)) ? -priv.verticalMargin : 0 | ||
454 | 210 | property real topMargin: (row == 0 || (collapsed && isCurrentWeek)) ? -priv.verticalMargin : 0 | ||
455 | 211 | property var dayStart: gridStart.addDays(index) | ||
463 | 212 | 317 | ||
464 | 213 | visible: collapsed ? isCurrentWeek : true | ||
465 | 214 | width: priv.squareUnit | 318 | width: priv.squareUnit |
466 | 215 | height: priv.squareUnit | 319 | height: priv.squareUnit |
467 | 216 | 320 | ||
503 | 217 | Item { | 321 | Loader { |
504 | 218 | anchors { | 322 | id: todayMarkerLoader |
505 | 219 | fill: parent | 323 | objectName: "todayMarkerLoader" + index |
506 | 220 | topMargin: dayItem.topMargin | 324 | active: isToday |
507 | 221 | bottomMargin: dayItem.bottomMargin | 325 | visible: active |
508 | 222 | } | 326 | anchors.fill: parent |
509 | 223 | 327 | sourceComponent: UbuntuShape { | |
510 | 224 | Rectangle { | 328 | aspect: UbuntuShape.Flat |
511 | 225 | anchors.fill: parent | 329 | radius: "small" |
512 | 226 | visible: isSunday | 330 | color: dayNumber.color |
513 | 227 | opacity: 0.1 | 331 | |
514 | 228 | color: UbuntuColors.warmGrey | 332 | UbuntuShape { |
515 | 229 | } | 333 | // XXX: since we can't just colorize the shape border |
516 | 230 | 334 | // we need another one to fill the center with bg color | |
517 | 231 | Label { | 335 | id: currentDayShape |
518 | 232 | anchors.centerIn: parent | 336 | radius: parent.radius |
519 | 233 | text: dayStart.day | 337 | aspect: parent.aspect |
520 | 234 | font.pixelSize: units.dp(isCurrent ? 36 : 20) | 338 | backgroundColor: theme.palette.normal.background |
521 | 235 | color: isCurrentMonth && isWithinBounds ? isToday ? UbuntuColors.green : | 339 | |
522 | 236 | theme.palette.normal.backgroundText : | 340 | anchors.fill: parent |
523 | 237 | theme.palette.disabled.backgroundText | 341 | anchors.margins: priv.todayRingThickness |
524 | 238 | opacity: isWithinBounds ? 1. : 0.33 | 342 | } |
525 | 239 | 343 | } | |
526 | 240 | Behavior on font.pixelSize { | 344 | } |
527 | 241 | NumberAnimation { duration: 50 } | 345 | |
528 | 242 | } | 346 | Label { |
529 | 243 | } | 347 | id: dayNumber |
530 | 244 | } | 348 | anchors.centerIn: parent |
531 | 245 | 349 | text: dayStart.toDate().toLocaleDateString(Qt.locale(), "dd") | |
532 | 246 | MouseArea { | 350 | textSize: Label.Medium |
533 | 247 | anchors { | 351 | color: { |
534 | 248 | fill: parent | 352 | if (!isCurrentMonth) { |
535 | 249 | topMargin: dayItem.topMargin | 353 | // FIXME: There's no good palette that covers both |
536 | 250 | bottomMargin: dayItem.bottomMargin | 354 | // Ambiance (silk) and Suru (inkstone) |
537 | 251 | } | 355 | return theme.palette.disabled.base |
538 | 356 | } | ||
539 | 357 | if (isSelected) { | ||
540 | 358 | return theme.palette.normal.positionText | ||
541 | 359 | } | ||
542 | 360 | if (isWeekend) { | ||
543 | 361 | return theme.palette.normal.backgroundTertiaryText | ||
544 | 362 | } | ||
545 | 363 | |||
546 | 364 | return theme.palette.normal.backgroundText | ||
547 | 365 | } | ||
548 | 366 | } | ||
549 | 367 | |||
550 | 368 | Loader{ | ||
551 | 369 | objectName: "eventMarkerLoader"+index | ||
552 | 370 | active: hasEvent | ||
553 | 371 | visible: active | ||
554 | 372 | width: units.gu(0.4) | ||
555 | 373 | height: width | ||
556 | 374 | y: dayNumber.height + (parent.height - dayNumber.height) / 2 - priv.todayRingThickness | ||
557 | 375 | anchors.horizontalCenter: parent.horizontalCenter | ||
558 | 376 | |||
559 | 377 | sourceComponent: UbuntuShape { | ||
560 | 378 | objectName: "eventMarker"+index | ||
561 | 379 | aspect: UbuntuShape.Flat | ||
562 | 380 | radius: "small" | ||
563 | 381 | color: isSelected ? dayNumber.color : theme.palette.selected.baseText | ||
564 | 382 | } | ||
565 | 383 | } | ||
566 | 384 | |||
567 | 385 | AbstractButton { | ||
568 | 386 | anchors.fill: dayNumber | ||
569 | 387 | visible: (currentIndex == monthIndex) | ||
570 | 252 | 388 | ||
571 | 253 | onClicked: { | 389 | onClicked: { |
573 | 254 | if (isWithinBounds) monthView.selectedDate = new Date(dayStart.year, dayStart.month, dayStart.day) | 390 | if (!isSelected) { |
574 | 391 | priv.userSelected = true | ||
575 | 392 | calendar.selectedDate = new Date(dayStart.year, dayStart.month, dayStart.day) | ||
576 | 393 | } else if (priv.userSelected) { | ||
577 | 394 | if (priv.today.getMonth().equals(month)) { | ||
578 | 395 | calendar.selectedDate = priv.today.toDate() | ||
579 | 396 | } else { | ||
580 | 397 | calendar.selectedDate = new Date(dayStart.year, dayStart.month) | ||
581 | 398 | } | ||
582 | 399 | priv.userSelected = false | ||
583 | 400 | } | ||
584 | 255 | } | 401 | } |
585 | 256 | } | 402 | } |
586 | 257 | } | 403 | } |
587 | @@ -259,3 +405,5 @@ | |||
588 | 259 | } | 405 | } |
589 | 260 | } | 406 | } |
590 | 261 | } | 407 | } |
591 | 408 | |||
592 | 409 | } | ||
593 | 262 | 410 | ||
594 | === modified file 'plugins/Ubuntu/Settings/Components/plugin.cpp' | |||
595 | --- plugins/Ubuntu/Settings/Components/plugin.cpp 2015-08-04 14:57:35 +0000 | |||
596 | +++ plugins/Ubuntu/Settings/Components/plugin.cpp 2016-11-15 18:02:52 +0000 | |||
597 | @@ -20,8 +20,24 @@ | |||
598 | 20 | 20 | ||
599 | 21 | // Qt | 21 | // Qt |
600 | 22 | #include <QtQml/qqml.h> | 22 | #include <QtQml/qqml.h> |
601 | 23 | #include <QDate> | ||
602 | 24 | |||
603 | 25 | class QtDateFunctions : public QObject | ||
604 | 26 | { | ||
605 | 27 | Q_OBJECT | ||
606 | 28 | public: | ||
607 | 29 | QtDateFunctions(QObject * parent = nullptr) : QObject(parent) {} | ||
608 | 30 | ~QtDateFunctions() = default; | ||
609 | 31 | |||
610 | 32 | Q_INVOKABLE int weekNumber(const QDate &date) const { return date.weekNumber(); } | ||
611 | 33 | Q_INVOKABLE QString formattedWeekNumber(const QDate &date) const { return QString("%1").arg(date.weekNumber(), 2, 10, QChar('0')); } | ||
612 | 34 | }; | ||
613 | 23 | 35 | ||
614 | 24 | void UbuntuSettingsComponentsPlugin::registerTypes(const char *uri) | 36 | void UbuntuSettingsComponentsPlugin::registerTypes(const char *uri) |
615 | 25 | { | 37 | { |
616 | 26 | qmlRegisterType<ServerPropertySynchroniser>(uri, 0, 1, "ServerPropertySynchroniser"); | 38 | qmlRegisterType<ServerPropertySynchroniser>(uri, 0, 1, "ServerPropertySynchroniser"); |
617 | 39 | qmlRegisterSingletonType<QtDateFunctions>(uri, 0, 1, "QtDateFunctions", | ||
618 | 40 | [](QQmlEngine*, QJSEngine*) -> QObject* { return new QtDateFunctions; }); | ||
619 | 27 | } | 41 | } |
620 | 42 | |||
621 | 43 | #include "plugin.moc" | ||
622 | 28 | 44 | ||
623 | === modified file 'plugins/Ubuntu/Settings/Menus/CalendarMenu.qml' | |||
624 | --- plugins/Ubuntu/Settings/Menus/CalendarMenu.qml 2016-11-15 18:02:52 +0000 | |||
625 | +++ plugins/Ubuntu/Settings/Menus/CalendarMenu.qml 2016-11-15 18:02:52 +0000 | |||
626 | @@ -1,5 +1,5 @@ | |||
627 | 1 | /* | 1 | /* |
629 | 2 | * Copyright 2013 Canonical Ltd. | 2 | * Copyright 2013-2016 Canonical Ltd. |
630 | 3 | * | 3 | * |
631 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
632 | 5 | * it under the terms of the GNU Lesser General Public License as published by | 5 | * it under the terms of the GNU Lesser General Public License as published by |
633 | @@ -13,7 +13,9 @@ | |||
634 | 13 | * You should have received a copy of the GNU Lesser General Public License | 13 | * You should have received a copy of the GNU Lesser General Public License |
635 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
636 | 15 | * | 15 | * |
638 | 16 | * Authored by Andrea Cimitan <andrea.cimitan@canonical.com> | 16 | * Authors: |
639 | 17 | * Andrea Cimitan <andrea.cimitan@canonical.com> | ||
640 | 18 | * Marco Trevisan <marco.trevisan@canonical.com> | ||
641 | 17 | */ | 19 | */ |
642 | 18 | 20 | ||
643 | 19 | import QtQuick 2.4 | 21 | import QtQuick 2.4 |
644 | @@ -23,42 +25,96 @@ | |||
645 | 23 | BaseMenu { | 25 | BaseMenu { |
646 | 24 | id: menu | 26 | id: menu |
647 | 25 | 27 | ||
648 | 26 | property alias collapsed: calendar.collapsed | ||
649 | 27 | property alias currentDate: calendar.currentDate | 28 | property alias currentDate: calendar.currentDate |
650 | 28 | property alias firstDayOfWeek: calendar.firstDayOfWeek | 29 | property alias firstDayOfWeek: calendar.firstDayOfWeek |
651 | 29 | property alias maximumDate: calendar.maximumDate | ||
652 | 30 | property alias minimumDate: calendar.minimumDate | ||
653 | 31 | property alias selectedDate: calendar.selectedDate | 30 | property alias selectedDate: calendar.selectedDate |
684 | 32 | 31 | property alias showWeekNumbers: calendar.showWeekNumbers | |
685 | 33 | menuHeight: slotsLayout.height | 32 | property alias eventDays: calendar.eventDays |
686 | 34 | 33 | ||
687 | 35 | StyledSlotsLayout { | 34 | menuHeight: layout.height |
688 | 36 | id: slotsLayout | 35 | highlightWhenPressed: false |
689 | 37 | objectName: "calenderMenuSlotsLayout" | 36 | |
690 | 38 | style: menuStyle | 37 | Column { |
691 | 39 | 38 | id: layout | |
692 | 40 | mainSlot: Column { | 39 | |
693 | 41 | id: column | 40 | anchors { |
694 | 42 | spacing: units.gu(1) | 41 | left: parent.left |
695 | 43 | 42 | right: parent.right | |
696 | 44 | Label { | 43 | } |
697 | 45 | id: label | 44 | |
698 | 46 | anchors { | 45 | ListItemLayout { |
699 | 47 | left: parent.left | 46 | id: monthLayout |
700 | 48 | right: parent.right | 47 | objectName: "monthLayout" |
701 | 49 | } | 48 | |
702 | 50 | fontSize: "large" | 49 | padding { |
703 | 51 | text: i18n.ctr("%1=month name, %2=4-digit year", "%1 %2") | 50 | top: menuStyle.padding.top |
704 | 52 | .arg(Qt.locale().standaloneMonthName(calendar.currentDate.getMonth(), Locale.LongFormat)) | 51 | bottom: menuStyle.padding.bottom |
705 | 53 | .arg(calendar.currentDate.getFullYear()) | 52 | leading: menuStyle.padding.leading |
706 | 54 | } | 53 | trailing: menuStyle.padding.trailing |
707 | 55 | 54 | } | |
708 | 56 | Calendar { | 55 | |
709 | 57 | id: calendar | 56 | title.horizontalAlignment: Text.AlignHCenter |
710 | 58 | objectName: "calendar" | 57 | title.font.pixelSize: menuStyle.fontSize |
711 | 59 | anchors { | 58 | title.color: menuStyle.foregroundColor |
712 | 60 | left: parent.left | 59 | title.text: i18n.ctr("%1=month name, %2=4-digit year", "%1 %2") |
713 | 61 | right: parent.right | 60 | .arg(Qt.locale().standaloneMonthName(calendar.currentDate.getMonth(), Locale.LongFormat)) |
714 | 61 | .arg(calendar.currentDate.getFullYear()) | ||
715 | 62 | |||
716 | 63 | title.children: [ | ||
717 | 64 | AbstractButton { | ||
718 | 65 | x: (parent.width - width) / 2 | ||
719 | 66 | width: parent.contentWidth | ||
720 | 67 | height: parent.contentHeight | ||
721 | 68 | onClicked: calendar.selectFistDayOfTheMonth() | ||
722 | 69 | } | ||
723 | 70 | ] | ||
724 | 71 | |||
725 | 72 | Icon { | ||
726 | 73 | objectName: "goPreviousMonth" | ||
727 | 74 | name: "go-previous" | ||
728 | 75 | width: menuStyle.iconSize | ||
729 | 76 | height: menuStyle.iconSize | ||
730 | 77 | color: menuStyle.iconColor | ||
731 | 78 | SlotsLayout.position: SlotsLayout.Leading | ||
732 | 79 | |||
733 | 80 | AbstractButton { | ||
734 | 81 | anchors.fill: parent | ||
735 | 82 | onClicked: calendar.moveToMonth(-1) | ||
736 | 83 | } | ||
737 | 84 | } | ||
738 | 85 | |||
739 | 86 | Icon { | ||
740 | 87 | objectName: "goNextMonth" | ||
741 | 88 | name: "go-next" | ||
742 | 89 | width: menuStyle.iconSize | ||
743 | 90 | height: menuStyle.iconSize | ||
744 | 91 | color: menuStyle.iconColor | ||
745 | 92 | SlotsLayout.position: SlotsLayout.Trailing | ||
746 | 93 | |||
747 | 94 | AbstractButton { | ||
748 | 95 | anchors.fill: parent | ||
749 | 96 | onClicked: calendar.moveToMonth(1) | ||
750 | 97 | } | ||
751 | 98 | } | ||
752 | 99 | } | ||
753 | 100 | |||
754 | 101 | StyledSlotsLayout { | ||
755 | 102 | id: slotsLayout | ||
756 | 103 | objectName: "calenderMenuSlotsLayout" | ||
757 | 104 | style: menuStyle | ||
758 | 105 | |||
759 | 106 | mainSlot: Item { | ||
760 | 107 | // XXX: this extra Item seems to be needed by Qt 5.4, | ||
761 | 108 | // we can remove it once migrated to new versions | ||
762 | 109 | height: calendar.height | ||
763 | 110 | Calendar { | ||
764 | 111 | id: calendar | ||
765 | 112 | objectName: "calendar" | ||
766 | 113 | interactive: !pointerMode | ||
767 | 114 | anchors { | ||
768 | 115 | left: parent.left | ||
769 | 116 | right: parent.right | ||
770 | 117 | } | ||
771 | 62 | } | 118 | } |
772 | 63 | } | 119 | } |
773 | 64 | } | 120 | } |
774 | 65 | 121 | ||
775 | === modified file 'tests/qmltests/Components/tst_Calendar.qml' | |||
776 | --- tests/qmltests/Components/tst_Calendar.qml 2016-08-17 09:46:20 +0000 | |||
777 | +++ tests/qmltests/Components/tst_Calendar.qml 2016-11-15 18:02:52 +0000 | |||
778 | @@ -55,17 +55,6 @@ | |||
779 | 55 | 55 | ||
780 | 56 | function init() { | 56 | function init() { |
781 | 57 | calendar.selectedDate = new Date(2013, 4, 10); | 57 | calendar.selectedDate = new Date(2013, 4, 10); |
782 | 58 | calendar.maximumDate = undefined; | ||
783 | 59 | calendar.minimumDate = undefined; | ||
784 | 60 | } | ||
785 | 61 | |||
786 | 62 | function test_collapsed() { | ||
787 | 63 | calendar.collapsed = true; | ||
788 | 64 | compare(calendar.interactive, false, "Calendar should not be interactive"); | ||
789 | 65 | var collapsedHeight = calendar.height; | ||
790 | 66 | calendar.collapsed = false; | ||
791 | 67 | verify(calendar.height > collapsedHeight * 4 && calendar.height < collapsedHeight * 6, "Height did not expand properly"); | ||
792 | 68 | compare(calendar.interactive, true, "Calendar should be interactive"); | ||
793 | 69 | } | 58 | } |
794 | 70 | 59 | ||
795 | 71 | function test_selectedDate_data() { | 60 | function test_selectedDate_data() { |
796 | @@ -79,8 +68,8 @@ | |||
797 | 79 | function test_selectedDate(data) { | 68 | function test_selectedDate(data) { |
798 | 80 | calendar.selectedDate = data.date; | 69 | calendar.selectedDate = data.date; |
799 | 81 | 70 | ||
802 | 82 | compare(calendar.currentItem.monthStart.year, data.date.getFullYear(), "Current year does no correspond to set date"); | 71 | compare(calendar.currentItem.month.firstDay().year, data.date.getFullYear(), "Current year does no correspond to set date"); |
803 | 83 | compare(calendar.currentItem.monthStart.month, data.date.getMonth(), "Current month does no correspond to set date"); | 72 | compare(calendar.currentItem.month.firstDay().month, data.date.getMonth(), "Current month does no correspond to set date"); |
804 | 84 | } | 73 | } |
805 | 85 | 74 | ||
806 | 86 | function test_firstDayOfWeek_data() { | 75 | function test_firstDayOfWeek_data() { |
807 | @@ -102,29 +91,96 @@ | |||
808 | 102 | } | 91 | } |
809 | 103 | } | 92 | } |
810 | 104 | 93 | ||
812 | 105 | function test_minMaxDate_data() { | 94 | function test_selectedDateUpdatesCurrent_data() { |
813 | 106 | return [ | 95 | return [ |
827 | 107 | {tag: "Min=-0", date: new Date(), minDate: new Date(), maxDate: undefined, count: 3}, | 96 | { date: new Date(2010, 4, 10) }, |
828 | 108 | {tag: "Min=-1", date: new Date(), minDate: new Date().addMonths(-1), maxDate: undefined, count: 4}, | 97 | { date: new Date() }, |
829 | 109 | {tag: "Min=-22", date: new Date(), minDate: new Date().addMonths(-22), maxDate: undefined, count: 5}, // max out at +-2 | 98 | { date: new Date(2020, 10, 31)}, |
817 | 110 | |||
818 | 111 | {tag: "Max=+0", date: new Date(), minDate: undefined, maxDate: new Date(), count: 3}, | ||
819 | 112 | {tag: "Max=+1", date: new Date(), minDate: undefined, maxDate: new Date().addMonths(1), count: 4}, | ||
820 | 113 | {tag: "Max=+22", date: new Date(), minDate: undefined, maxDate: new Date().addMonths(22), count: 5}, // max out at +-2 | ||
821 | 114 | |||
822 | 115 | {tag: "Min=-0,Max=+0", date: new Date(), minDate: new Date(), maxDate: new Date(), count: 1}, | ||
823 | 116 | {tag: "Min=-1,Max=+1", date: new Date(), minDate: new Date().addMonths(-1), maxDate: new Date().addMonths(1), count: 3}, | ||
824 | 117 | {tag: "Min=-22,Max=+1", date: new Date(), minDate: new Date().addMonths(-22), maxDate: new Date().addMonths(1), count: 4}, // max out at +-2 | ||
825 | 118 | {tag: "Min=-1,Max=+22", date: new Date(), minDate: new Date().addMonths(-1), maxDate: new Date().addMonths(22), count: 4}, // max out at +-2 | ||
826 | 119 | {tag: "Min=-22,Max=+22", date: new Date(), minDate: new Date().addMonths(-22), maxDate: new Date().addMonths(22), count: 5}, // max out at +-2 | ||
830 | 120 | ]; | 99 | ]; |
831 | 121 | } | 100 | } |
832 | 122 | 101 | ||
838 | 123 | function test_minMaxDate(data) { | 102 | function test_selectedDateUpdatesCurrent(data) { |
839 | 124 | calendar.selectedDate = data.date; | 103 | calendar.selectedDate = data.date |
840 | 125 | calendar.minimumDate = data.minDate; | 104 | compare(calendar.currentDate, data.date) |
841 | 126 | calendar.maximumDate = data.maxDate; | 105 | } |
842 | 127 | compare(calendar.count, data.count, "The number of months should have changed"); | 106 | |
843 | 107 | function test_eventsMarker_data() | ||
844 | 108 | { | ||
845 | 109 | var values = [] | ||
846 | 110 | for (var i = 0; i < 20; ++i) { | ||
847 | 111 | values.push({tag: "eventDay "+i+": "+(i % 2 != 0), idx: i, dayEvent: (i % 2 != 0)}) | ||
848 | 112 | } | ||
849 | 113 | |||
850 | 114 | return values | ||
851 | 115 | } | ||
852 | 116 | |||
853 | 117 | function test_eventsMarker(data) { | ||
854 | 118 | var eventMarkerLoader = findChild(calendar, "eventMarkerLoader"+data.idx) | ||
855 | 119 | verify(eventMarkerLoader) | ||
856 | 120 | |||
857 | 121 | var expected = data.dayEvent | ||
858 | 122 | |||
859 | 123 | if (data.dayEvent) { | ||
860 | 124 | var dayItem = findChild(calendar, "dayItem"+data.idx) | ||
861 | 125 | verify(dayItem) | ||
862 | 126 | |||
863 | 127 | calendar.eventDays = [dayItem.dayStart.day] | ||
864 | 128 | expected = dayItem.isCurrentMonth | ||
865 | 129 | } | ||
866 | 130 | |||
867 | 131 | compare(eventMarkerLoader.visible, expected) | ||
868 | 132 | var eventMarker = findChild(eventMarkerLoader, "eventMarker"+data.idx) | ||
869 | 133 | verify(expected ? eventMarker : eventMarker === undefined) | ||
870 | 134 | } | ||
871 | 135 | |||
872 | 136 | function test_showWeeksNumber_data() { | ||
873 | 137 | return [{tag: "visible", visible: true}, {tag: "not visible", visible: false}] | ||
874 | 138 | } | ||
875 | 139 | |||
876 | 140 | function test_showWeeksNumber(data) { | ||
877 | 141 | var weekNumbersLoader = findChild(calendar, "weekNumbersLoader"+calendar.currentIndex) | ||
878 | 142 | verify(weekNumbersLoader) | ||
879 | 143 | |||
880 | 144 | calendar.showWeekNumbers = data.visible | ||
881 | 145 | var weekNumbersColumn = findChild(weekNumbersLoader, "weekNumbersColumn"+calendar.currentIndex) | ||
882 | 146 | verify(data.visible ? weekNumbersColumn !== undefined : weekNumbersColumn === undefined) | ||
883 | 147 | } | ||
884 | 148 | |||
885 | 149 | function test_isToday() { | ||
886 | 150 | for (var i = 0; i < 7*6; ++i) { | ||
887 | 151 | var dayItem = findChild(calendar, "dayItem"+i) | ||
888 | 152 | verify(dayItem) | ||
889 | 153 | var todayMarkerLoader = findChild(dayItem, "todayMarkerLoader"+i) | ||
890 | 154 | verify(todayMarkerLoader) | ||
891 | 155 | |||
892 | 156 | compare(todayMarkerLoader.visible, dayItem.isToday) | ||
893 | 157 | compare(todayMarkerLoader.active, dayItem.isToday) | ||
894 | 158 | } | ||
895 | 159 | } | ||
896 | 160 | |||
897 | 161 | function test_moveToMonth_data() { | ||
898 | 162 | var tests = [] | ||
899 | 163 | |||
900 | 164 | for (var i = 1; i <= 15; ++i) { | ||
901 | 165 | tests.push({tag: "previous "+i, delta: -i }) | ||
902 | 166 | tests.push({tag: "next "+i, delta: i }) | ||
903 | 167 | } | ||
904 | 168 | |||
905 | 169 | return tests | ||
906 | 170 | } | ||
907 | 171 | |||
908 | 172 | function test_moveToMonth(data) { | ||
909 | 173 | var expected = calendar.currentDate.addMonths(data.delta) | ||
910 | 174 | var now = new Date() | ||
911 | 175 | |||
912 | 176 | if (expected.getFullYear() != now.getFullYear() || expected.getMonth() != now.getMonth()) { | ||
913 | 177 | expected.setDate(1) | ||
914 | 178 | } else { | ||
915 | 179 | expected.setDate(now.getDate()) | ||
916 | 180 | } | ||
917 | 181 | |||
918 | 182 | calendar.moveToMonth(data.delta) | ||
919 | 183 | compare(calendar.currentDate, expected) | ||
920 | 128 | } | 184 | } |
921 | 129 | } | 185 | } |
922 | 130 | } | 186 | } |
923 | 131 | 187 | ||
924 | === modified file 'tests/qmltests/Menus/tst_CalendarMenu.qml' | |||
925 | --- tests/qmltests/Menus/tst_CalendarMenu.qml 2016-09-07 09:14:24 +0000 | |||
926 | +++ tests/qmltests/Menus/tst_CalendarMenu.qml 2016-11-15 18:02:52 +0000 | |||
927 | @@ -56,9 +56,16 @@ | |||
928 | 56 | 56 | ||
929 | 57 | property var calendar: findChild(calendarMenu, "calendar") | 57 | property var calendar: findChild(calendarMenu, "calendar") |
930 | 58 | 58 | ||
934 | 59 | function test_collapsed() { | 59 | function test_interactive_data() { |
935 | 60 | calendarMenu.collapsed = true | 60 | return [ |
936 | 61 | compare(calendar.collapsed, true, "Cannot set collapsed") | 61 | {tag: "pointer", pointer: true, expected: false }, |
937 | 62 | {tag: "touch", pointer: false, expected: true } | ||
938 | 63 | ] | ||
939 | 64 | } | ||
940 | 65 | |||
941 | 66 | function test_interactive(data) { | ||
942 | 67 | calendarMenu.pointerMode = data.pointer | ||
943 | 68 | compare(calendar.interactive, data.expected, "Cannot use interactive") | ||
944 | 62 | } | 69 | } |
945 | 63 | 70 | ||
946 | 64 | function test_currentDate() { | 71 | function test_currentDate() { |
947 | @@ -71,16 +78,6 @@ | |||
948 | 71 | compare(calendar.firstDayOfWeek, 5, "Cannot set firstDayOfWeek") | 78 | compare(calendar.firstDayOfWeek, 5, "Cannot set firstDayOfWeek") |
949 | 72 | } | 79 | } |
950 | 73 | 80 | ||
951 | 74 | function test_maximumDate() { | ||
952 | 75 | calendarMenu.maximumDate = date3 | ||
953 | 76 | compare(calendar.maximumDate, date3, "Cannot set maximumDate") | ||
954 | 77 | } | ||
955 | 78 | |||
956 | 79 | function test_minimumDate() { | ||
957 | 80 | calendar.minimumDate = date1 | ||
958 | 81 | compare(calendar.minimumDate, date1, "Cannot set minimumDate") | ||
959 | 82 | } | ||
960 | 83 | |||
961 | 84 | function test_selectedDate() { | 81 | function test_selectedDate() { |
962 | 85 | calendar.selectedDate = date2 | 82 | calendar.selectedDate = date2 |
963 | 86 | compare(calendar.selectedDate, date2, "Cannot set selectedDate") | 83 | compare(calendar.selectedDate, date2, "Cannot set selectedDate") |
964 | @@ -92,5 +89,40 @@ | |||
965 | 92 | calendar.selectedDate = calendar.selectedDate.addDays(1); | 89 | calendar.selectedDate = calendar.selectedDate.addDays(1); |
966 | 93 | compare(calendar.selectedDate, date5, "The next day after 2016-10-30 is not 2016-10-31"); | 90 | compare(calendar.selectedDate, date5, "The next day after 2016-10-30 is not 2016-10-31"); |
967 | 94 | } | 91 | } |
968 | 92 | |||
969 | 93 | function test_SwitchMonth_data() { | ||
970 | 94 | var tests = [] | ||
971 | 95 | |||
972 | 96 | for (var i = 1; i <= 15; ++i) { | ||
973 | 97 | tests.push({tag: "previous "+i, buttonName: "goPreviousMonth", delta: -i }) | ||
974 | 98 | tests.push({tag: "next "+i, buttonName: "goNextMonth", delta: i }) | ||
975 | 99 | } | ||
976 | 100 | |||
977 | 101 | return tests | ||
978 | 102 | } | ||
979 | 103 | |||
980 | 104 | function test_SwitchMonth(data) { | ||
981 | 105 | var button = findChild(calendarMenu, data.buttonName); | ||
982 | 106 | var monthLayout = findChild(calendarMenu, "monthLayout") | ||
983 | 107 | verify(button) | ||
984 | 108 | verify(monthLayout) | ||
985 | 109 | |||
986 | 110 | var expected = calendar.currentDate.addMonths(data.delta) | ||
987 | 111 | var now = new Date() | ||
988 | 112 | |||
989 | 113 | if (expected.getFullYear() != now.getFullYear() || expected.getMonth() != now.getMonth()) { | ||
990 | 114 | expected.setDate(1) | ||
991 | 115 | } else { | ||
992 | 116 | expected.setDate(now.getDate()) | ||
993 | 117 | } | ||
994 | 118 | |||
995 | 119 | for (var i = 0; i < Math.abs(data.delta); ++i) | ||
996 | 120 | mouseClick(button, button.width / 2, button.height / 2) | ||
997 | 121 | |||
998 | 122 | compare(calendar.currentDate, expected) | ||
999 | 123 | compare(monthLayout.title.text, i18n.ctr("%1=month name, %2=4-digit year", "%1 %2") | ||
1000 | 124 | .arg(Qt.locale().standaloneMonthName(expected.getMonth(), Locale.LongFormat)) | ||
1001 | 125 | .arg(expected.getFullYear())) | ||
1002 | 126 | } | ||
1003 | 95 | } | 127 | } |
1004 | 96 | } | 128 | } |
PASSED: Continuous integration, rev:299 /unity8- jenkins. ubuntu. com/job/ lp-ubuntu- settings- components- ci/88/ /unity8- jenkins. ubuntu. com/job/ build/3083 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= vivid+overlay, testname= qmluitests. sh/1728 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= xenial+ overlay, testname= qmluitests. sh/1728 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= yakkety, testname= qmluitests. sh/1728 /unity8- jenkins. ubuntu. com/job/ build-0- fetch/3111 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 2968 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 2968/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 2968 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 2968/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 2968 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 2968/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 2968 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 2968/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 2968 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 2968/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 2968 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 2968/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 2968 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 2968/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 2968 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 2968/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= yakkety/ 2968 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= yakkety/ 2968/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-ubuntu- settings- components- ci/88/rebuild
https:/