Merge lp:~fboucault/unity-2d/proper_grid into lp:unity-2d/3.0
- proper_grid
- Merge into natty
Proposed by
Florian Boucault
Status: | Merged |
---|---|
Approved by: | Florian Boucault |
Approved revision: | 637 |
Merged at revision: | 650 |
Proposed branch: | lp:~fboucault/unity-2d/proper_grid |
Merge into: | lp:unity-2d/3.0 |
Diff against target: |
642 lines (+363/-135) 9 files modified
places/Home.qml (+22/-11) places/ListViewWithHeaders.qml (+277/-0) places/ListViewWithScrollbar.qml (+5/-29) places/PlaceEntryView.qml (+35/-20) places/Renderer.qml (+2/-2) places/RendererGrid.qml (+14/-71) places/Scrollbar.qml (+1/-1) places/UnityEmptySearchRenderer.qml (+1/-1) places/dash.qml (+6/-0) |
To merge this branch: | bzr merge lp:~fboucault/unity-2d/proper_grid |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gerry Boland | Pending | ||
Review via email: mp+69460@code.launchpad.net |
Commit message
Description of the change
[dash] Cleaned up grid widget by introducing ListViewWithHea
To post a comment you must log in.
- 635. By Florian Boucault
-
Added documentation.
- 636. By Florian Boucault
-
PlaceEntryView.qml: use bindings so that RendererGrid's properties are synced with its parents
- 637. By Florian Boucault
-
Unload the current page when closing the dash
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'places/Home.qml' |
2 | --- places/Home.qml 2011-07-26 16:36:51 +0000 |
3 | +++ places/Home.qml 2011-07-27 19:03:02 +0000 |
4 | @@ -99,17 +99,28 @@ |
5 | opacity: globalSearchActive ? 1 : 0 |
6 | anchors.fill: parent |
7 | |
8 | - list.model: dash.places |
9 | - |
10 | - list.delegate: UnityDefaultRenderer { |
11 | - width: ListView.view.width |
12 | - |
13 | - parentListView: list |
14 | - placeEntryModel: item |
15 | - displayName: item.name |
16 | - iconHint: item.icon |
17 | - |
18 | - model: item.globalResultsModel |
19 | + model: dash.places |
20 | + |
21 | + bodyDelegate: UnityDefaultRenderer { |
22 | + placeEntryModel: model.item |
23 | + displayName: model.item.name |
24 | + iconHint: model.item.icon |
25 | + |
26 | + group_model: model.item.globalResultsModel |
27 | + property bool focusable: group_model != undefined && group_model.count > 0 |
28 | + } |
29 | + |
30 | + headerDelegate: GroupHeader { |
31 | + visible: body.needHeader && body.focusable |
32 | + height: visible ? 32 : 0 |
33 | + |
34 | + property bool foldable: body.folded != undefined |
35 | + availableCount: foldable && body.group_model != null ? body.group_model.count - body.cellsPerRow : 0 |
36 | + folded: foldable ? body.folded : false |
37 | + onClicked: if(foldable) body.folded = !body.folded |
38 | + |
39 | + icon: body.iconHint |
40 | + label: body.displayName |
41 | } |
42 | } |
43 | |
44 | |
45 | === added file 'places/ListViewWithHeaders.qml' |
46 | --- places/ListViewWithHeaders.qml 1970-01-01 00:00:00 +0000 |
47 | +++ places/ListViewWithHeaders.qml 2011-07-27 19:03:02 +0000 |
48 | @@ -0,0 +1,277 @@ |
49 | +/* |
50 | + * This file is part of unity-2d |
51 | + * |
52 | + * Copyright 2010-2011 Canonical Ltd. |
53 | + * |
54 | + * This program is free software; you can redistribute it and/or modify |
55 | + * it under the terms of the GNU General Public License as published by |
56 | + * the Free Software Foundation; version 3. |
57 | + * |
58 | + * This program is distributed in the hope that it will be useful, |
59 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
60 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
61 | + * GNU General Public License for more details. |
62 | + * |
63 | + * You should have received a copy of the GNU General Public License |
64 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
65 | + */ |
66 | + |
67 | +import QtQuick 1.0 |
68 | + |
69 | +/* |
70 | + List item that behaves similarly to a ListView but supports adding headers |
71 | + before every delegate. |
72 | + It works around the lack of flexibility in section headers positioning of |
73 | + ListView (cf. http://bugreports.qt.nokia.com/browse/QTBUG-12880). It also |
74 | + supports delegates that are flickable by flicking their content properly |
75 | + depending on where you are in the list. |
76 | + |
77 | + To use it the following properties need to be set: |
78 | + - bodyDelegate: Component used as a template for each item of the model; it |
79 | + must have the following properties: |
80 | + - 'contentY': same definition as a Flickable's |
81 | + - 'totalHeight': the total height of the content of the body |
82 | + - 'currentItem': a reference to the item of the body (e.g. a delegate of |
83 | + a ListView) currently focused by the body |
84 | + - headerDelegate: Component used as a template for the header preceding each body |
85 | + |
86 | + Two behaviours are available for the headers positioning: |
87 | + - normal: the headers are always positioned just before the body |
88 | + - accordion: the headers are stacked at the top and bottom of the list |
89 | + |
90 | + Currently, it only works in a vertical layout. |
91 | +*/ |
92 | +FocusScope { |
93 | + id: list |
94 | + |
95 | + property alias flickable: mouse |
96 | + property alias model: repeater.model |
97 | + property bool accordion: false |
98 | + /* bodyDelegate must be an item that has the following properties: |
99 | + - 'contentY' |
100 | + - 'totalHeight' |
101 | + - 'currentItem' |
102 | + */ |
103 | + property Component bodyDelegate |
104 | + property Component headerDelegate |
105 | + property int currentIndex: -1 |
106 | + /* FIXME: Should be read-only but it is not possible to define a read-only property from QML. |
107 | + Ref.: https://bugreports.qt.nokia.com//browse/QTBUG-15257 |
108 | + */ |
109 | + property variant currentItem: items.childFromIndex(currentIndex) |
110 | + |
111 | + |
112 | + clip: true |
113 | + |
114 | + /* updateMouseContentY() needs to be called when any of the variable |
115 | + involved in the computation of the 'y' property of the currentSubItem changes. |
116 | + |
117 | + if accordion is false: |
118 | + - heightFirstChildren(index) |
119 | + - headerLoader.height |
120 | + - list.height |
121 | + |
122 | + if accordion is true: |
123 | + - heightFirstChildren(index) |
124 | + - items.availableHeight |
125 | + - heightFirstHeaders(index) |
126 | + |
127 | + items.contentHeight seems to depend on all of those so it's enough to |
128 | + depend only on it. |
129 | + */ |
130 | + function updateMouseContentY() { |
131 | + if (currentSubItem != undefined) { |
132 | + mouse.contentY = Math.max(currentSubItem.mapToItem(mouse.contentItem, 0, 0).y -list.height/2, 0) |
133 | + } |
134 | + } |
135 | + property variant currentSubItem: currentItem != undefined ? currentItem.bodyLoader.item.currentItem : undefined |
136 | + onCurrentSubItemChanged: updateMouseContentY() |
137 | + |
138 | + Connections { |
139 | + target: items |
140 | + onContentHeightChanged: updateMouseContentY() |
141 | + } |
142 | + |
143 | + FocusScope { |
144 | + id: items |
145 | + |
146 | + property int availableHeight: list.height - heightFirstHeaders(repeater.count) |
147 | + property int contentHeight: items.heightFirstChildren(repeater.count) |
148 | + property real value: mouse.contentY |
149 | + |
150 | + anchors.fill: parent |
151 | + |
152 | + function heightFirstChildren(n) { |
153 | + var i |
154 | + var totalHeight = 0 |
155 | + /* items.children contains both the repeated items and the repeater |
156 | + itself. Skip and ignore the repeater. */ |
157 | + for (i=0; i<n && i<children.length; i++) { |
158 | + if(children[i] == repeater) {n += 1; continue} |
159 | + totalHeight += children[i].height |
160 | + } |
161 | + return totalHeight |
162 | + } |
163 | + |
164 | + function heightFirstHeaders(n) { |
165 | + var i |
166 | + var totalHeight = 0 |
167 | + /* items.children contains both the repeated items and the repeater |
168 | + itself. Skip and ignore the repeater. */ |
169 | + for (i=0; i<n && i<children.length; i++) { |
170 | + if(children[i] == repeater) {n += 1; continue} |
171 | + totalHeight += children[i].headerLoader.height |
172 | + } |
173 | + return totalHeight |
174 | + } |
175 | + |
176 | + function clamp(x, min, max) { |
177 | + return Math.max(Math.min(x, max), min) |
178 | + } |
179 | + |
180 | + |
181 | + /* Keyboard navigation */ |
182 | + function isIndexValid(index) { |
183 | + /* Assuming that children contains exactly one item that is not a child (repeater) */ |
184 | + return index >= 0 && index < children.length-1 |
185 | + } |
186 | + |
187 | + focus: true |
188 | + Keys.onPressed: if (handleKeyPress(event.key)) event.accepted = true |
189 | + function handleKeyPress(key) { |
190 | + switch (key) { |
191 | + case Qt.Key_Down: |
192 | + return selectNextEnabled() |
193 | + case Qt.Key_Up: |
194 | + return selectPreviousEnabled() |
195 | + } |
196 | + } |
197 | + |
198 | + function childFromIndex(index) { |
199 | + var indexInChildren = 0 |
200 | + for(var i=0; i<children.length; i++) { |
201 | + if (children[i] != repeater) { |
202 | + if (indexInChildren == index) return children[i] |
203 | + indexInChildren++ |
204 | + } |
205 | + } |
206 | + |
207 | + return undefined |
208 | + } |
209 | + |
210 | + function selectNextEnabled() { |
211 | + var index = currentIndex |
212 | + do { |
213 | + index += 1 |
214 | + if (!isIndexValid(index)) return false |
215 | + } while(!childFromIndex(index).focusable) |
216 | + currentIndex = index |
217 | + return true |
218 | + } |
219 | + |
220 | + function selectPreviousEnabled() { |
221 | + var index = currentIndex |
222 | + do { |
223 | + index -= 1 |
224 | + if (!isIndexValid(index)) return false |
225 | + } while(!childFromIndex(index).focusable) |
226 | + currentIndex = index |
227 | + return true |
228 | + } |
229 | + |
230 | + property bool needsFocus: false |
231 | + onChildrenChanged: { |
232 | + /* FIXME: this workarounds the fact that list.focus is set to false |
233 | + when the child with focus is destroyed |
234 | + */ |
235 | + if (needsFocus) { |
236 | + list.focus = true |
237 | + needsFocus = false |
238 | + } |
239 | + /* Assuming that children contains exactly one item that is not a child (repeater) */ |
240 | + if(children.length <= 1) { |
241 | + list.currentIndex = -1 |
242 | + } else { |
243 | + list.currentIndex = -1 |
244 | + selectNextEnabled() |
245 | + } |
246 | + } |
247 | + |
248 | + Repeater { |
249 | + id: repeater |
250 | + |
251 | + FocusScope { |
252 | + property alias bodyLoader: bodyLoader |
253 | + property alias headerLoader: headerLoader |
254 | + |
255 | + focus: index == list.currentIndex |
256 | + Component.onDestruction: items.needsFocus = true |
257 | + |
258 | + width: list.width |
259 | + height: headerLoader.height + bodyLoader.item.totalHeight |
260 | + property bool focusable: bodyLoader.item.focusable |
261 | + |
262 | + property int pmin: pmax - (ymax - ymin) |
263 | + property int pmax: items.heightFirstChildren(index) - ymin |
264 | + property int ymin: list.accordion ? items.heightFirstHeaders(index) : -headerLoader.height |
265 | + property int ymax: list.accordion ? ymin + items.availableHeight : list.height |
266 | + y: items.clamp(-items.value + ymax + pmin, ymin, ymax) |
267 | + |
268 | + Loader { |
269 | + id: headerLoader |
270 | + |
271 | + focus: visible |
272 | + KeyNavigation.down: bodyLoader |
273 | + sourceComponent: headerDelegate |
274 | + onLoaded: item.focus = true |
275 | + width: parent.width |
276 | + |
277 | + /* Workaround Qt bug http://bugreports.qt.nokia.com/browse/QTBUG-18857 |
278 | + More documentation at http://bugreports.qt.nokia.com/browse/QTBUG-18011 |
279 | + */ |
280 | + property int index |
281 | + Binding { target: headerLoader; property: "index"; value: index } |
282 | + property variant model |
283 | + Binding { target: headerLoader; property: "model"; value: model } |
284 | + property variant body |
285 | + Binding { target: headerLoader; property: "body"; value: bodyLoader.item } |
286 | + } |
287 | + |
288 | + Loader { |
289 | + id: bodyLoader |
290 | + |
291 | + focus: !headerLoader.focus |
292 | + KeyNavigation.up: headerLoader |
293 | + sourceComponent: list.bodyDelegate |
294 | + onLoaded: item.focus = true |
295 | + width: parent.width |
296 | + anchors.top: headerLoader.bottom |
297 | + height: items.clamp(parent.ymax - parent.y, 0, item.totalHeight) |
298 | + |
299 | + Binding { |
300 | + target: bodyLoader.item |
301 | + property: "contentY" |
302 | + value: Math.max(items.value - pmax, 0) |
303 | + } |
304 | + |
305 | + /* Workaround Qt bug http://bugreports.qt.nokia.com/browse/QTBUG-18857 |
306 | + More documentation at http://bugreports.qt.nokia.com/browse/QTBUG-18011 |
307 | + */ |
308 | + property int index |
309 | + Binding { target: bodyLoader; property: "index"; value: index } |
310 | + property variant model |
311 | + Binding { target: bodyLoader; property: "model"; value: model } |
312 | + } |
313 | + } |
314 | + } |
315 | + } |
316 | + |
317 | + Flickable { |
318 | + id: mouse |
319 | + |
320 | + z: -1 |
321 | + anchors.fill: parent |
322 | + contentWidth: parent.width |
323 | + contentHeight: items.contentHeight |
324 | + } |
325 | +} |
326 | |
327 | === modified file 'places/ListViewWithScrollbar.qml' |
328 | --- places/ListViewWithScrollbar.qml 2011-06-23 17:08:53 +0000 |
329 | +++ places/ListViewWithScrollbar.qml 2011-07-27 19:03:02 +0000 |
330 | @@ -19,10 +19,12 @@ |
331 | import QtQuick 1.0 |
332 | |
333 | Item { |
334 | - property alias list: list |
335 | property alias scrollbar: scrollbar |
336 | + property alias model: list.model |
337 | + property alias bodyDelegate: list.bodyDelegate |
338 | + property alias headerDelegate: list.headerDelegate |
339 | |
340 | - ListView { |
341 | + ListViewWithHeaders { |
342 | id: list |
343 | |
344 | anchors.top: parent.top |
345 | @@ -30,32 +32,6 @@ |
346 | anchors.left: parent.left |
347 | anchors.right: scrollbar.left |
348 | anchors.rightMargin: 15 |
349 | - |
350 | - clip: true |
351 | - /* FIXME: proper spacing cannot be set because of the hack in Group.qml |
352 | - whereby empty groups are still in the list but invisible and of |
353 | - height 0. |
354 | - */ |
355 | - //spacing: 31 |
356 | - |
357 | - orientation: ListView.Vertical |
358 | - |
359 | - /* WARNING - HACK - FIXME |
360 | - Issue: |
361 | - User wise annoying jumps in the list are observable if cacheBuffer is |
362 | - set to 0 (which is the default value). States such as 'folded' are |
363 | - lost when scrolling a lot. |
364 | - |
365 | - Explanation: |
366 | - The height of the Group delegate depends on its content. However its |
367 | - content is not known until the delegate is instantiated because it |
368 | - depends on the number of results displayed by its GridView. |
369 | - |
370 | - Resolution: |
371 | - We set the cacheBuffer to the biggest possible int in order to make |
372 | - sure all delegates are always instantiated. |
373 | - */ |
374 | - cacheBuffer: 2147483647 |
375 | } |
376 | |
377 | Scrollbar { |
378 | @@ -67,7 +43,7 @@ |
379 | anchors.bottomMargin: 10 |
380 | anchors.right: parent.right |
381 | |
382 | - targetFlickable: list |
383 | + targetFlickable: list.flickable |
384 | |
385 | /* Hide the scrollbar if there is less than a page of results */ |
386 | opacity: targetFlickable.visibleArea.heightRatio < 1.0 ? 1.0 : 0.0 |
387 | |
388 | === modified file 'places/PlaceEntryView.qml' |
389 | --- places/PlaceEntryView.qml 2011-07-19 07:46:03 +0000 |
390 | +++ places/PlaceEntryView.qml 2011-07-27 19:03:02 +0000 |
391 | @@ -74,10 +74,10 @@ |
392 | If groupRenderer == 'UnityShowcaseRenderer' then it will look for |
393 | the file 'UnityShowcaseRenderer.qml' and use it to render the group. |
394 | */ |
395 | - list.delegate: Loader { |
396 | - property string groupRenderer: column_0 |
397 | - property string displayName: column_1 |
398 | - property string iconHint: column_2 |
399 | + bodyDelegate: Loader { |
400 | + property string groupRenderer: model.column_0 |
401 | + property string displayName: model.column_1 |
402 | + property string iconHint: model.column_2 |
403 | property int groupId: index |
404 | |
405 | source: groupRenderer ? groupRenderer+".qml" : "" |
406 | @@ -86,12 +86,8 @@ |
407 | console.log("Failed to load renderer", groupRenderer) |
408 | } |
409 | |
410 | - width: ListView.view.width |
411 | - |
412 | /* Model that will be used by the group's delegate */ |
413 | - SortFilterProxyModel { |
414 | - id: group_model |
415 | - |
416 | + property variant group_model: SortFilterProxyModel { |
417 | model: placeEntryView.model.entryResultsModel |
418 | |
419 | /* resultsModel contains data for all the groups of a given Place. |
420 | @@ -102,16 +98,35 @@ |
421 | filterRegExp: RegExp("^%1$".arg(groupId)) /* exact match */ |
422 | } |
423 | |
424 | - onLoaded: { |
425 | - item.parentListView = results.list |
426 | - item.displayName = displayName |
427 | - item.iconHint = iconHint |
428 | - item.groupId = groupId |
429 | - item.model = group_model |
430 | - item.placeEntryModel = placeEntryView.model |
431 | - } |
432 | - } |
433 | - |
434 | - list.model: placeEntryView.model != undefined ? placeEntryView.model.entryGroupsModel : undefined |
435 | + /* Required by ListViewWithHeaders when the loaded Renderer is a Flickable. |
436 | + In that case the list view scrolls the Flickable appropriately. |
437 | + */ |
438 | + property int totalHeight: item.totalHeight != undefined ? item.totalHeight : 0 |
439 | + property int contentY |
440 | + Binding { target: item; property: "contentY"; value: contentY } |
441 | + property bool focusable: group_model.count > 0 |
442 | + property variant currentItem: item.currentItem |
443 | + |
444 | + Binding { target: item; property: "displayName"; value: displayName } |
445 | + Binding { target: item; property: "iconHint"; value: iconHint } |
446 | + Binding { target: item; property: "groupId"; value: groupId } |
447 | + Binding { target: item; property: "group_model"; value: group_model } |
448 | + Binding { target: item; property: "placeEntryModel"; value: placeEntryView.model } |
449 | + } |
450 | + |
451 | + headerDelegate: GroupHeader { |
452 | + visible: body.item.needHeader && body.focusable |
453 | + height: visible ? 32 : 0 |
454 | + |
455 | + property bool foldable: body.item.folded != undefined |
456 | + availableCount: foldable ? body.group_model.count - body.item.cellsPerRow : 0 |
457 | + folded: foldable ? body.item.folded : false |
458 | + onClicked: if(foldable) body.item.folded = !body.item.folded |
459 | + |
460 | + icon: body.iconHint |
461 | + label: body.displayName |
462 | + } |
463 | + |
464 | + model: placeEntryView.model != undefined ? placeEntryView.model.entryGroupsModel : undefined |
465 | } |
466 | } |
467 | |
468 | === modified file 'places/Renderer.qml' |
469 | --- places/Renderer.qml 2011-06-23 17:08:53 +0000 |
470 | +++ places/Renderer.qml 2011-07-27 19:03:02 +0000 |
471 | @@ -30,7 +30,7 @@ |
472 | property string displayName /* Name of the group typically displayed in the header */ |
473 | property string iconHint /* Icon id of the group */ |
474 | property int groupId /* Index of the group */ |
475 | - property variant model /* List model containing the items to be displayed by the renderer */ |
476 | + property variant group_model /* List model containing the items to be displayed by the renderer */ |
477 | property variant placeEntryModel /* Reference to the place entry the group belongs to */ |
478 | - property variant parentListView /* Reference to the ListView the renderer is nested into */ |
479 | + property bool needHeader: false /* Whether or not the renderer requires a header to be displayed */ |
480 | } |
481 | |
482 | === modified file 'places/RendererGrid.qml' |
483 | --- places/RendererGrid.qml 2011-06-26 15:41:06 +0000 |
484 | +++ places/RendererGrid.qml 2011-07-27 19:03:02 +0000 |
485 | @@ -28,6 +28,11 @@ |
486 | Renderer { |
487 | id: renderer |
488 | |
489 | + needHeader: true |
490 | + property alias cellsPerRow: results.cellsPerRow |
491 | + property alias contentY: results.contentY |
492 | + property alias currentItem: results.currentItem |
493 | + |
494 | property variant cellRenderer |
495 | property bool folded |
496 | folded: { |
497 | @@ -44,85 +49,23 @@ |
498 | property int horizontalSpacing: 26 |
499 | property int verticalSpacing: 26 |
500 | |
501 | - /* Using results.contentHeight produces binding loop warnings and potential |
502 | - rendering issues. We compute the height manually. |
503 | - */ |
504 | - /* FIXME: tricking the system by making the delegate of height 0 and invisible |
505 | - is no good: the item in the model still exists and some things |
506 | - such as keyboard selection break. |
507 | - */ |
508 | - visible: results.model.totalCount > 0 |
509 | - height: visible ? header.height + results_layout.anchors.topMargin + results.totalHeight : 0 |
510 | - //Behavior on height {NumberAnimation {duration: 200}} |
511 | - |
512 | - GroupHeader { |
513 | - id: header |
514 | - |
515 | - availableCount: results.model.totalCount - results.cellsPerRow |
516 | - folded: parent.folded |
517 | - anchors.top: parent.top |
518 | - anchors.left: parent.left |
519 | - anchors.right: parent.right |
520 | - height: 32 |
521 | - icon: parent.iconHint |
522 | - label: parent.displayName |
523 | - |
524 | - onClicked: parent.folded = !parent.folded |
525 | - } |
526 | + /* FIXME: using results_layout.anchors.topMargin in the following expression |
527 | + causes QML to think they might be an anchor loop. */ |
528 | + property int totalHeight: results.count > 0 ? results_layout.anchors.topMargin + results.totalHeight : 0 |
529 | |
530 | Item { |
531 | id: results_layout |
532 | |
533 | - anchors.top: header.bottom |
534 | - anchors.topMargin: 22 |
535 | - anchors.left: parent.left |
536 | + anchors.fill: parent |
537 | + anchors.topMargin: 12 |
538 | anchors.leftMargin: 2 |
539 | - anchors.right: parent.right |
540 | - anchors.bottom: parent.bottom |
541 | |
542 | CenteredGridView { |
543 | id: results |
544 | |
545 | - /* FIXME: this is a gross hack compensating for the lack of sections |
546 | - in GridView (see ListView.section). |
547 | - |
548 | - We nest GridViews inside a ListView and add headers manually |
549 | - (GroupHeader). The total height of each Group is computed |
550 | - manually and given back to the ListView. However that size cannot |
551 | - be used by the individual GridViews because it would make them |
552 | - load all of their delegates at once using far too much memory and |
553 | - processing power. Instead we constrain the height of the GridViews |
554 | - and compute their position manually to compensate for the position |
555 | - changes when flicking the ListView. |
556 | - |
557 | - We assume that renderer.parentListView is the ListView we nest our |
558 | - GridView into. |
559 | - */ |
560 | - property variant flickable: renderer.parentListView.contentItem |
561 | - |
562 | - /* flickable.contentY*0 is equal to 0 but is necessary in order to |
563 | - have the entire expression being evaluated at the right moment. |
564 | - */ |
565 | - property int inFlickableY: flickable.contentY*0+parent.mapToItem(flickable, 0, 0).y |
566 | - /* note: testing for flickable.height < 0 is probably useless since it is |
567 | - unlikely flickable.height will ever be negative. |
568 | - */ |
569 | - property int compensateY: inFlickableY > 0 || flickable.height < 0 || totalHeight < flickable.height ? 0 : -inFlickableY |
570 | - |
571 | - /* Synchronise the position and content's position of the GridView |
572 | - with the current position of flickable's visibleArea */ |
573 | - function synchronisePosition() { |
574 | - y = compensateY |
575 | - contentY = compensateY |
576 | - } |
577 | - |
578 | - onCompensateYChanged: synchronisePosition() |
579 | - /* Any change in content needs to trigger a synchronisation */ |
580 | - onCountChanged: synchronisePosition() |
581 | - onModelChanged: synchronisePosition() |
582 | - |
583 | - width: flickable.width |
584 | - height: Math.min(totalHeight, flickable.height) |
585 | + focus: true |
586 | + |
587 | + anchors.fill: parent |
588 | |
589 | property int totalHeight: results.cellHeight*Math.ceil(count/cellsPerRow) |
590 | |
591 | @@ -168,7 +111,7 @@ |
592 | |
593 | /* Only display one line of items when folded */ |
594 | model: SortFilterProxyModel { |
595 | - model: renderer.model != undefined ? renderer.model : null |
596 | + model: renderer.group_model != undefined ? renderer.group_model : null |
597 | limit: folded ? results.cellsPerRow : -1 |
598 | } |
599 | } |
600 | |
601 | === modified file 'places/Scrollbar.qml' |
602 | --- places/Scrollbar.qml 2011-06-26 15:16:43 +0000 |
603 | +++ places/Scrollbar.qml 2011-07-27 19:03:02 +0000 |
604 | @@ -83,7 +83,7 @@ |
605 | when: !dragMouseArea.drag.active |
606 | } |
607 | |
608 | - height: Math.max(minimalHeight, targetFlickable.visibleArea.heightRatio * scrollbar.height) |
609 | + height: Math.min(scrollbar.height, Math.max(minimalHeight, targetFlickable.visibleArea.heightRatio * scrollbar.height)) |
610 | |
611 | Behavior on height {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}} |
612 | |
613 | |
614 | === modified file 'places/UnityEmptySearchRenderer.qml' |
615 | --- places/UnityEmptySearchRenderer.qml 2011-06-23 17:08:53 +0000 |
616 | +++ places/UnityEmptySearchRenderer.qml 2011-07-27 19:03:02 +0000 |
617 | @@ -40,7 +40,7 @@ |
618 | boundsBehavior: ListView.StopAtBounds |
619 | orientation: ListView.Vertical |
620 | |
621 | - model: renderer.model |
622 | + model: renderer.group_model |
623 | delegate: Button { |
624 | property string uri: column_0 |
625 | property string iconHint: column_1 |
626 | |
627 | === modified file 'places/dash.qml' |
628 | --- places/dash.qml 2011-07-05 19:01:18 +0000 |
629 | +++ places/dash.qml 2011-07-27 19:03:02 +0000 |
630 | @@ -30,6 +30,12 @@ |
631 | value: (currentPage && currentPage.expanded != undefined) ? currentPage.expanded : true |
632 | } |
633 | |
634 | + /* Unload the current page when closing the dash */ |
635 | + Connections { |
636 | + target: dashView |
637 | + onActiveChanged: if (!dashView.active) pageLoader.source = "" |
638 | + } |
639 | + |
640 | function activatePage(page) { |
641 | if (page == currentPage) { |
642 | return |