Merge lp:~pkunal-parmar/ubuntu-calendar-app/Refactoring into lp:ubuntu-calendar-app

Proposed by Kunal Parmar
Status: Merged
Approved by: Olivier Tilloy
Approved revision: no longer in the source branch.
Merged at revision: 44
Proposed branch: lp:~pkunal-parmar/ubuntu-calendar-app/Refactoring
Merge into: lp:ubuntu-calendar-app
Diff against target: 811 lines (+325/-360)
7 files modified
DiaryView.qml (+34/-75)
DiaryViewDelegate.qml (+4/-6)
EventView.qml (+12/-11)
EventViewBase.qml (+70/-0)
TimeLineView.qml (+191/-244)
TimeSeparator.qml (+7/-0)
calendar.qml (+7/-24)
To merge this branch: bzr merge lp:~pkunal-parmar/ubuntu-calendar-app/Refactoring
Reviewer Review Type Date Requested Status
Olivier Tilloy (community) Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Review via email: mp+166263@code.launchpad.net

Commit message

Moved common code between DiaryView and TimeLineView to command EventViewBase QML.
Used state instead of property in EventViewBase

Description of the change

Moved common code between DiaryView and TimeLineView to command EventViewBase QML.
Used state instead of property in EventViewBase

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

761 - onExpand: {
762 + onExpand: {

767 - onCompress: {
768 + onCompress: {

The diff appends trailing whitespaces to those two lines, please revert the change.

review: Needs Fixing
Revision history for this message
Olivier Tilloy (osomon) wrote :

212 + property Flickable flickbleChild;

Typo: flickble

review: Needs Fixing
36. By Omer Akram

Initial autopilot structure.

Approved by Ubuntu Phone Apps Jenkins Bot, Olivier Tilloy.

37. By Launchpad Translations on behalf of ubuntu-calendar-dev

Launchpad automatic translations update.

Revision history for this message
Olivier Tilloy (osomon) wrote :

735 === added file 'TimeSeperator.qml'

Typo: the component should be name TimeSeparator.qml

review: Needs Fixing
Revision history for this message
Olivier Tilloy (osomon) wrote :

742 + id: separator

this id is unused, you can remove it

Revision history for this message
Olivier Tilloy (osomon) wrote :

158 - id: seperator
161 + id: seperator

165 - anchors.horizontalCenter: parent.horizontalCenter
167 + anchors.horizontalCenter: parent.horizontalCenter

Trailing whitespaces have been added to those lines, please remove them.

review: Needs Fixing
Revision history for this message
Olivier Tilloy (osomon) wrote :

675 + var separator = separatorComponent.createObject(bubbleOverLay);

This could be simplified and made more efficient by removing the need for the Component instance:

    var x = …
    var y = …
    var properties = {"x": x, "y": y, "visible": true}
    var component = Qt.createComponent("TimeSeperator.qml")
    var separator = component.createObject(bubbleOverLay, properties)

review: Needs Fixing
Revision history for this message
Olivier Tilloy (osomon) wrote :

> var properties = {"x": x, "y": y, "visible": true}

By the way, on an item visible is True by default, so this last property is useless, it can be removed.

Revision history for this message
Olivier Tilloy (osomon) wrote :

In EventView.qml, you should get rid of the expand() and compress() signals, and replace them by using the states only (use a Binding element to connect the state of the eventViewDelegate’s item to that of the eventView item).

review: Needs Fixing
Revision history for this message
Olivier Tilloy (osomon) wrote :

To make the code more readable, instead of explicitly triggering state changes upon contentYChanged or draggingChanged, use the 'when' property of the states (http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick2-state.html#when-prop).

38. By Launchpad Translations on behalf of ubuntu-calendar-dev

Launchpad automatic translations update.

39. By Launchpad Translations on behalf of ubuntu-calendar-dev

Launchpad automatic translations update.

Revision history for this message
Kunal Parmar (pkunal-parmar) wrote :

> To make the code more readable, instead of explicitly triggering state changes
> upon contentYChanged or draggingChanged, use the 'when' property of the states
> (http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick2-state.html#when-prop).

I tried to use this, but failed, mostly I got "Binding loop detected for property "when"" error.
I am not sure how this "when" works, but we want expand() and compress() to be called on the first time when Dragging and ContentY changes. Not sure how that can be captured with "when".

Revision history for this message
Kunal Parmar (pkunal-parmar) wrote :

I addressed your comments, but i was facing problem implementing your suggestion for removing explicit state changes on dragging and contentY change. It detects loop there.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
40. By Launchpad Translations on behalf of ubuntu-calendar-dev

Launchpad automatic translations update.

41. By Launchpad Translations on behalf of ubuntu-calendar-dev

Launchpad automatic translations update.

Revision history for this message
Olivier Tilloy (osomon) wrote :

192 + property string previousItemState: "COMPRESSED";

I’m not sure I understand what this property is for? If the goal is to ensure that all the delegates get the same state, then it’s not working. In that case, you’d need to define a 'delegateState' property on eventView, so that all delegates’ states are bound to it.

Revision history for this message
Olivier Tilloy (osomon) wrote :

> I addressed your comments, but i was facing problem implementing your
> suggestion for removing explicit state changes on dragging and contentY
> change. It detects loop there.

Could you share the code you were testing? Maybe I can lend a hand there.

Revision history for this message
Olivier Tilloy (osomon) wrote :

807 + onStateChanged: {
808 + if( state == "EXPANDED") {
809 + monthView.compressed = true
810 + yBehavior.enabled = true
811 + } else if( state == "COMPRESSED") {
812 + monthView.compressed = false
813 + }
814 }

Instead of the above, inside monthView, just set the value of 'compressed' to be (eventView.state == "EXPANDED"), and the same for the value of 'enabled' inside yBehavior.

review: Needs Fixing
42. By Launchpad Translations on behalf of ubuntu-calendar-dev

Launchpad automatic translations update.

43. By Launchpad Translations on behalf of ubuntu-calendar-dev

Launchpad automatic translations update.

Revision history for this message
Kunal Parmar (pkunal-parmar) wrote :

> 192 + property string previousItemState: "COMPRESSED";
>
> I’m not sure I understand what this property is for? If the goal is to ensure
> that all the delegates get the same state, then it’s not working. In that
> case, you’d need to define a 'delegateState' property on eventView, so that
> all delegates’ states are bound to it.

previousItemState property's intention was to preserve state, when going from DiaryView to TimeLineView.
But you are right, we also need to preserve state when we change day by scrolling, this I overlooked.

Revision history for this message
Kunal Parmar (pkunal-parmar) wrote :

> > 192 + property string previousItemState: "COMPRESSED";
> >
> > I’m not sure I understand what this property is for? If the goal is to
> ensure
> > that all the delegates get the same state, then it’s not working. In that
> > case, you’d need to define a 'delegateState' property on eventView, so that
> > all delegates’ states are bound to it.
>
> previousItemState property's intention was to preserve state, when going from
> DiaryView to TimeLineView.
> But you are right, we also need to preserve state when we change day by
> scrolling, this I overlooked.

This approach was not working, To resolve I put a reverse binding from EventView to Delegate so all delegate share the same state,
It also works when you change from DiaryView to TimeLineView.

        //share state from eventview to delegate, so that all delegate share the same state
        Binding{
            target: eventViewDelegate.item
            property: "state"
            value: eventView.state
        }

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Olivier Tilloy (osomon) wrote :

807 + onStateChanged: {
808 + monthView.compressed = (eventView.state == "EXPANDED");
809 }

As I was suggesting in a previous comment, this should be removed, and *inside* the MonthView instance, set the value of 'compressed':

    MonthView {
        […]
        compressed: eventView.state == "EXPANDED"
        […]
    }

review: Needs Fixing
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Kunal Parmar (pkunal-parmar) wrote :

> > I addressed your comments, but i was facing problem implementing your
> > suggestion for removing explicit state changes on dragging and contentY
> > change. It detects loop there.
>
> Could you share the code you were testing? Maybe I can lend a hand there.

I tried to resolve the errors, but still could not achieve required behavior.
I pushed code here

 lp:~pkunal-parmar/ubuntu-calendar-app/JUNK

Please have a look, most code change is in EventViewBase

Revision history for this message
Olivier Tilloy (osomon) wrote :

> > > I addressed your comments, but i was facing problem implementing your
> > > suggestion for removing explicit state changes on dragging and contentY
> > > change. It detects loop there.
> >
> > Could you share the code you were testing? Maybe I can lend a hand there.
>
> I tried to resolve the errors, but still could not achieve required behavior.
> I pushed code here
>
> lp:~pkunal-parmar/ubuntu-calendar-app/JUNK
>
> Please have a look, most code change is in EventViewBase

Ok, let’s not delay merging this branch any longer, it’s already a good improvement over the current trunk.
I’m convinced we can improve further the handling of states (in particular, it looks to me like we can get rid of the "EXPANDING" and "COMPRESSING" states), but let’s do that in another iteration.

review: Approve
44. By Kunal Parmar

Moved common code between DiaryView and TimeLineView to command EventViewBase QML.
Used state instead of property in EventViewBase.

Approved by Olivier Tilloy, Ubuntu Phone Apps Jenkins Bot.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'DiaryView.qml'
2--- DiaryView.qml 2013-05-17 02:11:27 +0000
3+++ DiaryView.qml 2013-06-10 11:03:26 +0000
4@@ -5,84 +5,43 @@
5 import "dateExt.js" as DateExt
6 import "colorUtils.js" as Color
7
8-ListView {
9- id: diaryView
10-
11- property var dayStart: new Date()
12-
13- property bool expanded: false
14-
15- property bool expanding: false
16- property bool compressing: false
17-
18- signal expand()
19- signal compress()
20- signal newEvent()
21-
22- clip: true
23-
24- model: EventListModel {
25- id: eventModel
26- termStart: dayStart
27- termLength: Date.msPerDay
28- }
29-
30- section {
31- property: "category"
32- // labelPositioning: ViewSection.CurrentLabelAtStart // FIXME, unreliable
33- delegate: ListItem.Header {
34- text: i18n.tr(section)
35- MouseArea {
36- anchors.fill: parent
37- onClicked: {
38- if (expanded)
39- compress()
40- else
41- expand()
42+EventViewBase{
43+ id: root
44+
45+ flickableChild: diaryView
46+
47+ ListView {
48+ id: diaryView
49+
50+ model: root.eventModel
51+ anchors.fill: parent
52+
53+ section {
54+ property: "category"
55+ // labelPositioning: ViewSection.CurrentLabelAtStart // FIXME, unreliable
56+ delegate: ListItem.Header {
57+ text: i18n.tr(section)
58+ MouseArea {
59+ anchors.fill: parent
60+ onClicked: {
61+ if (expanded)
62+ compress()
63+ else
64+ expand()
65+ }
66 }
67 }
68 }
69- }
70-
71- delegate: DiaryViewDelegate{
72- onClicked: {
73- pageStack.push(Qt.resolvedUrl("EventDetails.qml"),{event:diaryView.model.get(index)});
74- }
75- }
76-
77- footer: ListItem.Standard {
78- text: i18n.tr("(+) New Event")
79- onClicked: newEvent()
80- }
81-
82- onContentYChanged: {
83- // console.log(expanded, expanding, compressing, dragging, flicking, moving, contentY)
84- if (expanding || compressing || !dragging) return
85-
86- if (expanded) {
87- if (contentY < -units.gu(0.5)) {
88- compressing = true
89- expanding = false
90- }
91- }
92- else {
93- if (contentY < -units.gu(0.5)) {
94- expanding = true
95- compressing = false
96- }
97- }
98- }
99-
100- onDraggingChanged: {
101- if (dragging) return
102-
103- if (expanding) {
104- expanding = false
105- expand()
106- }
107- else if (compressing) {
108- compressing = false
109- compress()
110+
111+ delegate: DiaryViewDelegate{
112+ onClicked: {
113+ pageStack.push(Qt.resolvedUrl("EventDetails.qml"),{event:diaryView.model.get(index)});
114+ }
115+ }
116+
117+ footer: ListItem.Standard {
118+ text: i18n.tr("(+) New Event")
119+ onClicked: newEvent()
120 }
121 }
122 }
123
124=== modified file 'DiaryViewDelegate.qml'
125--- DiaryViewDelegate.qml 2013-04-21 07:52:56 +0000
126+++ DiaryViewDelegate.qml 2013-06-10 11:03:26 +0000
127@@ -21,14 +21,14 @@
128 function showEventData() {
129 // FIXME: remove test value, need to decide what to do if there is no location, hide it ?
130 var venues = [{"name":"Test Venue"}]
131- DataService.getVenues(eventModel.get(index), venues)
132+ DataService.getVenues(diaryView.model.get(index), venues)
133 if( venues.length > 0 ) {
134 locationLabel.text = venues[0].name;
135 }
136
137 // FIXME: remove test value, need to decide what to do if there are no attendees, hide it ?
138 var attendees = ["Test One","Test Two"]
139- DataService.getAttendees(eventModel.get(index),attendees)
140+ DataService.getAttendees(diaryView.model.get(index),attendees)
141 attendeeLabel.text = attendees.toString();
142 }
143
144@@ -36,7 +36,7 @@
145 collapse(true);
146
147 var now = new Date;
148- var lastEvent = eventModel.get(index-1);
149+ var lastEvent = diaryView.model.get(index-1);
150
151 if( endTime >= now
152 && (lastEvent === undefined || lastEvent.endTime < now )
153@@ -54,14 +54,12 @@
154 height: eventRoot.height + seperator.height + (seperator.visible ? units.gu(1.5) : units.gu(0.5)) /*margins*/
155 width: parent.width
156
157- Rectangle {
158+ TimeSeparator {
159 id: seperator
160- height: units.gu(0.5)
161 width: delegateRoot.width - units.gu(2)
162 anchors.top: parent.top
163 anchors.topMargin: units.gu(1)
164 anchors.horizontalCenter: parent.horizontalCenter
165- color: "#c94212"
166 visible: false
167 }
168
169
170=== modified file 'EventView.qml'
171--- EventView.qml 2013-05-18 02:16:07 +0000
172+++ EventView.qml 2013-06-10 11:03:26 +0000
173@@ -11,14 +11,8 @@
174 signal incrementCurrentDay
175 signal decrementCurrentDay
176
177- property bool expanded: false
178-
179- signal compress()
180- signal expand()
181 signal newEvent()
182
183- readonly property real visibleHeight: parent.height - y
184-
185 QtObject {
186 id: intern
187 property int currentIndexSaved: 0
188@@ -74,8 +68,6 @@
189 }
190
191 onLoaded: {
192- item.expand.connect(eventView.expand);
193- item.compress.connect(eventView.compress);
194 item.newEvent.connect(eventView.newEvent);
195 }
196
197@@ -85,10 +77,19 @@
198 value: eventViewDelegate.dayStart
199 }
200
201+ //share state from delegate to eventView, if state change is from current delegate
202 Binding {
203- target: item
204- property: "expanded"
205- value: eventView.expanded
206+ target: eventView
207+ property: "state"
208+ value: eventViewDelegate.item.state;
209+ when: index == eventView.currentIndex
210+ }
211+
212+ //share state from eventview to delegate, so that all delegate share the same state
213+ Binding{
214+ target: eventViewDelegate.item
215+ property: "state"
216+ value: eventView.state
217 }
218 }
219 }
220
221=== added file 'EventViewBase.qml'
222--- EventViewBase.qml 1970-01-01 00:00:00 +0000
223+++ EventViewBase.qml 2013-06-10 11:03:26 +0000
224@@ -0,0 +1,70 @@
225+import QtQuick 2.0
226+import Ubuntu.Components 0.1
227+
228+import "dateExt.js" as DateExt
229+import "colorUtils.js" as Color
230+
231+Item {
232+ id: baseView
233+
234+ property var dayStart: new Date()
235+ property alias eventModel: model;
236+ property Flickable flickableChild;
237+
238+ state: "COMPRESSED"
239+
240+ signal newEvent()
241+ signal modelRefreshed();
242+
243+ clip: true
244+
245+ EventListModel {
246+ id: model
247+ termStart: dayStart
248+ termLength: Date.msPerDay
249+
250+ onReload: {
251+ modelRefreshed();
252+ }
253+ }
254+
255+ Connections{
256+ target: flickableChild
257+
258+ onContentYChanged: {
259+ if (state == "COMPRESSING" || state == "EXPANDING" || !flickableChild.dragging ) return
260+
261+ if ( state == "EXPANDED" && flickableChild.contentY < -units.gu(0.5) ) {
262+ state = "COMPRESSING";
263+ }
264+ else if (flickableChild.contentY < -units.gu(0.5)) {
265+ state = "EXPANDING";
266+ }
267+ }
268+
269+ onDraggingChanged: {
270+ if (flickableChild.dragging) return;
271+
272+ if( state == "EXPANDING" ) {
273+ state = "EXPANDED";
274+ } else if ( state == "COMPRESSING") {
275+ state = "COMPRESSED";
276+ }
277+ }
278+ }
279+
280+ states: [
281+ State {
282+ name: "EXPANDING"
283+ },
284+ State {
285+ name: "COMPRESSING"
286+ },
287+ State {
288+ name: "EXPANDED"
289+ },
290+ State {
291+ name: "COMPRESSED"
292+ }
293+ ]
294+}
295
296=== modified file 'TimeLineView.qml'
297--- TimeLineView.qml 2013-05-23 14:02:01 +0000
298+++ TimeLineView.qml 2013-06-10 11:03:26 +0000
299@@ -4,256 +4,203 @@
300 import "dateExt.js" as DateExt
301 import "dataService.js" as DataService
302
303-
304-Flickable{
305- id: timeLineView
306-
307- property var dayStart : new Date();
308-
309- property bool expanded: false
310- property bool expanding: false
311- property bool compressing: false
312-
313- signal expand()
314- signal compress()
315- signal newEvent()
316-
317- function scroll() {
318- //scroll to first event or current hour
319- var hour = intern.now.getHours();
320- if(eventListModel.count > 0) {
321- hour = eventListModel.get(0).startTime.getHours();
322- }
323-
324- timeLineView.contentY = hour * units.gu(10);
325-
326- if(timeLineView.contentY >= timeLineView.contentHeight - timeLineView.height) {
327- timeLineView.contentY = timeLineView.contentHeight - timeLineView.height
328- }
329- }
330-
331- function createEventMap() {
332- var eventMap = {};
333- for(var i = 0 ; i < eventListModel.count ; ++i) {
334- var event = eventListModel.get(i);
335- eventMap[event.startTime.getHours()] = event
336- }
337- return eventMap;
338- }
339-
340- function createEvents() {
341- intern.eventMap = createEventMap();
342-
343- bubbleOverLay.destroyAllChildren();
344-
345- for( var i=0; i < 24; ++i ) {
346- var event = intern.eventMap[i];
347- if( event ) {
348- bubbleOverLay.createEvent(event,i);
349- } else if( i === intern.now.getHours()
350- && intern.now.isSameDay( timeLineView.dayStart )) {
351- bubbleOverLay.createSeparator(i);
352- }
353- }
354-
355- scroll();
356- }
357-
358- function showEventDetails(hour) {
359- var event = intern.eventMap[hour];
360- pageStack.push(Qt.resolvedUrl("EventDetails.qml"),{"event":event});
361- }
362-
363- onContentYChanged: {
364- // console.log(expanded, expanding, compressing, dragging, flicking, moving, contentY)
365- if (expanding || compressing || !dragging) return
366-
367- if (expanded) {
368- if (contentY < -units.gu(0.5)) {
369- compressing = true
370- expanding = false
371- }
372- }
373- else {
374- if (contentY < -units.gu(0.5)) {
375- expanding = true
376- compressing = false
377- }
378- }
379- }
380-
381- onDraggingChanged: {
382- if (dragging) return
383-
384- if (expanding) {
385- expanding = false
386- expand()
387- }
388- else if (compressing) {
389- compressing = false
390- compress()
391- }
392- }
393-
394- clip: true
395-
396- contentHeight: timeLineColumn.height + units.gu(3)
397- contentWidth: width
398-
399- QtObject {
400- id: intern
401- property var eventMap;
402- property var now : new Date();
403- property var hourHeight : units.gu(10)
404- }
405-
406- EventListModel {
407- id: eventListModel
408- termStart: timeLineView.dayStart
409- termLength: Date.msPerDay
410-
411- onReload: {
412- createEvents();
413- }
414- }
415-
416- Rectangle{
417- id: background; anchors.fill: parent
418- color: "white"
419- }
420-
421- //Time line view
422- Column{
423- id: timeLineColumn
424- anchors.top: parent.top
425- anchors.topMargin: units.gu(3)
426- width: parent.width
427-
428- Repeater{
429- model: 24 // hour in a day
430-
431- delegate: Item {
432- id: delegate
433- width: parent.width
434- height: intern.hourHeight
435-
436- Row {
437+EventViewBase{
438+ id: root
439+
440+ flickableChild: timeLineView
441+
442+ onModelRefreshed: {
443+ timeLineView.createEvents();
444+ }
445+
446+ Flickable{
447+ id: timeLineView
448+ anchors.fill: parent
449+
450+ function scroll() {
451+ //scroll to first event or current hour
452+ var hour = intern.now.getHours();
453+ if( eventModel.count > 0) {
454+ hour = eventModel.get(0).startTime.getHours();
455+ }
456+
457+ timeLineView.contentY = hour * intern.hourHeight;
458+
459+ if(timeLineView.contentY >= timeLineView.contentHeight - timeLineView.height) {
460+ timeLineView.contentY = timeLineView.contentHeight - timeLineView.height
461+ }
462+ }
463+
464+ function createEventMap() {
465+ var eventMap = {};
466+ for(var i = 0 ; i < eventModel.count ; ++i) {
467+ var event = eventModel.get(i);
468+ eventMap[event.startTime.getHours()] = event
469+ }
470+ return eventMap;
471+ }
472+
473+ function createEvents() {
474+ intern.eventMap = createEventMap();
475+
476+ bubbleOverLay.destroyAllChildren();
477+
478+ for( var i=0; i < 24; ++i ) {
479+ var event = intern.eventMap[i];
480+ if( event ) {
481+ bubbleOverLay.createEvent(event,i);
482+ } else if( i === intern.now.getHours()
483+ && intern.now.isSameDay( root.dayStart )) {
484+ bubbleOverLay.createSeparator(i);
485+ }
486+ }
487+
488+ scroll();
489+ }
490+
491+ function showEventDetails(hour) {
492+ var event = intern.eventMap[hour];
493+ pageStack.push(Qt.resolvedUrl("EventDetails.qml"),{"event":event});
494+ }
495+
496+ contentHeight: timeLineColumn.height + units.gu(3)
497+ contentWidth: width
498+
499+ QtObject {
500+ id: intern
501+ property var eventMap;
502+ property var now : new Date();
503+ property var hourHeight : units.gu(10)
504+ }
505+
506+ Rectangle{
507+ id: background; anchors.fill: parent
508+ color: "white"
509+ }
510+
511+ //Time line view
512+ Column{
513+ id: timeLineColumn
514+ anchors.top: parent.top
515+ anchors.topMargin: units.gu(3)
516+ width: parent.width
517+
518+ Repeater{
519+ model: 24 // hour in a day
520+
521+ delegate: Item {
522+ id: delegate
523 width: parent.width
524- y: -timeLabel.height/2
525- Label{
526- id: timeLabel
527- // TRANSLATORS: this is a time formatting string,
528- // see http://qt-project.org/doc/qt-5.0/qtqml/qml-qtquick2-date.html#details for valid expressions
529- text: new Date(0, 0, 0, index).toLocaleTimeString(Qt.locale(), i18n.tr("HH:mm"))
530- color:"gray"
531- anchors.top: parent.top
532+ height: intern.hourHeight
533+
534+ Row {
535+ width: parent.width
536+ y: -timeLabel.height/2
537+ Label{
538+ id: timeLabel
539+ // TRANSLATORS: this is a time formatting string,
540+ // see http://qt-project.org/doc/qt-5.0/qtqml/qml-qtquick2-date.html#details for valid expressions
541+ text: new Date(0, 0, 0, index).toLocaleTimeString(Qt.locale(), i18n.tr("HH:mm"))
542+ color:"gray"
543+ anchors.top: parent.top
544+ }
545+ Rectangle{
546+ width: parent.width -timeLabel.width
547+ height:units.dp(1)
548+ color:"gray"
549+ anchors.verticalCenter: parent.verticalCenter
550+ }
551 }
552+
553 Rectangle{
554- width: parent.width -timeLabel.width
555+ width: parent.width - units.gu(5)
556 height:units.dp(1)
557 color:"gray"
558 anchors.verticalCenter: parent.verticalCenter
559- }
560- }
561-
562- Rectangle{
563- width: parent.width - units.gu(5)
564- height:units.dp(1)
565- color:"gray"
566- anchors.verticalCenter: parent.verticalCenter
567- anchors.horizontalCenter: parent.horizontalCenter
568- }
569- }
570- }
571- }
572-
573- Item {
574- id: bubbleOverLay
575-
576- width: timeLineColumn.width
577- height: timeLineColumn.height
578- anchors.top: parent.top
579- anchors.topMargin: units.gu(3)
580-
581- function destroyAllChildren() {
582- for( var i = children.length - 1; i >= 0; --i ) {
583- children[i].destroy();
584- }
585- }
586-
587- function createEvent( event ,hour) {
588- var eventBubble = infoBubbleComponent.createObject(bubbleOverLay);
589- eventBubble.title = event.title;
590- eventBubble.location = "test";
591- eventBubble.hour = hour;
592-
593- var yPos = (( event.startTime.getMinutes() * intern.hourHeight) / 60) + hour * intern.hourHeight
594- eventBubble.y = yPos;
595-
596- var durationMin = (event.endTime.getHours() - event.startTime.getHours()) * 60;
597- durationMin += (event.endTime.getMinutes() - event.startTime.getMinutes());
598- var height = (durationMin * intern.hourHeight )/ 60;
599- eventBubble.height = height;
600- }
601-
602- function createSeparator(hour) {
603- var separator = separatorComponent.createObject(bubbleOverLay);
604- var yPos = ((intern.now.getMinutes() * intern.hourHeight) / 60) + hour * intern.hourHeight
605- separator.visible = true;
606- separator.y = yPos;
607- separator.x = (parent.width - separator.width)/2
608- }
609- }
610-
611- Component{
612- id: infoBubbleComponent
613- Rectangle{
614- id: infoBubble
615-
616- property string title;
617- property string location;
618- property int hour;
619-
620- color:'#fffdaa';
621- width: timeLineView.width - units.gu(8)
622- x: units.gu(5)
623-
624- border.color: "#f4d690"
625-
626- Column{
627- id: column
628- anchors {
629- left: parent.left
630- right: parent.right
631- top: parent.top
632-
633- leftMargin: units.gu(1)
634- rightMargin: units.gu(1)
635- topMargin: units.gu(1)
636- }
637- spacing: units.gu(1)
638- Label{text:infoBubble.title;fontSize:"medium";color:"black"}
639- Label{text:infoBubble.location; fontSize:"small"; color:"black"}
640- }
641-
642- MouseArea{
643- anchors.fill: parent
644- onClicked: {
645- timeLineView.showEventDetails(hour);
646- }
647- }
648- }
649- }
650-
651- Component {
652- id: separatorComponent
653- Rectangle {
654- id: separator
655- height: units.gu(0.5)
656- width: timeLineView.width - units.gu(2)
657- color: "#c94212"
658- visible: false
659+ anchors.horizontalCenter: parent.horizontalCenter
660+ }
661+ }
662+ }
663+ }
664+
665+ Item {
666+ id: bubbleOverLay
667+
668+ width: timeLineColumn.width
669+ height: timeLineColumn.height
670+ anchors.top: parent.top
671+ anchors.topMargin: units.gu(3)
672+
673+ function destroyAllChildren() {
674+ for( var i = children.length - 1; i >= 0; --i ) {
675+ children[i].destroy();
676+ }
677+ }
678+
679+ function createEvent( event ,hour) {
680+ var eventBubble = infoBubbleComponent.createObject(bubbleOverLay);
681+ eventBubble.title = event.title;
682+ eventBubble.location = "test";
683+ eventBubble.hour = hour;
684+
685+ var yPos = (( event.startTime.getMinutes() * intern.hourHeight) / 60) + hour * intern.hourHeight
686+ eventBubble.y = yPos;
687+
688+ var durationMin = (event.endTime.getHours() - event.startTime.getHours()) * 60;
689+ durationMin += (event.endTime.getMinutes() - event.startTime.getMinutes());
690+ var height = (durationMin * intern.hourHeight )/ 60;
691+ eventBubble.height = height;
692+ }
693+
694+ function createSeparator(hour) {
695+ var w = timeLineView.width - units.gu(2);
696+ var y = ((intern.now.getMinutes() * intern.hourHeight) / 60) + hour * intern.hourHeight;
697+ var x = (parent.width - w)/ 2;
698+ var properties = {"x": x, "y": y, "width": w}
699+
700+ var component = Qt.createComponent("TimeSeparator.qml");
701+ var separator = component.createObject(bubbleOverLay, properties);
702+ }
703+ }
704+
705+ Component{
706+ id: infoBubbleComponent
707+ Rectangle{
708+ id: infoBubble
709+
710+ property string title;
711+ property string location;
712+ property int hour;
713+
714+ color:'#fffdaa';
715+ width: timeLineView.width - units.gu(8)
716+ x: units.gu(5)
717+
718+ border.color: "#f4d690"
719+
720+ Column{
721+ id: column
722+ anchors {
723+ left: parent.left
724+ right: parent.right
725+ top: parent.top
726+
727+ leftMargin: units.gu(1)
728+ rightMargin: units.gu(1)
729+ topMargin: units.gu(1)
730+ }
731+ spacing: units.gu(1)
732+ Label{text:infoBubble.title;fontSize:"medium";color:"black"}
733+ Label{text:infoBubble.location; fontSize:"small"; color:"black"}
734+ }
735+
736+ MouseArea{
737+ anchors.fill: parent
738+ onClicked: {
739+ timeLineView.showEventDetails(hour);
740+ }
741+ }
742+ }
743 }
744 }
745 }
746-
747
748=== added file 'TimeSeparator.qml'
749--- TimeSeparator.qml 1970-01-01 00:00:00 +0000
750+++ TimeSeparator.qml 2013-06-10 11:03:26 +0000
751@@ -0,0 +1,7 @@
752+import QtQuick 2.0
753+
754+Rectangle {
755+ id: separator
756+ height: units.gu(0.5)
757+ color: "#c94212"
758+}
759
760=== modified file 'calendar.qml'
761--- calendar.qml 2013-05-23 12:31:50 +0000
762+++ calendar.qml 2013-06-10 11:03:26 +0000
763@@ -81,42 +81,25 @@
764 //y: units.gu(9.5) // FIXME
765 onMovementEnded: eventView.currentDayStart = currentDayStart
766 onCurrentDayStartChanged: if (!(dragging || flicking)) eventView.currentDayStart = currentDayStart
767- Component.onCompleted: eventView.currentDayStart = currentDayStart
768+ Component.onCompleted: eventView.currentDayStart = currentDayStart
769+ compressed: (eventView.state == "EXPANDED")
770+ Behavior on height {
771+ NumberAnimation { duration: 100 }
772+ }
773 }
774
775 EventView {
776 id: eventView
777
778- property real minY: monthView.y + monthView.compressedHeight
779- property real maxY: monthView.y + monthView.expandedHeight
780-
781- y: maxY
782+ height: parent.height - monthView.height
783 width: mainView.width
784- height: parent.height - y
785-
786- expanded: monthView.compressed
787+ anchors.top: monthView.bottom
788
789 Component.onCompleted: {
790 incrementCurrentDay.connect(monthView.incrementCurrentDay)
791 decrementCurrentDay.connect(monthView.decrementCurrentDay)
792 }
793
794- onExpand: {
795- monthView.compressed = true
796- yBehavior.enabled = true
797- y = minY
798- }
799- onCompress: {
800- monthView.compressed = false
801- y = maxY
802- }
803-
804- Behavior on y {
805- id: yBehavior
806- enabled: false
807- NumberAnimation { duration: 100 }
808- }
809-
810 onNewEvent: monthViewPage.newEvent()
811 }
812

Subscribers

People subscribed via source and target branches

to status/vote changes: