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

Proposed by Zsombor Egri
Status: Merged
Approved by: Tim Peeters
Approved revision: 1405
Merged at revision: 1383
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/76-refactoring
Merge into: lp:ubuntu-ui-toolkit/staging
Prerequisite: lp:~zsombi/ubuntu-ui-toolkit/75-listitem-highlight
Diff against target: 2565 lines (+736/-782)
18 files modified
components.api (+9/-12)
modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml (+30/-29)
modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml (+0/-1)
modules/Ubuntu/Components/plugin/plugin.cpp (+1/-0)
modules/Ubuntu/Components/plugin/plugin.pro (+4/-3)
modules/Ubuntu/Components/plugin/ucaction.h (+1/-1)
modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp (+132/-0)
modules/Ubuntu/Components/plugin/uclistitem.cpp (+250/-168)
modules/Ubuntu/Components/plugin/uclistitem.h (+58/-7)
modules/Ubuntu/Components/plugin/uclistitem_p.h (+75/-13)
modules/Ubuntu/Components/plugin/uclistitemactions.cpp (+26/-271)
modules/Ubuntu/Components/plugin/uclistitemactions.h (+1/-65)
modules/Ubuntu/Components/plugin/uclistitemactions_p.h (+0/-16)
modules/Ubuntu/Components/plugin/uclistitemattached.cpp (+93/-159)
modules/Ubuntu/Components/plugin/uclistitemstyle.h (+1/-1)
modules/Ubuntu/Components/plugin/ucviewitemsattached.cpp (+34/-29)
tests/resources/listitems/ListItemTest.qml (+8/-3)
tests/unit_x11/tst_components/tst_listitem.qml (+13/-4)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/76-refactoring
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Tim Peeters Approve
Review via email: mp+245714@code.launchpad.net

Commit message

Small refactoring to follow upstream concept on naming attached properties. Panels visualising ListItemActions are owned by ListItem and not being shared by the ListItemActiomns. In this way the same ListItemActions instance can be used on both leading and trailing side.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
1394. By Zsombor Egri

missing reset function

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Zsombor Egri (zsombi) wrote :

ubuntuuitoolkit.tests.custom_proxy_objects.test_header.ActionsTestCase.test_click_header_action_button_with_hidden_header(actions)
Failure ain't has anything to do with the changes in this MR.

1395. By Zsombor Egri

staging sync

1396. By Zsombor Egri

binding loop on swiping fixed; multiple panel swiping fixed

Revision history for this message
Tim Peeters (tpeeters) wrote :

62 - ListItemActions.visibleActions.length * MathUtils.clamp(visualizedActionWidth, height, actionsRow.maxItemWidth))
63 + ListItem.visibleActions.length * MathUtils.clamp(visualizedActionWidth, height, actionsRow.maxItemWidth))

visualizedActionWidth was there before, but I noticed this only now:
would it be more consistent with other QML classes if we named this paintedActionWidth? For example, Image has a paintedWidth.

Text had paintedWidth also.. but it seems to be removed in QtQuick 2.4? I don't see it here any more http://doc.qt.io/qt-5/qml-qtquick-text.html

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

76 - readonly property bool leading: panel.ListItemActions.status == panel.ListItemActions.Leading
77 + readonly property bool leading: ListItem.panelStatus == ListItem.Leading

I like that a bunch of pieces of code become shorter :)

Revision history for this message
Tim Peeters (tpeeters) wrote :

79 + /*
80 + Swiped offset.
81 + */
82 + readonly property real swipedOffset: leading ? width + x : ListItem.item.width - x;

would this be panelOffset? Or maybe just offset since we are inside ListItemPanel?

Revision history for this message
Tim Peeters (tpeeters) wrote :

79 + /*
80 + Swiped offset.
81 + */
82 + readonly property real swipedOffset: leading ? width + x : ListItem.item.width - x;
83 +
84 + /*
85 + Swiping
86 + */
87 + readonly property bool swiping: ListItem.item.highlighted && ListItem.item.contentMoving

The comments here don't add any information so can be removed.

Revision history for this message
Tim Peeters (tpeeters) wrote :

94 + left: (leading ? undefined : ListItem.item.contentItem.right)
95 + right: (leading ? ListItem.item.contentItem.left : undefined)

remove the '(' and ')' here.

Revision history for this message
Tim Peeters (tpeeters) wrote :

118 + Connections {
119 + target: panel.ListItem.item
120 + onContentMovementEnded: {
121 + if (actionsRow.selectedAction) {
122 + actionsRow.selectedAction.trigger(actionsRow.listItemIndex >= 0 ? actionsRow.listItemIndex : null);
123 + actionsRow.selectedAction = null;
124 + }

I'm just wondering if it would make sense to return -1 when listItemIndex < 0 (or listItemIndex is undefined?). That way in the Action.trigger(), the developer only has to deal with integer values.

review: Needs Information
Revision history for this message
Tim Peeters (tpeeters) wrote :

143 - var snapPos = (ListItemActions.offset > ListItemActions.listItem.swipeOvershoot && snapIn) ? panel.width : 0.0;
144 - ListItemActions.snapToPosition(snapPos);
145 + var snapPos = (swipedOffset > units.gu(2) && snapIn) ? panel.width : 0.0;
146 + ListItem.snapToPosition(snapPos);
147 }

You replaced swipeOvershoot by a hard-coded value here. Is that an improvement? It is better to have a constant defined.

Revision history for this message
Tim Peeters (tpeeters) wrote :

245 --- modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp 1970-01-01 00:00:00 +0000
246 +++ modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp 2015-01-12 15:45:30 +0000
247 @@ -0,0 +1,132 @@
248 +/*
249 + * Copyright 2014 Canonical Ltd.

I don't remember when was the first version of this file (no idea why the diff shows 1970), but let's make it 2015.

review: Needs Fixing
Revision history for this message
Tim Peeters (tpeeters) wrote :

412 + // make sure teh animation is not running

your favorite typo ;)

Revision history for this message
Tim Peeters (tpeeters) wrote :

412 + // make sure teh animation is not running
413 + snap->stop();
414 snap->setFrom(listItem->contentItem->property(snap->property().toLocal8Bit().constData()));
415 snap->setTo(to);
416 - snap->setAlwaysRunToEnd(true);
417 + snap->setAlwaysRunToEnd(false);

do you still need this now that you removed

195 - alwaysRunToEnd: true

Revision history for this message
Tim Peeters (tpeeters) wrote :

423 +void UCListItemSnapAnimator::stop()
424 +{
425 + QQuickPropertyAnimation *snap = getDefaultAnimation();
426 + if (snap && snap->isRunning()) {
427 + snap->stop();
428 + }
429 +}

where do you use this?
perhaps you should be calling this function in snap() instead of calling snap->stop() there.

Revision history for this message
Tim Peeters (tpeeters) wrote :

void UCListItem::setHighlightColor(const QColor &color)
{
    Q_D(UCListItem);
    if (d->highlightColor == color) {
        return;
    }
    d->highlightColor = color;
    // no more theme change watch
    d->customColor = true;
    update();
    Q_EMIT highlightColorChanged();
}
void UCListItem::resetHighlightColor()
{
    Q_D(UCListItem);
    d->customColor = false;
    d->highlightColor = getPaletteColor("selected", "background");
    update();
    Q_EMIT highlightColorChanged();
}

if you call setHighlightColor(color) // color == getPaletteColor("selected", "background") then customColor is not set to true, and you are still watching for palette updates, while it may be purely coincidence that you set the color to the palette color. So customColor = true should be moved before the if() (maybe update() too).

Revision history for this message
Tim Peeters (tpeeters) wrote :

Since we only have an overshoot for swiping,
1131 +void UCListItemPrivate::resetSwipeOvershoot()
may be called resetOvershoot()?

Revision history for this message
Tim Peeters (tpeeters) wrote :

1193 + Q_PROPERTY(UCListItemActions *actions READ actions NOTIFY actionsChanged)
1194 + Q_PROPERTY(QQmlListProperty<UCAction> visibleActions READ visibleActions NOTIFY visibleActionsChanged)
1195 + Q_PROPERTY(UCListItem *item READ item NOTIFY itemChanged)
1196 + Q_PROPERTY(int index READ index NOTIFY indexChanged)
1197 + Q_PROPERTY(UCListItem::PanelStatus panelStatus READ panelStatus NOTIFY panelStatusChanged)

why do we need to expose all of these publicly?

Revision history for this message
Tim Peeters (tpeeters) wrote :

2459 ListItem {
2460 Label {
2461 + id: label2
2462 anchors.fill: parent
2463 - text: "Another standalone ListItem"
2464 + text: "Another standalone ListItem\nStarted with custom style, reset to theme style on first click"
2465 }
2466 leadingActions: testItem.leadingActions
2467 trailingActions: ListItemActions {
2468 actions: leading.actions
2469 }
2470 + style: ListItemStyle {}
2471 + onClicked: { style = undefined; label2.text = "Another standalone ListItem" }
2472 }

This example would be more interesting if the custom style did something. Now it is basically an Item.

Revision history for this message
Tim Peeters (tpeeters) wrote :

2526 + Component { id: customStyle; ListItemStyle {} }
2527 +
2528 + function test_style_reset() {
2529 + testItem.style = customStyle;
2530 + testItem.style = undefined;
2531 + verify(testItem.style != 0, "Style set back to theme")
2532 + }

; missing

You only verify here that the style is not 0. Can we get the type of the style and validate that?

Revision history for this message
Zsombor Egri (zsombi) wrote :

> void UCListItem::setHighlightColor(const QColor &color)
> {
> Q_D(UCListItem);
> if (d->highlightColor == color) {
> return;
> }
> d->highlightColor = color;
> // no more theme change watch
> d->customColor = true;
> update();
> Q_EMIT highlightColorChanged();
> }
> void UCListItem::resetHighlightColor()
> {
> Q_D(UCListItem);
> d->customColor = false;
> d->highlightColor = getPaletteColor("selected", "background");
> update();
> Q_EMIT highlightColorChanged();
> }
>
>
> if you call setHighlightColor(color) // color == getPaletteColor("selected",
> "background") then customColor is not set to true, and you are still watching
> for palette updates, while it may be purely coincidence that you set the color
> to the palette color. So customColor = true should be moved before the if()
> (maybe update() too).

Well, if a property's default value is set again as value, there will be no change done either.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 62 - ListItemActions.visibleActions.length *
> MathUtils.clamp(visualizedActionWidth, height, actionsRow.maxItemWidth))
> 63 + ListItem.visibleActions.length *
> MathUtils.clamp(visualizedActionWidth, height, actionsRow.maxItemWidth))
>
> visualizedActionWidth was there before, but I noticed this only now:
> would it be more consistent with other QML classes if we named this
> paintedActionWidth? For example, Image has a paintedWidth.
>
> Text had paintedWidth also.. but it seems to be removed in QtQuick 2.4? I
> don't see it here any more http://doc.qt.io/qt-5/qml-qtquick-text.html

Ack, revno 1397.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 79 + /*
> 80 + Swiped offset.
> 81 + */
> 82 + readonly property real swipedOffset: leading ? width + x :
> ListItem.item.width - x;
>
> would this be panelOffset? Or maybe just offset since we are inside
> ListItemPanel?

The property tells what it is: the offset the swipe happened. I think it is good as is.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 79 + /*
> 80 + Swiped offset.
> 81 + */
> 82 + readonly property real swipedOffset: leading ? width + x :
> ListItem.item.width - x;
> 83 +
> 84 + /*
> 85 + Swiping
> 86 + */
> 87 + readonly property bool swiping: ListItem.item.highlighted &&
> ListItem.item.contentMoving
>
> The comments here don't add any information so can be removed.

Ok... revno 1398.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 94 + left: (leading ? undefined : ListItem.item.contentItem.right)
> 95 + right: (leading ? ListItem.item.contentItem.left : undefined)
>
> remove the '(' and ')' here.

Ack. revno 1399.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 118 + Connections {
> 119 + target: panel.ListItem.item
> 120 + onContentMovementEnded: {
> 121 + if (actionsRow.selectedAction) {
> 122 +
> actionsRow.selectedAction.trigger(actionsRow.listItemIndex >= 0 ?
> actionsRow.listItemIndex : null);
> 123 + actionsRow.selectedAction = null;
> 124 + }
>
>
> I'm just wondering if it would make sense to return -1 when listItemIndex < 0
> (or listItemIndex is undefined?). That way in the Action.trigger(), the
> developer only has to deal with integer values.

Fair point! I guess it is a remainder from times when it was checking the parameterType. revno 1400.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 143 - var snapPos = (ListItemActions.offset >
> ListItemActions.listItem.swipeOvershoot && snapIn) ? panel.width : 0.0;
> 144 - ListItemActions.snapToPosition(snapPos);
> 145 + var snapPos = (swipedOffset > units.gu(2) && snapIn) ?
> panel.width : 0.0;
> 146 + ListItem.snapToPosition(snapPos);
> 147 }
>
> You replaced swipeOvershoot by a hard-coded value here. Is that an
> improvement? It is better to have a constant defined.

The thing is that if we use swipeOvershoot, and that one is set to 10GU, it will snap out even if the first 2 actions will be visible, as those get visible on <10GU swiped offset. So as last time discussed, the magic number for the swipe is 2GU, that's why I have it.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 245 --- modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp
> 1970-01-01 00:00:00 +0000
> 246 +++ modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp
> 2015-01-12 15:45:30 +0000
> 247 @@ -0,0 +1,132 @@
> 248 +/*
> 249 + * Copyright 2014 Canonical Ltd.
>
>
> I don't remember when was the first version of this file (no idea why the diff
> shows 1970), but let's make it 2015.

Ok... I hope you won't change all the new files which were added last year in the future MRs... :) revno 1401

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 412 + // make sure teh animation is not running
>
> your favorite typo ;)

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 412 + // make sure teh animation is not running
> 413 + snap->stop();
> 414 snap->setFrom(listItem->contentItem->property(snap->property().to
> Local8Bit().constData()));
> 415 snap->setTo(to);
> 416 - snap->setAlwaysRunToEnd(true);
> 417 + snap->setAlwaysRunToEnd(false);
>
> do you still need this now that you removed
>
> 195 - alwaysRunToEnd: true

Just to make sure whenever I call complete() or stop() it will stop the animation.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 423 +void UCListItemSnapAnimator::stop()
> 424 +{
> 425 + QQuickPropertyAnimation *snap = getDefaultAnimation();
> 426 + if (snap && snap->isRunning()) {
> 427 + snap->stop();
> 428 + }
> 429 +}
>
> where do you use this?
> perhaps you should be calling this function in snap() instead of calling
> snap->stop() there.

Check the code :) It is used when mousePressed() is called, so if there is an animation, it will stop it => no binding loop on swiped property

Revision history for this message
Zsombor Egri (zsombi) wrote :

> Since we only have an overshoot for swiping,
> 1131 +void UCListItemPrivate::resetSwipeOvershoot()
> may be called resetOvershoot()?

The property is called swipeOvershoot afaik, so teh reset follows the naming follows the getter/setter/reset naming convention.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 1193 + Q_PROPERTY(UCListItemActions *actions READ actions NOTIFY
> actionsChanged)
> 1194 + Q_PROPERTY(QQmlListProperty<UCAction> visibleActions READ
> visibleActions NOTIFY visibleActionsChanged)
> 1195 + Q_PROPERTY(UCListItem *item READ item NOTIFY itemChanged)
> 1196 + Q_PROPERTY(int index READ index NOTIFY indexChanged)
> 1197 + Q_PROPERTY(UCListItem::PanelStatus panelStatus READ panelStatus
> NOTIFY panelStatusChanged)
>
> why do we need to expose all of these publicly?

How would you implement a panel without them?
- actions contains the ListItemActions the panell is about to visualize
- visibleActions is a helper property, which is updated automatically whenever an action.visible is changed, without this the QML code would be a bit painful
- index provides info about the ListItem index, however that can be accessed as well as context property, perhaps we can remove it
- the panelStatus is needed in order to know which panel is the instance

So apart from 'index' I don't know what to remove.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 2459 ListItem {
> 2460 Label {
> 2461 + id: label2
> 2462 anchors.fill: parent
> 2463 - text: "Another standalone ListItem"
> 2464 + text: "Another standalone ListItem\nStarted with
> custom style, reset to theme style on first click"
> 2465 }
> 2466 leadingActions: testItem.leadingActions
> 2467 trailingActions: ListItemActions {
> 2468 actions: leading.actions
> 2469 }
> 2470 + style: ListItemStyle {}
> 2471 + onClicked: { style = undefined; label2.text = "Another
> standalone ListItem" }
> 2472 }
>
> This example would be more interesting if the custom style did something. Now
> it is basically an Item.

Perhaps. I did not wanted to deal with any complicated there, it is enough to see that it doesn't do anything if nothing is set.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 2526 + Component { id: customStyle; ListItemStyle {} }
> 2527 +
> 2528 + function test_style_reset() {
> 2529 + testItem.style = customStyle;
> 2530 + testItem.style = undefined;
> 2531 + verify(testItem.style != 0, "Style set back to theme")
> 2532 + }
>
> ; missing
>
> You only verify here that the style is not 0. Can we get the type of the style
> and validate that?

Fixed in revno 1402.

1397. By Zsombor Egri

property rename

1398. By Zsombor Egri

comments removed

1399. By Zsombor Egri

parenthesis removed

1400. By Zsombor Egri

parameter when action triggered fixed

1401. By Zsombor Egri

year changed

1402. By Zsombor Egri

theme restoration test fixed

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

> > void UCListItem::setHighlightColor(const QColor &color)
> > {
> > Q_D(UCListItem);
> > if (d->highlightColor == color) {
> > return;
> > }
> > d->highlightColor = color;
> > // no more theme change watch
> > d->customColor = true;
> > update();
> > Q_EMIT highlightColorChanged();
> > }
> > void UCListItem::resetHighlightColor()
> > {
> > Q_D(UCListItem);
> > d->customColor = false;
> > d->highlightColor = getPaletteColor("selected", "background");
> > update();
> > Q_EMIT highlightColorChanged();
> > }
> >
> >
> > if you call setHighlightColor(color) // color == getPaletteColor("selected",
> > "background") then customColor is not set to true, and you are still
> watching
> > for palette updates, while it may be purely coincidence that you set the
> color
> > to the palette color. So customColor = true should be moved before the if()
> > (maybe update() too).
>
> Well, if a property's default value is set again as value, there will be no
> change done either.

But the link to the theme color should be broken, when you set a manual color (same as the theme color), the color should not be updated automatically any more when the theme color changes.

Revision history for this message
Tim Peeters (tpeeters) wrote :

> > 2526 + Component { id: customStyle; ListItemStyle {} }
> > 2527 +
> > 2528 + function test_style_reset() {
> > 2529 + testItem.style = customStyle;
> > 2530 + testItem.style = undefined;
> > 2531 + verify(testItem.style != 0, "Style set back to theme")
> > 2532 + }
> >
> > ; missing
> >
> > You only verify here that the style is not 0. Can we get the type of the
> style
> > and validate that?
>
> Fixed in revno 1402.

All changes are good, except this one. What I meant is to check the actual type of the component, but that can be difficult. The approach with the objectName can work, but I propose to use a more descriptive objectName ("ListItemThemeStyle"?), and to add a comment in uclistitem.cpp when you set the objectName, saying that you use it in tst_listitem.qml because from reading only the cpp now it is not clear why this code is there. Perhaps even comment in tst_listitem.qml that the objectName is set in UCListItemPrivate.resetStyle().

Revision history for this message
Zsombor Egri (zsombi) wrote :

> > > void UCListItem::setHighlightColor(const QColor &color)
> > > {
> > > Q_D(UCListItem);
> > > if (d->highlightColor == color) {
> > > return;
> > > }
> > > d->highlightColor = color;
> > > // no more theme change watch
> > > d->customColor = true;
> > > update();
> > > Q_EMIT highlightColorChanged();
> > > }
> > > void UCListItem::resetHighlightColor()
> > > {
> > > Q_D(UCListItem);
> > > d->customColor = false;
> > > d->highlightColor = getPaletteColor("selected", "background");
> > > update();
> > > Q_EMIT highlightColorChanged();
> > > }
> > >
> > >
> > > if you call setHighlightColor(color) // color ==
> getPaletteColor("selected",
> > > "background") then customColor is not set to true, and you are still
> > watching
> > > for palette updates, while it may be purely coincidence that you set the
> > color
> > > to the palette color. So customColor = true should be moved before the
> if()
> > > (maybe update() too).
> >
> > Well, if a property's default value is set again as value, there will be no
> > change done either.
>
> But the link to the theme color should be broken, when you set a manual color
> (same as the theme color), the color should not be updated automatically any
> more when the theme color changes.

We need to check how font.family is handled. That one gets its value from the default value set - the one we patched in the plugin. I need to check what happens if I set that default value in C++ to something else, while having the same value assigned to the property value in QML. If changing the default value changes the Text font, then we're good as we are now, e behave the same way. If it doesn't change, then we fix our code as well.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> > > 2526 + Component { id: customStyle; ListItemStyle {} }
> > > 2527 +
> > > 2528 + function test_style_reset() {
> > > 2529 + testItem.style = customStyle;
> > > 2530 + testItem.style = undefined;
> > > 2531 + verify(testItem.style != 0, "Style set back to
> theme")
> > > 2532 + }
> > >
> > > ; missing
> > >
> > > You only verify here that the style is not 0. Can we get the type of the
> > style
> > > and validate that?
> >
> > Fixed in revno 1402.
>
>
> All changes are good, except this one. What I meant is to check the actual
> type of the component, but that can be difficult. The approach with the
> objectName can work, but I propose to use a more descriptive objectName
> ("ListItemThemeStyle"?), and to add a comment in uclistitem.cpp when you set
> the objectName, saying that you use it in tst_listitem.qml because from
> reading only the cpp now it is not clear why this code is there. Perhaps even
> comment in tst_listitem.qml that the objectName is set in
> UCListItemPrivate.resetStyle().

Ok, will do that tomorrow.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> > > > void UCListItem::setHighlightColor(const QColor &color)
> > > > {
> > > > Q_D(UCListItem);
> > > > if (d->highlightColor == color) {
> > > > return;
> > > > }
> > > > d->highlightColor = color;
> > > > // no more theme change watch
> > > > d->customColor = true;
> > > > update();
> > > > Q_EMIT highlightColorChanged();
> > > > }
> > > > void UCListItem::resetHighlightColor()
> > > > {
> > > > Q_D(UCListItem);
> > > > d->customColor = false;
> > > > d->highlightColor = getPaletteColor("selected", "background");
> > > > update();
> > > > Q_EMIT highlightColorChanged();
> > > > }
> > > >
> > > >
> > > > if you call setHighlightColor(color) // color ==
> > getPaletteColor("selected",
> > > > "background") then customColor is not set to true, and you are still
> > > watching
> > > > for palette updates, while it may be purely coincidence that you set the
> > > color
> > > > to the palette color. So customColor = true should be moved before the
> > if()
> > > > (maybe update() too).
> > >
> > > Well, if a property's default value is set again as value, there will be
> no
> > > change done either.
> >
> > But the link to the theme color should be broken, when you set a manual
> color
> > (same as the theme color), the color should not be updated automatically any
> > more when the theme color changes.
>
> We need to check how font.family is handled. That one gets its value from the
> default value set - the one we patched in the plugin. I need to check what
> happens if I set that default value in C++ to something else, while having the
> same value assigned to the property value in QML. If changing the default
> value changes the Text font, then we're good as we are now, e behave the same
> way. If it doesn't change, then we fix our code as well.

Seems the font.family was a bad example, as it does not change the font of the text even if the font.family is not having any static value bound. So let's do the way that we mark it as custom color even if it is the same as the default one.

1403. By Zsombor Egri

style testing made more descriptive

1404. By Zsombor Egri

final comments applied

1405. By Zsombor Egri

staging merge

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

great, thanks! :)

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'components.api'
2--- components.api 2014-12-18 10:08:56 +0000
3+++ components.api 2015-01-16 14:53:38 +0000
4@@ -867,6 +867,7 @@
5 name: "UCListItem"
6 prototype: "UCStyledItemBase"
7 exports: ["ListItem 1.2"]
8+ name: "PanelStatus"
9 Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true }
10 Property { name: "divider"; type: "UCListItemDivider"; isReadonly: true; isPointer: true }
11 Property { name: "leadingActions"; type: "UCListItemActions"; isPointer: true }
12@@ -886,26 +887,19 @@
13 name: "UCListItemActions"
14 prototype: "QObject"
15 exports: ["ListItemActions 1.2"]
16- name: "Status"
17 Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
18 Property { name: "actions"; type: "UCAction"; isList: true; isReadonly: true }
19 Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
20- Signal {
21- name: "statusChanged"
22- Parameter { name: "status"; type: "Status" }
23- name: "UCListItemActionsAttached"
24+ name: "UCListItemAttached"
25 prototype: "QObject"
26- Property { name: "container"; type: "UCListItemActions"; isReadonly: true; isPointer: true }
27+ Property { name: "actions"; type: "UCListItemActions"; isReadonly: true; isPointer: true }
28 Property { name: "visibleActions"; type: "UCAction"; isList: true; isReadonly: true }
29- Property { name: "listItem"; type: "UCListItem"; isReadonly: true; isPointer: true }
30- Property { name: "listItemIndex"; type: "int"; isReadonly: true }
31- Property { name: "offset"; type: "double"; isReadonly: true }
32- Property { name: "status"; type: "UCListItemActions::Status"; isReadonly: true }
33- Property { name: "swiping"; type: "bool"; isReadonly: true }
34+ Property { name: "item"; type: "UCListItem"; isReadonly: true; isPointer: true }
35+ Property { name: "index"; type: "int"; isReadonly: true }
36+ Property { name: "panelStatus"; type: "UCListItem::PanelStatus"; isReadonly: true }
37 Method {
38 name: "snapToPosition"
39 Parameter { name: "position"; type: "double" }
40- Component { name: "UCListItemAttached"; prototype: "QObject" }
41 name: "UCListItemDivider"
42 prototype: "QObject"
43 Property { name: "visible"; type: "bool" }
44@@ -1010,6 +1004,9 @@
45 Signal {
46 name: "opened"
47 Parameter { name: "uris"; type: "QStringList" }
48+ name: "UCViewItemsAttached"
49+ prototype: "QObject"
50+ exports: ["ViewItems 1.2"]
51 name: "UbuntuI18n"
52 prototype: "QObject"
53 exports: ["i18n 0.1", "i18n 1.0"]
54
55=== modified file 'modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml'
56--- modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml 2014-12-17 07:06:31 +0000
57+++ modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml 2015-01-16 14:53:38 +0000
58@@ -38,32 +38,29 @@
59 /*
60 Specifies the width of the component visualizing the action.
61 */
62- property real visualizedActionWidth: units.gu(2.5)
63+ property real paintedActionWidth: units.gu(2.5)
64
65 // panel implementation
66 id: panel
67 width: Math.max(
68 actionsRow.childrenRect.width,
69- ListItemActions.visibleActions.length * MathUtils.clamp(visualizedActionWidth, height, actionsRow.maxItemWidth))
70+ ListItem.visibleActions.length * MathUtils.clamp(paintedActionWidth, height, actionsRow.maxItemWidth))
71
72 // used for module/autopilot testing
73 objectName: "ListItemPanel" + (leading ? "Leading" : "Trailing")
74
75 /*
76- Property holding the ListItem's contentItem instance
77- */
78- readonly property Item contentItem: parent ? parent.contentItem : null
79-
80- /*
81 Specifies whether the panel is used to visualize leading or trailing actions.
82 */
83- readonly property bool leading: panel.ListItemActions.status == panel.ListItemActions.Leading
84+ readonly property bool leading: ListItem.panelStatus == ListItem.Leading
85+ readonly property real swipedOffset: leading ? width + x : ListItem.item.width - x;
86+ readonly property bool swiping: ListItem.item.highlighted && ListItem.item.contentMoving
87
88 anchors {
89- left: contentItem ? (leading ? undefined : contentItem.right) : undefined
90- right: contentItem ? (leading ? contentItem.left : undefined) : undefined
91- top: contentItem ? contentItem.top : undefined
92- bottom: contentItem ? contentItem.bottom : undefined
93+ left: leading ? undefined : ListItem.item.contentItem.right
94+ right: leading ? ListItem.item.contentItem.left : undefined
95+ top: ListItem.item.contentItem.top
96+ bottom: ListItem.item.contentItem.bottom
97 }
98
99 Rectangle {
100@@ -71,17 +68,21 @@
101 anchors {
102 fill: parent
103 // add 4 times the overshoot margins to cover the background when tugged
104- leftMargin: (leading && panel.ListItemActions.listItem) ? -units.gu(4 * panel.ListItemActions.listItem.swipeOvershoot) : 0
105- rightMargin: (!leading && panel.ListItemActions.listItem) ? -units.gu(4 * panel.ListItemActions.listItem.swipeOvershoot) : 0
106+ leftMargin: (leading && panel.ListItem.item) ? -units.gu(4 * panel.ListItem.item.swipeOvershoot) : 0
107+ rightMargin: (!leading && panel.ListItem.item) ? -units.gu(4 * panel.ListItem.item.swipeOvershoot) : 0
108 }
109 color: panel.backgroundColor
110 }
111
112 // handle action triggering
113- ListItemActions.onStatusChanged: {
114- if (ListItemActions.status === ListItemActions.Disconnected && actionsRow.selectedAction) {
115- actionsRow.selectedAction.trigger(actionsRow.listItemIndex >= 0 ? actionsRow.listItemIndex : null);
116- actionsRow.selectedAction = null;
117+ Connections {
118+ target: panel.ListItem.item
119+ onContentMovementEnded: {
120+ if (actionsRow.selectedAction) {
121+ actionsRow.selectedAction.trigger(actionsRow.listItemIndex);
122+ actionsRow.listItemIndex = -1;
123+ actionsRow.selectedAction = null;
124+ }
125 }
126 }
127
128@@ -101,8 +102,8 @@
129 prevX = x;
130 }
131 // default snapping!
132- ListItemActions.onSwipingChanged: {
133- if (ListItemActions.swiping) {
134+ onSwipingChanged: {
135+ if (swiping) {
136 // the dragging got started, set prevX
137 prevX = panel.x;
138 return;
139@@ -111,8 +112,8 @@
140 return;
141 }
142 // snap in if the offset is bigger than the overshoot and the direction of the drag is to reveal the panel
143- var snapPos = (ListItemActions.offset > ListItemActions.listItem.swipeOvershoot && snapIn) ? panel.width : 0.0;
144- ListItemActions.snapToPosition(snapPos);
145+ var snapPos = (swipedOffset > units.gu(2) && snapIn) ? panel.width : 0.0;
146+ ListItem.snapToPosition(snapPos);
147 }
148
149 Row {
150@@ -124,13 +125,13 @@
151 leftMargin: spacing
152 }
153
154- property real maxItemWidth: panel.parent ? (panel.parent.width / panel.ListItemActions.visibleActions.length) : 0
155+ property real maxItemWidth: panel.ListItem.item.width / panel.ListItem.visibleActions.length
156
157 property Action selectedAction
158- property int listItemIndex
159+ property int listItemIndex: -1
160
161 Repeater {
162- model: panel.ListItemActions.visibleActions
163+ model: panel.ListItem.visibleActions
164 AbstractButton {
165 id: actionButton
166 action: modelData
167@@ -143,8 +144,8 @@
168 }
169 function trigger() {
170 actionsRow.selectedAction = modelData;
171- actionsRow.listItemIndex = panel.ListItemActions.listItemIndex;
172- panel.ListItemActions.snapToPosition(0.0);
173+ actionsRow.listItemIndex = panel.ListItem.index;
174+ panel.ListItem.snapToPosition(0.0);
175 }
176
177 Rectangle {
178@@ -156,7 +157,7 @@
179 Loader {
180 id: delegateLoader
181 height: parent.height
182- sourceComponent: panel.ListItemActions.container.delegate ? panel.ListItemActions.container.delegate : defaultDelegate
183+ sourceComponent: panel.ListItem.actions.delegate ? panel.ListItem.actions.delegate : defaultDelegate
184 property Action action: modelData
185 property int index: index
186 property bool pressed: actionButton.pressed
187@@ -177,7 +178,7 @@
188 Item {
189 width: height
190 Icon {
191- width: panel.visualizedActionWidth
192+ width: panel.paintedActionWidth
193 height: width
194 name: action.iconName
195 color: panel.foregroundColor
196
197=== modified file 'modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml'
198--- modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml 2014-12-01 11:13:10 +0000
199+++ modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml 2015-01-16 14:53:38 +0000
200@@ -30,7 +30,6 @@
201 period: 0.5
202 }
203 duration: UbuntuAnimation.BriskDuration
204- alwaysRunToEnd: true
205 }
206
207 }
208
209=== modified file 'modules/Ubuntu/Components/plugin/plugin.cpp'
210--- modules/Ubuntu/Components/plugin/plugin.cpp 2014-12-03 14:43:27 +0000
211+++ modules/Ubuntu/Components/plugin/plugin.cpp 2015-01-16 14:53:38 +0000
212@@ -171,6 +171,7 @@
213 qmlRegisterType<UCListItem, 2>(uri, 1, 2, "ListItem");
214 qmlRegisterType<UCListItemDivider>();
215 qmlRegisterType<UCListItemActions, 2>(uri, 1, 2, "ListItemActions");
216+ qmlRegisterUncreatableType<UCViewItemsAttached, 2>(uri, 1, 2, "ViewItems", "Not instantiable");
217 }
218
219 void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
220
221=== modified file 'modules/Ubuntu/Components/plugin/plugin.pro'
222--- modules/Ubuntu/Components/plugin/plugin.pro 2014-12-03 14:43:27 +0000
223+++ modules/Ubuntu/Components/plugin/plugin.pro 2015-01-16 14:53:38 +0000
224@@ -111,10 +111,11 @@
225 adapters/actionsproxy_p.cpp \
226 uclistitem.cpp \
227 uclistitemactions.cpp \
228- uclistitemactionsattached.cpp \
229+ propertychange_p.cpp \
230+ uclistitemstyle.cpp \
231+ ucviewitemsattached.cpp \
232 uclistitemattached.cpp \
233- propertychange_p.cpp \
234- uclistitemstyle.cpp
235+ ucactionpanel_p.cpp
236
237 # adapters
238 SOURCES += adapters/alarmsadapter_organizer.cpp
239
240=== modified file 'modules/Ubuntu/Components/plugin/ucaction.h'
241--- modules/Ubuntu/Components/plugin/ucaction.h 2014-12-01 13:42:47 +0000
242+++ modules/Ubuntu/Components/plugin/ucaction.h 2015-01-16 14:53:38 +0000
243@@ -87,7 +87,7 @@
244 Type m_parameterType;
245
246 friend class UCActionContext;
247- friend class UCListItemActionsAttached;
248+ friend class UCListItemAttached;
249 friend class UCListItemActionsPrivate;
250
251 bool isValidType(QVariant::Type valueType);
252
253=== added file 'modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp'
254--- modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp 1970-01-01 00:00:00 +0000
255+++ modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp 2015-01-16 14:53:38 +0000
256@@ -0,0 +1,132 @@
257+/*
258+ * Copyright 2015 Canonical Ltd.
259+ *
260+ * This program is free software; you can redistribute it and/or modify
261+ * it under the terms of the GNU Lesser General Public License as published by
262+ * the Free Software Foundation; version 3.
263+ *
264+ * This program is distributed in the hope that it will be useful,
265+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
266+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
267+ * GNU Lesser General Public License for more details.
268+ *
269+ * You should have received a copy of the GNU Lesser General Public License
270+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
271+ */
272+
273+#include "uclistitemactions.h"
274+#include "uclistitemactions_p.h"
275+#include "uclistitem_p.h"
276+#include "quickutils.h"
277+#include "i18n.h"
278+#include "plugin.h"
279+#include <QtQml/QQmlInfo>
280+#include "ucaction.h"
281+#include "ucunits.h"
282+#include "uclistitemstyle.h"
283+
284+UCActionPanel::UCActionPanel(UCListItem *item, bool leading)
285+ : QObject(item)
286+ , listItem(item)
287+ , panelItem(0)
288+ , status(UCListItem::None)
289+ , leading(leading)
290+ , connected(false)
291+{
292+
293+}
294+
295+UCActionPanel::~UCActionPanel()
296+{
297+}
298+
299+UCListItemAttached *UCActionPanel::attachedObject()
300+{
301+ if (!panelItem) {
302+ return 0;
303+ }
304+ return static_cast<UCListItemAttached*>(
305+ qmlAttachedPropertiesObject<UCListItem>(panelItem, false));
306+}
307+
308+bool UCActionPanel::createPanel(QQmlComponent *panelDelegate)
309+{
310+ if (panelItem || !panelDelegate) {
311+ return false;
312+ }
313+ if (!panelDelegate->isError()) {
314+ QQmlContext *context = new QQmlContext(qmlContext(listItem));
315+ panelItem = qobject_cast<QQuickItem*>(panelDelegate->beginCreate(context));
316+ if (!panelItem) {
317+ qmlInfo(listItem) << UbuntuI18n::tr("Error creating ListItem actions panel");
318+ } else {
319+ context->setParent(panelItem);
320+ QQml_setParent_noEvent(panelItem, listItem);
321+ panelItem->setParentItem(listItem);
322+ // create attached property!
323+ UCListItemAttached *attached = static_cast<UCListItemAttached*>(
324+ qmlAttachedPropertiesObject<UCListItem>(panelItem));
325+ if (!attached->actions()) {
326+ attached->setList(listItem, leading, true);
327+ } else {
328+ // container is set, but we need to emit the signal again so we get the
329+ // attached props updated for those cases when the attached property is
330+ // created before the statement above
331+ Q_EMIT attached->actionsChanged();
332+ }
333+ panelDelegate->completeCreate();
334+ }
335+ } else {
336+ qmlInfo(listItem) << panelDelegate->errorString();
337+ }
338+ return panelItem != 0;
339+}
340+
341+UCListItemActions *UCActionPanel::actions()
342+{
343+ return leading ? UCListItemPrivate::get(listItem)->leadingActions :
344+ UCListItemPrivate::get(listItem)->trailingActions;
345+}
346+
347+QQuickItem *UCActionPanel::panel() const
348+{
349+ return panelItem;
350+}
351+
352+bool UCActionPanel::grabPanel(UCActionPanel **panel, UCListItem *item, bool leading)
353+{
354+ if (!(*panel) && item) {
355+ UCListItemActions *actions = leading ? UCListItemPrivate::get(item)->leadingActions :
356+ UCListItemPrivate::get(item)->trailingActions;
357+ if (actions) {
358+ (*panel) = new UCActionPanel(item, leading);
359+ UCListItemPrivate *pItem = UCListItemPrivate::get((*panel)->listItem);
360+ pItem->initStyleItem();
361+ if (!pItem->styleItem ||
362+ (pItem->styleItem && !(*panel)->createPanel(pItem->styleItem->m_actionsDelegate))) {
363+ delete (*panel);
364+ (*panel) = 0;
365+ }
366+ }
367+ }
368+ if (*panel) {
369+ (*panel)->connected = true;
370+ (*panel)->status = leading ? UCListItem::Leading : UCListItem::Trailing;
371+ Q_EMIT (*panel)->statusChanged();
372+ }
373+ return (*panel) != 0;
374+}
375+
376+void UCActionPanel::ungrabPanel(UCActionPanel *panel)
377+{
378+ if (!panel || !panel->connected) {
379+ return;
380+ }
381+ panel->connected = false;
382+ panel->panelItem->setVisible(false);
383+}
384+
385+bool UCActionPanel::isConnected(UCActionPanel *panel)
386+{
387+ return panel && panel->connected;
388+}
389
390=== modified file 'modules/Ubuntu/Components/plugin/uclistitem.cpp'
391--- modules/Ubuntu/Components/plugin/uclistitem.cpp 2015-01-07 06:42:09 +0000
392+++ modules/Ubuntu/Components/plugin/uclistitem.cpp 2015-01-16 14:53:38 +0000
393@@ -32,10 +32,6 @@
394 #include <QtQuick/private/qquickmousearea_p.h>
395 #include "uclistitemstyle.h"
396
397-#define MIN(x, y) ((x < y) ? x : y)
398-#define MAX(x, y) ((x > y) ? x : y)
399-#define CLAMP(v, min, max) (min <= max) ? MAX(min, MIN(v, max)) : MAX(max, MIN(v, min))
400-
401 QColor getPaletteColor(const char *profile, const char *color)
402 {
403 QColor result;
404@@ -85,6 +81,12 @@
405 if (!snap) {
406 // no animation, so we simply position the component
407 listItem->contentItem->setX(to);
408+ // and complete snap logic
409+ if (to == 0.0) {
410+ snapOut();
411+ } else {
412+ snapIn();
413+ }
414 return false;
415 }
416 snap->setTargetObject(listItem->contentItem);
417@@ -98,14 +100,24 @@
418 if (snap->properties().isEmpty() && snap->property().isEmpty()) {
419 snap->setProperty("x");
420 }
421+ // make sure the animation is not running
422+ snap->stop();
423 snap->setFrom(listItem->contentItem->property(snap->property().toLocal8Bit().constData()));
424 snap->setTo(to);
425- snap->setAlwaysRunToEnd(true);
426+ snap->setAlwaysRunToEnd(false);
427 listItem->setContentMoving(true);
428 snap->start();
429 return true;
430 }
431
432+void UCListItemSnapAnimator::stop()
433+{
434+ QQuickPropertyAnimation *snap = getDefaultAnimation();
435+ if (snap && snap->isRunning()) {
436+ snap->stop();
437+ }
438+}
439+
440 /*
441 * The function completes a running snap animation.
442 */
443@@ -131,17 +143,19 @@
444 QObject::disconnect(snap, 0, 0, 0);
445 }
446 UCListItemPrivate *listItem = UCListItemPrivate::get(item);
447- if (listItem->attachedProperties) {
448+ if (listItem->parentAttached) {
449 // restore flickable's interactive and cleanup
450- listItem->attachedProperties->disableInteractive(item, false);
451+ listItem->parentAttached->disableInteractive(item, false);
452 // no need to listen flickables any longer
453 listItem->listenToRebind(false);
454 }
455 // disconnect actions
456- listItem->grabPanel(listItem->leadingActions, false);
457- listItem->grabPanel(listItem->trailingActions, false);
458+ UCActionPanel::ungrabPanel(listItem->leadingPanel);
459+ UCActionPanel::ungrabPanel(listItem->trailingPanel);
460 // set contentMoved to false
461 listItem->setContentMoving(false);
462+ // lock contentItem left/right edges
463+ listItem->lockContentItem(true);
464 }
465
466 /*
467@@ -176,8 +190,6 @@
468 UCListItemDivider::UCListItemDivider(QObject *parent)
469 : QObject(parent)
470 , m_visible(true)
471- , m_leftMarginChanged(false)
472- , m_rightMarginChanged(false)
473 , m_colorFromChanged(false)
474 , m_colorToChanged(false)
475 , m_thickness(0)
476@@ -202,14 +214,9 @@
477
478 void UCListItemDivider::unitsChanged()
479 {
480- m_thickness = UCUnits::instance().dp(2);
481- if (!m_leftMarginChanged) {
482- m_leftMargin = UCUnits::instance().dp(2);
483- }
484- if (!m_rightMarginChanged) {
485- m_rightMargin = UCUnits::instance().dp(2);
486- }
487+ m_thickness = UCUnits::instance().dp(DIVIDER_THICKNESS_DP);
488 if (m_listItem) {
489+ m_listItem->adjustContentItemHeight();
490 m_listItem->update();
491 }
492 }
493@@ -273,9 +280,9 @@
494 return;
495 }
496 m_visible = visible;
497- m_listItem->resize();
498- m_listItem->update();
499 Q_EMIT visibleChanged();
500+ // set/reset contentItem's bottomMargin
501+ m_listItem->adjustContentItemHeight();
502 }
503
504 void UCListItemDivider::setLeftMargin(qreal leftMargin)
505@@ -284,7 +291,6 @@
506 return;
507 }
508 m_leftMargin = leftMargin;
509- m_leftMarginChanged = true;
510 m_listItem->update();
511 Q_EMIT leftMarginChanged();
512 }
513@@ -295,7 +301,6 @@
514 return;
515 }
516 m_rightMargin = rightMargin;
517- m_rightMarginChanged = true;
518 m_listItem->update();
519 Q_EMIT rightMarginChanged();
520 }
521@@ -329,25 +334,26 @@
522 : UCStyledItemBasePrivate()
523 , highlighted(false)
524 , contentMoved(false)
525- , highlightColorChanged(false)
526 , swiped(false)
527 , suppressClick(false)
528 , ready(false)
529- , customStyle(false)
530 , customColor(false)
531 , customOvershoot(false)
532 , flicked(false)
533- , xAxisMoveThresholdGU(1.5)
534+ , xAxisMoveThresholdGU(DEFAULT_SWIPE_THRESHOLD_GU)
535 , overshoot(0)
536 , color(Qt::transparent)
537 , highlightColor(Qt::transparent)
538- , attachedProperties(0)
539+ , parentAttached(0)
540 , contentItem(new QQuickItem)
541 , divider(new UCListItemDivider)
542 , leadingActions(0)
543 , trailingActions(0)
544+ , leadingPanel(0)
545+ , trailingPanel(0)
546 , animator(0)
547 , styleComponent(0)
548+ , implicitStyleComponent(0)
549 , styleItem(0)
550 {
551 }
552@@ -391,13 +397,17 @@
553
554 void UCListItemPrivate::_q_updateThemedData()
555 {
556+ Q_Q(UCListItem);
557+ // we reload the implicit style only if the custom style is not set, and
558+ // the component is ready
559+ if (!styleComponent && ready) {
560+ resetStyle();
561+ }
562+
563 // update colors, panels
564 if (!customColor) {
565- Q_Q(UCListItem);
566- highlightColor = getPaletteColor("selected", "background");
567- q->update();
568+ q->resetHighlightColor();
569 }
570- loadStyle(true);
571 }
572
573 void UCListItemPrivate::_q_rebound()
574@@ -405,8 +415,8 @@
575 setHighlighted(false);
576 // initiate rebinding only if there were actions tugged
577 Q_Q(UCListItem);
578- if (!UCListItemActionsPrivate::isConnectedTo(leadingActions, q) &&
579- !UCListItemActionsPrivate::isConnectedTo(trailingActions, q)) {
580+ if (!UCActionPanel::isConnected(leadingPanel) &&
581+ !UCActionPanel::isConnected(trailingPanel)) {
582 return;
583 }
584 setSwiped(false);
585@@ -430,7 +440,7 @@
586 */
587 QQmlComponent *UCListItemPrivate::style() const
588 {
589- return styleComponent;
590+ return styleComponent ? styleComponent : implicitStyleComponent;
591 }
592 void UCListItemPrivate::setStyle(QQmlComponent *delegate)
593 {
594@@ -438,54 +448,89 @@
595 return;
596 }
597 Q_Q(UCListItem);
598+ if (!delegate) {
599+ // undefined or null delegate resets the style to theme
600+ resetStyle();
601+ return;
602+ }
603 // make sure we're rebound before we change the panel component
604 promptRebound();
605+ bool reloadStyle = styleItem != 0;
606 if (styleItem) {
607- delete styleItem;
608+ styleItem->deleteLater();
609 styleItem = 0;
610 Q_EMIT q->__styleInstanceChanged();
611 }
612- delete styleComponent;
613- customStyle = (delegate == 0);
614 styleComponent = delegate;
615- loadStyle(false);
616+ // delete theme style for now
617+ if (implicitStyleComponent) {
618+ implicitStyleComponent->deleteLater();
619+ implicitStyleComponent = 0;
620+ }
621+ if (reloadStyle) {
622+ initStyleItem();
623+ }
624 Q_EMIT q->styleChanged();
625 }
626-
627-// update themed components
628-bool UCListItemPrivate::loadStyle(bool reload)
629+void UCListItemPrivate::resetStyle()
630 {
631- if (!ready) {
632- return false;
633- }
634- if (!customStyle) {
635- Q_Q(UCListItem);
636- if (reload && styleItem) {
637- delete styleItem;
638+ if (styleComponent || !implicitStyleComponent) {
639+ styleComponent = 0;
640+ // rebound as the current panels are not gonna be valid anymore
641+ if (swiped) {
642+ promptRebound();
643+ }
644+ bool reloadStyle = styleItem != 0;
645+ if (styleItem) {
646+ styleItem->deleteLater();
647 styleItem = 0;
648- Q_EMIT q->__styleInstanceChanged();
649- }
650- delete styleComponent;
651- styleComponent = UCTheme::instance().createStyleComponent("ListItemStyle.qml", q);
652+ }
653+ delete implicitStyleComponent;
654+ Q_Q(UCListItem);
655+ implicitStyleComponent = UCTheme::instance().createStyleComponent("ListItemStyle.qml", q);
656+ // set the objectnane for testing in tst_listitems.qml
657+ implicitStyleComponent->setObjectName("ListItemThemeStyle");
658+ // re-create style instance if it was created using the implicit style
659+ if (reloadStyle) {
660+ initStyleItem();
661+ }
662+ Q_EMIT q->styleChanged();
663 }
664- return (styleComponent != NULL);
665 }
666+
667 // creates the style item
668 void UCListItemPrivate::initStyleItem()
669 {
670- if (!styleItem && !loadStyle(false)) {
671+ if (!ready || styleItem) {
672 return;
673 }
674+ // get the component the style instance is created from
675 Q_Q(UCListItem);
676- QObject *object = styleComponent->beginCreate(qmlContext(q));
677+ QQmlComponent *delegate = style();
678+ if (!delegate) {
679+ // the style is not loaded from the theme yet
680+ _q_updateThemedData();
681+ delegate = style();
682+ }
683+ if (!delegate) {
684+ return;
685+ }
686+ if (delegate->isError()) {
687+ qmlInfo(q) << delegate->errorString();
688+ return;
689+ }
690+ QQmlContext *context = new QQmlContext(qmlContext(q));
691+ QObject *object = delegate->beginCreate(context);
692 styleItem = qobject_cast<UCListItemStyle*>(object);
693 if (!styleItem) {
694 delete object;
695- styleComponent->completeCreate();
696+ delegate->completeCreate();
697+ delete context;
698 return;
699 }
700+ context->setParent(styleItem);
701 QQml_setParent_noEvent(styleItem, q);
702- styleComponent->completeCreate();
703+ delegate->completeCreate();
704 Q_EMIT q->__styleInstanceChanged();
705
706 // get the overshoot value from the style!
707@@ -519,8 +564,8 @@
708 {
709 Q_Q(UCListItem);
710 QQuickItem *owner = flickable ? flickable : parentItem;
711- q->setImplicitWidth(owner ? owner->width() : UCUnits::instance().gu(40));
712- q->setImplicitHeight(UCUnits::instance().gu(7));
713+ q->setImplicitWidth(owner ? owner->width() : UCUnits::instance().gu(IMPLICIT_LISTITEM_WIDTH_GU));
714+ q->setImplicitHeight(UCUnits::instance().gu(IMPLICIT_LISTITEM_HEIGHT_GU));
715 }
716
717 // returns the index of the list item when used in model driven views,
718@@ -580,40 +625,37 @@
719 }
720 }
721
722-// grabs the panels from the leading/trailing actions and disables all ascending flickables
723-bool UCListItemPrivate::grabPanel(UCListItemActions *actionsList, bool isTugged)
724-{
725- Q_Q(UCListItem);
726- if (isTugged) {
727- bool grab = UCListItemActionsPrivate::connectToListItem(actionsList, q, (actionsList == leadingActions));
728- if (attachedProperties) {
729- attachedProperties->disableInteractive(q, true);
730- }
731- return grab;
732- } else {
733- UCListItemActionsPrivate::disconnectFromListItem(actionsList);
734- return false;
735- }
736-}
737-
738-
739 // connects/disconnects from the Flickable anchestor to get notified when to do rebound
740 void UCListItemPrivate::listenToRebind(bool listen)
741 {
742- if (attachedProperties) {
743+ if (parentAttached) {
744 Q_Q(UCListItem);
745- attachedProperties->listenToRebind(q, listen);
746- }
747-}
748-
749-void UCListItemPrivate::resize()
750-{
751- Q_Q(UCListItem);
752- QRectF rect(q->boundingRect());
753- if (divider && divider->m_visible) {
754- rect.setHeight(rect.height() - divider->m_thickness);
755- }
756- contentItem->setSize(rect.size());
757+ parentAttached->listenToRebind(q, listen);
758+ }
759+}
760+
761+// lock/unlock contentItem's left and right anchors to the ListItem's left and right
762+void UCListItemPrivate::lockContentItem(bool lock)
763+{
764+ QQuickAnchors *contentAnchors = QQuickItemPrivate::get(contentItem)->anchors();
765+ if (lock) {
766+ contentAnchors->setLeft(left());
767+ contentAnchors->setRight(right());
768+ } else {
769+ contentAnchors->resetLeft();
770+ contentAnchors->resetRight();
771+ }
772+}
773+
774+// adjust contentItem height depending on teh divider's visibility
775+void UCListItemPrivate::adjustContentItemHeight()
776+{
777+ QQuickAnchors *contentAnchors = QQuickItemPrivate::get(contentItem)->anchors();
778+ if (divider->m_visible) {
779+ contentAnchors->setBottomMargin(divider->m_thickness);
780+ } else {
781+ contentAnchors->resetBottomMargin();
782+ }
783 }
784
785 void UCListItemPrivate::update()
786@@ -628,13 +670,13 @@
787 // clamps the X value and moves the contentItem to the new X value
788 void UCListItemPrivate::clampAndMoveX(qreal &x, qreal dx)
789 {
790- UCListItemActionsPrivate *leading = UCListItemActionsPrivate::get(leadingActions);
791- UCListItemActionsPrivate *trailing = UCListItemActionsPrivate::get(trailingActions);
792 x += dx;
793 // min cannot be less than the trailing's panel width
794- qreal min = (trailing && trailing->panelItem) ? -trailing->panelItem->width() - overshoot: 0;
795+ QQuickItem *leadingPanelItem = leadingPanel ? leadingPanel->panel() : 0;
796+ QQuickItem *trailingPanelItem = trailingPanel ? trailingPanel->panel() : 0;
797+ qreal min = (trailingPanelItem) ? -trailingPanelItem->width() - overshoot: 0;
798 // max cannot be bigger than 0 or the leading's width in case we have leading panel
799- qreal max = (leading && leading->panelItem) ? leading->panelItem->width() + overshoot: 0;
800+ qreal max = (leadingPanelItem) ? leadingPanelItem->width() + overshoot: 0;
801 x = CLAMP(x, min, max);
802 }
803
804@@ -722,11 +764,14 @@
805 * When used in \c ListView or \l UbuntuListView, the last list item will not
806 * show the divider no matter of the visible property value set.
807 *
808- * ListItem can handle actions that can get tugged from front to back of the item.
809+ * ListItem can handle actions that can get swiped from front to back of the item.
810 * These actions are Action elements visualized in panels attached to the front
811 * or to the back of the item, and are revealed by swiping the item horizontally.
812- * The tug is started only after the mouse/touch move had passed a given threshold.
813- * These actions are configured through the \l leadingActions as well as \l
814+ * The swipe is started only after the mouse/touch move had passed a given threshold.
815+ * The actions are visualized by a panel, which is configurable through the \l
816+ * ListItemStyle::actionsDelegate style property.
817+ *
818+ * The actions are configured through the \l leadingActions as well as \l
819 * trailingActions properties.
820 * \qml
821 * ListItem {
822@@ -751,13 +796,11 @@
823 * }
824 * }
825 * \endqml
826- * \note When a list item is tugged, it automatically connects both leading and
827- * trailing actions to the list item. This implies that a ListItem cannot use
828- * the same ListItemActions instance for both leading and trailing actions. If
829- * it is desired to have the same action present in both leading and trailing
830- * actions, one of the ListItemActions actions list can use the other's list. In
831- * the following example the list item can be deleted through both leading and
832- * trailing actions:
833+ * \note When a list item is swiped, it automatically connects both leading and
834+ * trailing actions to the list item. If needed, the same ListItemActions instance
835+ * can be used in both leading and trailing side. In the following example the
836+ * list item can be deleted through both leading and trailing actions using the
837+ * same container:
838 * \qml
839 * ListItem {
840 * id: listItem
841@@ -769,13 +812,15 @@
842 * }
843 * ]
844 * }
845- * trailingActions: ListItemActions {
846- * actions: leadingActions.actions
847- * }
848+ * trailingActions: leadingActions
849 * }
850 * \endqml
851+ * The action is triggered only after all the animations are completed.
852 * \sa ListItemActions
853 *
854+ * ListItem provides a set of attached properties which are attached to each panel
855+ * of the ListItem. However not all properties are valid in all the circumstances.
856+ *
857 * The component is styled using the \l ListItemStyle style interface.
858 */
859
860@@ -799,13 +844,37 @@
861
862 UCListItemAttached *UCListItem::qmlAttachedProperties(QObject *owner)
863 {
864- return new UCListItemAttached(owner);
865+ /*
866+ * Detect the attachee, whether is it a child item of the panelItem. The panelItem
867+ * itself cannot be detected, as the object can be attached during the call of
868+ * component.beginCreate().
869+ */
870+ UCListItemAttached *attached = new UCListItemAttached(owner);
871+ QQuickItem *item = qobject_cast<QQuickItem*>(owner);
872+ while (item) {
873+ // has item our attached property?
874+ UCListItemAttached *itemAttached = static_cast<UCListItemAttached*>(
875+ qmlAttachedPropertiesObject<UCListItem>(item, false));
876+ if (itemAttached) {
877+ attached->connectToAttached(itemAttached);
878+ break;
879+ }
880+ item = item->parentItem();
881+ }
882+ return attached;
883 }
884
885 void UCListItem::componentComplete()
886 {
887 UCStyledItemBase::componentComplete();
888 Q_D(UCListItem);
889+ // anchor contentItem prior doing anything else
890+ QQuickAnchors *contentAnchors = QQuickItemPrivate::get(d->contentItem)->anchors();
891+ contentAnchors->setTop(d->top());
892+ contentAnchors->setBottom(d->bottom());
893+ d->adjustContentItemHeight();
894+ d->lockContentItem(true);
895+
896 d->ready = true;
897 /* We only deal with ListView, as for other cases we would need to check the children
898 * changes, which would have an enormous impact on performance in case of huge amount
899@@ -838,21 +907,23 @@
900 d->flickable = qobject_cast<QQuickFlickable*>(data.item->parentItem());
901 }
902
903- // attach ListItem properties to the flickable or to the parent item
904- if (d->flickable) {
905- // connect to flickable to get width changes
906- d->attachedProperties = static_cast<UCListItemAttached*>(qmlAttachedPropertiesObject<UCListItem>(d->flickable));
907+ // attach ViewItems to parent item or to ListView
908+ QQuickItem *parentAttachee = data.item;
909+ if (d->flickable && d->flickable->inherits("QQuickListView")) {
910+ // attach to ListView
911+ d->parentAttached = static_cast<UCViewItemsAttached*>(qmlAttachedPropertiesObject<UCViewItemsAttached>(d->flickable));
912+ parentAttachee = d->flickable;
913 } else if (data.item) {
914- d->attachedProperties = static_cast<UCListItemAttached*>(qmlAttachedPropertiesObject<UCListItem>(data.item));
915+ d->parentAttached = static_cast<UCViewItemsAttached*>(qmlAttachedPropertiesObject<UCViewItemsAttached>(data.item));
916 } else {
917 // mark as not ready, so no action should be performed which depends on readyness
918 d->ready = false;
919 // about to be deleted or reparented, disable attached
920- d->attachedProperties = 0;
921+ d->parentAttached = 0;
922 }
923
924- if (data.item) {
925- QObject::connect(d->flickable ? d->flickable : data.item, SIGNAL(widthChanged()), this, SLOT(_q_updateSize()));
926+ if (parentAttachee) {
927+ QObject::connect(parentAttachee, SIGNAL(widthChanged()), this, SLOT(_q_updateSize()), Qt::DirectConnection);
928 }
929
930 // update size
931@@ -860,14 +931,6 @@
932 }
933 }
934
935-void UCListItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
936-{
937- UCStyledItemBase::geometryChanged(newGeometry, oldGeometry);
938- // resize contentItem item
939- Q_D(UCListItem);
940- d->resize();
941-}
942-
943 QSGNode *UCListItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
944 {
945 Q_UNUSED(data);
946@@ -924,19 +987,26 @@
947 {
948 UCStyledItemBase::mousePressEvent(event);
949 Q_D(UCListItem);
950- if (d->attachedProperties && d->attachedProperties->isMoving()) {
951+ if (d->parentAttached && d->parentAttached->isMoving()) {
952 // while moving, we cannot select any items
953 return;
954 }
955 if (event->button() == Qt::LeftButton && d->canHighlight(event)) {
956+ // stop any ongoing animation!
957+ if (d->animator) {
958+ d->animator->stop();
959+ }
960 d->setHighlighted(true);
961 d->lastPos = d->pressedPos = event->localPos();
962 // connect the Flickable to know when to rebound
963 d->listenToRebind(true);
964 // if it was moved, grab the panels
965 if (d->swiped) {
966- d->grabPanel(d->leadingActions, true);
967- d->grabPanel(d->trailingActions, true);
968+ UCActionPanel::grabPanel(&d->leadingPanel, this, true);
969+ UCActionPanel::grabPanel(&d->trailingPanel, this, false);
970+ if (d->parentAttached) {
971+ d->parentAttached->disableInteractive(this, true);
972+ }
973 }
974 }
975 // accept the event so we get the rest of the events as well
976@@ -950,8 +1020,8 @@
977 // set released
978 if (d->highlighted) {
979 d->listenToRebind(false);
980- if (d->attachedProperties) {
981- d->attachedProperties->disableInteractive(this, false);
982+ if (d->parentAttached) {
983+ d->parentAttached->disableInteractive(this, false);
984 }
985
986 if (!d->suppressClick) {
987@@ -968,8 +1038,8 @@
988 UCStyledItemBase::mouseMoveEvent(event);
989
990 // accept the tugging only if the move is within the threshold
991- bool leadingAttached = UCListItemActionsPrivate::isConnectedTo(d->leadingActions, this);
992- bool trailingAttached = UCListItemActionsPrivate::isConnectedTo(d->trailingActions, this);
993+ bool leadingAttached = UCActionPanel::isConnected(d->leadingPanel);
994+ bool trailingAttached = UCActionPanel::isConnected(d->trailingPanel);
995 if (d->highlighted && !(leadingAttached || trailingAttached)) {
996 // check if we can initiate the drag at all
997 // only X direction matters, if Y-direction leaves the threshold, but X not, the tug is not valid
998@@ -984,8 +1054,13 @@
999 // got connected ad which not; this may fail in case of shared ListItemActions,
1000 // as then the panel is shared between the list items, and the panel might be
1001 // still in use in other panels. See UCListItemActionsPrivate::connectToListItem
1002- leadingAttached = d->grabPanel(d->leadingActions, true);
1003- trailingAttached = d->grabPanel(d->trailingActions, true);
1004+ leadingAttached = UCActionPanel::grabPanel(&d->leadingPanel, this, true);
1005+ trailingAttached = UCActionPanel::grabPanel(&d->trailingPanel, this, false);
1006+ // unlock contentItem's left/right edges
1007+ d->lockContentItem(false);
1008+ if (d->parentAttached) {
1009+ d->parentAttached->disableInteractive(this, true);
1010+ }
1011 // create animator if not created yet
1012 if (!d->animator) {
1013 d->animator = new UCListItemSnapAnimator(this);
1014@@ -1007,19 +1082,19 @@
1015 d->contentItem->setX(x);
1016 // decide which panel is visible by checking the contentItem's X coordinates
1017 if (d->contentItem->x() > 0) {
1018- if (leadingAttached) {
1019- UCListItemActionsPrivate::get(d->leadingActions)->panelItem->setVisible(true);
1020+ if (d->leadingPanel) {
1021+ d->leadingPanel->panel()->setVisible(true);
1022 }
1023- if (trailingAttached) {
1024- UCListItemActionsPrivate::get(d->trailingActions)->panelItem->setVisible(false);
1025+ if (d->trailingPanel) {
1026+ d->trailingPanel->panel()->setVisible(false);
1027 }
1028 } else if (d->contentItem->x() < 0) {
1029 // trailing revealed
1030- if (leadingAttached) {
1031- UCListItemActionsPrivate::get(d->leadingActions)->panelItem->setVisible(false);
1032+ if (d->leadingPanel) {
1033+ d->leadingPanel->panel()->setVisible(false);
1034 }
1035- if (trailingAttached) {
1036- UCListItemActionsPrivate::get(d->trailingActions)->panelItem->setVisible(true);
1037+ if (d->trailingPanel) {
1038+ d->trailingPanel->panel()->setVisible(true);
1039 }
1040 }
1041 }
1042@@ -1093,16 +1168,10 @@
1043 }
1044 // snap out before we change the actions
1045 d->promptRebound();
1046- // then delete panelItem
1047- if (d->leadingActions) {
1048- UCListItemActionsPrivate *list = UCListItemActionsPrivate::get(d->leadingActions);
1049- delete list->panelItem;
1050- list->panelItem = 0;
1051- }
1052+ // then delete panel
1053+ delete d->leadingPanel;
1054+ d->leadingPanel = 0;
1055 d->leadingActions = actions;
1056- if (d->leadingActions == d->trailingActions && d->leadingActions) {
1057- qmlInfo(this) << UbuntuI18n::tr("leadingActions and trailingActions cannot share the same object!");
1058- }
1059 Q_EMIT leadingActionsChanged();
1060 }
1061
1062@@ -1127,16 +1196,10 @@
1063 }
1064 // snap out before we change the actions
1065 d->promptRebound();
1066- // then delete panelItem
1067- if (d->trailingActions) {
1068- UCListItemActionsPrivate *list = UCListItemActionsPrivate::get(d->trailingActions);
1069- delete list->panelItem;
1070- list->panelItem = 0;
1071- }
1072+ // then delete panel
1073+ delete d->trailingPanel;
1074+ d->trailingPanel = 0;
1075 d->trailingActions = actions;
1076- if (d->leadingActions == d->trailingActions && d->trailingActions) {
1077- qmlInfo(this) << UbuntuI18n::tr("leadingActions and trailingActions cannot share the same object!");
1078- }
1079 Q_EMIT trailingActionsChanged();
1080 }
1081
1082@@ -1171,8 +1234,8 @@
1083 * The default values for the properties are:
1084 * \list
1085 * \li \c visible: true
1086- * \li \c leftMargin: 2 GU
1087- * \li \c rightMargin: 2 GU
1088+ * \li \c leftMargin: 0
1089+ * \li \c rightMargin: 0
1090 * \endlist
1091 */
1092 UCListItemDivider* UCListItem::divider() const
1093@@ -1253,7 +1316,8 @@
1094
1095 /*!
1096 * \qmlproperty color ListItem::highlightColor
1097- * Configures the color when highlighted. Defaults to the theme palette's background color.
1098+ * Configures the color when highlighted. Defaults to the theme palette's background
1099+ * color. If changed, it can be reset by assigning undefined as value.
1100 */
1101 QColor UCListItem::highlightColor() const
1102 {
1103@@ -1263,12 +1327,20 @@
1104 void UCListItem::setHighlightColor(const QColor &color)
1105 {
1106 Q_D(UCListItem);
1107+ // mark it as custom even if the value is the same as the previous one
1108+ d->customColor = true;
1109 if (d->highlightColor == color) {
1110 return;
1111 }
1112 d->highlightColor = color;
1113- // no more theme change watch
1114- d->customColor = true;
1115+ update();
1116+ Q_EMIT highlightColorChanged();
1117+}
1118+void UCListItem::resetHighlightColor()
1119+{
1120+ Q_D(UCListItem);
1121+ d->customColor = false;
1122+ d->highlightColor = getPaletteColor("selected", "background");
1123 update();
1124 Q_EMIT highlightColorChanged();
1125 }
1126@@ -1277,7 +1349,7 @@
1127 * \qmlproperty real ListItem::swipeOvershoot
1128 * The property configures the overshoot value on swiping. Its default value is
1129 * configured by the \l {ListItemStyle}{style}. Any positive value overrides the
1130- * default value, and any negative value resets it back to the default.
1131+ * default value, and any negative or undefined value resets it back to the default.
1132 */
1133 qreal UCListItemPrivate::swipeOvershoot() const
1134 {
1135@@ -1285,16 +1357,26 @@
1136 }
1137 void UCListItemPrivate::setSwipeOvershoot(qreal overshoot)
1138 {
1139+ // mark any positive value as custom even if it is the same as the previous one
1140+ customOvershoot = (overshoot >= 0.0);
1141 // same value should be guarded only if the style hasn't been loaded yet
1142 // swipeOvershoot can be set to 0 prior the style is loaded.
1143 if (this->overshoot == overshoot && styleItem) {
1144 return;
1145 }
1146- customOvershoot = (overshoot >= 0.0);
1147- this->overshoot = (overshoot < 0.0) ?
1148- // reset, use style to get the overshoot value
1149- (styleItem ? styleItem->m_swipeOvershoot : 0.0) :
1150- overshoot;
1151+ if (!customOvershoot) {
1152+ resetSwipeOvershoot();
1153+ return;
1154+ }
1155+ this->overshoot = overshoot;
1156+ update();
1157+ Q_Q(UCListItem);
1158+ Q_EMIT q->swipeOvershootChanged();
1159+}
1160+void UCListItemPrivate::resetSwipeOvershoot()
1161+{
1162+ customOvershoot = false;
1163+ overshoot = styleItem ? styleItem->m_swipeOvershoot : 0.0;
1164 update();
1165 Q_Q(UCListItem);
1166 Q_EMIT q->swipeOvershootChanged();
1167
1168=== modified file 'modules/Ubuntu/Components/plugin/uclistitem.h'
1169--- modules/Ubuntu/Components/plugin/uclistitem.h 2014-12-18 10:08:56 +0000
1170+++ modules/Ubuntu/Components/plugin/uclistitem.h 2015-01-16 14:53:38 +0000
1171@@ -34,17 +34,23 @@
1172 Q_PROPERTY(UCListItemActions *leadingActions READ leadingActions WRITE setLeadingActions NOTIFY leadingActionsChanged DESIGNABLE false)
1173 Q_PROPERTY(UCListItemActions *trailingActions READ trailingActions WRITE setTrailingActions NOTIFY trailingActionsChanged DESIGNABLE false)
1174 Q_PROPERTY(bool highlighted READ highlighted NOTIFY highlightedChanged)
1175- Q_PRIVATE_PROPERTY(UCListItem::d_func(), qreal swipeOvershoot READ swipeOvershoot WRITE setSwipeOvershoot NOTIFY swipeOvershootChanged)
1176+ Q_PRIVATE_PROPERTY(UCListItem::d_func(), qreal swipeOvershoot READ swipeOvershoot WRITE setSwipeOvershoot RESET resetSwipeOvershoot NOTIFY swipeOvershootChanged)
1177 Q_PRIVATE_PROPERTY(UCListItem::d_func(), bool contentMoving READ contentMoving NOTIFY contentMovingChanged)
1178 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
1179- Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setHighlightColor NOTIFY highlightColorChanged)
1180+ Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setHighlightColor RESET resetHighlightColor NOTIFY highlightColorChanged)
1181 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlListProperty<QObject> listItemData READ data DESIGNABLE false)
1182 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlListProperty<QQuickItem> listItemChildren READ children NOTIFY listItemChildrenChanged DESIGNABLE false)
1183 // FIXME move these to StyledItemBase with subtheming
1184- Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlComponent *style READ style WRITE setStyle NOTIFY styleChanged)
1185+ Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlComponent *style READ style WRITE setStyle RESET resetStyle NOTIFY styleChanged)
1186 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQuickItem *__styleInstance READ styleInstance NOTIFY __styleInstanceChanged)
1187 Q_CLASSINFO("DefaultProperty", "listItemData")
1188+ Q_ENUMS(PanelStatus)
1189 public:
1190+ enum PanelStatus {
1191+ None,
1192+ Leading,
1193+ Trailing
1194+ };
1195 explicit UCListItem(QQuickItem *parent = 0);
1196 ~UCListItem();
1197
1198@@ -61,12 +67,12 @@
1199 void setColor(const QColor &color);
1200 QColor highlightColor() const;
1201 void setHighlightColor(const QColor &color);
1202+ void resetHighlightColor();
1203
1204 protected:
1205 void componentComplete();
1206 QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
1207 void itemChange(ItemChange change, const ItemChangeData &data);
1208- void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
1209 void mousePressEvent(QMouseEvent *event);
1210 void mouseReleaseEvent(QMouseEvent *event);
1211 void mouseMoveEvent(QMouseEvent *event);
1212@@ -103,13 +109,57 @@
1213
1214 QML_DECLARE_TYPEINFO(UCListItem, QML_HAS_ATTACHED_PROPERTIES)
1215
1216+class UCAction;
1217+class UCListItemActions;
1218 class UCListItemAttachedPrivate;
1219 class UCListItemAttached : public QObject
1220 {
1221 Q_OBJECT
1222+ Q_PROPERTY(UCListItemActions *actions READ actions NOTIFY actionsChanged)
1223+ Q_PROPERTY(QQmlListProperty<UCAction> visibleActions READ visibleActions NOTIFY visibleActionsChanged)
1224+ Q_PROPERTY(UCListItem *item READ item NOTIFY itemChanged)
1225+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
1226+ Q_PROPERTY(UCListItem::PanelStatus panelStatus READ panelStatus NOTIFY panelStatusChanged)
1227 public:
1228- explicit UCListItemAttached(QObject *owner);
1229+ UCListItemAttached(QObject *parent = 0);
1230 ~UCListItemAttached();
1231+ void setList(UCListItem *list, bool leading, bool visualizeActions);
1232+ void connectToAttached(UCListItemAttached *parentAttached);
1233+
1234+ UCListItemActions *actions() const;
1235+ QQmlListProperty<UCAction> visibleActions();
1236+ UCListItem *item();
1237+ int index();
1238+ UCListItem::PanelStatus panelStatus();
1239+
1240+public Q_SLOTS:
1241+ void snapToPosition(qreal position);
1242+
1243+Q_SIGNALS:
1244+ void actionsChanged();
1245+ void visibleActionsChanged();
1246+ void itemChanged();
1247+ void indexChanged();
1248+ void panelStatusChanged();
1249+
1250+private:
1251+ Q_DECLARE_PRIVATE(UCListItemAttached)
1252+ friend class UCListItemAction;
1253+
1254+private Q_SLOTS:
1255+ void updateVisibleActions();
1256+};
1257+
1258+
1259+class UCViewItemsAttachedPrivate;
1260+class UCViewItemsAttached : public QObject
1261+{
1262+ Q_OBJECT
1263+public:
1264+ explicit UCViewItemsAttached(QObject *owner);
1265+ ~UCViewItemsAttached();
1266+
1267+ static UCViewItemsAttached *qmlAttachedProperties(QObject *owner);
1268
1269 bool listenToRebind(UCListItem *item, bool listen);
1270 void disableInteractive(UCListItem *item, bool disable);
1271@@ -119,8 +169,9 @@
1272 private Q_SLOTS:
1273 void unbindItem();
1274 private:
1275- Q_DECLARE_PRIVATE(UCListItemAttached)
1276- QScopedPointer<UCListItemAttachedPrivate> d_ptr;
1277+ Q_DECLARE_PRIVATE(UCViewItemsAttached)
1278+ QScopedPointer<UCViewItemsAttachedPrivate> d_ptr;
1279 };
1280+QML_DECLARE_TYPEINFO(UCViewItemsAttached, QML_HAS_ATTACHED_PROPERTIES)
1281
1282 #endif // UCLISTITEM_H
1283
1284=== modified file 'modules/Ubuntu/Components/plugin/uclistitem_p.h'
1285--- modules/Ubuntu/Components/plugin/uclistitem_p.h 2015-01-07 06:42:09 +0000
1286+++ modules/Ubuntu/Components/plugin/uclistitem_p.h 2015-01-16 14:53:38 +0000
1287@@ -22,6 +22,15 @@
1288 #include <QtCore/QPointer>
1289 #include <QtQuick/private/qquickrectangle_p.h>
1290
1291+#define MIN(x, y) ((x < y) ? x : y)
1292+#define MAX(x, y) ((x > y) ? x : y)
1293+#define CLAMP(v, min, max) (min <= max) ? MAX(min, MIN(v, max)) : MAX(max, MIN(v, min))
1294+
1295+#define IMPLICIT_LISTITEM_WIDTH_GU 40
1296+#define IMPLICIT_LISTITEM_HEIGHT_GU 7
1297+#define DIVIDER_THICKNESS_DP 2
1298+#define DEFAULT_SWIPE_THRESHOLD_GU 1.5
1299+
1300 class QQuickFlickable;
1301 class QQuickPropertyAnimation;
1302 class UCListItemContent;
1303@@ -29,6 +38,7 @@
1304 class UCListItemActions;
1305 class UCListItemSnapAnimator;
1306 class UCListItemStyle;
1307+class UCActionPanel;
1308 class UCListItemPrivate : public UCStyledItemBasePrivate
1309 {
1310 Q_DECLARE_PUBLIC(UCListItem)
1311@@ -53,19 +63,17 @@
1312 bool canHighlight(QMouseEvent *event);
1313 void setHighlighted(bool pressed);
1314 void setSwiped(bool tugged);
1315- bool grabPanel(UCListItemActions *optionList, bool isTugged);
1316 void listenToRebind(bool listen);
1317- void resize();
1318+ void lockContentItem(bool lock);
1319+ void adjustContentItemHeight();
1320 void update();
1321 void clampAndMoveX(qreal &x, qreal dx);
1322
1323 bool highlighted:1;
1324 bool contentMoved:1;
1325- bool highlightColorChanged:1;
1326 bool swiped:1;
1327 bool suppressClick:1;
1328 bool ready:1;
1329- bool customStyle:1;
1330 bool customColor:1;
1331 bool customOvershoot:1;
1332 bool flicked:1;
1333@@ -77,45 +85,65 @@
1334 QColor highlightColor;
1335 QPointer<QQuickItem> countOwner;
1336 QPointer<QQuickFlickable> flickable;
1337- QPointer<UCListItemAttached> attachedProperties;
1338+ QPointer<UCViewItemsAttached> parentAttached;
1339 QQuickItem *contentItem;
1340 UCListItemDivider *divider;
1341 UCListItemActions *leadingActions;
1342 UCListItemActions *trailingActions;
1343+ UCActionPanel *leadingPanel;
1344+ UCActionPanel *trailingPanel;
1345 UCListItemSnapAnimator *animator;
1346
1347 // FIXME move these to StyledItemBase togehther with subtheming.
1348 QQmlComponent *styleComponent;
1349+ QQmlComponent *implicitStyleComponent;
1350 UCListItemStyle *styleItem;
1351
1352 // getters/setters
1353 qreal swipeOvershoot() const;
1354 void setSwipeOvershoot(qreal overshoot);
1355+ void resetSwipeOvershoot();
1356 QQmlListProperty<QObject> data();
1357 QQmlListProperty<QQuickItem> children();
1358 bool contentMoving() const;
1359 void setContentMoving(bool moved);
1360 QQmlComponent *style() const;
1361 void setStyle(QQmlComponent *delegate);
1362- bool loadStyle(bool reload);
1363+ void resetStyle();
1364 void initStyleItem();
1365 QQuickItem *styleInstance() const;
1366 };
1367
1368+class UCListItemAttachedPrivate : public QObjectPrivate
1369+{
1370+ Q_DECLARE_PUBLIC(UCListItemAttached)
1371+public:
1372+ UCListItemAttachedPrivate() : QObjectPrivate(), panel(0), listItem(0) {}
1373+
1374+ static UCListItemAttachedPrivate* get(UCListItemAttached *that)
1375+ {
1376+ return that->d_func();
1377+ }
1378+
1379+ UCActionPanel *panel;
1380+ UCListItem *listItem;
1381+ QList<UCAction*> visibleActions;
1382+};
1383+
1384 class PropertyChange;
1385-class UCListItemAttachedPrivate
1386+class UCViewItemsAttachedPrivate
1387 {
1388- Q_DECLARE_PUBLIC(UCListItemAttached)
1389+ Q_DECLARE_PUBLIC(UCViewItemsAttached)
1390 public:
1391- UCListItemAttachedPrivate(UCListItemAttached *qq);
1392- ~UCListItemAttachedPrivate();
1393+ UCViewItemsAttachedPrivate(UCViewItemsAttached *qq);
1394+ ~UCViewItemsAttachedPrivate();
1395
1396 void clearFlickablesList();
1397 void buildFlickablesList();
1398 void clearChangesList();
1399 void buildChangesList(const QVariant &newValue);
1400
1401- UCListItemAttached *q_ptr;
1402+ UCViewItemsAttached *q_ptr;
1403 bool globalDisabled;
1404 QList< QPointer<QQuickFlickable> > flickables;
1405 QList< PropertyChange* > changes;
1406@@ -123,6 +151,41 @@
1407 QPointer<UCListItem> disablerItem;
1408 };
1409
1410+class UCActionPanel : public QObject
1411+{
1412+ Q_OBJECT
1413+public:
1414+ ~UCActionPanel();
1415+ static bool grabPanel(UCActionPanel **panel, UCListItem *item, bool leading);
1416+ static void ungrabPanel(UCActionPanel *panel);
1417+ static bool isConnected(UCActionPanel *panel);
1418+
1419+ UCListItemActions *actions();
1420+ QQuickItem *panel() const;
1421+ UCListItem::PanelStatus panelStatus()
1422+ {
1423+ return status;
1424+ }
1425+ bool isLeading() const
1426+ {
1427+ return leading;
1428+ }
1429+
1430+Q_SIGNALS:
1431+ void statusChanged();
1432+
1433+private:
1434+ UCActionPanel(UCListItem *item, bool leading);
1435+ bool createPanel(QQmlComponent *panelDelegate);
1436+ UCListItemAttached *attachedObject();
1437+
1438+ UCListItem *listItem;
1439+ QQuickItem *panelItem;
1440+ UCListItem::PanelStatus status;
1441+ bool leading:1;
1442+ bool connected:1;
1443+};
1444+
1445 class UCListItemDivider : public QObject
1446 {
1447 Q_OBJECT
1448@@ -159,8 +222,6 @@
1449 void setColorTo(const QColor &color);
1450
1451 bool m_visible:1;
1452- bool m_leftMarginChanged:1;
1453- bool m_rightMarginChanged:1;
1454 bool m_colorFromChanged:1;
1455 bool m_colorToChanged:1;
1456 qreal m_thickness;
1457@@ -187,6 +248,7 @@
1458 ~UCListItemSnapAnimator();
1459
1460 bool snap(qreal to);
1461+ void stop();
1462 void complete();
1463
1464 public Q_SLOTS:
1465
1466=== modified file 'modules/Ubuntu/Components/plugin/uclistitemactions.cpp'
1467--- modules/Ubuntu/Components/plugin/uclistitemactions.cpp 2014-12-01 14:50:13 +0000
1468+++ modules/Ubuntu/Components/plugin/uclistitemactions.cpp 2015-01-16 14:53:38 +0000
1469@@ -27,167 +27,13 @@
1470
1471 UCListItemActionsPrivate::UCListItemActionsPrivate()
1472 : QObjectPrivate()
1473- , status(UCListItemActions::Disconnected)
1474- , offsetDragged(0)
1475- , optionSlotWidth(0.0)
1476 , delegate(0)
1477- , panelDelegate(0)
1478- , panelItem(0)
1479 {
1480 }
1481 UCListItemActionsPrivate::~UCListItemActionsPrivate()
1482 {
1483 }
1484
1485-void UCListItemActionsPrivate::_q_updateDraggedOffset()
1486-{
1487- UCListItem *listItem = qobject_cast<UCListItem*>(panelItem->parentItem());
1488- if (!listItem) {
1489- return;
1490- }
1491-
1492- Q_Q(UCListItemActions);
1493- offsetDragged = (status == UCListItemActions::Leading) ? panelItem->width() + panelItem->x() :
1494- listItem->width() - panelItem->x();
1495- if (offsetDragged < 0.0) {
1496- offsetDragged = 0.0;
1497- }
1498-}
1499-
1500-UCListItemActionsAttached *UCListItemActionsPrivate::attachedObject()
1501-{
1502- if (!panelItem) {
1503- return 0;
1504- }
1505- return static_cast<UCListItemActionsAttached*>(
1506- qmlAttachedPropertiesObject<UCListItemActions>(panelItem, false));
1507-}
1508-
1509-/*
1510- * Connects a ListItem to the ListItemActions' panel and returns true upon successful connection.
1511- * Connection may fail if there is a different ListItem connected. In this case the new ListItem
1512- * will be queued and automatically connected when the previous ListItem disconnects.
1513- * The panel is only re-created when a different Component is used to create it.
1514- * FIXME - despite each ListItem uses the same document to create the panel, theming engine
1515- * provides different Component objects for each, due to not caching the components created.
1516- * This must be fixed to optimize memory usage.
1517- */
1518-bool UCListItemActionsPrivate::connectToListItem(UCListItemActions *actions, UCListItem *listItem, bool leading)
1519-{
1520- UCListItemActionsPrivate *_this = get(actions);
1521- if (!_this) {
1522- return false;
1523- }
1524- // do we have a panel created already?
1525- if (_this->panelItem) {
1526- if (isConnectedTo(actions, listItem)) {
1527- return true;
1528- }
1529- if (_this->panelItem->parentItem() && _this->panelItem->parentItem() != listItem) {
1530- // set the requesting listItem as queuedItem
1531- _this->queuedItem = listItem;
1532- return false;
1533- }
1534- }
1535- // no parent set or panelItem yet, proceed with panel creation
1536- UCListItemPrivate *pItem = UCListItemPrivate::get(listItem);
1537- pItem->initStyleItem();
1538- if (!pItem->styleItem || (pItem->styleItem && !_this->createPanelItem(pItem->styleItem->m_actionsDelegate))) {
1539- return false;
1540- }
1541-
1542- // check if the panel is still connected to a ListItem
1543- // this may happen if there is a swipe over an other item while the previous
1544- // one is rebounding
1545- _this->panelItem->setParentItem(listItem);
1546- if (_this->attachedObject()) {
1547- _this->attachedObject()->connectListItem(listItem, true);
1548- }
1549- _this->offsetDragged = 0.0;
1550- _this->status = leading ? UCListItemActions::Leading : UCListItemActions::Trailing;
1551- Q_EMIT actions->statusChanged(_this->status);
1552- return true;
1553-}
1554-
1555-void UCListItemActionsPrivate::disconnectFromListItem(UCListItemActions *actions)
1556-{
1557- UCListItemActionsPrivate *_this = get(actions);
1558- if (!_this || !_this->panelItem || !_this->panelItem->parentItem()) {
1559- return;
1560- }
1561-
1562- if (_this->attachedObject()) {
1563- _this->attachedObject()->connectListItem(static_cast<UCListItem*>(_this->panelItem->parentItem()), false);
1564- }
1565- _this->panelItem->setParentItem(0);
1566- _this->status = UCListItemActions::Disconnected;
1567- Q_EMIT actions->statusChanged(_this->status);
1568- // if there was a queuedItem, make it grab the actions list
1569- if (_this->queuedItem) {
1570- UCListItemPrivate::get(_this->queuedItem.data())->grabPanel(actions, true);
1571- // remove item from queue
1572- _this->queuedItem.clear();
1573- }
1574-}
1575-
1576-bool UCListItemActionsPrivate::isConnectedTo(UCListItemActions *actions, UCListItem *listItem)
1577-{
1578- UCListItemActionsPrivate *_this = get(actions);
1579- return _this && _this->panelItem &&
1580- (_this->status != UCListItemActions::Disconnected) &&
1581- (_this->panelItem->parentItem() == listItem);
1582-}
1583-
1584-QQuickItem *UCListItemActionsPrivate::createPanelItem(QQmlComponent *panel)
1585-{
1586- if (panelItem && panelDelegate == panel) {
1587- return panelItem;
1588- }
1589- // delete the panel if the next item's actionsDelegate differs from the
1590- // one this panel was created from
1591- if (panelDelegate != panel) {
1592- delete panelItem;
1593- panelItem = 0;
1594- }
1595-
1596- Q_Q(UCListItemActions);
1597- if (!panel) {
1598- qmlInfo(q) << UbuntuI18n::instance().tr("actionsDelegate not set!");
1599- return 0;
1600- }
1601-
1602- panelDelegate = panel;
1603- if (!panelDelegate->isError()) {
1604- panelItem = qobject_cast<QQuickItem*>(panelDelegate->beginCreate(qmlContext(q)));
1605- if (panelItem) {
1606- QQml_setParent_noEvent(panelItem, q);
1607- // add panelItem to data so we can access it in case is needed (i.e. tests)
1608- data.append(panelItem);
1609- // create attached property!
1610- UCListItemActionsAttached *attached = static_cast<UCListItemActionsAttached*>(
1611- qmlAttachedPropertiesObject<UCListItemActions>(panelItem));
1612- if (!attached->container()) {
1613- attached->setList(q);
1614- } else {
1615- // container is set, but we need to emit the signal again so we get the
1616- // attached props updated for those cases when the attached property is
1617- // created before the statement above
1618- Q_EMIT attached->containerChanged();
1619- }
1620- panelDelegate->completeCreate();
1621-
1622- // calculate option's slot size
1623- offsetDragged = 0.0;
1624- // connect to panel to catch dragging
1625- QObject::connect(panelItem, SIGNAL(xChanged()), q, SLOT(_q_updateDraggedOffset()));
1626- }
1627- } else {
1628- qmlInfo(q) << panelDelegate->errorString();
1629- }
1630-
1631- return panelItem;
1632-}
1633-
1634 /*!
1635 * \qmltype ListItemActions
1636 * \instantiates UCListItemActions
1637@@ -199,86 +45,22 @@
1638 *
1639 * ListItem accepts actions that can be configured to appear when swiped to left
1640 * or right. The API does not limit the number of actions to be assigned for leading
1641- * or trailing actions, however the design constrains are allowing a maximum of
1642+ * or trailing actions, however the design constraints are allowing a maximum of
1643 * 1 action on leading- and a maximum of 3 actions on trailing side of the ListItem.
1644 *
1645 * The \l actions are Action instances or elements derived from Action. The default
1646 * visualization of the actions can be overridden using the \l delegate property,
1647 * and the default implementation uses the \c name property of the Action.
1648 *
1649- * The leading and trailing actions are placed on a panel item, which is created
1650- * the first time the actions are accessed. The colors of the panel is taken from
1651- * the theme's palette.
1652- *
1653- * When swiped, panels reveal the actions one by one. In case an action is revealed
1654- * more than 50%, the action will be snapped and revealed completely. This is also
1655- * valid for the case when the action is visible less than 50%, in which case the
1656- * action is hidden. Actions can be triggered by tapping.
1657- *
1658- * \note You can use the same ListItemActions for leading and for trailing actions
1659- * the same time only if the instance is used by different groups of list items,
1660- * where one group uses it as leading and other group as trailing. In any other
1661- * circumstances use separate ListItemActions for leading and trailing actions.
1662- * \qml
1663- * import QtQuick 2.2
1664- * import Ubuntu.Components 1.2
1665- * MainView {
1666- * width: units.gu(40)
1667- * height: units.gu(71)
1668- *
1669- * ListItemActions {
1670- * id: sharedActions
1671- * actions: [
1672- * Action {
1673- * iconName: "search"
1674- * },
1675- * Action {
1676- * iconName: "edit"
1677- * },
1678- * Action {
1679- * iconName: "copy"
1680- * }
1681- * ]
1682- * }
1683- *
1684- * Column {
1685- * ListItem {
1686- * leadingActions: sharedActions
1687- * }
1688- * UbuntuListView {
1689- * anchors.fill: parent
1690- * model: 10000
1691- * delegate: ListItem {
1692- * trailingActions: sharedActions
1693- * }
1694- * }
1695- * }
1696- * }
1697- * \endqml
1698- *
1699 * \section3 Using with ListViews
1700 * ListItemActions instances can be shared between ListItem instances within the
1701 * same view. When shared, the memory footprint of the view will be lot smaller,
1702- * as there will be no individual panel created for each list's actions visualization.
1703- * Depending on how long the initialization of the component used in \l {ListItemStyle::actionsDelegate}
1704- * {actionsDelegate} takes, creation time will be also reduced to one time per view.
1705- * However, this implies that swiping a new ListItem content while another one is
1706- * swiped will result in showing the newly swiped item's panel delayed, as the
1707- * panel can be shown only after the previous item's snapping is completed. Depending
1708- * on the \l {ListItemStyle::snapAnimation}{snapAnimation} duration, this may take some time, and the
1709- * response time of the UI can become unacceptable.
1710- *
1711+ * as there will be no individual action container created for each list's actions.
1712 * Having individual ListItemActions instances increases the memory footprint,
1713- * however the UI will be more responsive as swiping individual ListItems will
1714- * not have to wait till the previous ListItem's panel is snapped out (rebound).
1715- * On the other hand, memory consumption will increase significantly due to
1716- * separate panel creation, and performance may decrease with up to 40%, depending
1717- * on what way are the actions declared, within the ListItemActions or as shared
1718- * actions.
1719+ * and also has performance impact on kinetic scrolling.
1720 *
1721- * The example above illustrates how to share ListItemActions between ListItem
1722- * delegates, which can be the worst-performant but most lightwaight memory consumer
1723- * setup. The following example illustrates the worst case:
1724+ * The examples below illustrate the worst and best practice when used in a ListView.
1725+ * The worst case:
1726 * \qml
1727 * import QtQuick 2.2
1728 * import Ubuntu.Components 1.2
1729@@ -323,33 +105,33 @@
1730 * width: units.gu(40)
1731 * height: units.gu(71)
1732 *
1733- * property list<Action> leading: [
1734- * Action {
1735+ * ListItemActions {
1736+ * id: leading
1737+ * actions: Action {
1738 * iconName: "delete"
1739 * }
1740- * ]
1741- * property list<Action> trailing: [
1742- * Action {
1743- * iconName: "search"
1744- * },
1745- * Action {
1746- * iconName: "edit"
1747- * },
1748- * Action {
1749- * iconName: "copy"
1750- * }
1751- * ]
1752+ * }
1753+ * ListItemActions {
1754+ * id: trailing
1755+ * actions: [
1756+ * Action {
1757+ * iconName: "search"
1758+ * },
1759+ * Action {
1760+ * iconName: "edit"
1761+ * },
1762+ * Action {
1763+ * iconName: "copy"
1764+ * }
1765+ * ]
1766+ * }
1767 *
1768 * UbuntuListView {
1769 * anchors.fill: parent
1770 * model: 10000
1771 * delegate: ListItem {
1772- * leadingActions: ListItemActions {
1773- * actions: leading
1774- * }
1775- * trailingActions: ListItemActions {
1776- * actions: trailing
1777- * }
1778+ * leadingActions: leading
1779+ * trailingActions: trailing
1780 * }
1781 * }
1782 * }
1783@@ -362,11 +144,6 @@
1784 * parameter to identify the instance of the ListItem on which it was executed,
1785 * in which case ListItem will change the type from \c Actions.None to \c Actions.Integer
1786 * when it is triggered.
1787- *
1788- * \section3 Attached properties
1789- * ListItemActions provides a set of attached properties to the panels visualizing
1790- * the actions. These properties can be used by implementations visualizing the
1791- * actions.
1792 */
1793
1794 UCListItemActions::UCListItemActions(QObject *parent)
1795@@ -377,28 +154,6 @@
1796 {
1797 }
1798
1799-UCListItemActionsAttached *UCListItemActions::qmlAttachedProperties(QObject *owner)
1800-{
1801- /*
1802- * Detect the attachee, whether is it a child item of the panelItem. The panelItem
1803- * itself cannot be detected, as the object can be attached during the call of
1804- * component.beginCreate().
1805- */
1806- UCListItemActionsAttached *attached = new UCListItemActionsAttached(owner);
1807- QQuickItem *item = qobject_cast<QQuickItem*>(owner);
1808- while (item) {
1809- // has item our attached property?
1810- UCListItemActionsAttached *itemAttached = static_cast<UCListItemActionsAttached*>(
1811- qmlAttachedPropertiesObject<UCListItemActions>(item, false));
1812- if (itemAttached) {
1813- attached->setList(itemAttached->container());
1814- break;
1815- }
1816- item = item->parentItem();
1817- }
1818- return attached;
1819-}
1820-
1821 /*!
1822 * \qmlproperty Component ListItemActions::delegate
1823 * The property holds the custom delegate to visualize the actions listed in the
1824@@ -461,7 +216,7 @@
1825 * }
1826 * \endqml
1827 * \note Putting a Rectangle in the delegate can be used to override the color
1828- * of the panel.
1829+ * of the panel. Also all ListItem attached properties can be used in the delegates.
1830 *
1831 * Defaults to null.
1832 */
1833
1834=== modified file 'modules/Ubuntu/Components/plugin/uclistitemactions.h'
1835--- modules/Ubuntu/Components/plugin/uclistitemactions.h 2014-12-01 12:20:02 +0000
1836+++ modules/Ubuntu/Components/plugin/uclistitemactions.h 2015-01-16 14:53:38 +0000
1837@@ -22,7 +22,6 @@
1838
1839 class QQmlComponent;
1840 class UCAction;
1841-class UCListItemActionsAttached;
1842 class UCListItemActionsPrivate;
1843 class UCListItemActions : public QObject
1844 {
1845@@ -31,18 +30,10 @@
1846 Q_PROPERTY(QQmlListProperty<UCAction> actions READ actions CONSTANT)
1847 Q_PROPERTY(QQmlListProperty<QObject> data READ data)
1848 Q_CLASSINFO("DefaultProperty", "data")
1849- Q_ENUMS(Status)
1850 public:
1851- enum Status {
1852- Disconnected,
1853- Leading,
1854- Trailing
1855- };
1856 explicit UCListItemActions(QObject *parent = 0);
1857 ~UCListItemActions();
1858
1859- static UCListItemActionsAttached *qmlAttachedProperties(QObject *owner);
1860-
1861 QQmlComponent *delegate() const;
1862 void setDelegate(QQmlComponent *delegate);
1863 QQmlListProperty<UCAction> actions();
1864@@ -50,64 +41,9 @@
1865
1866 Q_SIGNALS:
1867 void delegateChanged();
1868- void statusChanged(Status status);
1869
1870 private:
1871 Q_DECLARE_PRIVATE(UCListItemActions)
1872- Q_PRIVATE_SLOT(d_func(), void _q_updateDraggedOffset())
1873-};
1874-
1875-class UCListItemActionsAttached : public QObject
1876-{
1877- Q_OBJECT
1878- Q_PROPERTY(UCListItemActions *container READ container NOTIFY containerChanged)
1879- Q_PROPERTY(QQmlListProperty<UCAction> visibleActions READ visibleActions NOTIFY visibleActionsChanged)
1880- Q_PROPERTY(UCListItem *listItem READ listItem NOTIFY listItemChanged)
1881- Q_PROPERTY(int listItemIndex READ listItemIndex NOTIFY listItemIndexChanged)
1882- Q_PROPERTY(qreal offset READ offset NOTIFY offsetChanged)
1883- Q_PROPERTY(UCListItemActions::Status status READ status NOTIFY statusChanged)
1884- Q_PROPERTY(bool swiping READ swiping NOTIFY swipingChanged)
1885-public:
1886- UCListItemActionsAttached(QObject *parent = 0);
1887- ~UCListItemActionsAttached();
1888- void setList(UCListItemActions *list);
1889- void connectListItem(UCListItem *item, bool connect);
1890-
1891- UCListItemActions *container() const
1892- {
1893- return m_container.data();
1894- }
1895- QQmlListProperty<UCAction> visibleActions();
1896- UCListItem *listItem();
1897- int listItemIndex();
1898- bool swiping();
1899- qreal offset();
1900- UCListItemActions::Status status();
1901-
1902-
1903-public Q_SLOTS:
1904- void snapToPosition(qreal position);
1905-
1906-Q_SIGNALS:
1907- void containerChanged();
1908- void visibleActionsChanged();
1909- void listItemChanged();
1910- void listItemIndexChanged();
1911- void offsetChanged();
1912- void statusChanged();
1913- void swipingChanged();
1914-
1915-private:
1916- QPointer<UCListItemActions> m_container;
1917- QList<UCAction*> m_visibleActions;
1918- bool m_swiping;
1919- friend class UCListItemAction;
1920-
1921-private Q_SLOTS:
1922- void updateVisibleActions();
1923- void updateSwipeState();
1924-};
1925-
1926-QML_DECLARE_TYPEINFO(UCListItemActions, QML_HAS_ATTACHED_PROPERTIES)
1927+};
1928
1929 #endif // UCLISTITEMACTIONS_H
1930
1931=== modified file 'modules/Ubuntu/Components/plugin/uclistitemactions_p.h'
1932--- modules/Ubuntu/Components/plugin/uclistitemactions_p.h 2014-12-01 13:42:47 +0000
1933+++ modules/Ubuntu/Components/plugin/uclistitemactions_p.h 2015-01-16 14:53:38 +0000
1934@@ -32,30 +32,14 @@
1935 return actions ? actions->d_func() : 0;
1936 }
1937
1938- UCListItemActions::Status status;
1939- qreal offsetDragged;
1940- qreal optionSlotWidth;
1941-
1942 QQmlComponent *delegate;
1943- QQmlComponent *panelDelegate;
1944- QQuickItem *panelItem;
1945 QList<UCAction*> actions;
1946 QList<QObject*> data;
1947- QPointer<UCListItem> queuedItem;
1948-
1949- void _q_updateDraggedOffset();
1950- UCListItemActionsAttached *attachedObject();
1951-
1952- static bool connectToListItem(UCListItemActions *options, UCListItem *listItem, bool leading);
1953- static void disconnectFromListItem(UCListItemActions *options);
1954- static bool isConnectedTo(UCListItemActions *options, UCListItem *listItem);
1955
1956 static int actions_count(QQmlListProperty<UCAction> *p);
1957 static void actions_append(QQmlListProperty<UCAction> *p, UCAction *v);
1958 static UCAction *actions_at(QQmlListProperty<UCAction>*, int);
1959 static void actions_clear(QQmlListProperty<UCAction>*);
1960-
1961- QQuickItem *createPanelItem(QQmlComponent *delegate);
1962 };
1963
1964 #endif // UCLISTITEMACTIONS_P_H
1965
1966=== renamed file 'modules/Ubuntu/Components/plugin/uclistitemactionsattached.cpp' => 'modules/Ubuntu/Components/plugin/uclistitemattached.cpp'
1967--- modules/Ubuntu/Components/plugin/uclistitemactionsattached.cpp 2014-12-18 10:08:56 +0000
1968+++ modules/Ubuntu/Components/plugin/uclistitemattached.cpp 2015-01-16 14:53:38 +0000
1969@@ -21,218 +21,154 @@
1970 #include "ucunits.h"
1971 #include "ucaction.h"
1972
1973-UCListItemActionsAttached::UCListItemActionsAttached(QObject *parent)
1974- : QObject(parent)
1975- , m_swiping(false)
1976-{
1977-}
1978-
1979-UCListItemActionsAttached::~UCListItemActionsAttached()
1980-{
1981-}
1982-
1983-/*!
1984- * \qmlattachedproperty ListItemActions ListItemActions::container
1985- * \readonly
1986- * The property holds the instance of the \l ListItemActions the ListItem's actions
1987- * panel is visualizing.
1988- */
1989-void UCListItemActionsAttached::setList(UCListItemActions *list)
1990-{
1991- if (list == m_container) {
1992+UCListItemAttached::UCListItemAttached(QObject *parent)
1993+ : QObject(*(new UCListItemAttachedPrivate()), parent)
1994+{
1995+}
1996+
1997+UCListItemAttached::~UCListItemAttached()
1998+{
1999+}
2000+
2001+void UCListItemAttached::connectToAttached(UCListItemAttached *parentAttached)
2002+{
2003+ bool visualizeActions = UCListItemAttachedPrivate::get(parentAttached)->panel;
2004+ bool isLeading = visualizeActions ? UCListItemAttachedPrivate::get(parentAttached)->panel->isLeading() : false;
2005+ setList(parentAttached->item(), isLeading, visualizeActions);
2006+}
2007+
2008+void UCListItemAttached::setList(UCListItem *list, bool leading, bool visualizeActions)
2009+{
2010+ Q_D(UCListItemAttached);
2011+ if (d->listItem == list) {
2012 return;
2013 }
2014- m_container = list;
2015- if (!m_container.isNull()) {
2016+ d->listItem = list;
2017+ Q_EMIT itemChanged();
2018+
2019+ if (visualizeActions) {
2020+ d->panel = leading ? UCListItemPrivate::get(d->listItem)->leadingPanel : UCListItemPrivate::get(d->listItem)->trailingPanel;
2021+ } else {
2022+ d->panel = 0;
2023+ }
2024+ if (d->panel) {
2025 // connect statusChanged() to update status, listItem, listItemIndex and overshoot values
2026- QObject::connect(m_container.data(), &UCListItemActions::statusChanged,
2027- this, &UCListItemActionsAttached::statusChanged);
2028- QObject::connect(m_container.data(), &UCListItemActions::statusChanged,
2029- this, &UCListItemActionsAttached::listItemChanged);
2030- QObject::connect(m_container.data(), &UCListItemActions::statusChanged,
2031- this, &UCListItemActionsAttached::listItemIndexChanged);
2032-
2033- UCListItemActionsPrivate *actions = UCListItemActionsPrivate::get(m_container.data());
2034- // connect panel's xChanged to update the dragged offset
2035- QObject::connect(actions->panelItem, &QQuickItem::xChanged,
2036- this, &UCListItemActionsAttached::offsetChanged);
2037+ QObject::connect(d->panel, &UCActionPanel::statusChanged,
2038+ this, &UCListItemAttached::panelStatusChanged);
2039
2040 // connect actions to get updates about visible changes
2041- Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(m_container)->actions) {
2042+ Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(d->panel->actions())->actions) {
2043 QObject::connect(action, &UCAction::visibleChanged,
2044- this, &UCListItemActionsAttached::updateVisibleActions);
2045+ this, &UCListItemAttached::updateVisibleActions);
2046 }
2047 updateVisibleActions();
2048- }
2049- Q_EMIT containerChanged();
2050- Q_EMIT visibleActionsChanged();
2051-}
2052-
2053-void UCListItemActionsAttached::connectListItem(UCListItem *item, bool connect)
2054-{
2055- if (!item) {
2056- return;
2057- }
2058- if (connect) {
2059- QObject::connect(item, &UCListItem::highlightedChanged,
2060- this, &UCListItemActionsAttached::updateSwipeState);
2061- QObject::connect(item, &UCListItem::contentMovingChanged,
2062- this, &UCListItemActionsAttached::updateSwipeState);
2063- } else {
2064- QObject::disconnect(item, &UCListItem::highlightedChanged,
2065- this, &UCListItemActionsAttached::updateSwipeState);
2066- QObject::disconnect(item, &UCListItem::contentMovingChanged,
2067- this, &UCListItemActionsAttached::updateSwipeState);
2068+ Q_EMIT actionsChanged();
2069+ Q_EMIT visibleActionsChanged();
2070 }
2071 }
2072
2073 // private slot to update visible actions
2074-void UCListItemActionsAttached::updateVisibleActions()
2075+void UCListItemAttached::updateVisibleActions()
2076 {
2077- m_visibleActions.clear();
2078- if (!m_container.isNull()) {
2079- Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(m_container)->actions) {
2080+ Q_D(UCListItemAttached);
2081+ if (d->panel) {
2082+ d->visibleActions.clear();
2083+ Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(d->panel->actions())->actions) {
2084 if (action->m_visible) {
2085- m_visibleActions << action;
2086+ d->visibleActions << action;
2087 }
2088 }
2089+ Q_EMIT visibleActionsChanged();
2090 }
2091- Q_EMIT visibleActionsChanged();
2092 }
2093
2094-// private slot updating swipe state
2095-void UCListItemActionsAttached::updateSwipeState()
2096+/*!
2097+ * \qmlattachedproperty ListItemActions ListItem::actions
2098+ * \readonly
2099+ * The property holds the instance of the \l ListItemActions the ListItem's actions
2100+ * panel is visualizing. The property holds a valid value only when attached to
2101+ * the action visualizing panel defined in \l ListItemStyle::actionsDelegate style
2102+ * property.
2103+ */
2104+UCListItemActions *UCListItemAttached::actions() const
2105 {
2106- if (m_container.isNull()) {
2107- return;
2108- }
2109- QQuickItem *panelItem = UCListItemActionsPrivate::get(m_container)->panelItem;
2110- if (!panelItem || !panelItem->parentItem()) {
2111- return;
2112- }
2113- UCListItem *item = static_cast<UCListItem*>(panelItem->parentItem());
2114- UCListItemPrivate *listItem = UCListItemPrivate::get(item);
2115- bool swiped = listItem->highlighted && listItem->contentMoved;
2116- if (swiped != m_swiping) {
2117- m_swiping = swiped;
2118- Q_EMIT swipingChanged();
2119- }
2120+ Q_D(const UCListItemAttached);
2121+ return d->panel ? d->panel->actions() : 0;
2122 }
2123
2124 /*!
2125- * \qmlattachedproperty list<Action> ListItemActions::visibleActions
2126+ * \qmlattachedproperty list<Action> ListItem::visibleActions
2127 * Holds the list of visible actions. This is a convenience property to help action
2128- * visualization panel implementations to consider only visible actions.
2129+ * visualization panel implementations to consider only visible actions. Similar to
2130+ * \l actions attached property, it is only valid when attached to \l ListItemStyle::actionsDelegate
2131+ * component.
2132 */
2133-QQmlListProperty<UCAction> UCListItemActionsAttached::visibleActions()
2134+QQmlListProperty<UCAction> UCListItemAttached::visibleActions()
2135 {
2136- return QQmlListProperty<UCAction>(this, m_visibleActions);
2137+ Q_D(UCListItemAttached);
2138+ return QQmlListProperty<UCAction>(this, d->visibleActions);
2139 }
2140
2141 /*!
2142- * \qmlattachedproperty ListItem ListItemActions::listItem
2143+ * \qmlattachedproperty ListItem ListItem::item
2144 * \readonly
2145- * The property reports the connected \l ListItem to the list of actions.
2146+ * The property reports the connected \l ListItem to the panel. Valid in every attachee.
2147 */
2148-UCListItem *UCListItemActionsAttached::listItem()
2149+UCListItem *UCListItemAttached::item()
2150 {
2151- if (m_container.isNull()) {
2152- return NULL;
2153- }
2154- QQuickItem *panelItem = UCListItemActionsPrivate::get(m_container)->panelItem;
2155- if (!panelItem) {
2156- return NULL;
2157- }
2158- QQuickItem *listItem = panelItem->parentItem();
2159- return static_cast<UCListItem*>(listItem);
2160+ Q_D(UCListItemAttached);
2161+ return d->listItem;
2162 }
2163
2164 /*!
2165- * \qmlattachedproperty int ListItemActions::listItemIndex
2166+ * \qmlattachedproperty int ListItem::index
2167 * \readonly
2168 * Holds the index of the \l ListItem within a view, if the \l ListItem is used
2169- * in a model driven view. Otherwise it is set to -1.
2170- */
2171-int UCListItemActionsAttached::listItemIndex() {
2172- if (m_container.isNull()) {
2173- return -1;
2174- }
2175- QQuickItem *panelItem = UCListItemActionsPrivate::get(m_container)->panelItem;
2176- if (!panelItem) {
2177- return -1;
2178- }
2179- QQuickItem *listItem = panelItem->parentItem();
2180- return listItem ? UCListItemPrivate::get(static_cast<UCListItem*>(listItem))->index() : -1;
2181-}
2182-
2183-/*!
2184- * \qmlattachedproperty bool ListItemActions::swiping
2185- * \readonly
2186- * The property notifies whether the panel is swiped or not. The property does
2187- * not notify the rebounding.
2188- */
2189-bool UCListItemActionsAttached::swiping()
2190-{
2191- return m_swiping;
2192-}
2193-
2194-/*!
2195- * \qmlattachedproperty real ListItemActions::offset
2196- * The property returns the offset the panel item holding the visualized actions
2197- * is visible. This can be used to do different animations on the panel and on
2198- * the action visualizations.
2199- */
2200-qreal UCListItemActionsAttached::offset()
2201-{
2202- if (m_container.isNull()) {
2203- return 0.0;
2204- }
2205- return UCListItemActionsPrivate::get(m_container)->offsetDragged;
2206-}
2207-
2208-/*!
2209- * \qmlattachedproperty enum ListItemActions::status
2210+ * in a model driven view, or the child index otherwise. Valid in every attachee.
2211+ */
2212+int UCListItemAttached::index() {
2213+ Q_D(UCListItemAttached);
2214+ return d->listItem ? UCListItemPrivate::get(d->listItem)->index() : -1;
2215+}
2216+
2217+/*!
2218+ * \qmlattachedproperty enum ListItem::panelStatus
2219 * \readonly
2220 * The property holds the status of the ListItemActions, whether is connected
2221 * as leading or as trailing action list to a \l ListItem. Possible valueas are:
2222 * \list A
2223- * \li \b Disconnected - default, the actions list is not connected to any \l ListItem
2224+ * \li \b None - default, the actions list is not connected to any \l ListItem
2225 * \li \b Leading - the actions list is connected as leading list
2226 * \li \b Trailing - the actions list is connected as trailing list
2227 * \endlist
2228+ * The property is valid only when attached to \l ListItemStyle::actionsDelegate component.
2229 */
2230-UCListItemActions::Status UCListItemActionsAttached::status()
2231+UCListItem::PanelStatus UCListItemAttached::panelStatus()
2232 {
2233- if (m_container.isNull()) {
2234- return UCListItemActions::Disconnected;
2235+ Q_D(UCListItemAttached);
2236+ if (!d->panel) {
2237+ return UCListItem::None;
2238 }
2239- return UCListItemActionsPrivate::get(m_container)->status;
2240+ return d->panel->panelStatus();
2241 }
2242
2243 /*!
2244- * \qmlattachedmethod void ListItemActions::snapToPosition(real position)
2245+ * \qmlattachedmethod void ListItem::snapToPosition(real position)
2246 * The function can be used to perform custom snapping, or to execute rebounding
2247 * and also disconnecting from the connected \l ListItem. This can be achieved by
2248- * calling the function with 0.0 value.
2249+ * calling the function with 0.0 value. The slot has effect only when used from
2250+ * \l ListItemStyle::actionsDelegate component.
2251 */
2252-void UCListItemActionsAttached::snapToPosition(qreal position)
2253+void UCListItemAttached::snapToPosition(qreal position)
2254 {
2255+ UCListItem::PanelStatus itemStatus = panelStatus();
2256+ Q_D(UCListItemAttached);
2257 //if it is disconnected, leave (this also includes the case when m_container is null)
2258- if (status() == UCListItemActions::Disconnected) {
2259- return;
2260- }
2261- QQuickItem *panelItem = UCListItemActionsPrivate::get(m_container)->panelItem;
2262- if (!panelItem) {
2263- // we don't have the panel created yet
2264- return;
2265- }
2266- UCListItem *item = static_cast<UCListItem*>(panelItem->parentItem());
2267- if (!item) {
2268- // no ListItem attached
2269- return;
2270- }
2271- UCListItemPrivate *listItem = UCListItemPrivate::get(item);
2272- position *= (status() == UCListItemActions::Leading) ? 1 : -1;
2273+ if (!d->listItem || !d->panel || itemStatus == UCListItem::None) {
2274+ return;
2275+ }
2276+ UCListItemPrivate *listItem = UCListItemPrivate::get(d->listItem);
2277+ position *= (itemStatus == UCListItem::Leading) ? 1 : -1;
2278 if (position == 0.0) {
2279 listItem->_q_rebound();
2280 } else {
2281@@ -243,5 +179,3 @@
2282 }
2283 }
2284 }
2285-
2286-
2287
2288=== modified file 'modules/Ubuntu/Components/plugin/uclistitemstyle.h'
2289--- modules/Ubuntu/Components/plugin/uclistitemstyle.h 2014-12-01 11:13:10 +0000
2290+++ modules/Ubuntu/Components/plugin/uclistitemstyle.h 2015-01-16 14:53:38 +0000
2291@@ -46,7 +46,7 @@
2292 qreal m_swipeOvershoot;
2293
2294 friend class UCListItemPrivate;
2295- friend class UCListItemActionsPrivate;
2296+ friend class UCActionPanel;
2297 friend class UCListItemSnapAnimator;
2298 };
2299
2300
2301=== renamed file 'modules/Ubuntu/Components/plugin/uclistitemattached.cpp' => 'modules/Ubuntu/Components/plugin/ucviewitemsattached.cpp'
2302--- modules/Ubuntu/Components/plugin/uclistitemattached.cpp 2014-11-18 15:27:08 +0000
2303+++ modules/Ubuntu/Components/plugin/ucviewitemsattached.cpp 2015-01-16 14:53:38 +0000
2304@@ -28,34 +28,34 @@
2305 * in this way the controlling of the interactive flag of the Flickable and all
2306 * its ascendant Flickables.
2307 */
2308-UCListItemAttachedPrivate::UCListItemAttachedPrivate(UCListItemAttached *qq)
2309+UCViewItemsAttachedPrivate::UCViewItemsAttachedPrivate(UCViewItemsAttached *qq)
2310 : q_ptr(qq)
2311 , globalDisabled(false)
2312 {
2313 }
2314
2315-UCListItemAttachedPrivate::~UCListItemAttachedPrivate()
2316+UCViewItemsAttachedPrivate::~UCViewItemsAttachedPrivate()
2317 {
2318 clearChangesList();
2319 clearFlickablesList();
2320 }
2321
2322 // disconnect all flickables
2323-void UCListItemAttachedPrivate::clearFlickablesList()
2324+void UCViewItemsAttachedPrivate::clearFlickablesList()
2325 {
2326- Q_Q(UCListItemAttached);
2327+ Q_Q(UCViewItemsAttached);
2328 Q_FOREACH(const QPointer<QQuickFlickable> &flickable, flickables) {
2329 if (flickable.data())
2330 QObject::disconnect(flickable.data(), &QQuickFlickable::movementStarted,
2331- q, &UCListItemAttached::unbindItem);
2332+ q, &UCViewItemsAttached::unbindItem);
2333 }
2334 flickables.clear();
2335 }
2336
2337 // connect all flickables
2338-void UCListItemAttachedPrivate::buildFlickablesList()
2339+void UCViewItemsAttachedPrivate::buildFlickablesList()
2340 {
2341- Q_Q(UCListItemAttached);
2342+ Q_Q(UCViewItemsAttached);
2343 QQuickItem *item = qobject_cast<QQuickItem*>(q->parent());
2344 if (!item) {
2345 return;
2346@@ -65,17 +65,17 @@
2347 QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(item);
2348 if (flickable) {
2349 QObject::connect(flickable, &QQuickFlickable::movementStarted,
2350- q, &UCListItemAttached::unbindItem);
2351+ q, &UCViewItemsAttached::unbindItem);
2352 flickables << flickable;
2353 }
2354 item = item->parentItem();
2355 }
2356 }
2357
2358-void UCListItemAttachedPrivate::clearChangesList()
2359+void UCViewItemsAttachedPrivate::clearChangesList()
2360 {
2361 // clear property change objects
2362- Q_Q(UCListItemAttached);
2363+ Q_Q(UCViewItemsAttached);
2364 Q_FOREACH(PropertyChange *change, changes) {
2365 // deleting PropertyChange will restore the saved property
2366 // to its original binding/value
2367@@ -84,10 +84,10 @@
2368 changes.clear();
2369 }
2370
2371-void UCListItemAttachedPrivate::buildChangesList(const QVariant &newValue)
2372+void UCViewItemsAttachedPrivate::buildChangesList(const QVariant &newValue)
2373 {
2374 // collect all ascendant flickables
2375- Q_Q(UCListItemAttached);
2376+ Q_Q(UCViewItemsAttached);
2377 QQuickItem *item = qobject_cast<QQuickItem*>(q->parent());
2378 if (!item) {
2379 return;
2380@@ -104,22 +104,27 @@
2381 }
2382 }
2383
2384-UCListItemAttached::UCListItemAttached(QObject *owner)
2385+UCViewItemsAttached::UCViewItemsAttached(QObject *owner)
2386 : QObject(owner)
2387- , d_ptr(new UCListItemAttachedPrivate(this))
2388-{
2389-}
2390-
2391-UCListItemAttached::~UCListItemAttached()
2392-{
2393+ , d_ptr(new UCViewItemsAttachedPrivate(this))
2394+{
2395+}
2396+
2397+UCViewItemsAttached::~UCViewItemsAttached()
2398+{
2399+}
2400+
2401+UCViewItemsAttached *UCViewItemsAttached::qmlAttachedProperties(QObject *owner)
2402+{
2403+ return new UCViewItemsAttached(owner);
2404 }
2405
2406 // register item to be rebound
2407-bool UCListItemAttached::listenToRebind(UCListItem *item, bool listen)
2408+bool UCViewItemsAttached::listenToRebind(UCListItem *item, bool listen)
2409 {
2410 // we cannot bind the item until we have an other one bound
2411 bool result = false;
2412- Q_D(UCListItemAttached);
2413+ Q_D(UCViewItemsAttached);
2414 if (listen) {
2415 if (d->boundItem.isNull() || (d->boundItem == item)) {
2416 d->boundItem = item;
2417@@ -135,9 +140,9 @@
2418 }
2419
2420 // reports true if any of the ascendant flickables is moving
2421-bool UCListItemAttached::isMoving()
2422+bool UCViewItemsAttached::isMoving()
2423 {
2424- Q_D(UCListItemAttached);
2425+ Q_D(UCViewItemsAttached);
2426 Q_FOREACH(const QPointer<QQuickFlickable> &flickable, d->flickables) {
2427 if (flickable && flickable->isMoving()) {
2428 return true;
2429@@ -147,9 +152,9 @@
2430 }
2431
2432 // returns true if the given ListItem is bound to listen on moving changes
2433-bool UCListItemAttached::isBoundTo(UCListItem *item)
2434+bool UCViewItemsAttached::isBoundTo(UCListItem *item)
2435 {
2436- Q_D(UCListItemAttached);
2437+ Q_D(UCViewItemsAttached);
2438 return d->boundItem == item;
2439 }
2440
2441@@ -161,9 +166,9 @@
2442 * When disabled, always the last item disabling will be kept as active disabler,
2443 * and only the active disabler can enable (restore) the interactive flag state.
2444 */
2445-void UCListItemAttached::disableInteractive(UCListItem *item, bool disable)
2446+void UCViewItemsAttached::disableInteractive(UCListItem *item, bool disable)
2447 {
2448- Q_D(UCListItemAttached);
2449+ Q_D(UCViewItemsAttached);
2450 if (disable) {
2451 // disabling or re-disabling
2452 d->disablerItem = item;
2453@@ -188,9 +193,9 @@
2454 }
2455 }
2456
2457-void UCListItemAttached::unbindItem()
2458+void UCViewItemsAttached::unbindItem()
2459 {
2460- Q_D(UCListItemAttached);
2461+ Q_D(UCViewItemsAttached);
2462 if (d->boundItem) {
2463 // depending on content item's X coordinate, we either do animated or prompt rebind
2464 if (d->boundItem->contentItem()->x() != 0.0) {
2465
2466=== modified file 'tests/resources/listitems/ListItemTest.qml'
2467--- tests/resources/listitems/ListItemTest.qml 2014-12-04 13:23:18 +0000
2468+++ tests/resources/listitems/ListItemTest.qml 2015-01-16 14:53:38 +0000
2469@@ -16,6 +16,7 @@
2470
2471 import QtQuick 2.2
2472 import Ubuntu.Components 1.2
2473+import Ubuntu.Components.Styles 1.2
2474
2475 MainView {
2476 id: main
2477@@ -109,7 +110,7 @@
2478 width: units.gu(3)
2479 height: width
2480 name: action.iconName
2481- color: "blue"
2482+ color: pressed ? "blue" : "pink"
2483 anchors.horizontalCenter: parent.horizontalCenter
2484 }
2485 Label {
2486@@ -131,13 +132,16 @@
2487
2488 ListItem {
2489 Label {
2490+ id: label2
2491 anchors.fill: parent
2492- text: "Another standalone ListItem"
2493+ text: "Another standalone ListItem\nStarted with custom style, reset to theme style on first click"
2494 }
2495 leadingActions: testItem.leadingActions
2496 trailingActions: ListItemActions {
2497 actions: leading.actions
2498 }
2499+ style: ListItemStyle {}
2500+ onClicked: { style = undefined; label2.text = "Another standalone ListItem" }
2501 }
2502
2503 ListView {
2504@@ -152,6 +156,7 @@
2505 id: listItem
2506 onClicked: print(" clicked")
2507 leadingActions: leading
2508+ trailingActions: leadingActions
2509 Label {
2510 text: modelData + " item"
2511 }
2512@@ -179,7 +184,7 @@
2513
2514 Column {
2515 id: column
2516- width: view.width
2517+ width: flicker.width
2518 property alias count: repeater.count
2519 Repeater {
2520 id: repeater
2521
2522=== modified file 'tests/unit_x11/tst_components/tst_listitem.qml'
2523--- tests/unit_x11/tst_components/tst_listitem.qml 2014-12-19 06:32:11 +0000
2524+++ tests/unit_x11/tst_components/tst_listitem.qml 2015-01-16 14:53:38 +0000
2525@@ -18,11 +18,12 @@
2526 import QtTest 1.0
2527 import Ubuntu.Test 1.0
2528 import Ubuntu.Components 1.2
2529+import Ubuntu.Components.Styles 1.2
2530
2531 Item {
2532 id: main
2533- width: units.gu(40)
2534- height: units.gu(71)
2535+ width: units.gu(50)
2536+ height: units.gu(100)
2537
2538 Action {
2539 id: stockAction
2540@@ -192,8 +193,8 @@
2541 compare(defaults.highlighted, false, "Not highlighted by default");
2542 compare(defaults.swipeOvershoot, 0.0, "No overshoot till the style is loaded!");
2543 compare(defaults.divider.visible, true, "divider is visible by default");
2544- compare(defaults.divider.leftMargin, units.dp(2), "divider's left margin is 2GU");
2545- compare(defaults.divider.rightMargin, units.dp(2), "divider's right margin is 2GU");
2546+ compare(defaults.divider.leftMargin, 0, "divider's left margin is 0");
2547+ compare(defaults.divider.rightMargin, 0, "divider's right margin is 0");
2548 compare(defaults.divider.colorFrom, "#000000", "colorFrom differs.");
2549 fuzzyCompare(defaults.divider.colorFrom.a, 0.14, 0.01, "colorFrom alpha differs");
2550 compare(defaults.divider.colorTo, "#ffffff", "colorTo differs.");
2551@@ -206,6 +207,14 @@
2552 compare(actionsDefault.actions.length, 0, "ListItemActions has no actions set.");
2553 }
2554
2555+ Component { id: customStyle; ListItemStyle {} }
2556+
2557+ function test_style_reset() {
2558+ testItem.style = customStyle;
2559+ testItem.style = undefined;
2560+ verify(testItem.style != 0 && testItem.style.objectName == "ListItemThemeStyle", "Style set back to theme");
2561+ }
2562+
2563 function test_children_in_content_item() {
2564 compare(bodyItem.parent, testItem.contentItem, "Content is not in the right holder!");
2565 }

Subscribers

People subscribed via source and target branches