Merge lp:~majster-pl/ubuntu-calendar-app/new-event-page2 into lp:ubuntu-calendar-app

Proposed by Szymon Waliczek on 2016-04-11
Status: Superseded
Proposed branch: lp:~majster-pl/ubuntu-calendar-app/new-event-page2
Merge into: lp:ubuntu-calendar-app
Diff against target: 1600 lines (+766/-533)
5 files modified
ContactChoicePopup.qml (+268/-125)
KeyboardRectangle.qml (+12/-10)
NewEvent.qml (+329/-283)
NewEventTimePicker.qml (+100/-59)
po/com.ubuntu.calendar.pot (+57/-56)
To merge this branch: bzr merge lp:~majster-pl/ubuntu-calendar-app/new-event-page2
Reviewer Review Type Date Requested Status
Renato Araujo Oliveira Filho (community) 2016-04-11 Needs Fixing on 2016-04-14
Review via email: mp+291516@code.launchpad.net

This proposal has been superseded by a proposal from 2016-05-12.

Description of the change

this is very first proposal for new Event Page, adding new guest is currently to be work on... but first implementation is done.

To post a comment you must log in.

Good work. Some small inline comments.

review: Needs Fixing

Thanks for the work. I will create a new branch based on this one to fix some small problems.

Unmerged revisions

821. By Szymon Waliczek on 2016-04-11

First implementation of new designs for New Event page.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ContactChoicePopup.qml'
2--- ContactChoicePopup.qml 2016-02-04 13:37:00 +0000
3+++ ContactChoicePopup.qml 2016-04-11 14:35:38 +0000
4@@ -1,154 +1,297 @@
5-/*
6- * Copyright (C) 2013-2014 Canonical Ltd
7- *
8- * This file is part of Ubuntu Calendar App
9- *
10- * Ubuntu Calendar App is free software: you can redistribute it and/or modify
11- * it under the terms of the GNU General Public License version 3 as
12- * published by the Free Software Foundation.
13- *
14- * Ubuntu Calendar App is distributed in the hope that it will be useful,
15- * but WITHOUT ANY WARRANTY; without even the implied warranty of
16- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17- * GNU General Public License for more details.
18- *
19- * You should have received a copy of the GNU General Public License
20- * along with this program. If not, see <http://www.gnu.org/licenses/>.
21- */
22+///*
23+// * Copyright (C) 2013-2014 Canonical Ltd
24+// *
25+// * This file is part of Ubuntu Calendar App
26+// *
27+// * Ubuntu Calendar App is free software: you can redistribute it and/or modify
28+// * it under the terms of the GNU General Public License version 3 as
29+// * published by the Free Software Foundation.
30+// *
31+// * Ubuntu Calendar App is distributed in the hope that it will be useful,
32+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
33+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34+// * GNU General Public License for more details.
35+// *
36+// * You should have received a copy of the GNU General Public License
37+// * along with this program. If not, see <http://www.gnu.org/licenses/>.
38+// */
39 import QtQuick 2.4
40 import Ubuntu.Components 1.3
41-import Ubuntu.Components.Popups 1.3
42-import Ubuntu.Components.ListItems 1.0
43-import Ubuntu.Components.Themes.Ambiance 1.0
44-import QtOrganizer 5.0
45 import QtContacts 5.0
46
47-import "Defines.js" as Defines
48-
49-Popover {
50+Item {
51 id: root
52- objectName: "contactPopover"
53+
54+ width: parent.width
55+ height: mainColumn.height
56+
57+ property bool contactOpen: false
58+ property var openContanctObject
59
60 signal contactSelected(var contact, string emailAddress);
61
62- Label {
63- id: noContact
64- anchors.centerIn: parent
65- text: i18n.tr("No contact")
66- visible: contactModel.contacts.length === 0
67- }
68-
69- UnionFilter {
70- id: filter
71-
72- property string searchString: ""
73-
74- filters: [
75- DetailFilter{
76- detail: ContactDetail.Name
77- field: Name.FirstName
78- matchFlags: Filter.MatchContains
79- value: filter.searchString
80- },
81- DetailFilter{
82- detail: ContactDetail.Name
83- field: Name.LastName
84- matchFlags: Filter.MatchContains
85- value: filter.searchString
86- },
87- DetailFilter{
88- detail: ContactDetail.DisplayLabel
89- field: DisplayLabel.Label
90- matchFlags: Filter.MatchContains
91- value: filter.searchString
92- }
93- ]
94- }
95+ onContactOpenChanged: {
96+ positionDelay.start()
97+ }
98+
99+ Timer {
100+ id: positionDelay
101+ interval: 300
102+ onTriggered: suggestionsFlickable.contentY = openContanctObject.y
103+ }
104+
105+ states: [
106+ State {
107+ name: "open"
108+ PropertyChanges { target: contactsSuggestionItem; height: units.gu(10)}
109+ },
110+ State {
111+ name: "close"
112+ PropertyChanges { target: contactsSuggestionItem; height: 0}
113+ }
114+
115+ ]
116+
117+ Behavior on height {
118+ UbuntuNumberAnimation {}
119+ }
120+
121
122 ContactModel {
123 id: contactModel
124 manager: "galera"
125- filter: filter
126 autoUpdate: true
127 }
128
129- Timer {
130- id: idleSearch
131
132- interval: 500
133- repeat: false
134- onTriggered: {
135- filter.searchString = searchBox.text
136- }
137- }
138
139 Column {
140- anchors.top: parent.top
141- anchors.left: parent.left
142- anchors.right: parent.right
143- anchors.margins: units.gu(1)
144+ id: mainColumn
145+ width: parent.width
146+ spacing: units.gu(1)
147+
148+ Item {
149+ id: guestsAdded
150+ width: parent.width
151+
152+ }
153
154 TextField {
155- id: searchBox
156- objectName: "contactPopoverInput"
157- focus: true
158+ id: addGuestTestField
159+ objectName: "addGuestTestField"
160+
161 width: parent.width
162- placeholderText: i18n.tr("Search contact")
163 inputMethodHints: Qt.ImhNoPredictiveText
164- primaryItem: Icon {
165- height: parent.height*0.5
166- width: parent.height*0.5
167- anchors.verticalCenter: parent.verticalCenter
168- name:"find"
169- }
170- onTextChanged: {
171- idleSearch.restart()
172- }
173+ placeholderText: i18n.tr("Guests")
174+
175+ onActiveFocusChanged: {
176+ if(addGuestTestField.activeFocus) {
177+ lol2.state = "open"
178+ flickable.makeMeVisible(addGuestListItem);
179+ } else {
180+ lol2.state = "close"
181+ }
182+ }
183+
184 }
185
186- ListView {
187- id: contactList
188- objectName: "contactPopoverList"
189- width: parent.width
190- model: contactModel
191- height: units.gu(15)
192- clip: true
193- focus: false
194- delegate: Column {
195- width: contactList.width
196- Repeater {
197- anchors {
198- left: parent.left
199- right: parent.right
200- }
201- height: childrenRect.height
202-
203- model: Math.max(1, contact.emails.length)
204- delegate: ListItem {
205- property string emailAddress: contact.emails.length > index ? contact.emails[index].emailAddress : ""
206-
207+ Component {
208+ id: suggestionsDelegate
209+ Item {
210+ id: rootSug
211+
212+ clip: true
213+ width: String(contact.displayLabel.label).toLowerCase().search(addGuestTestField.text.toLowerCase()) == - 1 ? 0 : mainGrid.width
214+ height: mainGrid.height
215+
216+ ListModel {
217+ id: addressesModel
218+ }
219+
220+
221+ function getEmails() {
222+ for(var i=0; contact.emails.length > i; i++) {
223+ addressesModel.append({"email": contact.emails[i].emailAddress})
224+ }
225+ }
226+
227+
228+ Behavior on width {
229+ UbuntuNumberAnimation {}
230+ }
231+
232+ Connections {
233+ target: root
234+ onContactOpenChanged: {
235+ if(!contactOpen) {
236+ emailAddressesColumn.state = "default"
237+ }
238+ }
239+ }
240+
241+
242+
243+ Row {
244+ id: mainGrid
245+
246+ AbstractButton {
247+ id: contactNameAbstractButton
248+
249+ width: contactNameLabel.width + units.gu(1)
250+ height: contactNameLabel.height + units.gu(1)
251 activeFocusOnPress: false
252- opacity: emailAddress.length > 0 ? 1.0 : 0.3
253- width: contactList.width
254- objectName: "contactPopoverList%1".arg(index)
255- ListItemLayout {
256- title.text: contact.displayLabel.label
257- subtitle.text: emailAddress
258- }
259- MouseArea {
260+ enabled: contact.emails.length > 0
261+
262+ Rectangle {
263 anchors.fill: parent
264- onClicked: {
265- if (emailAddress.length > 0) {
266- root.contactSelected(contact, emailAddress);
267- PopupUtils.close(root)
268- }
269- }
270- }
271- }
272- }
273- }
274- }
275+ color: (parent.pressed || (emailAddressesColumn.state === "open")) ? UbuntuColors.lightGrey : "transparent"
276+ }
277+
278+ Label {
279+ id: contactNameLabel
280+ text: emailAddressesColumn.state === "open" ? contact.displayLabel.label+":" : contact.displayLabel.label
281+ anchors.centerIn: parent
282+ color: contact.emails.length > 0 ? "black" : UbuntuColors.lightGrey
283+ font.italic: contact.emails.length > 0 ? false : true
284+ fontSize: "medium"
285+ }
286+ onClicked: {
287+ if(contact.emails.length > 1) {
288+// emailAddressesColumn.openClose()
289+ if(contactOpen) {
290+ contactOpen = false
291+ } else {
292+ emailAddressesColumn.openClose()
293+ openContanctObject = rootSug
294+ }
295+
296+ } else {
297+ root.contactSelected(contact, contact.email.emailAddress);
298+ }
299+ }
300+ }
301+ Column {
302+ id: emailAddressesColumn
303+
304+ clip: true
305+ state: "default"
306+
307+ function openClose() {
308+ if(emailAddressesColumn.state === "open") {
309+ emailAddressesColumn.state = "default"
310+ } else {
311+ emailAddressesColumn.state = "open"
312+ }
313+ }
314+
315+ states: [
316+ State {
317+ name: "default"
318+ PropertyChanges { target: emailAddressesColumn; width: 0 }
319+ },
320+ State {
321+ name: "open"
322+ PropertyChanges { target: emailAddressesColumn; width: mainColumn.width - contactNameAbstractButton.width }
323+ }
324+
325+ ]
326+
327+ onStateChanged: {
328+ if(state === "open") {
329+ rootSug.getEmails()
330+// suggestionsFlickable.contentY = rootSug.y
331+ contactOpen = true
332+ } else {
333+ addressesModel.clear()
334+ }
335+ }
336+
337+ Repeater {
338+ model: addressesModel
339+ delegate: AbstractButton {
340+ width: contactEmailLabel.width + units.gu(2)
341+ height: contactEmailLabel.height + units.gu(1)
342+ activeFocusOnPress: false
343+
344+ Rectangle {
345+ anchors.fill: parent
346+ color: parent.pressed ? UbuntuColors.lightGrey : "transparent"
347+ }
348+
349+ Label {
350+ id: contactEmailLabel
351+ anchors.verticalCenter: parent.verticalCenter
352+ anchors.left: parent.left
353+ anchors.leftMargin: units.gu(1)
354+ text: email
355+ color: contact.emails.length > 0 ? "black" : UbuntuColors.lightGrey
356+ font.italic: contact.emails.length > 0 ? false : true
357+ fontSize: "medium"
358+ elide: Text.ElideRight
359+ }
360+
361+ onClicked: {
362+ root.contactSelected(contact, email);
363+ emailAddressesColumn.state = "default"
364+ }
365+ }
366+
367+ }
368+
369+ }
370+ }
371+
372+
373+ }
374+
375+ }
376+
377+ Item {
378+ id: contactsSuggestionItem
379+ width: parent.width
380+ clip: true
381+
382+ Flickable {
383+ id: suggestionsFlickable
384+ width: parent.width - units.gu(0)
385+ height: parent.height - units.gu(1)
386+ anchors.top: parent.top
387+ anchors.topMargin: units.gu(1)
388+// anchors.horizontalCenter: parent.horizontalCenter
389+ contentHeight: suggestionsListView.height + units.gu(1)
390+
391+ // animation on flickable contentY change
392+ Behavior on contentY {
393+ UbuntuNumberAnimation {}
394+ }
395+
396+ onFlickStarted: contactOpen = false
397+// contentY: contactOpen && !flicking ? openContanctObject.y : NaN
398+
399+
400+ Flow {
401+ id: suggestionsListView
402+ width: parent.width
403+ spacing: units.gu(1.5)
404+
405+ Repeater {
406+ model: contactModel
407+ delegate: suggestionsDelegate
408+ }
409+
410+ }
411+ }
412+
413+ Scrollbar {
414+ flickableItem: suggestionsFlickable
415+ align: Qt.AlignTrailing
416+ }
417+ }
418+
419 }
420
421- Component.onCompleted: searchBox.forceActiveFocus()
422+
423+
424+
425 }
426+
427
428=== modified file 'KeyboardRectangle.qml'
429--- KeyboardRectangle.qml 2016-02-03 19:53:46 +0000
430+++ KeyboardRectangle.qml 2016-04-11 14:35:38 +0000
431@@ -26,16 +26,18 @@
432 anchors.bottom: parent.bottom
433 height: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
434
435- states: [
436- State {
437- name: "hidden"
438- when: keyboardRect.height == 0
439- },
440- State {
441- name: "shown"
442- when: keyboardRect.height == Qt.inputMethod.keyboardRectangle.height
443- }
444- ]
445+ property bool isVisible: Qt.inputMethod.visible
446+
447+// states: [
448+// State {
449+// name: "hidden"
450+// when: keyboardRect.height == 0
451+// },
452+// State {
453+// name: "shown"
454+// when: keyboardRect.height == Qt.inputMethod.keyboardRectangle.height
455+// }
456+// ]
457
458 function recursiveFindFocusedItem(parent) {
459 if (parent.activeFocus) {
460
461=== modified file 'NewEvent.qml'
462--- NewEvent.qml 2016-04-06 18:46:29 +0000
463+++ NewEvent.qml 2016-04-11 14:35:38 +0000
464@@ -319,46 +319,69 @@
465 }
466
467 Keys.onEscapePressed: root.cancel()
468+
469 header: PageHeader {
470 id: pageHeader
471
472 flickable: null
473- title: isEdit ? i18n.tr("Edit Event"):i18n.tr("New Event")
474- leadingActionBar.actions: Action {
475- id: backAction
476-
477- name: "cancel"
478- text: i18n.tr("Cancel")
479- iconName: isEdit ? "back" : "down"
480- onTriggered: root.cancel()
481- }
482-
483- trailingActionBar.actions: [
484- Action {
485- text: i18n.tr("Delete");
486- objectName: "delete"
487- iconName: "delete"
488- visible : isEdit
489- onTriggered: {
490- var dialog = PopupUtils.open(Qt.resolvedUrl("DeleteConfirmationDialog.qml"),root,{"event": event});
491- dialog.deleteEvent.connect( function(eventId){
492- model.removeItem(eventId);
493- if (pageStack)
494- pageStack.pop();
495- root.eventDeleted(eventId);
496- });
497- }
498- },
499- Action {
500- iconName: "ok"
501- objectName: "save"
502- text: i18n.tr("Save")
503- enabled: !!titleEdit.text.trim()
504- onTriggered: saveToQtPim();
505- }
506- ]
507+ property Component delegate: Component {
508+ AbstractButton {
509+ id: button
510+ action: modelData
511+ width: label.width + units.gu(4)
512+ height: parent.height
513+ Rectangle {
514+ color: parent.pressed ? UbuntuColors.coolGrey : UbuntuColors.slate
515+ opacity: 0.1
516+ anchors.fill: parent
517+ visible: button.pressed
518+ }
519+ Label {
520+ anchors.centerIn: parent
521+ id: label
522+ text: action.text
523+ color: text === i18n.tr("Delete") ? UbuntuColors.red : Theme.palette.selected.fieldText
524+ font.weight: text === i18n.tr("Save") ? Font.Normal : Font.Light
525+ }
526+ }
527+ }
528+ leadingActionBar {
529+ anchors.leftMargin: 0
530+ actions: Action {
531+ text: i18n.tr("Cancel")
532+ iconName: "close"
533+ onTriggered: root.cancel()
534+ }
535+ delegate: pageHeader.delegate
536+ }
537+ trailingActionBar {
538+ anchors.rightMargin: 0
539+ actions: [
540+ Action {
541+ text: i18n.tr("Save")
542+ iconName: "tick"
543+ onTriggered: saveToQtPim();
544+ },
545+ Action {
546+ text: i18n.tr("Delete")
547+ iconName: "delete"
548+ visible : isEdit
549+ onTriggered: {
550+ var dialog = PopupUtils.open(Qt.resolvedUrl("DeleteConfirmationDialog.qml"),root,{"event": event});
551+ dialog.deleteEvent.connect( function(eventId){
552+ model.removeItem(eventId);
553+ if (pageStack)
554+ pageStack.pop();
555+ root.eventDeleted(eventId);
556+ });
557+ }
558+ }
559+ ]
560+ delegate: pageHeader.delegate
561+ }
562 }
563
564+
565 Component{
566 id: errorDlgComponent
567 Dialog {
568@@ -399,7 +422,7 @@
569 // if it is not, try to scroll and make it visible
570 var targetY = position.y + item.height - flickable.height
571 if (targetY >= 0 && position.y) {
572- flickable.contentY = targetY;
573+ flickable.contentY = targetY + units.gu(1);
574 } else if (position.y < flickable.contentY) {
575 // if it is hidden at the top, also show it
576 flickable.contentY = position.y;
577@@ -407,6 +430,11 @@
578 flickable.returnToBounds()
579 }
580
581+ // animation on flickable contentY change
582+ Behavior on contentY {
583+ UbuntuNumberAnimation {}
584+ }
585+
586 flickableDirection: Flickable.VerticalFlick
587 anchors{
588 left: parent.left
589@@ -425,9 +453,8 @@
590
591 NewEventTimePicker{
592 id: startDateTimeInput
593- objectName: "startDateTimeInput"
594-
595- header: i18n.tr("From")
596+ //TRANSLATORS: this referes to date. eg: To: Wendsday, 9 March 2016
597+ headerText: i18n.tr("From")
598 showTimePicker: !allDayEventCheckbox.checked
599 anchors {
600 left: parent.left
601@@ -435,257 +462,277 @@
602 }
603 onDateTimeChanged: {
604 startDate = dateTime;
605- endDateTimeInput.dateTime = new Date(startDate.getTime() + root.eventSize)
606 }
607 }
608
609 NewEventTimePicker{
610 id: endDateTimeInput
611- objectName: "endDateTimeInput"
612-
613- header: i18n.tr("To")
614+ //TRANSLATORS: this referes to date. eg: From: Wendsday, 9 March 2016
615+ headerText: i18n.tr("To")
616 showTimePicker: !allDayEventCheckbox.checked
617 anchors {
618 left: parent.left
619 right: parent.right
620 }
621 onDateTimeChanged: {
622- if (dateTime.getTime() < startDate.getTime()) {
623- root.eventSize = root.allDay ? 0 : root.millisecsInAnHour
624- dateTime = new Date(startDate.getTime() + root.eventSize)
625- return
626- }
627-
628 endDate = dateTime;
629- if (allDay)
630- root.eventSize = endDate.midnight().getTime() - startDate.midnight().getTime()
631- else
632- root.eventSize = endDate.getTime() - startDate.getTime()
633- }
634- }
635-
636- ListItems.Standard {
637- anchors {
638- left: parent.left
639- right: parent.right
640- }
641-
642- text: i18n.tr("All day event")
643- __foregroundColor: Theme.palette.normal.baseText
644- showDivider: false
645- control: CheckBox {
646- objectName: "allDayEventCheckbox"
647- id: allDayEventCheckbox
648- checked: false
649- onCheckedChanged: {
650- if (checked)
651- root.eventSize = Math.max(endDate.midnight().getTime() - startDate.midnight().getTime(), 0)
652- else
653- root.eventSize = Math.max(endDate.getTime() - startDate.getTime(), root.millisecsInAnHour)
654- }
655- }
656- }
657-
658- ListItems.ThinDivider {}
659-
660- Column {
661- width: parent.width
662- spacing: units.gu(1)
663-
664- ListItems.Header{
665- text: i18n.tr("Event Details")
666- __foregroundColor: Theme.palette.normal.baseText
667- }
668-
669- TextField {
670- id: titleEdit
671- objectName: "newEventName"
672-
673- anchors {
674- left: parent.left
675- right: parent.right
676- margins: units.gu(2)
677- }
678-
679- placeholderText: i18n.tr("Event Name")
680- onFocusChanged: {
681- if(titleEdit.focus) {
682- flickable.makeMeVisible(titleEdit);
683- }
684- }
685- }
686-
687- TextArea{
688- id: messageEdit
689- objectName: "eventDescriptionInput"
690-
691- anchors {
692- left: parent.left
693- right: parent.right
694- margins: units.gu(2)
695- }
696-
697- placeholderText: i18n.tr("Description")
698- onFocusChanged: {
699- if(messageEdit.focus) {
700- flickable.makeMeVisible(messageEdit);
701- }
702- }
703- }
704-
705- TextField {
706- id: locationEdit
707- objectName: "eventLocationInput"
708-
709- anchors {
710- left: parent.left
711- right: parent.right
712- margins: units.gu(2)
713- }
714-
715- inputMethodHints: Qt.ImhNoPredictiveText
716- placeholderText: i18n.tr("Location")
717-
718- onFocusChanged: {
719- if(locationEdit.focus) {
720- flickable.makeMeVisible(locationEdit);
721- }
722- }
723- }
724- }
725-
726- Column {
727- width: parent.width
728- spacing: units.gu(1)
729-
730- ListItems.Header {
731- text: i18n.tr("Calendar")
732- __foregroundColor: Theme.palette.normal.baseText
733- }
734-
735- OptionSelector{
736- id: calendarsOption
737- objectName: "calendarsOption"
738-
739- anchors {
740- left: parent.left
741- right: parent.right
742- margins: units.gu(2)
743- }
744-
745- containerHeight: itemHeight * 4
746- model: root.model ? root.model.getWritableAndSelectedCollections() : []
747-
748- delegate: OptionSelectorDelegate{
749- text: modelData.name
750-
751- UbuntuShape{
752- id: calColor
753- width: height
754- height: parent.height - units.gu(2)
755- color: modelData.color
756- anchors {
757- right: parent.right
758- rightMargin: units.gu(4)
759- verticalCenter: parent.verticalCenter
760- }
761- }
762- }
763- onExpandedChanged: Qt.inputMethod.hide();
764- }
765- }
766-
767- Column {
768- width: parent.width
769- spacing: units.gu(1)
770-
771- ListItems.Header {
772- text: i18n.tr("Guests")
773- __foregroundColor: Theme.palette.normal.baseText
774- }
775-
776- Button{
777- id: addGuestButton
778- objectName: "addGuestButton"
779-
780- property var contactsPopup: null
781-
782- text: i18n.tr("Add Guest")
783- anchors {
784- left: parent.left
785- right: parent.right
786- margins: units.gu(2)
787- }
788-
789- onClicked: {
790- if (contactsPopup)
791- return
792-
793- flickable.makeMeVisible(addGuestButton)
794- contactsPopup = PopupUtils.open(Qt.resolvedUrl("ContactChoicePopup.qml"), addGuestButton);
795- contactsPopup.contactSelected.connect( function(contact, emailAddress) {
796- if(!internal.isContactAlreadyAdded(contact, emailAddress) ) {
797- var t = internal.contactToAttendee(contact, emailAddress);
798- contactModel.append({"contact": t});
799- }
800-
801- });
802- contactsPopup.Component.onDestruction.connect( function() {
803- addGuestButton.contactsPopup = null
804- })
805- }
806- }
807-
808- UbuntuShape {
809- anchors {
810- left: parent.left
811- right: parent.right
812- margins: units.gu(2)
813- }
814-
815- height: contactList.height
816-
817- Column{
818- id: contactList
819- objectName: "guestList"
820-
821- spacing: units.gu(1)
822- width: parent.width
823- clip: true
824-
825- ListModel{
826- id: contactModel
827- }
828-
829- Repeater{
830- model: contactModel
831- delegate: ListItem {
832- objectName: "eventGuest%1".arg(index)
833-
834- ListItemLayout {
835- title.text: contact.name
836- subtitle.text: contact.emailAddress
837- }
838-
839- leadingActions: ListItemActions {
840- actions: Action {
841- iconName: "delete"
842- onTriggered: {
843- contactModel.remove(index)
844- }
845+ }
846+ }
847+
848+ // All day event ListItem with Switch
849+ ListItem {
850+ width: parent.width
851+
852+ ListItemLayout {
853+ title.text: i18n.tr("All day event")
854+ Switch {
855+ id: allDayEventCheckbox
856+ checked: false
857+ SlotsLayout.position: SlotsLayout.Trailing;
858+ }
859+ }
860+ onClicked: {
861+// Haptics.play()
862+ allDayEventCheckbox.checked = !allDayEventCheckbox.checked
863+ }
864+
865+ }
866+
867+ // ListItem which holds "Event details" label + TextField + TextArea + TextField
868+ ListItem {
869+ height: eventDetailsColumn.height + (eventDetailsColumn.anchors.margins*2)
870+
871+ Column {
872+ id: eventDetailsColumn
873+ spacing: units.gu(2)
874+ anchors {
875+ left: parent.left
876+ right: parent.right
877+ top: parent.top
878+ margins: units.gu(2)
879+ }
880+
881+ Label {
882+ width: parent.width
883+ text: i18n.tr("Event details")
884+ elide: Text.ElideRight
885+ }
886+
887+ TextField {
888+ id: titleEdit
889+ objectName: "newEventName"
890+
891+ width: parent.width
892+ inputMethodHints: Qt.ImhNoPredictiveText
893+ placeholderText: i18n.tr("Event Name")
894+
895+ onActiveFocusChanged: {
896+ if(titleEdit.activeFocus) {
897+ flickable.makeMeVisible(titleEdit);
898+ }
899+ }
900+ }
901+
902+ TextArea{
903+ id: messageEdit
904+ objectName: "eventDescriptionInput"
905+
906+ width: parent.width
907+ placeholderText: i18n.tr("Description")
908+
909+ onActiveFocusChanged: {
910+ if(messageEdit.activeFocus) {
911+ flickable.makeMeVisible(messageEdit);
912+ }
913+ }
914+ }
915+
916+ TextField {
917+ id: locationEdit
918+ objectName: "eventLocationInput"
919+
920+ width: parent.width
921+ inputMethodHints: Qt.ImhNoPredictiveText
922+ placeholderText: i18n.tr("Location")
923+
924+ onActiveFocusChanged: {
925+ if(locationEdit.activeFocus) {
926+ flickable.makeMeVisible(locationEdit);
927+ }
928+ }
929+ }
930+ }
931+ }
932+
933+ // ListItem to hold calendars selector
934+ ListItem {
935+ height: chooseCalendarColumn.height + (eventDetailsColumn.anchors.topMargin*2)
936+
937+ Column {
938+ id: chooseCalendarColumn
939+ spacing: units.gu(2)
940+ anchors {
941+ left: parent.left
942+ right: parent.right
943+ top: parent.top
944+ topMargin: units.gu(2)
945+ }
946+
947+ Label {
948+ width: parent.width
949+ anchors {
950+ left: parent.left
951+ leftMargin: units.gu(2)
952+ right: parent.right
953+ rightMargin: units.gu(2)
954+ }
955+ text: i18n.tr("Choose calendar")
956+ elide: Text.ElideRight
957+ }
958+
959+ ListItems.ItemSelector {
960+ id: calendarsOption
961+ model: root.model.getWritableCollections();
962+ delegate: OptionSelectorDelegate { text: modelData.name }
963+ }
964+
965+ }
966+ }
967+
968+
969+ // add guest field
970+ ListItem {
971+ id: addGuestListItem
972+ height: addGusestColumn.height + (addGusestColumn.anchors.margins*2)
973+
974+ Column {
975+ id: addGusestColumn
976+// spacing: units.gu(2)
977+ anchors {
978+ left: parent.left
979+ right: parent.right
980+ top: parent.top
981+ margins: units.gu(2)
982+ }
983+
984+ Behavior on height {
985+ UbuntuNumberAnimation {}
986+ }
987+
988+ Label {
989+ width: parent.width
990+ text: i18n.tr("Event details")
991+ elide: Text.ElideRight
992+ }
993+
994+ Item {
995+ width: parent.width
996+ height: units.gu(1)
997+ }
998+
999+ ListModel{
1000+ id: contactModel
1001+ }
1002+
1003+ Component {
1004+ id: addedGusestDelegate
1005+ Item {
1006+ width: delegateRow.width + units.gu(1)
1007+ height: units.gu(3)
1008+
1009+ Rectangle {
1010+ anchors.fill: parent
1011+ color: delegateMouseArea.pressed ? UbuntuColors.lightGrey : "transparent"
1012+ }
1013+
1014+ Row {
1015+ id: delegateRow
1016+ height: parent.height
1017+// width: rec.width + lab.width + units.gu(1)
1018+ spacing: units.gu(0.5)
1019+ anchors.horizontalCenter: parent.horizontalCenter
1020+
1021+ UbuntuShape {
1022+ id: rec
1023+ height: parent.height - units.gu(0.5)
1024+ anchors.verticalCenter: parent.verticalCenter
1025+ width: height
1026+ color: "green"
1027+ Text {
1028+ anchors.centerIn: parent
1029+ text: contact.name.charAt(0).toUpperCase()
1030+ font.bold: true
1031+ color: "white"
1032 }
1033 }
1034- }
1035- }
1036- }
1037- }
1038-
1039- ListItems.ThinDivider {
1040- visible: (event != undefined) && (event.itemType === Type.Event)
1041- }
1042-
1043+ Label {
1044+ id: lab
1045+// id: delagateLabel
1046+ anchors.verticalCenter: parent.verticalCenter
1047+ text: contact.name
1048+ }
1049+ }
1050+
1051+ MouseArea {
1052+ id: delegateMouseArea
1053+ anchors.fill: parent
1054+ onClicked: contactModel.remove(index)
1055+
1056+ }
1057+
1058+ }
1059+ }
1060+
1061+ // Add guest section (this is now in development)
1062+ Item {
1063+ width: parent.width
1064+// height: contactModel.count > 0 ? units.gu(5) : 0
1065+ height: suggestionsListView.height + units.gu(0.5)
1066+ Behavior on height {
1067+ UbuntuNumberAnimation {}
1068+ }
1069+
1070+ Flow {
1071+ id: suggestionsListView
1072+ width: parent.width
1073+ spacing: units.gu(1.5)
1074+ move: Transition {
1075+ NumberAnimation {
1076+ properties: "x,y"
1077+ }
1078+ }
1079+ add: Transition {
1080+ NumberAnimation {
1081+ properties: "x,y"
1082+ }
1083+ }
1084+
1085+ Repeater {
1086+ model: contactModel
1087+ delegate: addedGusestDelegate
1088+ }
1089+
1090+ }
1091+
1092+ }
1093+
1094+ ContactChoicePopup {
1095+ id: lol2
1096+ width: parent.width
1097+
1098+ onContactSelected: {
1099+ if(!internal.isContactAlreadyAdded(contact, emailAddress) ) {
1100+ var t = internal.contactToAttendee(contact, emailAddress);
1101+ contactModel.append({"contact": t});
1102+ }
1103+
1104+ }
1105+ }
1106+
1107+ }
1108 }
1109
1110+
1111 ListItem {
1112 id:thisHappens
1113 objectName :"thisHappens"
1114@@ -768,6 +815,12 @@
1115 }
1116 }
1117
1118+ // Scrollbar
1119+ Scrollbar{
1120+ flickableItem: flickable
1121+ align: Qt.AlignTrailing
1122+ }
1123+
1124 // used to keep the field visible when the keyboard appear or dismiss
1125 KeyboardRectangle {
1126 id: keyboardRectangle
1127@@ -783,14 +836,8 @@
1128 PauseAnimation { duration: 200 }
1129 ScriptAction {
1130 script: {
1131- if (addGuestButton.contactsPopup) {
1132- // WORKAROUND: causes the popover to follow the buttom position when keyboard appears
1133- flickable.makeMeVisible(addGuestButton)
1134- addGuestButton.contactsPopup.caller = null
1135- addGuestButton.contactsPopup.caller = addGuestButton
1136- } else {
1137- flickable.makeMeVisible(flickable.activeItem)
1138- }
1139+ flickable.makeMeVisible(flickable.activeItem)
1140+
1141 }
1142 }
1143 }
1144@@ -827,8 +874,7 @@
1145 return false;
1146 }
1147
1148- function attendeeFromData(id, name, emailAddress)
1149- {
1150+ function attendeeFromData(id, name, emailAddress) {
1151 var attendee = Qt.createQmlObject("import QtOrganizer 5.0; EventAttendee{}", internal, "NewEvent.qml");
1152 attendee.name = name
1153 attendee.emailAddress = emailAddress
1154
1155=== modified file 'NewEventTimePicker.qml'
1156--- NewEventTimePicker.qml 2016-03-22 20:09:08 +0000
1157+++ NewEventTimePicker.qml 2016-04-11 14:35:38 +0000
1158@@ -1,76 +1,117 @@
1159 import QtQuick 2.4
1160-import Ubuntu.Components.ListItems 1.0 as ListItem
1161+import Ubuntu.Components 1.3
1162 import Ubuntu.Components.Themes.Ambiance 1.0
1163-import Ubuntu.Components.Pickers 1.0
1164+import Ubuntu.Components.Pickers 1.3
1165+//import QtQuick.Layouts 1.1
1166
1167-Column {
1168+ListItem {
1169 id: dateTimeInput
1170- property alias header: listHeader.text
1171-
1172- property date dateTime;
1173- property bool showTimePicker;
1174+
1175+ property string headerText //header label ("From" or "To")
1176+ property date dateTime //keep date from DatePicker
1177+ property bool showTimePicker //if true then user is able to set time on event
1178+
1179+ // when new date set in DatePicker then this will be run.
1180+ onDateTimeChanged: {
1181+ layout.summary.text = dateTime.toLocaleDateString() // set date
1182+ secondLabel.text = Qt.formatTime(dateTime, "hh:mm AP").replace(/\./g, "") // set time
1183+ }
1184
1185 function clearFocus() {
1186- dateInput.focus = false;
1187- timeInput.focus = false;
1188+ dateBG.focus = false;
1189+ timeBG.focus = false;
1190 }
1191
1192+ // function to open date/time picker
1193 function openDatePicker (element, caller, callerProperty, mode) {
1194 element.highlighted = true;
1195 var picker = PickerPanel.openDatePicker(caller, callerProperty, mode);
1196 if (!picker) return;
1197- picker.closed.connect(function () {
1198- element.highlighted = false;
1199- });
1200- }
1201-
1202- onDateTimeChanged: {
1203- dateInput.text = dateTime.toLocaleDateString();
1204- timeInput.text = Qt.formatTime(dateTime);
1205- }
1206-
1207- ListItem.Header {
1208- id: listHeader
1209- __foregroundColor: Theme.palette.normal.baseText
1210- }
1211-
1212- Item {
1213- anchors {
1214- left: parent.left
1215- right: parent.right
1216- margins: units.gu(2)
1217- }
1218-
1219- height: dateInput.height
1220-
1221- NewEventEntryField{
1222- id: dateInput
1223- objectName: "dateInput"
1224-
1225- text: ""
1226- anchors.left: parent.left
1227- width: !showTimePicker ? parent.width : 4 * parent.width / 5
1228-
1229- MouseArea{
1230- anchors.fill: parent
1231- onClicked: openDatePicker(dateInput, dateTimeInput, "dateTime", "Years|Months|Days")
1232- }
1233- }
1234-
1235- NewEventEntryField{
1236- id: timeInput
1237- objectName: "timeInput"
1238-
1239- text: ""
1240- anchors.right: parent.right
1241- width: parent.width / 5
1242+ picker.closed.connect(function () { element.highlighted = false; });
1243+ }
1244+
1245+ height: layout.height + divider.height
1246+
1247+ // backgroud color of full date fabel, to be shown when user click on date and DatePicker is visable
1248+ Rectangle {
1249+ id: dateBG
1250+
1251+ property bool highlighted: false
1252+
1253+ height: layout.summary.height + units.gu(3.5)
1254+ width: showTimePicker ? layout.title.width + units.gu(3) : layout.width
1255+ anchors.bottom: parent.bottom
1256+ color: highlighted || abstractButtonDate.pressed ? UbuntuColors.lightGrey : "transparent"
1257+
1258+// Behavior on color { ColorAnimation {} }
1259+ }
1260+
1261+ // backgroud color of time label, to be shown when user click on date and DatePicker is visable
1262+ Rectangle {
1263+ id: timeBG
1264+
1265+ property bool highlighted: false
1266+
1267+ height: dateBG.height
1268+ width: slot.width + units.gu(4)
1269+ anchors.bottom: parent.bottom
1270+ anchors.right: parent.right
1271+ color: (highlighted || abstractButtonTime.pressed) ? UbuntuColors.lightGrey : "transparent"
1272+
1273+// Behavior on color { ColorAnimation {} }
1274+ }
1275+
1276+ // ListItemLayout to keep full date label and time label
1277+ ListItemLayout {
1278+ id: layout
1279+
1280+ title.text: headerText
1281+ title.color: Theme.palette.selected.overlayText
1282+ title.font.pixelSize: FontUtils.sizeToPixels("small")
1283+ subtitle.text: " "
1284+ summary.color: dateBG.highlighted ? "white" : Theme.palette.selected.fieldText
1285+ summary.font.pixelSize: FontUtils.sizeToPixels("medium")
1286+
1287+// Behavior on summary.color { ColorAnimation {} }
1288+
1289+ // Item to hold Trailing tile label item
1290+ Item {
1291+ id: slot
1292+
1293+ width: secondLabel.width
1294+ height: parent.height
1295 visible: showTimePicker
1296- horizontalAlignment: Text.AlignRight
1297-
1298- MouseArea{
1299- anchors.fill: parent
1300- onClicked: openDatePicker(timeInput, dateTimeInput, "dateTime", "Hours|Minutes")
1301+ SlotsLayout.overrideVerticalPositioning: true
1302+
1303+ // label to keep time [ 10:20 AM ]
1304+ Label {
1305+ id: secondLabel
1306+
1307+ fontSize: "medium"
1308+ color: timeBG.highlighted ? "white" : Theme.palette.selected.fieldText
1309+ y: layout.mainSlot.y + layout.summary.y + layout.summary.baselineOffset - baselineOffset
1310+// Behavior on color { ColorAnimation {} }
1311+// Behavior on color { ColorAnimation {duration: 700} }
1312+
1313 }
1314 }
1315 }
1316+
1317+ // AbstractButton to be triggered when user click on full date
1318+ AbstractButton {
1319+ id: abstractButtonDate
1320+
1321+ anchors.fill: dateBG
1322+ onClicked: { openDatePicker(dateBG, dateTimeInput, "dateTime", "Years|Months|Days")}
1323+ }
1324+
1325+ // AbstractButton to be triggered when user click on time
1326+ AbstractButton {
1327+ id: abstractButtonTime
1328+
1329+ anchors.fill: timeBG
1330+ visible: showTimePicker
1331+ onClicked: { openDatePicker(timeBG, dateTimeInput, "dateTime", "Hours|Minutes")}
1332+ }
1333+
1334 }
1335
1336=== modified file 'po/com.ubuntu.calendar.pot'
1337--- po/com.ubuntu.calendar.pot 2016-03-23 03:59:15 +0000
1338+++ po/com.ubuntu.calendar.pot 2016-04-11 14:35:38 +0000
1339@@ -1,6 +1,6 @@
1340 # SOME DESCRIPTIVE TITLE.
1341 # Copyright (C) YEAR Canonical Ltd.
1342-# This file is distributed under the same license as the PACKAGE package.
1343+# This file is distributed under the same license as the package.
1344 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
1345 #
1346 #, fuzzy
1347@@ -8,7 +8,7 @@
1348 msgstr ""
1349 "Project-Id-Version: \n"
1350 "Report-Msgid-Bugs-To: \n"
1351-"POT-Creation-Date: 2016-03-23 00:58-0300\n"
1352+"POT-Creation-Date: 2016-04-11 15:19+0100\n"
1353 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1354 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1355 "Language-Team: LANGUAGE <LL@li.org>\n"
1356@@ -18,7 +18,7 @@
1357 "Content-Transfer-Encoding: 8bit\n"
1358 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
1359
1360-#: ../AgendaView.qml:50 ../calendar.qml:344 ../calendar.qml:576
1361+#: ../AgendaView.qml:50 ../calendar.qml:348 ../calendar.qml:580
1362 msgid "Agenda"
1363 msgstr ""
1364
1365@@ -104,16 +104,12 @@
1366 msgstr ""
1367
1368 #: ../ColorPickerDialog.qml:55 ../DeleteConfirmationDialog.qml:60
1369-#: ../EditEventConfirmationDialog.qml:53 ../NewEvent.qml:341
1370+#: ../EditEventConfirmationDialog.qml:53 ../NewEvent.qml:351
1371 msgid "Cancel"
1372 msgstr ""
1373
1374-#: ../ContactChoicePopup.qml:37
1375-msgid "No contact"
1376-msgstr ""
1377-
1378-#: ../ContactChoicePopup.qml:96
1379-msgid "Search contact"
1380+#: ../ContactChoicePopup.qml:85
1381+msgid "Guests"
1382 msgstr ""
1383
1384 #: ../DayView.qml:72 ../MonthView.qml:50 ../WeekView.qml:55 ../YearView.qml:57
1385@@ -154,11 +150,11 @@
1386 msgid "Delete this"
1387 msgstr ""
1388
1389-#: ../DeleteConfirmationDialog.qml:51 ../NewEvent.qml:348
1390+#: ../DeleteConfirmationDialog.qml:51 ../NewEvent.qml:343 ../NewEvent.qml:366
1391 msgid "Delete"
1392 msgstr ""
1393
1394-#: ../EditEventConfirmationDialog.qml:29 ../NewEvent.qml:336
1395+#: ../EditEventConfirmationDialog.qml:29
1396 msgid "Edit Event"
1397 msgstr ""
1398
1399@@ -182,12 +178,12 @@
1400
1401 #. TRANSLATORS: the first argument (%1) refers to a start time for an event,
1402 #. while the second one (%2) refers to the end time
1403-#: ../EventBubble.qml:100
1404+#: ../EventBubble.qml:136
1405 #, qt-format
1406 msgid "%1 - %2"
1407 msgstr ""
1408
1409-#: ../EventDetails.qml:37 ../NewEvent.qml:484
1410+#: ../EventDetails.qml:37
1411 msgid "Event Details"
1412 msgstr ""
1413
1414@@ -195,32 +191,35 @@
1415 msgid "Edit"
1416 msgstr ""
1417
1418-#: ../EventDetails.qml:164 ../TimeLineHeader.qml:66
1419+#: ../EventDetails.qml:117
1420+msgid "Attending"
1421+msgstr ""
1422+
1423+#: ../EventDetails.qml:120
1424+msgid "Not Attending"
1425+msgstr ""
1426+
1427+#: ../EventDetails.qml:123
1428+msgid "Maybe"
1429+msgstr ""
1430+
1431+#: ../EventDetails.qml:126
1432+msgid "No Reply"
1433+msgstr ""
1434+
1435+#: ../EventDetails.qml:162 ../TimeLineHeader.qml:66
1436 msgid "All Day"
1437 msgstr ""
1438
1439-#: ../EventDetails.qml:336 ../NewEvent.qml:549
1440-#: com.ubuntu.calendar_calendar.desktop.in.in.h:1
1441+#: ../EventDetails.qml:334 com.ubuntu.calendar_calendar.desktop.in.in.h:1
1442 msgid "Calendar"
1443 msgstr ""
1444
1445-#: ../EventDetails.qml:369
1446-msgid "Not Attending"
1447-msgstr ""
1448-
1449-#: ../EventDetails.qml:373
1450-msgid "Attending"
1451-msgstr ""
1452-
1453-#: ../EventDetails.qml:377
1454-msgid "No Reply"
1455-msgstr ""
1456-
1457-#: ../EventDetails.qml:400 ../NewEvent.qml:515
1458+#: ../EventDetails.qml:391 ../NewEvent.qml:541
1459 msgid "Description"
1460 msgstr ""
1461
1462-#: ../EventDetails.qml:418 ../EventReminder.qml:36 ../NewEvent.qml:711
1463+#: ../EventDetails.qml:409 ../NewEvent.qml:768 ../NewEvent.qml:807
1464 msgid "Reminder"
1465 msgstr ""
1466
1467@@ -228,7 +227,7 @@
1468 #. and it is shown as the header of the page to choose repetition
1469 #. and as the header of the list item that shows the repetition
1470 #. summary in the page that displays the event details
1471-#: ../EventRepetition.qml:40 ../EventRepetition.qml:153
1472+#: ../EventRepetition.qml:40 ../EventRepetition.qml:152
1473 msgid "Repeat"
1474 msgstr ""
1475
1476@@ -236,18 +235,18 @@
1477 msgid "Repeats On:"
1478 msgstr ""
1479
1480-#: ../EventRepetition.qml:217
1481+#: ../EventRepetition.qml:218
1482 msgid "Recurring event ends"
1483 msgstr ""
1484
1485 #. TRANSLATORS: this refers to how often a recurrent event repeats
1486 #. and it is shown as the header of the option selector to choose
1487 #. its repetition
1488-#: ../EventRepetition.qml:240 ../NewEvent.qml:685
1489+#: ../EventRepetition.qml:242 ../NewEvent.qml:744
1490 msgid "Repeats"
1491 msgstr ""
1492
1493-#: ../EventRepetition.qml:265
1494+#: ../EventRepetition.qml:268
1495 msgid "Date"
1496 msgstr ""
1497
1498@@ -288,7 +287,7 @@
1499
1500 #. TRANSLATORS: This is shown in the month view as "Wk" as a title
1501 #. to indicate the week numbers. It should be a max of up to 3 characters.
1502-#: ../MonthComponent.qml:317
1503+#: ../MonthComponent.qml:316
1504 msgid "Wk"
1505 msgstr ""
1506
1507@@ -297,52 +296,54 @@
1508 msgid "%1 %2"
1509 msgstr ""
1510
1511-#: ../NewEvent.qml:179
1512+#: ../NewEvent.qml:185
1513 msgid "End time can't be before start time"
1514 msgstr ""
1515
1516-#: ../NewEvent.qml:336 ../NewEventBottomEdge.qml:53
1517-msgid "New Event"
1518-msgstr ""
1519-
1520-#: ../NewEvent.qml:365
1521+#: ../NewEvent.qml:344 ../NewEvent.qml:361
1522 msgid "Save"
1523 msgstr ""
1524
1525-#: ../NewEvent.qml:376
1526+#: ../NewEvent.qml:389
1527 msgid "Error"
1528 msgstr ""
1529
1530-#: ../NewEvent.qml:378
1531+#: ../NewEvent.qml:391
1532 msgid "OK"
1533 msgstr ""
1534
1535-#: ../NewEvent.qml:438
1536+#. TRANSLATORS: this referes to date. eg: To: Wendsday, 9 March 2016
1537+#: ../NewEvent.qml:457
1538 msgid "From"
1539 msgstr ""
1540
1541-#: ../NewEvent.qml:451
1542+#. TRANSLATORS: this referes to date. eg: From: Wendsday, 9 March 2016
1543+#: ../NewEvent.qml:471
1544 msgid "To"
1545 msgstr ""
1546
1547-#: ../NewEvent.qml:468
1548+#: ../NewEvent.qml:487
1549 msgid "All day event"
1550 msgstr ""
1551
1552-#: ../NewEvent.qml:497
1553+#: ../NewEvent.qml:517 ../NewEvent.qml:624
1554+msgid "Event details"
1555+msgstr ""
1556+
1557+#: ../NewEvent.qml:527
1558 msgid "Event Name"
1559 msgstr ""
1560
1561-#: ../NewEvent.qml:534
1562+#: ../NewEvent.qml:556
1563 msgid "Location"
1564 msgstr ""
1565
1566 #: ../NewEvent.qml:589
1567-msgid "Guests"
1568+msgid "Choose calendar"
1569 msgstr ""
1570
1571-#: ../NewEvent.qml:598
1572-msgid "Add Guest"
1573+#: ../NewEventBottomEdge.qml:53
1574+msgid "New Event"
1575 msgstr ""
1576
1577 #: ../RecurrenceLabelDefines.qml:23
1578@@ -466,19 +467,19 @@
1579 "about them"
1580 msgstr ""
1581
1582-#: ../calendar.qml:312 ../calendar.qml:492
1583+#: ../calendar.qml:316 ../calendar.qml:496
1584 msgid "Year"
1585 msgstr ""
1586
1587-#: ../calendar.qml:320 ../calendar.qml:513
1588+#: ../calendar.qml:324 ../calendar.qml:517
1589 msgid "Month"
1590 msgstr ""
1591
1592-#: ../calendar.qml:328 ../calendar.qml:534
1593+#: ../calendar.qml:332 ../calendar.qml:538
1594 msgid "Week"
1595 msgstr ""
1596
1597-#: ../calendar.qml:336 ../calendar.qml:555
1598+#: ../calendar.qml:340 ../calendar.qml:559
1599 msgid "Day"
1600 msgstr ""
1601

Subscribers

People subscribed via source and target branches

to status/vote changes: