Merge lp:~zsombi/ubuntu-ui-toolkit/listItemExpandContent into lp:ubuntu-ui-toolkit/staging

Proposed by Zsombor Egri
Status: Work in progress
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/listItemExpandContent
Merge into: lp:ubuntu-ui-toolkit/staging
Prerequisite: lp:~zsombi/ubuntu-ui-toolkit/listitem_expansion
Diff against target: 832 lines (+476/-34)
10 files modified
components.api (+4/-0)
examples/ubuntu-ui-toolkit-gallery/ListItemWithLabel.qml (+0/-1)
examples/ubuntu-ui-toolkit-gallery/NewListItems.qml (+117/-1)
src/Ubuntu/Components/Themes/Ambiance/1.3/ListItemStyle.qml (+159/-10)
src/Ubuntu/Components/plugin/privates/listitemexpansion.cpp (+72/-0)
src/Ubuntu/Components/plugin/uclistitem.cpp (+69/-5)
src/Ubuntu/Components/plugin/uclistitem.h (+14/-0)
src/Ubuntu/Components/plugin/uclistitem_p.h (+2/-0)
src/Ubuntu/Components/plugin/ucviewitemsattached.cpp (+8/-1)
tests/resources/listitems/ListItemExpansion.qml (+31/-16)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/listItemExpandContent
Reviewer Review Type Date Requested Status
Ubuntu SDK team Pending
Review via email: mp+269910@code.launchpad.net
To post a comment you must log in.
1626. By Zsombor Egri

API added

1627. By Zsombor Egri

preparing states

1628. By Zsombor Egri

transition management

1629. By Zsombor Egri

style transitions on the go

1630. By Zsombor Egri

reverting custom transitions

1631. By Zsombor Egri

contentItem added, expansion under ListItem.contentItem implemented

1632. By Zsombor Egri

rename hideCollapsedContent with overlapListItem

1633. By Zsombor Egri

API updated

1634. By Zsombor Egri

overlapping content support

1635. By Zsombor Egri

docs updated

1636. By Zsombor Egri

few examples in gallery

1637. By Zsombor Egri

sync

1638. By Zsombor Egri

simplifying transitions

1639. By Zsombor Egri

small tweaks to avoid expanded being highlighted when the expanded content is scrollable

1640. By Zsombor Egri

lock expanded when content is Flickable

Unmerged revisions

1640. By Zsombor Egri

lock expanded when content is Flickable

1639. By Zsombor Egri

small tweaks to avoid expanded being highlighted when the expanded content is scrollable

1638. By Zsombor Egri

simplifying transitions

1637. By Zsombor Egri

sync

1636. By Zsombor Egri

few examples in gallery

1635. By Zsombor Egri

docs updated

1634. By Zsombor Egri

overlapping content support

1633. By Zsombor Egri

API updated

1632. By Zsombor Egri

rename hideCollapsedContent with overlapListItem

1631. By Zsombor Egri

contentItem added, expansion under ListItem.contentItem implemented

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'components.api'
--- components.api 2015-09-04 12:35:16 +0000
+++ components.api 2015-09-09 10:37:17 +0000
@@ -472,6 +472,7 @@
472 Started472 Started
473Ubuntu.Components.Styles.ListItemStyle 1.3 1.2: Item473Ubuntu.Components.Styles.ListItemStyle 1.3 1.2: Item
474 readonly property bool animatePanels474 readonly property bool animatePanels
475 readonly property bool completed 1.3
475 property Item dragPanel476 property Item dragPanel
476 property PropertyAnimation dropAnimation477 property PropertyAnimation dropAnimation
477 readonly property Flickable flickable 1.3478 readonly property Flickable flickable 1.3
@@ -1248,8 +1249,11 @@
1248 property color colorFrom1249 property color colorFrom
1249 property color colorTo1250 property color colorTo
1250UCListItemExpansion: QtObject1251UCListItemExpansion: QtObject
1252 property Component content
1253 readonly property Item contentItem
1251 property bool expanded1254 property bool expanded
1252 property double height1255 property double height
1256 property bool overlapListItem
1253UCStateSaverAttached: QtObject1257UCStateSaverAttached: QtObject
1254 property bool enabled1258 property bool enabled
1255 property string properties1259 property string properties
12561260
=== modified file 'examples/ubuntu-ui-toolkit-gallery/ListItemWithLabel.qml'
--- examples/ubuntu-ui-toolkit-gallery/ListItemWithLabel.qml 2015-07-03 16:52:20 +0000
+++ examples/ubuntu-ui-toolkit-gallery/ListItemWithLabel.qml 2015-09-09 10:37:17 +0000
@@ -27,5 +27,4 @@
27 verticalCenter: parent.verticalCenter27 verticalCenter: parent.verticalCenter
28 }28 }
29 }29 }
30 onPressAndHold: selectMode = !selectMode
31}30}
3231
=== modified file 'examples/ubuntu-ui-toolkit-gallery/NewListItems.qml'
--- examples/ubuntu-ui-toolkit-gallery/NewListItems.qml 2015-04-25 08:18:45 +0000
+++ examples/ubuntu-ui-toolkit-gallery/NewListItems.qml 2015-09-09 10:37:17 +0000
@@ -34,13 +34,15 @@
34 // clip the action delegates while swiping left/right34 // clip the action delegates while swiping left/right
35 clip: true35 clip: true
3636
37 ListItemWithLabel {37 ListItemWithLabel {
38 color: UbuntuColors.blue38 color: UbuntuColors.blue
39 text: i18n.tr("Colored")39 text: i18n.tr("Colored")
40 onPressAndHold: selectMode = !selectMode
40 }41 }
41 ListItemWithLabel {42 ListItemWithLabel {
42 text: i18n.tr("Highlight color")43 text: i18n.tr("Highlight color")
43 highlightColor: UbuntuColors.orange44 highlightColor: UbuntuColors.orange
45 onPressAndHold: selectMode = !selectMode
44 // no highlight without clicked() or leading/trailing actions46 // no highlight without clicked() or leading/trailing actions
45 }47 }
4648
@@ -70,18 +72,22 @@
70 ListItemWithLabel {72 ListItemWithLabel {
71 text: i18n.tr("Leading actions")73 text: i18n.tr("Leading actions")
72 leadingActions: exampleLeadingActions74 leadingActions: exampleLeadingActions
75 onPressAndHold: selectMode = !selectMode
73 }76 }
74 ListItemWithLabel {77 ListItemWithLabel {
75 text: i18n.tr("Trailing actions")78 text: i18n.tr("Trailing actions")
76 trailingActions: exampleTrailingActions79 trailingActions: exampleTrailingActions
80 onPressAndHold: selectMode = !selectMode
77 }81 }
78 ListItemWithLabel {82 ListItemWithLabel {
79 text: i18n.tr("Leading and trailing actions")83 text: i18n.tr("Leading and trailing actions")
80 leadingActions: exampleLeadingActions84 leadingActions: exampleLeadingActions
81 trailingActions: exampleTrailingActions85 trailingActions: exampleTrailingActions
86 onPressAndHold: selectMode = !selectMode
82 }87 }
83 ListItemWithLabel {88 ListItemWithLabel {
84 text: i18n.tr("Custom action delegates")89 text: i18n.tr("Custom action delegates")
90 onPressAndHold: selectMode = !selectMode
85 leadingActions: ListItemActions {91 leadingActions: ListItemActions {
86 actions: [92 actions: [
87 Action {93 Action {
@@ -163,6 +169,7 @@
163 model: [ i18n.tr("Basic"), i18n.tr("Colored divider"), i18n.tr("Immutable"), i18n.tr("No divider") ]169 model: [ i18n.tr("Basic"), i18n.tr("Colored divider"), i18n.tr("Immutable"), i18n.tr("No divider") ]
164 delegate: ListItemWithLabel {170 delegate: ListItemWithLabel {
165 text: modelData171 text: modelData
172 onPressAndHold: selectMode = !selectMode
166 color: dragging ? "lightblue" : "transparent"173 color: dragging ? "lightblue" : "transparent"
167 divider {174 divider {
168 colorFrom: modelData == i18n.tr("Colored divider") ? UbuntuColors.red : Qt.rgba(0.0, 0.0, 0.0, 0.0)175 colorFrom: modelData == i18n.tr("Colored divider") ? UbuntuColors.red : Qt.rgba(0.0, 0.0, 0.0, 0.0)
@@ -209,6 +216,7 @@
209 delegate: ListItemWithLabel {216 delegate: ListItemWithLabel {
210 text: modelData217 text: modelData
211 color: dragMode ? "lightblue" : "lightgray"218 color: dragMode ? "lightblue" : "lightgray"
219 onPressAndHold: selectMode = !selectMode
212 divider {220 divider {
213 colorFrom: modelData == i18n.tr("Colored divider") ? UbuntuColors.red : Qt.rgba(0.0, 0.0, 0.0, 0.0)221 colorFrom: modelData == i18n.tr("Colored divider") ? UbuntuColors.red : Qt.rgba(0.0, 0.0, 0.0, 0.0)
214 colorTo: modelData == i18n.tr("Colored divider") ? UbuntuColors.green : Qt.rgba(0.0, 0.0, 0.0, 0.0)222 colorTo: modelData == i18n.tr("Colored divider") ? UbuntuColors.green : Qt.rgba(0.0, 0.0, 0.0, 0.0)
@@ -217,4 +225,112 @@
217 }225 }
218 }226 }
219 }227 }
228
229 TemplateSection {
230 className: "ListItem"
231 title: "Expansion - exclusive, unlocked, auto-collapsing"
232
233 UbuntuListView {
234 width: parent.width
235 height: units.gu(28)
236 clip: true
237 model: 5
238 ViewItems.expansionFlags: ViewItems.CollapseOnOutsidePress | ViewItems.UnlockExpanded
239 delegate: ListItemWithLabel {
240 text: i18n.tr("Item #%1: pressAndHold to expand/collapse").arg(modelData)
241 leadingActions: exampleLeadingActions
242 trailingActions: exampleTrailingActions
243 expansion.height: units.gu(15)
244 onPressAndHold: expansion.expanded = !expansion.expanded
245 }
246 }
247 }
248
249 TemplateSection {
250 className: "ListItem"
251 title: "Expansion - content under collapsed layout"
252
253 UbuntuListView {
254 id: view
255 width: parent.width
256 height: units.gu(28)
257 clip: true
258 model: ListModel {
259 Component.onCompleted: {
260 for (var i = 0; i < 5; i++) {
261 append({label: i18n.tr("Item #%1: pressAndHold to expand/collapse").arg(i)})
262 }
263 }
264 }
265
266 delegate: ListItemWithLabel {
267 id: mainItem
268 property int itemIndex: index
269 text: label
270 onPressAndHold: expansion.expanded = !expansion.expanded
271 expansion {
272 height: units.gu(21)
273 content: UbuntuListView {
274 clip: true
275 anchors.right: parent.right
276 width: parent.width - units.gu(4)
277 height: units.gu(14)
278 model: 5
279 delegate: ListItemWithLabel {
280 text: i18n.tr("Sub-item #%1").arg(modelData)
281 onClicked: {
282 view.model.get(mainItem.itemIndex).label = "Replaced with " + text;
283 mainItem.expansion.expanded = false;
284 }
285 }
286 }
287 }
288 }
289 }
290 }
291
292 TemplateSection {
293 className: "ListItem"
294 title: "Expansion - content over ListItem"
295
296 UbuntuListView {
297 id: view2
298 width: parent.width
299 height: units.gu(28)
300 clip: true
301 model: ListModel {
302 Component.onCompleted: {
303 for (var i = 0; i < 5; i++) {
304 append({label: i18n.tr("Item #%1: pressAndHold to expand/collapse").arg(i)})
305 }
306 }
307 }
308 ViewItems.expansionFlags: ViewItems.CollapseOnOutsidePress
309
310 delegate: ListItemWithLabel {
311 id: mainItem2
312 property int itemIndex: index
313 text: label
314 onPressAndHold: { print(1); expansion.expanded = !expansion.expanded}
315 expansion {
316 height: units.gu(21)
317 overlapListItem: true
318 content: UbuntuListView {
319 clip: true
320 anchors.right: parent.right
321 width: parent.width - units.gu(4)
322 height: units.gu(14)
323 model: 5
324 delegate: ListItemWithLabel {
325 text: i18n.tr("Sub-item #%1").arg(modelData)
326 onClicked: {
327 view2.model.get(mainItem2.itemIndex).label = "Replaced with " + text;
328 mainItem2.expansion.expanded = false;
329 }
330 }
331 }
332 }
333 }
334 }
335 }
220}336}
221337
=== modified file 'src/Ubuntu/Components/Themes/Ambiance/1.3/ListItemStyle.qml'
--- src/Ubuntu/Components/Themes/Ambiance/1.3/ListItemStyle.qml 2015-09-04 09:32:31 +0000
+++ src/Ubuntu/Components/Themes/Ambiance/1.3/ListItemStyle.qml 2015-09-09 10:37:17 +0000
@@ -423,7 +423,24 @@
423423
424 // expansion424 // expansion
425 Component.onCompleted: internals.completed = true425 Component.onCompleted: internals.completed = true
426 state: (internals.completed && styledItem.expansion.expanded) ? (listItemStyle.flickable ? "expandedWithFlickable" : "expandedNoFlickable") : ""426 state: {
427 if (!internals.completed || !styledItem.expansion.expanded) {
428 return "";
429 }
430 // states are:
431 // expandedWithFlickable, expandedNoFlickable
432 // expandedOverContentWithFlickable, expandedOverContentNoFlickable
433 // expandedUnderContentWithFlickable, expandedUnderContentNoFlickable
434 var result = "expanded";
435
436 if (styledItem.expansion.content) {
437 result += styledItem.expansion.overlapListItem ? "OverContent" : "UnderContent";
438 }
439
440 result += (listItemStyle.flickable) ? "WithFlickable" : "NoFlickable";
441
442 return result;
443 }
427 states: [444 states: [
428 State {445 State {
429 name: "expandedNoFlickable"446 name: "expandedNoFlickable"
@@ -454,6 +471,104 @@
454 }471 }
455 }472 }
456 }473 }
474 },
475 State {
476 name: "expandedUnderContentNoFlickable"
477 AnchorChanges {
478 target: styledItem.contentItem
479 anchors.bottom: undefined
480 }
481 PropertyChanges {
482 target: styledItem.expansion.contentItem
483 opacity: 1.0
484 z: 1
485 }
486 PropertyChanges {
487 target: styledItem
488 height: styledItem.expansion.height
489 }
490 },
491 State {
492 name: "expandedUnderContentWithFlickable"
493 AnchorChanges {
494 target: styledItem.contentItem
495 anchors.bottom: undefined
496 }
497 PropertyChanges {
498 target: styledItem.expansion.contentItem
499 opacity: 1.0
500 z: 1
501 }
502 PropertyChanges {
503 target: styledItem
504 height: styledItem.expansion.height
505 }
506 PropertyChanges {
507 target: listItemStyle.flickable
508 // we do not need to restore the original values
509 restoreEntryValues: false
510 // and we should not get any binding updates even
511 explicit: true
512 contentY: {
513 var bottom = styledItem.y + styledItem.expansion.height - listItemStyle.flickable.contentY + listItemStyle.flickable.originY;
514 var dy = bottom - listItemStyle.flickable.height;
515 if (dy > 0) {
516 return listItemStyle.flickable.contentY + dy - listItemStyle.flickable.originY;
517 } else {
518 return listItemStyle.flickable.contentY;
519 }
520 }
521 }
522 },
523 State {
524 name: "expandedOverContentNoFlickable"
525 PropertyChanges {
526 target: styledItem.contentItem
527 opacity: 0.0
528 enabled: false
529 }
530 PropertyChanges {
531 target: styledItem.expansion.contentItem
532 opacity: 1.0
533 z: 1
534 }
535 PropertyChanges {
536 target: styledItem
537 height: styledItem.expansion.height
538 }
539 },
540 State {
541 name: "expandedOverContentWithFlickable"
542 PropertyChanges {
543 target: styledItem.contentItem
544 opacity: 0.0
545 enabled: false
546 }
547 PropertyChanges {
548 target: styledItem.expansion.contentItem
549 opacity: 1.0
550 z: 1
551 }
552 PropertyChanges {
553 target: styledItem
554 height: styledItem.expansion.height
555 }
556 PropertyChanges {
557 target: listItemStyle.flickable
558 // we do not need to restore the original values
559 restoreEntryValues: false
560 // and we should not get any binding updates even
561 explicit: true
562 contentY: {
563 var bottom = styledItem.y + styledItem.expansion.height - listItemStyle.flickable.contentY + listItemStyle.flickable.originY;
564 var dy = bottom - listItemStyle.flickable.height;
565 if (dy > 0) {
566 return listItemStyle.flickable.contentY + dy - listItemStyle.flickable.originY;
567 } else {
568 return listItemStyle.flickable.contentY;
569 }
570 }
571 }
457 }572 }
458 ]573 ]
459 transitions: [574 transitions: [
@@ -462,15 +577,29 @@
462 to: "expandedWithFlickable"577 to: "expandedWithFlickable"
463 reversible: true578 reversible: true
464 enabled: listItemStyle.animatePanels579 enabled: listItemStyle.animatePanels
465 ParallelAnimation {580 UbuntuNumberAnimation {
466 UbuntuNumberAnimation {581 targets: [listItemStyle.flickable, styledItem]
467 target: listItemStyle.flickable582 properties: "contentY, height"
468 property: "contentY"583 }
469 }584 },
470 UbuntuNumberAnimation {585 Transition {
471 target: styledItem586 from: ""
472 property: "height"587 to: "expandedUnderContentWithFlickable"
473 }588 reversible: true
589 enabled: listItemStyle.animatePanels
590 UbuntuNumberAnimation {
591 targets: [styledItem.expansion.contentItem, listItemStyle.flickable, styledItem]
592 properties: "opacity, contentY, height"
593 }
594 },
595 Transition {
596 from: ""
597 to: "expandedOverContentWithFlickable"
598 reversible: true
599 enabled: listItemStyle.animatePanels
600 UbuntuNumberAnimation {
601 targets: [styledItem.contentItem, styledItem.expansion.contentItem, listItemStyle.flickable, styledItem]
602 properties: "opacity, contentY, height"
474 }603 }
475 },604 },
476 Transition {605 Transition {
@@ -482,6 +611,26 @@
482 target: styledItem611 target: styledItem
483 property: "height"612 property: "height"
484 }613 }
614 },
615 Transition {
616 from: ""
617 to: "expandedUnderContentNoFlickable"
618 reversible: true
619 enabled: listItemStyle.animatePanels
620 UbuntuNumberAnimation {
621 targets: [styledItem.expansion.contentItem, styledItem]
622 properties: "opacity, height"
623 }
624 },
625 Transition {
626 from: ""
627 to: "expandedOverContentNoFlickable"
628 reversible: true
629 enabled: listItemStyle.animatePanels
630 UbuntuNumberAnimation {
631 targets: [styledItem.expansion.contentItem, styledItem.contentItem, styledItem]
632 properties: "opacity, height"
633 }
485 }634 }
486 ]635 ]
487}636}
488637
=== modified file 'src/Ubuntu/Components/plugin/privates/listitemexpansion.cpp'
--- src/Ubuntu/Components/plugin/privates/listitemexpansion.cpp 2015-09-04 09:32:31 +0000
+++ src/Ubuntu/Components/plugin/privates/listitemexpansion.cpp 2015-09-09 10:37:17 +0000
@@ -16,15 +16,45 @@
1616
17#include "uclistitem.h"17#include "uclistitem.h"
18#include "uclistitem_p.h"18#include "uclistitem_p.h"
19#include <QtQuick/private/qquickflickable_p.h>
1920
20UCListItemExpansion::UCListItemExpansion(QObject *parent)21UCListItemExpansion::UCListItemExpansion(QObject *parent)
21 : QObject(parent)22 : QObject(parent)
22 , m_listItem(static_cast<UCListItem13*>(parent))23 , m_listItem(static_cast<UCListItem13*>(parent))
24 , m_content(Q_NULLPTR)
25 , m_contentItem(Q_NULLPTR)
23 , m_height(0.0)26 , m_height(0.0)
27 , m_overlapListItem(false)
24 , m_filtering(false)28 , m_filtering(false)
25{29{
26}30}
2731
32void UCListItemExpansion::createOrUpdateContentItem()
33{
34 if (!m_contentItem && m_content && expanded()) {
35 m_contentItem = static_cast<QQuickItem*>(m_content->create(qmlContext(m_listItem)));
36 m_contentItem->setParentItem(m_listItem);
37 m_contentItem->setOpacity(0.0);
38 m_listItem->setClip(true);
39 // cal update to handle ListItem restrictions
40 updateContent(expanded());
41 }
42
43 // adjust expanded contentItem anchoring
44 if (m_contentItem) {
45 QQuickAnchors *contentAnchors = QQuickItemPrivate::get(m_contentItem)->anchors();
46 QQuickItemPrivate *contentItem = QQuickItemPrivate::get(m_listItem->contentItem());
47 if (m_overlapListItem) {
48 contentAnchors->resetTop();
49 contentAnchors->setFill(m_listItem->contentItem());
50 } else {
51 // make sure we remove the fill
52 contentAnchors->resetFill();
53 contentAnchors->setTop(contentItem->bottom());
54 }
55 }
56}
57
28bool UCListItemExpansion::expandedLocked()58bool UCListItemExpansion::expandedLocked()
29{59{
30 UCListItemPrivate *listItem = UCListItemPrivate::get(m_listItem);60 UCListItemPrivate *listItem = UCListItemPrivate::get(m_listItem);
@@ -45,6 +75,21 @@
45 }75 }
46}76}
4777
78// called when ViewItems expands/collapses the content
79void UCListItemExpansion::updateContent(bool expanded)
80{
81 if (!m_contentItem) {
82 return;
83 }
84 m_contentItem->setEnabled(expanded);
85 // if contentItem is a Flickable, lock ListItem from being highlighted
86 if (qobject_cast<QQuickFlickable*>(m_contentItem)) {
87 UCListItemPrivate *listItem = UCListItemPrivate::get(m_listItem);
88 listItem->blockHighlighting(expanded);
89 }
90}
91
92
48// event filter for external mouse presses to collapse when pressed outside93// event filter for external mouse presses to collapse when pressed outside
49bool UCListItemExpansion::eventFilter(QObject *target, QEvent *event)94bool UCListItemExpansion::eventFilter(QObject *target, QEvent *event)
50{95{
@@ -104,3 +149,30 @@
104 m_height = height;149 m_height = height;
105 Q_EMIT heightChanged();150 Q_EMIT heightChanged();
106}151}
152
153void UCListItemExpansion::setContent(QQmlComponent *component)
154{
155 if (component == m_content) {
156 return;
157 }
158 m_content = component;
159 Q_EMIT contentChanged();
160 Q_EMIT contentItemChanged();
161}
162
163QQuickItem *UCListItemExpansion::contentItem()
164{
165 createOrUpdateContentItem();
166 return m_contentItem;
167}
168
169
170void UCListItemExpansion::setOverlapListItem(bool overlap)
171{
172 if (m_overlapListItem == overlap) {
173 return;
174 }
175 m_overlapListItem = overlap;
176 Q_EMIT overlapListItemChanged();
177 createOrUpdateContentItem();
178}
107179
=== modified file 'src/Ubuntu/Components/plugin/uclistitem.cpp'
--- src/Ubuntu/Components/plugin/uclistitem.cpp 2015-09-04 09:32:31 +0000
+++ src/Ubuntu/Components/plugin/uclistitem.cpp 2015-09-09 10:37:17 +0000
@@ -186,6 +186,7 @@
186 : UCStyledItemBasePrivate()186 : UCStyledItemBasePrivate()
187 , defaultThemeVersion(0)187 , defaultThemeVersion(0)
188 , highlighted(false)188 , highlighted(false)
189 , highlightBlocked(false)
189 , contentMoved(false)190 , contentMoved(false)
190 , swiped(false)191 , swiped(false)
191 , suppressClick(false)192 , suppressClick(false)
@@ -383,10 +384,21 @@
383 return (isClickedConnected() || isPressAndHoldConnected() || mainAction || leadingActions || trailingActions);384 return (isClickedConnected() || isPressAndHoldConnected() || mainAction || leadingActions || trailingActions);
384}385}
385386
387// block the highlight mechanism (and swiping) on the ListItem; called when the ListItem
388// is expanded and the content specified is a Flickable
389void UCListItemPrivate::blockHighlighting(bool block)
390{
391 if (block) {
392 setHighlighted(false);
393 listenToRebind(false);
394 }
395 highlightBlocked = block;
396}
397
386// set highlighted flag and update contentItem398// set highlighted flag and update contentItem
387void UCListItemPrivate::setHighlighted(bool highlighted)399void UCListItemPrivate::setHighlighted(bool highlighted)
388{400{
389 if (this->highlighted != highlighted) {401 if (this->highlighted != highlighted && !highlightBlocked) {
390 this->highlighted = highlighted;402 this->highlighted = highlighted;
391 suppressClick = false;403 suppressClick = false;
392 Q_Q(UCListItem);404 Q_Q(UCListItem);
@@ -1125,6 +1137,9 @@
1125// swipe events; child items should no longer get mouse events1137// swipe events; child items should no longer get mouse events
1126void UCListItemPrivate::grabLeftButtonEvents(QMouseEvent *event)1138void UCListItemPrivate::grabLeftButtonEvents(QMouseEvent *event)
1127{1139{
1140 if (highlightBlocked) {
1141 return;
1142 }
1128 Q_Q(UCListItem);1143 Q_Q(UCListItem);
1129 button = event->button();1144 button = event->button();
1130 // create style instance1145 // create style instance
@@ -1239,7 +1254,7 @@
1239 Q_D(UCListItem);1254 Q_D(UCListItem);
1240 d->ungrabLeftButtonEvents(event);1255 d->ungrabLeftButtonEvents(event);
1241 // make sure we ungrab the mouse!1256 // make sure we ungrab the mouse!
1242 ungrabMouse();1257 setKeepMouseGrab(false);
1243}1258}
12441259
1245void UCListItem13::mouseReleaseEvent(QMouseEvent *event)1260void UCListItem13::mouseReleaseEvent(QMouseEvent *event)
@@ -1323,7 +1338,7 @@
1323 } else if (type == QEvent::MouseMove) {1338 } else if (type == QEvent::MouseMove) {
1324 QMouseEvent *mouse = static_cast<QMouseEvent*>(event);1339 QMouseEvent *mouse = static_cast<QMouseEvent*>(event);
1325 const QPointF localPos = mapFromItem(child, mouse->localPos());1340 const QPointF localPos = mapFromItem(child, mouse->localPos());
1326 if ((mouse->buttons() & Qt::LeftButton) && d->swipedOverThreshold(localPos, d->pressedPos) && !d->highlighted) {1341 if ((mouse->buttons() & Qt::LeftButton) && d->swipedOverThreshold(localPos, d->pressedPos) && !d->highlighted && !d->highlightBlocked) {
1327 // grab the event from the child, so the click doesn't happen anymore, and initiate swiping1342 // grab the event from the child, so the click doesn't happen anymore, and initiate swiping
1328 QMouseEvent pressed(QEvent::MouseButtonPress, localPos, mouse->windowPos(), mouse->screenPos(),1343 QMouseEvent pressed(QEvent::MouseButtonPress, localPos, mouse->windowPos(), mouse->screenPos(),
1329 Qt::LeftButton, mouse->buttons(), mouse->modifiers());1344 Qt::LeftButton, mouse->buttons(), mouse->modifiers());
@@ -1331,7 +1346,7 @@
1331 // stop click and pressAndHold, then grab the mouse so children do not get the mouse events anymore1346 // stop click and pressAndHold, then grab the mouse so children do not get the mouse events anymore
1332 d->suppressClick = true;1347 d->suppressClick = true;
1333 d->pressAndHoldTimer.stop();1348 d->pressAndHoldTimer.stop();
1334 grabMouse();1349 setKeepMouseGrab(true);
1335 }1350 }
1336 }1351 }
1337 return UCStyledItemBase::childMouseEventFilter(child, event);1352 return UCStyledItemBase::childMouseEventFilter(child, event);
@@ -1761,8 +1776,57 @@
1761 * \qmlpropertygroup ::ListItem::expansion1776 * \qmlpropertygroup ::ListItem::expansion
1762 * \qmlproperty bool ListItem::expansion.expanded1777 * \qmlproperty bool ListItem::expansion.expanded
1763 * \qmlproperty real ListItem::expansion.height1778 * \qmlproperty real ListItem::expansion.height
1779 * \qmlproperty Component ListItem::expansion.content
1780 * \qmlproperty Item ListItem::expansion.contentItem
1781 * \qmlproperty bool ListItem::expansion.overlapListItem
1764 * \since Ubuntu.Components 1.31782 * \since Ubuntu.Components 1.3
1765 * The group drefines the expansion state of the ListItem.1783 * The group drefines the expansion state of the ListItem. \c expanded drives
1784 * the expansion of the ListItem, \c height specifies the height of the expanded
1785 * ListItem. By default the ListItem's content is expanded together with the
1786 * ListItem. There may be use cases where the expanded content may have slightly
1787 * different content. This can be achieved by specifying a component in \c content
1788 * property. When content is specified, it will be anchored to the bottom of the
1789 * \l ListItem::contentItem, which in turn will not resize together with the
1790 * ListItem. Setting \c overlapListItem will hide the \l ListItem::contentItem
1791 * and will fill the entire ListItem with the \c content. Setting \c overlapListItem
1792 * without a valid \c content component will have no effect.
1793 * /note Setting \e ViewItems.UnlockExpanded flag to a view of ListItems where the
1794 * expanded content is a Flickable derivate will have no effect.
1795 * Example:
1796 * \qml
1797 * import QtQuick 2.4
1798 * import Ubuntu.Components 1.3
1799 *
1800 * UbuntuListView {
1801 * width: units.gu(40)
1802 * height: units.gu(71)
1803 * ViewItems.expansionFlags: ViewItems.CollapseOnOutsidePress
1804 *
1805 * model: 50
1806 * delegate: ListItem {
1807 * id: listItem
1808 * contentItem.anchors.margins: units.gu(1.5)
1809 * Label { text: "List Item #" + modelData }
1810 * onPressAndHold: expansion.expanded = true
1811 * expansion {
1812 * height: units.gu(21)
1813 * overlapListItem: true
1814 * content: UbuntuListView {
1815 * anchors {
1816 * leftMargin: units.gu(2)
1817 * rightMargin: units.gu(2)
1818 * }
1819 * model: 5
1820 * delegate: ListItem {
1821 * contentItem.anchors.margins: units.gu(1.5)
1822 * Label { text: "Expanded item # + modelData }
1823 * onClicked: listItem.expansion.expanded = false
1824 * }
1825 * }
1826 * }
1827 * }
1828 * }
1829 * \endqml
1766 */1830 */
1767UCListItemExpansion *UCListItem13::expansion()1831UCListItemExpansion *UCListItem13::expansion()
1768{1832{
17691833
=== modified file 'src/Ubuntu/Components/plugin/uclistitem.h'
--- src/Ubuntu/Components/plugin/uclistitem.h 2015-09-04 09:32:31 +0000
+++ src/Ubuntu/Components/plugin/uclistitem.h 2015-09-09 10:37:17 +0000
@@ -241,26 +241,40 @@
241 Q_OBJECT241 Q_OBJECT
242 Q_PROPERTY(bool expanded READ expanded WRITE setExpanded NOTIFY expandedChanged)242 Q_PROPERTY(bool expanded READ expanded WRITE setExpanded NOTIFY expandedChanged)
243 Q_PROPERTY(qreal height MEMBER m_height WRITE setHeight NOTIFY heightChanged)243 Q_PROPERTY(qreal height MEMBER m_height WRITE setHeight NOTIFY heightChanged)
244 Q_PROPERTY(QQmlComponent *content MEMBER m_content WRITE setContent NOTIFY contentChanged)
245 Q_PROPERTY(QQuickItem *contentItem READ contentItem NOTIFY contentItemChanged)
246 Q_PROPERTY(bool overlapListItem MEMBER m_overlapListItem WRITE setOverlapListItem NOTIFY overlapListItemChanged)
244public:247public:
245 explicit UCListItemExpansion(QObject *parent = 0);248 explicit UCListItemExpansion(QObject *parent = 0);
246249
247 bool expandedLocked();250 bool expandedLocked();
248 void enableClickFiltering(bool enable);251 void enableClickFiltering(bool enable);
252 void updateContent(bool expanded);
249253
250 bool expanded();254 bool expanded();
251 void setExpanded(bool expanded);255 void setExpanded(bool expanded);
252 void setHeight(qreal height);256 void setHeight(qreal height);
257 void setContent(QQmlComponent *component);
258 QQuickItem *contentItem();
259 void setOverlapListItem(bool overlap);
253260
254Q_SIGNALS:261Q_SIGNALS:
255 void expandedChanged();262 void expandedChanged();
256 void heightChanged();263 void heightChanged();
264 void contentChanged();
265 void contentItemChanged();
266 void overlapListItemChanged();
257267
258protected:268protected:
259 bool eventFilter(QObject *, QEvent *);269 bool eventFilter(QObject *, QEvent *);
270 void createOrUpdateContentItem();
260271
261private:272private:
262 UCListItem13 *m_listItem;273 UCListItem13 *m_listItem;
274 QQmlComponent *m_content;
275 QQuickItem *m_contentItem;
263 qreal m_height;276 qreal m_height;
277 bool m_overlapListItem:1;
264 bool m_filtering:1;278 bool m_filtering:1;
265279
266 friend class UCListItem;280 friend class UCListItem;
267281
=== modified file 'src/Ubuntu/Components/plugin/uclistitem_p.h'
--- src/Ubuntu/Components/plugin/uclistitem_p.h 2015-09-01 07:16:59 +0000
+++ src/Ubuntu/Components/plugin/uclistitem_p.h 2015-09-09 10:37:17 +0000
@@ -61,6 +61,7 @@
61 void _q_syncDragMode();61 void _q_syncDragMode();
62 int index();62 int index();
63 bool canHighlight();63 bool canHighlight();
64 void blockHighlighting(bool block);
64 void setHighlighted(bool pressed);65 void setHighlighted(bool pressed);
65 void listenToRebind(bool listen);66 void listenToRebind(bool listen);
66 void lockContentItem(bool lock);67 void lockContentItem(bool lock);
@@ -73,6 +74,7 @@
7374
74 quint16 defaultThemeVersion;75 quint16 defaultThemeVersion;
75 bool highlighted:1;76 bool highlighted:1;
77 bool highlightBlocked:1;
76 bool contentMoved:1;78 bool contentMoved:1;
77 bool swiped:1;79 bool swiped:1;
78 bool suppressClick:1;80 bool suppressClick:1;
7981
=== modified file 'src/Ubuntu/Components/plugin/ucviewitemsattached.cpp'
--- src/Ubuntu/Components/plugin/ucviewitemsattached.cpp 2015-09-04 08:55:29 +0000
+++ src/Ubuntu/Components/plugin/ucviewitemsattached.cpp 2015-09-09 10:37:17 +0000
@@ -666,6 +666,9 @@
666 if (listItem && ((expansionFlags & UCViewItemsAttached::CollapseOnOutsidePress) == UCViewItemsAttached::CollapseOnOutsidePress)) {666 if (listItem && ((expansionFlags & UCViewItemsAttached::CollapseOnOutsidePress) == UCViewItemsAttached::CollapseOnOutsidePress)) {
667 listItem->expansion()->enableClickFiltering(true);667 listItem->expansion()->enableClickFiltering(true);
668 }668 }
669 if (listItem) {
670 listItem->expansion()->updateContent(true);
671 }
669 if (emitChangeSignal) {672 if (emitChangeSignal) {
670 Q_EMIT static_cast<UCViewItemsAttached13*>(q_func())->expandedIndicesChanged(expansionList.keys());673 Q_EMIT static_cast<UCViewItemsAttached13*>(q_func())->expandedIndicesChanged(expansionList.keys());
671 }674 }
@@ -679,6 +682,9 @@
679 if (item && ((expansionFlags & UCViewItemsAttached::CollapseOnOutsidePress) == UCViewItemsAttached::CollapseOnOutsidePress)) {682 if (item && ((expansionFlags & UCViewItemsAttached::CollapseOnOutsidePress) == UCViewItemsAttached::CollapseOnOutsidePress)) {
680 item->expansion()->enableClickFiltering(false);683 item->expansion()->enableClickFiltering(false);
681 }684 }
685 if (item) {
686 item->expansion()->updateContent(false);
687 }
682 if (emitChangeSignal && wasExpanded) {688 if (emitChangeSignal && wasExpanded) {
683 Q_EMIT static_cast<UCViewItemsAttached13*>(q_func())->expandedIndicesChanged(expansionList.keys());689 Q_EMIT static_cast<UCViewItemsAttached13*>(q_func())->expandedIndicesChanged(expansionList.keys());
684 }690 }
@@ -708,7 +714,8 @@
708 * \li When set, only one ListItem can be expanded at a time. \b {Set by default}.714 * \li When set, only one ListItem can be expanded at a time. \b {Set by default}.
709 * \row715 * \row
710 * \li ViewItems.UnlockExpanded716 * \li ViewItems.UnlockExpanded
711 * \li When set, the ListItem's leading/trailing actions can be swiped in.717 * \li When set, the ListItem's leading/trailing actions can be swiped in. The
718 * flag has no effect when the expanded content is a Flickable.
712 * \row719 * \row
713 * \li ViewItems.CollapseOnOutsidePress720 * \li ViewItems.CollapseOnOutsidePress
714 * \li When set, the active expaned ListItem collapses automatically when clicked721 * \li When set, the active expaned ListItem collapses automatically when clicked
715722
=== modified file 'tests/resources/listitems/ListItemExpansion.qml'
--- tests/resources/listitems/ListItemExpansion.qml 2015-09-02 06:47:25 +0000
+++ tests/resources/listitems/ListItemExpansion.qml 2015-09-09 10:37:17 +0000
@@ -38,6 +38,7 @@
38 iconName: "stock_website"38 iconName: "stock_website"
39 }39 }
40 ]40 ]
41
41 Page {42 Page {
42 title: "Expansion"43 title: "Expansion"
43 Column {44 Column {
@@ -50,18 +51,12 @@
50 height: parent.height / 251 height: parent.height / 2
51 clip: true52 clip: true
52 ViewItems.onExpandedIndicesChanged: print(ViewItems.expandedIndices)53 ViewItems.onExpandedIndicesChanged: print(ViewItems.expandedIndices)
53 ViewItems.expansionFlags: ViewItems.CollapseOnOutsidePress54 ViewItems.expansionFlags: ViewItems.CollapseOnOutsidePress | ViewItems.UnlockExpanded
5455
55 model: ListModel {56 model: ListModel {
56 Component.onCompleted: {57 Component.onCompleted: {
57 for (var i = 0; i < 3; i++) {58 for (var i = 0; i < 25; i++) {
58 append({label: "List item #"+i, sectionData: "Locked"});59 append({label: "List item #"+i});
59 }
60 for (i = 3; i < 11; i++) {
61 append({label: "List item #"+i, sectionData: "Limited, live move"});
62 }
63 for (i = 11; i < 25; i++) {
64 append({label: "List item #"+i, sectionData: "Unlimited, drag'n'drop"});
65 }60 }
66 }61 }
67 }62 }
@@ -75,7 +70,20 @@
75 trailingActions: ListItemActions {70 trailingActions: ListItemActions {
76 actions: contextualActions71 actions: contextualActions
77 }72 }
78 expansion.height: units.gu(15)73 expansion {
74 height: units.gu(15)
75 overlapListItem: true
76 content: UbuntuListView {
77 model: 5
78 delegate: ListItem {
79 contentItem.anchors.margins: units.gu(1)
80 Label { text: i18n.tr("Sub-item #%1").arg(modelData) }
81 onClicked: {
82 item.expansion.expanded = false;
83 }
84 }
85 }
86 }
7987
80 RowLayout {88 RowLayout {
81 anchors {89 anchors {
@@ -89,10 +97,6 @@
89 title.text: label97 title.text: label
90 subtitle.text: "from index #" + index98 subtitle.text: "from index #" + index
91 }99 }
92 Button {
93 text: "Enable drag mode"
94 onClicked: listView.ViewItems.dragMode = true
95 }
96 }100 }
97101
98 onPressAndHold: {102 onPressAndHold: {
@@ -103,12 +107,23 @@
103 }107 }
104 ListItem {108 ListItem {
105 Label { text: "Standalone ListItem" }109 Label { text: "Standalone ListItem" }
106 expansion.height: units.gu(15)110 expansion {
111 height: units.gu(15)
112 content: Rectangle {
113 color: UbuntuColors.darkGrey
114 width: parent.width
115 height: units.gu(8)
116 radius: units.gu(1)
117 }
118 }
107 onPressAndHold: expansion.expanded = !expansion.expanded;119 onPressAndHold: expansion.expanded = !expansion.expanded;
108 }120 }
109 ListItem {121 ListItem {
110 Label { text: "Other Standalone ListItem" }122 Label { text: "Other Standalone ListItem" }
111 expansion.height: units.gu(15)123 expansion {
124 height: units.gu(15)
125 overlapListItem: true
126 }
112 onPressAndHold: expansion.expanded = !expansion.expanded;127 onPressAndHold: expansion.expanded = !expansion.expanded;
113 }128 }
114129

Subscribers

People subscribed via source and target branches