Merge lp:~pkunal-parmar/ubuntu-calendar-app/Refactoring into lp:ubuntu-calendar-app
- Refactoring
- Merge into trunk
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 |
Related bugs: |
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
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
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.
Olivier Tilloy (osomon) wrote : | # |
212 + property Flickable flickbleChild;
Typo: flickble
- 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.
Olivier Tilloy (osomon) wrote : | # |
735 === added file 'TimeSeperator.qml'
Typo: the component should be name TimeSeparator.qml
Olivier Tilloy (osomon) wrote : | # |
742 + id: separator
this id is unused, you can remove it
Olivier Tilloy (osomon) wrote : | # |
158 - id: seperator
161 + id: seperator
165 - anchors.
167 + anchors.
Trailing whitespaces have been added to those lines, please remove them.
Olivier Tilloy (osomon) wrote : | # |
675 + var separator = separatorCompon
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.createCompon
var separator = component.
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.
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).
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://
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://
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".
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.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:41
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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.
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.
Olivier Tilloy (osomon) wrote : | # |
807 + onStateChanged: {
808 + if( state == "EXPANDED") {
809 + monthView.
810 + yBehavior.enabled = true
811 + } else if( state == "COMPRESSED") {
812 + monthView.
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.
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.
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: eventViewDelega
value: eventView.state
}
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:45
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Olivier Tilloy (osomon) wrote : | # |
807 + onStateChanged: {
808 + monthView.
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"
[…]
}
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:46
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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
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.
- 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
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 |
PASSED: Continuous integration, rev:35 91.189. 93.125: 8080/job/ ubuntu- calendar- app-ci/ 17/ 91.189. 93.125: 8080/job/ ubuntu- calendar- app-raring- amd64-ci/ 17
http://
Executed test runs:
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.125: 8080/job/ ubuntu- calendar- app-ci/ 17/rebuild
http://