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
=== modified file 'components.api'
--- components.api 2014-12-18 10:08:56 +0000
+++ components.api 2015-01-16 14:53:38 +0000
@@ -867,6 +867,7 @@
867 name: "UCListItem"867 name: "UCListItem"
868 prototype: "UCStyledItemBase"868 prototype: "UCStyledItemBase"
869 exports: ["ListItem 1.2"]869 exports: ["ListItem 1.2"]
870 name: "PanelStatus"
870 Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true }871 Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true }
871 Property { name: "divider"; type: "UCListItemDivider"; isReadonly: true; isPointer: true }872 Property { name: "divider"; type: "UCListItemDivider"; isReadonly: true; isPointer: true }
872 Property { name: "leadingActions"; type: "UCListItemActions"; isPointer: true }873 Property { name: "leadingActions"; type: "UCListItemActions"; isPointer: true }
@@ -886,26 +887,19 @@
886 name: "UCListItemActions"887 name: "UCListItemActions"
887 prototype: "QObject"888 prototype: "QObject"
888 exports: ["ListItemActions 1.2"]889 exports: ["ListItemActions 1.2"]
889 name: "Status"
890 Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }890 Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
891 Property { name: "actions"; type: "UCAction"; isList: true; isReadonly: true }891 Property { name: "actions"; type: "UCAction"; isList: true; isReadonly: true }
892 Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }892 Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
893 Signal {893 name: "UCListItemAttached"
894 name: "statusChanged"
895 Parameter { name: "status"; type: "Status" }
896 name: "UCListItemActionsAttached"
897 prototype: "QObject"894 prototype: "QObject"
898 Property { name: "container"; type: "UCListItemActions"; isReadonly: true; isPointer: true }895 Property { name: "actions"; type: "UCListItemActions"; isReadonly: true; isPointer: true }
899 Property { name: "visibleActions"; type: "UCAction"; isList: true; isReadonly: true }896 Property { name: "visibleActions"; type: "UCAction"; isList: true; isReadonly: true }
900 Property { name: "listItem"; type: "UCListItem"; isReadonly: true; isPointer: true }897 Property { name: "item"; type: "UCListItem"; isReadonly: true; isPointer: true }
901 Property { name: "listItemIndex"; type: "int"; isReadonly: true }898 Property { name: "index"; type: "int"; isReadonly: true }
902 Property { name: "offset"; type: "double"; isReadonly: true }899 Property { name: "panelStatus"; type: "UCListItem::PanelStatus"; isReadonly: true }
903 Property { name: "status"; type: "UCListItemActions::Status"; isReadonly: true }
904 Property { name: "swiping"; type: "bool"; isReadonly: true }
905 Method {900 Method {
906 name: "snapToPosition"901 name: "snapToPosition"
907 Parameter { name: "position"; type: "double" }902 Parameter { name: "position"; type: "double" }
908 Component { name: "UCListItemAttached"; prototype: "QObject" }
909 name: "UCListItemDivider"903 name: "UCListItemDivider"
910 prototype: "QObject"904 prototype: "QObject"
911 Property { name: "visible"; type: "bool" }905 Property { name: "visible"; type: "bool" }
@@ -1010,6 +1004,9 @@
1010 Signal {1004 Signal {
1011 name: "opened"1005 name: "opened"
1012 Parameter { name: "uris"; type: "QStringList" }1006 Parameter { name: "uris"; type: "QStringList" }
1007 name: "UCViewItemsAttached"
1008 prototype: "QObject"
1009 exports: ["ViewItems 1.2"]
1013 name: "UbuntuI18n"1010 name: "UbuntuI18n"
1014 prototype: "QObject"1011 prototype: "QObject"
1015 exports: ["i18n 0.1", "i18n 1.0"]1012 exports: ["i18n 0.1", "i18n 1.0"]
10161013
=== modified file 'modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml'
--- modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml 2014-12-17 07:06:31 +0000
+++ modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml 2015-01-16 14:53:38 +0000
@@ -38,32 +38,29 @@
38 /*38 /*
39 Specifies the width of the component visualizing the action.39 Specifies the width of the component visualizing the action.
40 */40 */
41 property real visualizedActionWidth: units.gu(2.5)41 property real paintedActionWidth: units.gu(2.5)
4242
43 // panel implementation43 // panel implementation
44 id: panel44 id: panel
45 width: Math.max(45 width: Math.max(
46 actionsRow.childrenRect.width,46 actionsRow.childrenRect.width,
47 ListItemActions.visibleActions.length * MathUtils.clamp(visualizedActionWidth, height, actionsRow.maxItemWidth))47 ListItem.visibleActions.length * MathUtils.clamp(paintedActionWidth, height, actionsRow.maxItemWidth))
4848
49 // used for module/autopilot testing49 // used for module/autopilot testing
50 objectName: "ListItemPanel" + (leading ? "Leading" : "Trailing")50 objectName: "ListItemPanel" + (leading ? "Leading" : "Trailing")
5151
52 /*52 /*
53 Property holding the ListItem's contentItem instance
54 */
55 readonly property Item contentItem: parent ? parent.contentItem : null
56
57 /*
58 Specifies whether the panel is used to visualize leading or trailing actions.53 Specifies whether the panel is used to visualize leading or trailing actions.
59 */54 */
60 readonly property bool leading: panel.ListItemActions.status == panel.ListItemActions.Leading55 readonly property bool leading: ListItem.panelStatus == ListItem.Leading
56 readonly property real swipedOffset: leading ? width + x : ListItem.item.width - x;
57 readonly property bool swiping: ListItem.item.highlighted && ListItem.item.contentMoving
6158
62 anchors {59 anchors {
63 left: contentItem ? (leading ? undefined : contentItem.right) : undefined60 left: leading ? undefined : ListItem.item.contentItem.right
64 right: contentItem ? (leading ? contentItem.left : undefined) : undefined61 right: leading ? ListItem.item.contentItem.left : undefined
65 top: contentItem ? contentItem.top : undefined62 top: ListItem.item.contentItem.top
66 bottom: contentItem ? contentItem.bottom : undefined63 bottom: ListItem.item.contentItem.bottom
67 }64 }
6865
69 Rectangle {66 Rectangle {
@@ -71,17 +68,21 @@
71 anchors {68 anchors {
72 fill: parent69 fill: parent
73 // add 4 times the overshoot margins to cover the background when tugged70 // add 4 times the overshoot margins to cover the background when tugged
74 leftMargin: (leading && panel.ListItemActions.listItem) ? -units.gu(4 * panel.ListItemActions.listItem.swipeOvershoot) : 071 leftMargin: (leading && panel.ListItem.item) ? -units.gu(4 * panel.ListItem.item.swipeOvershoot) : 0
75 rightMargin: (!leading && panel.ListItemActions.listItem) ? -units.gu(4 * panel.ListItemActions.listItem.swipeOvershoot) : 072 rightMargin: (!leading && panel.ListItem.item) ? -units.gu(4 * panel.ListItem.item.swipeOvershoot) : 0
76 }73 }
77 color: panel.backgroundColor74 color: panel.backgroundColor
78 }75 }
7976
80 // handle action triggering77 // handle action triggering
81 ListItemActions.onStatusChanged: {78 Connections {
82 if (ListItemActions.status === ListItemActions.Disconnected && actionsRow.selectedAction) {79 target: panel.ListItem.item
83 actionsRow.selectedAction.trigger(actionsRow.listItemIndex >= 0 ? actionsRow.listItemIndex : null);80 onContentMovementEnded: {
84 actionsRow.selectedAction = null;81 if (actionsRow.selectedAction) {
82 actionsRow.selectedAction.trigger(actionsRow.listItemIndex);
83 actionsRow.listItemIndex = -1;
84 actionsRow.selectedAction = null;
85 }
85 }86 }
86 }87 }
8788
@@ -101,8 +102,8 @@
101 prevX = x;102 prevX = x;
102 }103 }
103 // default snapping!104 // default snapping!
104 ListItemActions.onSwipingChanged: {105 onSwipingChanged: {
105 if (ListItemActions.swiping) {106 if (swiping) {
106 // the dragging got started, set prevX107 // the dragging got started, set prevX
107 prevX = panel.x;108 prevX = panel.x;
108 return;109 return;
@@ -111,8 +112,8 @@
111 return;112 return;
112 }113 }
113 // snap in if the offset is bigger than the overshoot and the direction of the drag is to reveal the panel114 // snap in if the offset is bigger than the overshoot and the direction of the drag is to reveal the panel
114 var snapPos = (ListItemActions.offset > ListItemActions.listItem.swipeOvershoot && snapIn) ? panel.width : 0.0;115 var snapPos = (swipedOffset > units.gu(2) && snapIn) ? panel.width : 0.0;
115 ListItemActions.snapToPosition(snapPos);116 ListItem.snapToPosition(snapPos);
116 }117 }
117118
118 Row {119 Row {
@@ -124,13 +125,13 @@
124 leftMargin: spacing125 leftMargin: spacing
125 }126 }
126127
127 property real maxItemWidth: panel.parent ? (panel.parent.width / panel.ListItemActions.visibleActions.length) : 0128 property real maxItemWidth: panel.ListItem.item.width / panel.ListItem.visibleActions.length
128129
129 property Action selectedAction130 property Action selectedAction
130 property int listItemIndex131 property int listItemIndex: -1
131132
132 Repeater {133 Repeater {
133 model: panel.ListItemActions.visibleActions134 model: panel.ListItem.visibleActions
134 AbstractButton {135 AbstractButton {
135 id: actionButton136 id: actionButton
136 action: modelData137 action: modelData
@@ -143,8 +144,8 @@
143 }144 }
144 function trigger() {145 function trigger() {
145 actionsRow.selectedAction = modelData;146 actionsRow.selectedAction = modelData;
146 actionsRow.listItemIndex = panel.ListItemActions.listItemIndex;147 actionsRow.listItemIndex = panel.ListItem.index;
147 panel.ListItemActions.snapToPosition(0.0);148 panel.ListItem.snapToPosition(0.0);
148 }149 }
149150
150 Rectangle {151 Rectangle {
@@ -156,7 +157,7 @@
156 Loader {157 Loader {
157 id: delegateLoader158 id: delegateLoader
158 height: parent.height159 height: parent.height
159 sourceComponent: panel.ListItemActions.container.delegate ? panel.ListItemActions.container.delegate : defaultDelegate160 sourceComponent: panel.ListItem.actions.delegate ? panel.ListItem.actions.delegate : defaultDelegate
160 property Action action: modelData161 property Action action: modelData
161 property int index: index162 property int index: index
162 property bool pressed: actionButton.pressed163 property bool pressed: actionButton.pressed
@@ -177,7 +178,7 @@
177 Item {178 Item {
178 width: height179 width: height
179 Icon {180 Icon {
180 width: panel.visualizedActionWidth181 width: panel.paintedActionWidth
181 height: width182 height: width
182 name: action.iconName183 name: action.iconName
183 color: panel.foregroundColor184 color: panel.foregroundColor
184185
=== modified file 'modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml'
--- modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml 2014-12-01 11:13:10 +0000
+++ modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml 2015-01-16 14:53:38 +0000
@@ -30,7 +30,6 @@
30 period: 0.530 period: 0.5
31 }31 }
32 duration: UbuntuAnimation.BriskDuration32 duration: UbuntuAnimation.BriskDuration
33 alwaysRunToEnd: true
34 }33 }
3534
36}35}
3736
=== modified file 'modules/Ubuntu/Components/plugin/plugin.cpp'
--- modules/Ubuntu/Components/plugin/plugin.cpp 2014-12-03 14:43:27 +0000
+++ modules/Ubuntu/Components/plugin/plugin.cpp 2015-01-16 14:53:38 +0000
@@ -171,6 +171,7 @@
171 qmlRegisterType<UCListItem, 2>(uri, 1, 2, "ListItem");171 qmlRegisterType<UCListItem, 2>(uri, 1, 2, "ListItem");
172 qmlRegisterType<UCListItemDivider>();172 qmlRegisterType<UCListItemDivider>();
173 qmlRegisterType<UCListItemActions, 2>(uri, 1, 2, "ListItemActions");173 qmlRegisterType<UCListItemActions, 2>(uri, 1, 2, "ListItemActions");
174 qmlRegisterUncreatableType<UCViewItemsAttached, 2>(uri, 1, 2, "ViewItems", "Not instantiable");
174}175}
175176
176void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)177void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
177178
=== modified file 'modules/Ubuntu/Components/plugin/plugin.pro'
--- modules/Ubuntu/Components/plugin/plugin.pro 2014-12-03 14:43:27 +0000
+++ modules/Ubuntu/Components/plugin/plugin.pro 2015-01-16 14:53:38 +0000
@@ -111,10 +111,11 @@
111 adapters/actionsproxy_p.cpp \111 adapters/actionsproxy_p.cpp \
112 uclistitem.cpp \112 uclistitem.cpp \
113 uclistitemactions.cpp \113 uclistitemactions.cpp \
114 uclistitemactionsattached.cpp \114 propertychange_p.cpp \
115 uclistitemstyle.cpp \
116 ucviewitemsattached.cpp \
115 uclistitemattached.cpp \117 uclistitemattached.cpp \
116 propertychange_p.cpp \118 ucactionpanel_p.cpp
117 uclistitemstyle.cpp
118119
119# adapters120# adapters
120SOURCES += adapters/alarmsadapter_organizer.cpp121SOURCES += adapters/alarmsadapter_organizer.cpp
121122
=== modified file 'modules/Ubuntu/Components/plugin/ucaction.h'
--- modules/Ubuntu/Components/plugin/ucaction.h 2014-12-01 13:42:47 +0000
+++ modules/Ubuntu/Components/plugin/ucaction.h 2015-01-16 14:53:38 +0000
@@ -87,7 +87,7 @@
87 Type m_parameterType;87 Type m_parameterType;
8888
89 friend class UCActionContext;89 friend class UCActionContext;
90 friend class UCListItemActionsAttached;90 friend class UCListItemAttached;
91 friend class UCListItemActionsPrivate;91 friend class UCListItemActionsPrivate;
9292
93 bool isValidType(QVariant::Type valueType);93 bool isValidType(QVariant::Type valueType);
9494
=== added file 'modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp'
--- modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp 1970-01-01 00:00:00 +0000
+++ modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp 2015-01-16 14:53:38 +0000
@@ -0,0 +1,132 @@
1/*
2 * Copyright 2015 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "uclistitemactions.h"
18#include "uclistitemactions_p.h"
19#include "uclistitem_p.h"
20#include "quickutils.h"
21#include "i18n.h"
22#include "plugin.h"
23#include <QtQml/QQmlInfo>
24#include "ucaction.h"
25#include "ucunits.h"
26#include "uclistitemstyle.h"
27
28UCActionPanel::UCActionPanel(UCListItem *item, bool leading)
29 : QObject(item)
30 , listItem(item)
31 , panelItem(0)
32 , status(UCListItem::None)
33 , leading(leading)
34 , connected(false)
35{
36
37}
38
39UCActionPanel::~UCActionPanel()
40{
41}
42
43UCListItemAttached *UCActionPanel::attachedObject()
44{
45 if (!panelItem) {
46 return 0;
47 }
48 return static_cast<UCListItemAttached*>(
49 qmlAttachedPropertiesObject<UCListItem>(panelItem, false));
50}
51
52bool UCActionPanel::createPanel(QQmlComponent *panelDelegate)
53{
54 if (panelItem || !panelDelegate) {
55 return false;
56 }
57 if (!panelDelegate->isError()) {
58 QQmlContext *context = new QQmlContext(qmlContext(listItem));
59 panelItem = qobject_cast<QQuickItem*>(panelDelegate->beginCreate(context));
60 if (!panelItem) {
61 qmlInfo(listItem) << UbuntuI18n::tr("Error creating ListItem actions panel");
62 } else {
63 context->setParent(panelItem);
64 QQml_setParent_noEvent(panelItem, listItem);
65 panelItem->setParentItem(listItem);
66 // create attached property!
67 UCListItemAttached *attached = static_cast<UCListItemAttached*>(
68 qmlAttachedPropertiesObject<UCListItem>(panelItem));
69 if (!attached->actions()) {
70 attached->setList(listItem, leading, true);
71 } else {
72 // container is set, but we need to emit the signal again so we get the
73 // attached props updated for those cases when the attached property is
74 // created before the statement above
75 Q_EMIT attached->actionsChanged();
76 }
77 panelDelegate->completeCreate();
78 }
79 } else {
80 qmlInfo(listItem) << panelDelegate->errorString();
81 }
82 return panelItem != 0;
83}
84
85UCListItemActions *UCActionPanel::actions()
86{
87 return leading ? UCListItemPrivate::get(listItem)->leadingActions :
88 UCListItemPrivate::get(listItem)->trailingActions;
89}
90
91QQuickItem *UCActionPanel::panel() const
92{
93 return panelItem;
94}
95
96bool UCActionPanel::grabPanel(UCActionPanel **panel, UCListItem *item, bool leading)
97{
98 if (!(*panel) && item) {
99 UCListItemActions *actions = leading ? UCListItemPrivate::get(item)->leadingActions :
100 UCListItemPrivate::get(item)->trailingActions;
101 if (actions) {
102 (*panel) = new UCActionPanel(item, leading);
103 UCListItemPrivate *pItem = UCListItemPrivate::get((*panel)->listItem);
104 pItem->initStyleItem();
105 if (!pItem->styleItem ||
106 (pItem->styleItem && !(*panel)->createPanel(pItem->styleItem->m_actionsDelegate))) {
107 delete (*panel);
108 (*panel) = 0;
109 }
110 }
111 }
112 if (*panel) {
113 (*panel)->connected = true;
114 (*panel)->status = leading ? UCListItem::Leading : UCListItem::Trailing;
115 Q_EMIT (*panel)->statusChanged();
116 }
117 return (*panel) != 0;
118}
119
120void UCActionPanel::ungrabPanel(UCActionPanel *panel)
121{
122 if (!panel || !panel->connected) {
123 return;
124 }
125 panel->connected = false;
126 panel->panelItem->setVisible(false);
127}
128
129bool UCActionPanel::isConnected(UCActionPanel *panel)
130{
131 return panel && panel->connected;
132}
0133
=== modified file 'modules/Ubuntu/Components/plugin/uclistitem.cpp'
--- modules/Ubuntu/Components/plugin/uclistitem.cpp 2015-01-07 06:42:09 +0000
+++ modules/Ubuntu/Components/plugin/uclistitem.cpp 2015-01-16 14:53:38 +0000
@@ -32,10 +32,6 @@
32#include <QtQuick/private/qquickmousearea_p.h>32#include <QtQuick/private/qquickmousearea_p.h>
33#include "uclistitemstyle.h"33#include "uclistitemstyle.h"
3434
35#define MIN(x, y) ((x < y) ? x : y)
36#define MAX(x, y) ((x > y) ? x : y)
37#define CLAMP(v, min, max) (min <= max) ? MAX(min, MIN(v, max)) : MAX(max, MIN(v, min))
38
39QColor getPaletteColor(const char *profile, const char *color)35QColor getPaletteColor(const char *profile, const char *color)
40{36{
41 QColor result;37 QColor result;
@@ -85,6 +81,12 @@
85 if (!snap) {81 if (!snap) {
86 // no animation, so we simply position the component82 // no animation, so we simply position the component
87 listItem->contentItem->setX(to);83 listItem->contentItem->setX(to);
84 // and complete snap logic
85 if (to == 0.0) {
86 snapOut();
87 } else {
88 snapIn();
89 }
88 return false;90 return false;
89 }91 }
90 snap->setTargetObject(listItem->contentItem);92 snap->setTargetObject(listItem->contentItem);
@@ -98,14 +100,24 @@
98 if (snap->properties().isEmpty() && snap->property().isEmpty()) {100 if (snap->properties().isEmpty() && snap->property().isEmpty()) {
99 snap->setProperty("x");101 snap->setProperty("x");
100 }102 }
103 // make sure the animation is not running
104 snap->stop();
101 snap->setFrom(listItem->contentItem->property(snap->property().toLocal8Bit().constData()));105 snap->setFrom(listItem->contentItem->property(snap->property().toLocal8Bit().constData()));
102 snap->setTo(to);106 snap->setTo(to);
103 snap->setAlwaysRunToEnd(true);107 snap->setAlwaysRunToEnd(false);
104 listItem->setContentMoving(true);108 listItem->setContentMoving(true);
105 snap->start();109 snap->start();
106 return true;110 return true;
107}111}
108112
113void UCListItemSnapAnimator::stop()
114{
115 QQuickPropertyAnimation *snap = getDefaultAnimation();
116 if (snap && snap->isRunning()) {
117 snap->stop();
118 }
119}
120
109/*121/*
110 * The function completes a running snap animation.122 * The function completes a running snap animation.
111 */123 */
@@ -131,17 +143,19 @@
131 QObject::disconnect(snap, 0, 0, 0);143 QObject::disconnect(snap, 0, 0, 0);
132 }144 }
133 UCListItemPrivate *listItem = UCListItemPrivate::get(item);145 UCListItemPrivate *listItem = UCListItemPrivate::get(item);
134 if (listItem->attachedProperties) {146 if (listItem->parentAttached) {
135 // restore flickable's interactive and cleanup147 // restore flickable's interactive and cleanup
136 listItem->attachedProperties->disableInteractive(item, false);148 listItem->parentAttached->disableInteractive(item, false);
137 // no need to listen flickables any longer149 // no need to listen flickables any longer
138 listItem->listenToRebind(false);150 listItem->listenToRebind(false);
139 }151 }
140 // disconnect actions152 // disconnect actions
141 listItem->grabPanel(listItem->leadingActions, false);153 UCActionPanel::ungrabPanel(listItem->leadingPanel);
142 listItem->grabPanel(listItem->trailingActions, false);154 UCActionPanel::ungrabPanel(listItem->trailingPanel);
143 // set contentMoved to false155 // set contentMoved to false
144 listItem->setContentMoving(false);156 listItem->setContentMoving(false);
157 // lock contentItem left/right edges
158 listItem->lockContentItem(true);
145}159}
146160
147/*161/*
@@ -176,8 +190,6 @@
176UCListItemDivider::UCListItemDivider(QObject *parent)190UCListItemDivider::UCListItemDivider(QObject *parent)
177 : QObject(parent)191 : QObject(parent)
178 , m_visible(true)192 , m_visible(true)
179 , m_leftMarginChanged(false)
180 , m_rightMarginChanged(false)
181 , m_colorFromChanged(false)193 , m_colorFromChanged(false)
182 , m_colorToChanged(false)194 , m_colorToChanged(false)
183 , m_thickness(0)195 , m_thickness(0)
@@ -202,14 +214,9 @@
202214
203void UCListItemDivider::unitsChanged()215void UCListItemDivider::unitsChanged()
204{216{
205 m_thickness = UCUnits::instance().dp(2);217 m_thickness = UCUnits::instance().dp(DIVIDER_THICKNESS_DP);
206 if (!m_leftMarginChanged) {
207 m_leftMargin = UCUnits::instance().dp(2);
208 }
209 if (!m_rightMarginChanged) {
210 m_rightMargin = UCUnits::instance().dp(2);
211 }
212 if (m_listItem) {218 if (m_listItem) {
219 m_listItem->adjustContentItemHeight();
213 m_listItem->update();220 m_listItem->update();
214 }221 }
215}222}
@@ -273,9 +280,9 @@
273 return;280 return;
274 }281 }
275 m_visible = visible;282 m_visible = visible;
276 m_listItem->resize();
277 m_listItem->update();
278 Q_EMIT visibleChanged();283 Q_EMIT visibleChanged();
284 // set/reset contentItem's bottomMargin
285 m_listItem->adjustContentItemHeight();
279}286}
280287
281void UCListItemDivider::setLeftMargin(qreal leftMargin)288void UCListItemDivider::setLeftMargin(qreal leftMargin)
@@ -284,7 +291,6 @@
284 return;291 return;
285 }292 }
286 m_leftMargin = leftMargin;293 m_leftMargin = leftMargin;
287 m_leftMarginChanged = true;
288 m_listItem->update();294 m_listItem->update();
289 Q_EMIT leftMarginChanged();295 Q_EMIT leftMarginChanged();
290}296}
@@ -295,7 +301,6 @@
295 return;301 return;
296 }302 }
297 m_rightMargin = rightMargin;303 m_rightMargin = rightMargin;
298 m_rightMarginChanged = true;
299 m_listItem->update();304 m_listItem->update();
300 Q_EMIT rightMarginChanged();305 Q_EMIT rightMarginChanged();
301}306}
@@ -329,25 +334,26 @@
329 : UCStyledItemBasePrivate()334 : UCStyledItemBasePrivate()
330 , highlighted(false)335 , highlighted(false)
331 , contentMoved(false)336 , contentMoved(false)
332 , highlightColorChanged(false)
333 , swiped(false)337 , swiped(false)
334 , suppressClick(false)338 , suppressClick(false)
335 , ready(false)339 , ready(false)
336 , customStyle(false)
337 , customColor(false)340 , customColor(false)
338 , customOvershoot(false)341 , customOvershoot(false)
339 , flicked(false)342 , flicked(false)
340 , xAxisMoveThresholdGU(1.5)343 , xAxisMoveThresholdGU(DEFAULT_SWIPE_THRESHOLD_GU)
341 , overshoot(0)344 , overshoot(0)
342 , color(Qt::transparent)345 , color(Qt::transparent)
343 , highlightColor(Qt::transparent)346 , highlightColor(Qt::transparent)
344 , attachedProperties(0)347 , parentAttached(0)
345 , contentItem(new QQuickItem)348 , contentItem(new QQuickItem)
346 , divider(new UCListItemDivider)349 , divider(new UCListItemDivider)
347 , leadingActions(0)350 , leadingActions(0)
348 , trailingActions(0)351 , trailingActions(0)
352 , leadingPanel(0)
353 , trailingPanel(0)
349 , animator(0)354 , animator(0)
350 , styleComponent(0)355 , styleComponent(0)
356 , implicitStyleComponent(0)
351 , styleItem(0)357 , styleItem(0)
352{358{
353}359}
@@ -391,13 +397,17 @@
391397
392void UCListItemPrivate::_q_updateThemedData()398void UCListItemPrivate::_q_updateThemedData()
393{399{
400 Q_Q(UCListItem);
401 // we reload the implicit style only if the custom style is not set, and
402 // the component is ready
403 if (!styleComponent && ready) {
404 resetStyle();
405 }
406
394 // update colors, panels407 // update colors, panels
395 if (!customColor) {408 if (!customColor) {
396 Q_Q(UCListItem);409 q->resetHighlightColor();
397 highlightColor = getPaletteColor("selected", "background");
398 q->update();
399 }410 }
400 loadStyle(true);
401}411}
402412
403void UCListItemPrivate::_q_rebound()413void UCListItemPrivate::_q_rebound()
@@ -405,8 +415,8 @@
405 setHighlighted(false);415 setHighlighted(false);
406 // initiate rebinding only if there were actions tugged416 // initiate rebinding only if there were actions tugged
407 Q_Q(UCListItem);417 Q_Q(UCListItem);
408 if (!UCListItemActionsPrivate::isConnectedTo(leadingActions, q) &&418 if (!UCActionPanel::isConnected(leadingPanel) &&
409 !UCListItemActionsPrivate::isConnectedTo(trailingActions, q)) {419 !UCActionPanel::isConnected(trailingPanel)) {
410 return;420 return;
411 }421 }
412 setSwiped(false);422 setSwiped(false);
@@ -430,7 +440,7 @@
430 */440 */
431QQmlComponent *UCListItemPrivate::style() const441QQmlComponent *UCListItemPrivate::style() const
432{442{
433 return styleComponent;443 return styleComponent ? styleComponent : implicitStyleComponent;
434}444}
435void UCListItemPrivate::setStyle(QQmlComponent *delegate)445void UCListItemPrivate::setStyle(QQmlComponent *delegate)
436{446{
@@ -438,54 +448,89 @@
438 return;448 return;
439 }449 }
440 Q_Q(UCListItem);450 Q_Q(UCListItem);
451 if (!delegate) {
452 // undefined or null delegate resets the style to theme
453 resetStyle();
454 return;
455 }
441 // make sure we're rebound before we change the panel component456 // make sure we're rebound before we change the panel component
442 promptRebound();457 promptRebound();
458 bool reloadStyle = styleItem != 0;
443 if (styleItem) {459 if (styleItem) {
444 delete styleItem;460 styleItem->deleteLater();
445 styleItem = 0;461 styleItem = 0;
446 Q_EMIT q->__styleInstanceChanged();462 Q_EMIT q->__styleInstanceChanged();
447 }463 }
448 delete styleComponent;
449 customStyle = (delegate == 0);
450 styleComponent = delegate;464 styleComponent = delegate;
451 loadStyle(false);465 // delete theme style for now
466 if (implicitStyleComponent) {
467 implicitStyleComponent->deleteLater();
468 implicitStyleComponent = 0;
469 }
470 if (reloadStyle) {
471 initStyleItem();
472 }
452 Q_EMIT q->styleChanged();473 Q_EMIT q->styleChanged();
453}474}
454475void UCListItemPrivate::resetStyle()
455// update themed components
456bool UCListItemPrivate::loadStyle(bool reload)
457{476{
458 if (!ready) {477 if (styleComponent || !implicitStyleComponent) {
459 return false;478 styleComponent = 0;
460 }479 // rebound as the current panels are not gonna be valid anymore
461 if (!customStyle) {480 if (swiped) {
462 Q_Q(UCListItem);481 promptRebound();
463 if (reload && styleItem) {482 }
464 delete styleItem;483 bool reloadStyle = styleItem != 0;
484 if (styleItem) {
485 styleItem->deleteLater();
465 styleItem = 0;486 styleItem = 0;
466 Q_EMIT q->__styleInstanceChanged();487 }
467 }488 delete implicitStyleComponent;
468 delete styleComponent;489 Q_Q(UCListItem);
469 styleComponent = UCTheme::instance().createStyleComponent("ListItemStyle.qml", q);490 implicitStyleComponent = UCTheme::instance().createStyleComponent("ListItemStyle.qml", q);
491 // set the objectnane for testing in tst_listitems.qml
492 implicitStyleComponent->setObjectName("ListItemThemeStyle");
493 // re-create style instance if it was created using the implicit style
494 if (reloadStyle) {
495 initStyleItem();
496 }
497 Q_EMIT q->styleChanged();
470 }498 }
471 return (styleComponent != NULL);
472}499}
500
473// creates the style item501// creates the style item
474void UCListItemPrivate::initStyleItem()502void UCListItemPrivate::initStyleItem()
475{503{
476 if (!styleItem && !loadStyle(false)) {504 if (!ready || styleItem) {
477 return;505 return;
478 }506 }
507 // get the component the style instance is created from
479 Q_Q(UCListItem);508 Q_Q(UCListItem);
480 QObject *object = styleComponent->beginCreate(qmlContext(q));509 QQmlComponent *delegate = style();
510 if (!delegate) {
511 // the style is not loaded from the theme yet
512 _q_updateThemedData();
513 delegate = style();
514 }
515 if (!delegate) {
516 return;
517 }
518 if (delegate->isError()) {
519 qmlInfo(q) << delegate->errorString();
520 return;
521 }
522 QQmlContext *context = new QQmlContext(qmlContext(q));
523 QObject *object = delegate->beginCreate(context);
481 styleItem = qobject_cast<UCListItemStyle*>(object);524 styleItem = qobject_cast<UCListItemStyle*>(object);
482 if (!styleItem) {525 if (!styleItem) {
483 delete object;526 delete object;
484 styleComponent->completeCreate();527 delegate->completeCreate();
528 delete context;
485 return;529 return;
486 }530 }
531 context->setParent(styleItem);
487 QQml_setParent_noEvent(styleItem, q);532 QQml_setParent_noEvent(styleItem, q);
488 styleComponent->completeCreate();533 delegate->completeCreate();
489 Q_EMIT q->__styleInstanceChanged();534 Q_EMIT q->__styleInstanceChanged();
490535
491 // get the overshoot value from the style!536 // get the overshoot value from the style!
@@ -519,8 +564,8 @@
519{564{
520 Q_Q(UCListItem);565 Q_Q(UCListItem);
521 QQuickItem *owner = flickable ? flickable : parentItem;566 QQuickItem *owner = flickable ? flickable : parentItem;
522 q->setImplicitWidth(owner ? owner->width() : UCUnits::instance().gu(40));567 q->setImplicitWidth(owner ? owner->width() : UCUnits::instance().gu(IMPLICIT_LISTITEM_WIDTH_GU));
523 q->setImplicitHeight(UCUnits::instance().gu(7));568 q->setImplicitHeight(UCUnits::instance().gu(IMPLICIT_LISTITEM_HEIGHT_GU));
524}569}
525570
526// returns the index of the list item when used in model driven views,571// returns the index of the list item when used in model driven views,
@@ -580,40 +625,37 @@
580 }625 }
581}626}
582627
583// grabs the panels from the leading/trailing actions and disables all ascending flickables
584bool UCListItemPrivate::grabPanel(UCListItemActions *actionsList, bool isTugged)
585{
586 Q_Q(UCListItem);
587 if (isTugged) {
588 bool grab = UCListItemActionsPrivate::connectToListItem(actionsList, q, (actionsList == leadingActions));
589 if (attachedProperties) {
590 attachedProperties->disableInteractive(q, true);
591 }
592 return grab;
593 } else {
594 UCListItemActionsPrivate::disconnectFromListItem(actionsList);
595 return false;
596 }
597}
598
599
600// connects/disconnects from the Flickable anchestor to get notified when to do rebound628// connects/disconnects from the Flickable anchestor to get notified when to do rebound
601void UCListItemPrivate::listenToRebind(bool listen)629void UCListItemPrivate::listenToRebind(bool listen)
602{630{
603 if (attachedProperties) {631 if (parentAttached) {
604 Q_Q(UCListItem);632 Q_Q(UCListItem);
605 attachedProperties->listenToRebind(q, listen);633 parentAttached->listenToRebind(q, listen);
606 }634 }
607}635}
608636
609void UCListItemPrivate::resize()637// lock/unlock contentItem's left and right anchors to the ListItem's left and right
610{638void UCListItemPrivate::lockContentItem(bool lock)
611 Q_Q(UCListItem);639{
612 QRectF rect(q->boundingRect());640 QQuickAnchors *contentAnchors = QQuickItemPrivate::get(contentItem)->anchors();
613 if (divider && divider->m_visible) {641 if (lock) {
614 rect.setHeight(rect.height() - divider->m_thickness);642 contentAnchors->setLeft(left());
615 }643 contentAnchors->setRight(right());
616 contentItem->setSize(rect.size());644 } else {
645 contentAnchors->resetLeft();
646 contentAnchors->resetRight();
647 }
648}
649
650// adjust contentItem height depending on teh divider's visibility
651void UCListItemPrivate::adjustContentItemHeight()
652{
653 QQuickAnchors *contentAnchors = QQuickItemPrivate::get(contentItem)->anchors();
654 if (divider->m_visible) {
655 contentAnchors->setBottomMargin(divider->m_thickness);
656 } else {
657 contentAnchors->resetBottomMargin();
658 }
617}659}
618660
619void UCListItemPrivate::update()661void UCListItemPrivate::update()
@@ -628,13 +670,13 @@
628// clamps the X value and moves the contentItem to the new X value670// clamps the X value and moves the contentItem to the new X value
629void UCListItemPrivate::clampAndMoveX(qreal &x, qreal dx)671void UCListItemPrivate::clampAndMoveX(qreal &x, qreal dx)
630{672{
631 UCListItemActionsPrivate *leading = UCListItemActionsPrivate::get(leadingActions);
632 UCListItemActionsPrivate *trailing = UCListItemActionsPrivate::get(trailingActions);
633 x += dx;673 x += dx;
634 // min cannot be less than the trailing's panel width674 // min cannot be less than the trailing's panel width
635 qreal min = (trailing && trailing->panelItem) ? -trailing->panelItem->width() - overshoot: 0;675 QQuickItem *leadingPanelItem = leadingPanel ? leadingPanel->panel() : 0;
676 QQuickItem *trailingPanelItem = trailingPanel ? trailingPanel->panel() : 0;
677 qreal min = (trailingPanelItem) ? -trailingPanelItem->width() - overshoot: 0;
636 // max cannot be bigger than 0 or the leading's width in case we have leading panel678 // max cannot be bigger than 0 or the leading's width in case we have leading panel
637 qreal max = (leading && leading->panelItem) ? leading->panelItem->width() + overshoot: 0;679 qreal max = (leadingPanelItem) ? leadingPanelItem->width() + overshoot: 0;
638 x = CLAMP(x, min, max);680 x = CLAMP(x, min, max);
639}681}
640682
@@ -722,11 +764,14 @@
722 * When used in \c ListView or \l UbuntuListView, the last list item will not764 * When used in \c ListView or \l UbuntuListView, the last list item will not
723 * show the divider no matter of the visible property value set.765 * show the divider no matter of the visible property value set.
724 *766 *
725 * ListItem can handle actions that can get tugged from front to back of the item.767 * ListItem can handle actions that can get swiped from front to back of the item.
726 * These actions are Action elements visualized in panels attached to the front768 * These actions are Action elements visualized in panels attached to the front
727 * or to the back of the item, and are revealed by swiping the item horizontally.769 * or to the back of the item, and are revealed by swiping the item horizontally.
728 * The tug is started only after the mouse/touch move had passed a given threshold.770 * The swipe is started only after the mouse/touch move had passed a given threshold.
729 * These actions are configured through the \l leadingActions as well as \l771 * The actions are visualized by a panel, which is configurable through the \l
772 * ListItemStyle::actionsDelegate style property.
773 *
774 * The actions are configured through the \l leadingActions as well as \l
730 * trailingActions properties.775 * trailingActions properties.
731 * \qml776 * \qml
732 * ListItem {777 * ListItem {
@@ -751,13 +796,11 @@
751 * }796 * }
752 * }797 * }
753 * \endqml798 * \endqml
754 * \note When a list item is tugged, it automatically connects both leading and799 * \note When a list item is swiped, it automatically connects both leading and
755 * trailing actions to the list item. This implies that a ListItem cannot use800 * trailing actions to the list item. If needed, the same ListItemActions instance
756 * the same ListItemActions instance for both leading and trailing actions. If801 * can be used in both leading and trailing side. In the following example the
757 * it is desired to have the same action present in both leading and trailing802 * list item can be deleted through both leading and trailing actions using the
758 * actions, one of the ListItemActions actions list can use the other's list. In803 * same container:
759 * the following example the list item can be deleted through both leading and
760 * trailing actions:
761 * \qml804 * \qml
762 * ListItem {805 * ListItem {
763 * id: listItem806 * id: listItem
@@ -769,13 +812,15 @@
769 * }812 * }
770 * ]813 * ]
771 * }814 * }
772 * trailingActions: ListItemActions {815 * trailingActions: leadingActions
773 * actions: leadingActions.actions
774 * }
775 * }816 * }
776 * \endqml817 * \endqml
818 * The action is triggered only after all the animations are completed.
777 * \sa ListItemActions819 * \sa ListItemActions
778 *820 *
821 * ListItem provides a set of attached properties which are attached to each panel
822 * of the ListItem. However not all properties are valid in all the circumstances.
823 *
779 * The component is styled using the \l ListItemStyle style interface.824 * The component is styled using the \l ListItemStyle style interface.
780 */825 */
781826
@@ -799,13 +844,37 @@
799844
800UCListItemAttached *UCListItem::qmlAttachedProperties(QObject *owner)845UCListItemAttached *UCListItem::qmlAttachedProperties(QObject *owner)
801{846{
802 return new UCListItemAttached(owner);847 /*
848 * Detect the attachee, whether is it a child item of the panelItem. The panelItem
849 * itself cannot be detected, as the object can be attached during the call of
850 * component.beginCreate().
851 */
852 UCListItemAttached *attached = new UCListItemAttached(owner);
853 QQuickItem *item = qobject_cast<QQuickItem*>(owner);
854 while (item) {
855 // has item our attached property?
856 UCListItemAttached *itemAttached = static_cast<UCListItemAttached*>(
857 qmlAttachedPropertiesObject<UCListItem>(item, false));
858 if (itemAttached) {
859 attached->connectToAttached(itemAttached);
860 break;
861 }
862 item = item->parentItem();
863 }
864 return attached;
803}865}
804866
805void UCListItem::componentComplete()867void UCListItem::componentComplete()
806{868{
807 UCStyledItemBase::componentComplete();869 UCStyledItemBase::componentComplete();
808 Q_D(UCListItem);870 Q_D(UCListItem);
871 // anchor contentItem prior doing anything else
872 QQuickAnchors *contentAnchors = QQuickItemPrivate::get(d->contentItem)->anchors();
873 contentAnchors->setTop(d->top());
874 contentAnchors->setBottom(d->bottom());
875 d->adjustContentItemHeight();
876 d->lockContentItem(true);
877
809 d->ready = true;878 d->ready = true;
810 /* We only deal with ListView, as for other cases we would need to check the children879 /* We only deal with ListView, as for other cases we would need to check the children
811 * changes, which would have an enormous impact on performance in case of huge amount880 * changes, which would have an enormous impact on performance in case of huge amount
@@ -838,21 +907,23 @@
838 d->flickable = qobject_cast<QQuickFlickable*>(data.item->parentItem());907 d->flickable = qobject_cast<QQuickFlickable*>(data.item->parentItem());
839 }908 }
840909
841 // attach ListItem properties to the flickable or to the parent item910 // attach ViewItems to parent item or to ListView
842 if (d->flickable) {911 QQuickItem *parentAttachee = data.item;
843 // connect to flickable to get width changes912 if (d->flickable && d->flickable->inherits("QQuickListView")) {
844 d->attachedProperties = static_cast<UCListItemAttached*>(qmlAttachedPropertiesObject<UCListItem>(d->flickable));913 // attach to ListView
914 d->parentAttached = static_cast<UCViewItemsAttached*>(qmlAttachedPropertiesObject<UCViewItemsAttached>(d->flickable));
915 parentAttachee = d->flickable;
845 } else if (data.item) {916 } else if (data.item) {
846 d->attachedProperties = static_cast<UCListItemAttached*>(qmlAttachedPropertiesObject<UCListItem>(data.item));917 d->parentAttached = static_cast<UCViewItemsAttached*>(qmlAttachedPropertiesObject<UCViewItemsAttached>(data.item));
847 } else {918 } else {
848 // mark as not ready, so no action should be performed which depends on readyness919 // mark as not ready, so no action should be performed which depends on readyness
849 d->ready = false;920 d->ready = false;
850 // about to be deleted or reparented, disable attached921 // about to be deleted or reparented, disable attached
851 d->attachedProperties = 0;922 d->parentAttached = 0;
852 }923 }
853924
854 if (data.item) {925 if (parentAttachee) {
855 QObject::connect(d->flickable ? d->flickable : data.item, SIGNAL(widthChanged()), this, SLOT(_q_updateSize()));926 QObject::connect(parentAttachee, SIGNAL(widthChanged()), this, SLOT(_q_updateSize()), Qt::DirectConnection);
856 }927 }
857928
858 // update size929 // update size
@@ -860,14 +931,6 @@
860 }931 }
861}932}
862933
863void UCListItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
864{
865 UCStyledItemBase::geometryChanged(newGeometry, oldGeometry);
866 // resize contentItem item
867 Q_D(UCListItem);
868 d->resize();
869}
870
871QSGNode *UCListItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)934QSGNode *UCListItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
872{935{
873 Q_UNUSED(data);936 Q_UNUSED(data);
@@ -924,19 +987,26 @@
924{987{
925 UCStyledItemBase::mousePressEvent(event);988 UCStyledItemBase::mousePressEvent(event);
926 Q_D(UCListItem);989 Q_D(UCListItem);
927 if (d->attachedProperties && d->attachedProperties->isMoving()) {990 if (d->parentAttached && d->parentAttached->isMoving()) {
928 // while moving, we cannot select any items991 // while moving, we cannot select any items
929 return;992 return;
930 }993 }
931 if (event->button() == Qt::LeftButton && d->canHighlight(event)) {994 if (event->button() == Qt::LeftButton && d->canHighlight(event)) {
995 // stop any ongoing animation!
996 if (d->animator) {
997 d->animator->stop();
998 }
932 d->setHighlighted(true);999 d->setHighlighted(true);
933 d->lastPos = d->pressedPos = event->localPos();1000 d->lastPos = d->pressedPos = event->localPos();
934 // connect the Flickable to know when to rebound1001 // connect the Flickable to know when to rebound
935 d->listenToRebind(true);1002 d->listenToRebind(true);
936 // if it was moved, grab the panels1003 // if it was moved, grab the panels
937 if (d->swiped) {1004 if (d->swiped) {
938 d->grabPanel(d->leadingActions, true);1005 UCActionPanel::grabPanel(&d->leadingPanel, this, true);
939 d->grabPanel(d->trailingActions, true);1006 UCActionPanel::grabPanel(&d->trailingPanel, this, false);
1007 if (d->parentAttached) {
1008 d->parentAttached->disableInteractive(this, true);
1009 }
940 }1010 }
941 }1011 }
942 // accept the event so we get the rest of the events as well1012 // accept the event so we get the rest of the events as well
@@ -950,8 +1020,8 @@
950 // set released1020 // set released
951 if (d->highlighted) {1021 if (d->highlighted) {
952 d->listenToRebind(false);1022 d->listenToRebind(false);
953 if (d->attachedProperties) {1023 if (d->parentAttached) {
954 d->attachedProperties->disableInteractive(this, false);1024 d->parentAttached->disableInteractive(this, false);
955 }1025 }
9561026
957 if (!d->suppressClick) {1027 if (!d->suppressClick) {
@@ -968,8 +1038,8 @@
968 UCStyledItemBase::mouseMoveEvent(event);1038 UCStyledItemBase::mouseMoveEvent(event);
9691039
970 // accept the tugging only if the move is within the threshold1040 // accept the tugging only if the move is within the threshold
971 bool leadingAttached = UCListItemActionsPrivate::isConnectedTo(d->leadingActions, this);1041 bool leadingAttached = UCActionPanel::isConnected(d->leadingPanel);
972 bool trailingAttached = UCListItemActionsPrivate::isConnectedTo(d->trailingActions, this);1042 bool trailingAttached = UCActionPanel::isConnected(d->trailingPanel);
973 if (d->highlighted && !(leadingAttached || trailingAttached)) {1043 if (d->highlighted && !(leadingAttached || trailingAttached)) {
974 // check if we can initiate the drag at all1044 // check if we can initiate the drag at all
975 // only X direction matters, if Y-direction leaves the threshold, but X not, the tug is not valid1045 // only X direction matters, if Y-direction leaves the threshold, but X not, the tug is not valid
@@ -984,8 +1054,13 @@
984 // got connected ad which not; this may fail in case of shared ListItemActions,1054 // got connected ad which not; this may fail in case of shared ListItemActions,
985 // as then the panel is shared between the list items, and the panel might be1055 // as then the panel is shared between the list items, and the panel might be
986 // still in use in other panels. See UCListItemActionsPrivate::connectToListItem1056 // still in use in other panels. See UCListItemActionsPrivate::connectToListItem
987 leadingAttached = d->grabPanel(d->leadingActions, true);1057 leadingAttached = UCActionPanel::grabPanel(&d->leadingPanel, this, true);
988 trailingAttached = d->grabPanel(d->trailingActions, true);1058 trailingAttached = UCActionPanel::grabPanel(&d->trailingPanel, this, false);
1059 // unlock contentItem's left/right edges
1060 d->lockContentItem(false);
1061 if (d->parentAttached) {
1062 d->parentAttached->disableInteractive(this, true);
1063 }
989 // create animator if not created yet1064 // create animator if not created yet
990 if (!d->animator) {1065 if (!d->animator) {
991 d->animator = new UCListItemSnapAnimator(this);1066 d->animator = new UCListItemSnapAnimator(this);
@@ -1007,19 +1082,19 @@
1007 d->contentItem->setX(x);1082 d->contentItem->setX(x);
1008 // decide which panel is visible by checking the contentItem's X coordinates1083 // decide which panel is visible by checking the contentItem's X coordinates
1009 if (d->contentItem->x() > 0) {1084 if (d->contentItem->x() > 0) {
1010 if (leadingAttached) {1085 if (d->leadingPanel) {
1011 UCListItemActionsPrivate::get(d->leadingActions)->panelItem->setVisible(true);1086 d->leadingPanel->panel()->setVisible(true);
1012 }1087 }
1013 if (trailingAttached) {1088 if (d->trailingPanel) {
1014 UCListItemActionsPrivate::get(d->trailingActions)->panelItem->setVisible(false);1089 d->trailingPanel->panel()->setVisible(false);
1015 }1090 }
1016 } else if (d->contentItem->x() < 0) {1091 } else if (d->contentItem->x() < 0) {
1017 // trailing revealed1092 // trailing revealed
1018 if (leadingAttached) {1093 if (d->leadingPanel) {
1019 UCListItemActionsPrivate::get(d->leadingActions)->panelItem->setVisible(false);1094 d->leadingPanel->panel()->setVisible(false);
1020 }1095 }
1021 if (trailingAttached) {1096 if (d->trailingPanel) {
1022 UCListItemActionsPrivate::get(d->trailingActions)->panelItem->setVisible(true);1097 d->trailingPanel->panel()->setVisible(true);
1023 }1098 }
1024 }1099 }
1025 }1100 }
@@ -1093,16 +1168,10 @@
1093 }1168 }
1094 // snap out before we change the actions1169 // snap out before we change the actions
1095 d->promptRebound();1170 d->promptRebound();
1096 // then delete panelItem1171 // then delete panel
1097 if (d->leadingActions) {1172 delete d->leadingPanel;
1098 UCListItemActionsPrivate *list = UCListItemActionsPrivate::get(d->leadingActions);1173 d->leadingPanel = 0;
1099 delete list->panelItem;
1100 list->panelItem = 0;
1101 }
1102 d->leadingActions = actions;1174 d->leadingActions = actions;
1103 if (d->leadingActions == d->trailingActions && d->leadingActions) {
1104 qmlInfo(this) << UbuntuI18n::tr("leadingActions and trailingActions cannot share the same object!");
1105 }
1106 Q_EMIT leadingActionsChanged();1175 Q_EMIT leadingActionsChanged();
1107}1176}
11081177
@@ -1127,16 +1196,10 @@
1127 }1196 }
1128 // snap out before we change the actions1197 // snap out before we change the actions
1129 d->promptRebound();1198 d->promptRebound();
1130 // then delete panelItem1199 // then delete panel
1131 if (d->trailingActions) {1200 delete d->trailingPanel;
1132 UCListItemActionsPrivate *list = UCListItemActionsPrivate::get(d->trailingActions);1201 d->trailingPanel = 0;
1133 delete list->panelItem;
1134 list->panelItem = 0;
1135 }
1136 d->trailingActions = actions;1202 d->trailingActions = actions;
1137 if (d->leadingActions == d->trailingActions && d->trailingActions) {
1138 qmlInfo(this) << UbuntuI18n::tr("leadingActions and trailingActions cannot share the same object!");
1139 }
1140 Q_EMIT trailingActionsChanged();1203 Q_EMIT trailingActionsChanged();
1141}1204}
11421205
@@ -1171,8 +1234,8 @@
1171 * The default values for the properties are:1234 * The default values for the properties are:
1172 * \list1235 * \list
1173 * \li \c visible: true1236 * \li \c visible: true
1174 * \li \c leftMargin: 2 GU1237 * \li \c leftMargin: 0
1175 * \li \c rightMargin: 2 GU1238 * \li \c rightMargin: 0
1176 * \endlist1239 * \endlist
1177 */1240 */
1178UCListItemDivider* UCListItem::divider() const1241UCListItemDivider* UCListItem::divider() const
@@ -1253,7 +1316,8 @@
12531316
1254/*!1317/*!
1255 * \qmlproperty color ListItem::highlightColor1318 * \qmlproperty color ListItem::highlightColor
1256 * Configures the color when highlighted. Defaults to the theme palette's background color.1319 * Configures the color when highlighted. Defaults to the theme palette's background
1320 * color. If changed, it can be reset by assigning undefined as value.
1257 */1321 */
1258QColor UCListItem::highlightColor() const1322QColor UCListItem::highlightColor() const
1259{1323{
@@ -1263,12 +1327,20 @@
1263void UCListItem::setHighlightColor(const QColor &color)1327void UCListItem::setHighlightColor(const QColor &color)
1264{1328{
1265 Q_D(UCListItem);1329 Q_D(UCListItem);
1330 // mark it as custom even if the value is the same as the previous one
1331 d->customColor = true;
1266 if (d->highlightColor == color) {1332 if (d->highlightColor == color) {
1267 return;1333 return;
1268 }1334 }
1269 d->highlightColor = color;1335 d->highlightColor = color;
1270 // no more theme change watch1336 update();
1271 d->customColor = true;1337 Q_EMIT highlightColorChanged();
1338}
1339void UCListItem::resetHighlightColor()
1340{
1341 Q_D(UCListItem);
1342 d->customColor = false;
1343 d->highlightColor = getPaletteColor("selected", "background");
1272 update();1344 update();
1273 Q_EMIT highlightColorChanged();1345 Q_EMIT highlightColorChanged();
1274}1346}
@@ -1277,7 +1349,7 @@
1277 * \qmlproperty real ListItem::swipeOvershoot1349 * \qmlproperty real ListItem::swipeOvershoot
1278 * The property configures the overshoot value on swiping. Its default value is1350 * The property configures the overshoot value on swiping. Its default value is
1279 * configured by the \l {ListItemStyle}{style}. Any positive value overrides the1351 * configured by the \l {ListItemStyle}{style}. Any positive value overrides the
1280 * default value, and any negative value resets it back to the default.1352 * default value, and any negative or undefined value resets it back to the default.
1281 */1353 */
1282qreal UCListItemPrivate::swipeOvershoot() const1354qreal UCListItemPrivate::swipeOvershoot() const
1283{1355{
@@ -1285,16 +1357,26 @@
1285}1357}
1286void UCListItemPrivate::setSwipeOvershoot(qreal overshoot)1358void UCListItemPrivate::setSwipeOvershoot(qreal overshoot)
1287{1359{
1360 // mark any positive value as custom even if it is the same as the previous one
1361 customOvershoot = (overshoot >= 0.0);
1288 // same value should be guarded only if the style hasn't been loaded yet1362 // same value should be guarded only if the style hasn't been loaded yet
1289 // swipeOvershoot can be set to 0 prior the style is loaded.1363 // swipeOvershoot can be set to 0 prior the style is loaded.
1290 if (this->overshoot == overshoot && styleItem) {1364 if (this->overshoot == overshoot && styleItem) {
1291 return;1365 return;
1292 }1366 }
1293 customOvershoot = (overshoot >= 0.0);1367 if (!customOvershoot) {
1294 this->overshoot = (overshoot < 0.0) ?1368 resetSwipeOvershoot();
1295 // reset, use style to get the overshoot value1369 return;
1296 (styleItem ? styleItem->m_swipeOvershoot : 0.0) :1370 }
1297 overshoot;1371 this->overshoot = overshoot;
1372 update();
1373 Q_Q(UCListItem);
1374 Q_EMIT q->swipeOvershootChanged();
1375}
1376void UCListItemPrivate::resetSwipeOvershoot()
1377{
1378 customOvershoot = false;
1379 overshoot = styleItem ? styleItem->m_swipeOvershoot : 0.0;
1298 update();1380 update();
1299 Q_Q(UCListItem);1381 Q_Q(UCListItem);
1300 Q_EMIT q->swipeOvershootChanged();1382 Q_EMIT q->swipeOvershootChanged();
13011383
=== modified file 'modules/Ubuntu/Components/plugin/uclistitem.h'
--- modules/Ubuntu/Components/plugin/uclistitem.h 2014-12-18 10:08:56 +0000
+++ modules/Ubuntu/Components/plugin/uclistitem.h 2015-01-16 14:53:38 +0000
@@ -34,17 +34,23 @@
34 Q_PROPERTY(UCListItemActions *leadingActions READ leadingActions WRITE setLeadingActions NOTIFY leadingActionsChanged DESIGNABLE false)34 Q_PROPERTY(UCListItemActions *leadingActions READ leadingActions WRITE setLeadingActions NOTIFY leadingActionsChanged DESIGNABLE false)
35 Q_PROPERTY(UCListItemActions *trailingActions READ trailingActions WRITE setTrailingActions NOTIFY trailingActionsChanged DESIGNABLE false)35 Q_PROPERTY(UCListItemActions *trailingActions READ trailingActions WRITE setTrailingActions NOTIFY trailingActionsChanged DESIGNABLE false)
36 Q_PROPERTY(bool highlighted READ highlighted NOTIFY highlightedChanged)36 Q_PROPERTY(bool highlighted READ highlighted NOTIFY highlightedChanged)
37 Q_PRIVATE_PROPERTY(UCListItem::d_func(), qreal swipeOvershoot READ swipeOvershoot WRITE setSwipeOvershoot NOTIFY swipeOvershootChanged)37 Q_PRIVATE_PROPERTY(UCListItem::d_func(), qreal swipeOvershoot READ swipeOvershoot WRITE setSwipeOvershoot RESET resetSwipeOvershoot NOTIFY swipeOvershootChanged)
38 Q_PRIVATE_PROPERTY(UCListItem::d_func(), bool contentMoving READ contentMoving NOTIFY contentMovingChanged)38 Q_PRIVATE_PROPERTY(UCListItem::d_func(), bool contentMoving READ contentMoving NOTIFY contentMovingChanged)
39 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)39 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
40 Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setHighlightColor NOTIFY highlightColorChanged)40 Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setHighlightColor RESET resetHighlightColor NOTIFY highlightColorChanged)
41 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlListProperty<QObject> listItemData READ data DESIGNABLE false)41 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlListProperty<QObject> listItemData READ data DESIGNABLE false)
42 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlListProperty<QQuickItem> listItemChildren READ children NOTIFY listItemChildrenChanged DESIGNABLE false)42 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlListProperty<QQuickItem> listItemChildren READ children NOTIFY listItemChildrenChanged DESIGNABLE false)
43 // FIXME move these to StyledItemBase with subtheming43 // FIXME move these to StyledItemBase with subtheming
44 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlComponent *style READ style WRITE setStyle NOTIFY styleChanged)44 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlComponent *style READ style WRITE setStyle RESET resetStyle NOTIFY styleChanged)
45 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQuickItem *__styleInstance READ styleInstance NOTIFY __styleInstanceChanged)45 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQuickItem *__styleInstance READ styleInstance NOTIFY __styleInstanceChanged)
46 Q_CLASSINFO("DefaultProperty", "listItemData")46 Q_CLASSINFO("DefaultProperty", "listItemData")
47 Q_ENUMS(PanelStatus)
47public:48public:
49 enum PanelStatus {
50 None,
51 Leading,
52 Trailing
53 };
48 explicit UCListItem(QQuickItem *parent = 0);54 explicit UCListItem(QQuickItem *parent = 0);
49 ~UCListItem();55 ~UCListItem();
5056
@@ -61,12 +67,12 @@
61 void setColor(const QColor &color);67 void setColor(const QColor &color);
62 QColor highlightColor() const;68 QColor highlightColor() const;
63 void setHighlightColor(const QColor &color);69 void setHighlightColor(const QColor &color);
70 void resetHighlightColor();
6471
65protected:72protected:
66 void componentComplete();73 void componentComplete();
67 QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);74 QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
68 void itemChange(ItemChange change, const ItemChangeData &data);75 void itemChange(ItemChange change, const ItemChangeData &data);
69 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
70 void mousePressEvent(QMouseEvent *event);76 void mousePressEvent(QMouseEvent *event);
71 void mouseReleaseEvent(QMouseEvent *event);77 void mouseReleaseEvent(QMouseEvent *event);
72 void mouseMoveEvent(QMouseEvent *event);78 void mouseMoveEvent(QMouseEvent *event);
@@ -103,13 +109,57 @@
103109
104QML_DECLARE_TYPEINFO(UCListItem, QML_HAS_ATTACHED_PROPERTIES)110QML_DECLARE_TYPEINFO(UCListItem, QML_HAS_ATTACHED_PROPERTIES)
105111
112class UCAction;
113class UCListItemActions;
106class UCListItemAttachedPrivate;114class UCListItemAttachedPrivate;
107class UCListItemAttached : public QObject115class UCListItemAttached : public QObject
108{116{
109 Q_OBJECT117 Q_OBJECT
118 Q_PROPERTY(UCListItemActions *actions READ actions NOTIFY actionsChanged)
119 Q_PROPERTY(QQmlListProperty<UCAction> visibleActions READ visibleActions NOTIFY visibleActionsChanged)
120 Q_PROPERTY(UCListItem *item READ item NOTIFY itemChanged)
121 Q_PROPERTY(int index READ index NOTIFY indexChanged)
122 Q_PROPERTY(UCListItem::PanelStatus panelStatus READ panelStatus NOTIFY panelStatusChanged)
110public:123public:
111 explicit UCListItemAttached(QObject *owner);124 UCListItemAttached(QObject *parent = 0);
112 ~UCListItemAttached();125 ~UCListItemAttached();
126 void setList(UCListItem *list, bool leading, bool visualizeActions);
127 void connectToAttached(UCListItemAttached *parentAttached);
128
129 UCListItemActions *actions() const;
130 QQmlListProperty<UCAction> visibleActions();
131 UCListItem *item();
132 int index();
133 UCListItem::PanelStatus panelStatus();
134
135public Q_SLOTS:
136 void snapToPosition(qreal position);
137
138Q_SIGNALS:
139 void actionsChanged();
140 void visibleActionsChanged();
141 void itemChanged();
142 void indexChanged();
143 void panelStatusChanged();
144
145private:
146 Q_DECLARE_PRIVATE(UCListItemAttached)
147 friend class UCListItemAction;
148
149private Q_SLOTS:
150 void updateVisibleActions();
151};
152
153
154class UCViewItemsAttachedPrivate;
155class UCViewItemsAttached : public QObject
156{
157 Q_OBJECT
158public:
159 explicit UCViewItemsAttached(QObject *owner);
160 ~UCViewItemsAttached();
161
162 static UCViewItemsAttached *qmlAttachedProperties(QObject *owner);
113163
114 bool listenToRebind(UCListItem *item, bool listen);164 bool listenToRebind(UCListItem *item, bool listen);
115 void disableInteractive(UCListItem *item, bool disable);165 void disableInteractive(UCListItem *item, bool disable);
@@ -119,8 +169,9 @@
119private Q_SLOTS:169private Q_SLOTS:
120 void unbindItem();170 void unbindItem();
121private:171private:
122 Q_DECLARE_PRIVATE(UCListItemAttached)172 Q_DECLARE_PRIVATE(UCViewItemsAttached)
123 QScopedPointer<UCListItemAttachedPrivate> d_ptr;173 QScopedPointer<UCViewItemsAttachedPrivate> d_ptr;
124};174};
175QML_DECLARE_TYPEINFO(UCViewItemsAttached, QML_HAS_ATTACHED_PROPERTIES)
125176
126#endif // UCLISTITEM_H177#endif // UCLISTITEM_H
127178
=== modified file 'modules/Ubuntu/Components/plugin/uclistitem_p.h'
--- modules/Ubuntu/Components/plugin/uclistitem_p.h 2015-01-07 06:42:09 +0000
+++ modules/Ubuntu/Components/plugin/uclistitem_p.h 2015-01-16 14:53:38 +0000
@@ -22,6 +22,15 @@
22#include <QtCore/QPointer>22#include <QtCore/QPointer>
23#include <QtQuick/private/qquickrectangle_p.h>23#include <QtQuick/private/qquickrectangle_p.h>
2424
25#define MIN(x, y) ((x < y) ? x : y)
26#define MAX(x, y) ((x > y) ? x : y)
27#define CLAMP(v, min, max) (min <= max) ? MAX(min, MIN(v, max)) : MAX(max, MIN(v, min))
28
29#define IMPLICIT_LISTITEM_WIDTH_GU 40
30#define IMPLICIT_LISTITEM_HEIGHT_GU 7
31#define DIVIDER_THICKNESS_DP 2
32#define DEFAULT_SWIPE_THRESHOLD_GU 1.5
33
25class QQuickFlickable;34class QQuickFlickable;
26class QQuickPropertyAnimation;35class QQuickPropertyAnimation;
27class UCListItemContent;36class UCListItemContent;
@@ -29,6 +38,7 @@
29class UCListItemActions;38class UCListItemActions;
30class UCListItemSnapAnimator;39class UCListItemSnapAnimator;
31class UCListItemStyle;40class UCListItemStyle;
41class UCActionPanel;
32class UCListItemPrivate : public UCStyledItemBasePrivate42class UCListItemPrivate : public UCStyledItemBasePrivate
33{43{
34 Q_DECLARE_PUBLIC(UCListItem)44 Q_DECLARE_PUBLIC(UCListItem)
@@ -53,19 +63,17 @@
53 bool canHighlight(QMouseEvent *event);63 bool canHighlight(QMouseEvent *event);
54 void setHighlighted(bool pressed);64 void setHighlighted(bool pressed);
55 void setSwiped(bool tugged);65 void setSwiped(bool tugged);
56 bool grabPanel(UCListItemActions *optionList, bool isTugged);
57 void listenToRebind(bool listen);66 void listenToRebind(bool listen);
58 void resize();67 void lockContentItem(bool lock);
68 void adjustContentItemHeight();
59 void update();69 void update();
60 void clampAndMoveX(qreal &x, qreal dx);70 void clampAndMoveX(qreal &x, qreal dx);
6171
62 bool highlighted:1;72 bool highlighted:1;
63 bool contentMoved:1;73 bool contentMoved:1;
64 bool highlightColorChanged:1;
65 bool swiped:1;74 bool swiped:1;
66 bool suppressClick:1;75 bool suppressClick:1;
67 bool ready:1;76 bool ready:1;
68 bool customStyle:1;
69 bool customColor:1;77 bool customColor:1;
70 bool customOvershoot:1;78 bool customOvershoot:1;
71 bool flicked:1;79 bool flicked:1;
@@ -77,45 +85,65 @@
77 QColor highlightColor;85 QColor highlightColor;
78 QPointer<QQuickItem> countOwner;86 QPointer<QQuickItem> countOwner;
79 QPointer<QQuickFlickable> flickable;87 QPointer<QQuickFlickable> flickable;
80 QPointer<UCListItemAttached> attachedProperties;88 QPointer<UCViewItemsAttached> parentAttached;
81 QQuickItem *contentItem;89 QQuickItem *contentItem;
82 UCListItemDivider *divider;90 UCListItemDivider *divider;
83 UCListItemActions *leadingActions;91 UCListItemActions *leadingActions;
84 UCListItemActions *trailingActions;92 UCListItemActions *trailingActions;
93 UCActionPanel *leadingPanel;
94 UCActionPanel *trailingPanel;
85 UCListItemSnapAnimator *animator;95 UCListItemSnapAnimator *animator;
8696
87 // FIXME move these to StyledItemBase togehther with subtheming.97 // FIXME move these to StyledItemBase togehther with subtheming.
88 QQmlComponent *styleComponent;98 QQmlComponent *styleComponent;
99 QQmlComponent *implicitStyleComponent;
89 UCListItemStyle *styleItem;100 UCListItemStyle *styleItem;
90101
91 // getters/setters102 // getters/setters
92 qreal swipeOvershoot() const;103 qreal swipeOvershoot() const;
93 void setSwipeOvershoot(qreal overshoot);104 void setSwipeOvershoot(qreal overshoot);
105 void resetSwipeOvershoot();
94 QQmlListProperty<QObject> data();106 QQmlListProperty<QObject> data();
95 QQmlListProperty<QQuickItem> children();107 QQmlListProperty<QQuickItem> children();
96 bool contentMoving() const;108 bool contentMoving() const;
97 void setContentMoving(bool moved);109 void setContentMoving(bool moved);
98 QQmlComponent *style() const;110 QQmlComponent *style() const;
99 void setStyle(QQmlComponent *delegate);111 void setStyle(QQmlComponent *delegate);
100 bool loadStyle(bool reload);112 void resetStyle();
101 void initStyleItem();113 void initStyleItem();
102 QQuickItem *styleInstance() const;114 QQuickItem *styleInstance() const;
103};115};
104116
117class UCListItemAttachedPrivate : public QObjectPrivate
118{
119 Q_DECLARE_PUBLIC(UCListItemAttached)
120public:
121 UCListItemAttachedPrivate() : QObjectPrivate(), panel(0), listItem(0) {}
122
123 static UCListItemAttachedPrivate* get(UCListItemAttached *that)
124 {
125 return that->d_func();
126 }
127
128 UCActionPanel *panel;
129 UCListItem *listItem;
130 QList<UCAction*> visibleActions;
131};
132
105class PropertyChange;133class PropertyChange;
106class UCListItemAttachedPrivate134class UCViewItemsAttachedPrivate
107{135{
108 Q_DECLARE_PUBLIC(UCListItemAttached)136 Q_DECLARE_PUBLIC(UCViewItemsAttached)
109public:137public:
110 UCListItemAttachedPrivate(UCListItemAttached *qq);138 UCViewItemsAttachedPrivate(UCViewItemsAttached *qq);
111 ~UCListItemAttachedPrivate();139 ~UCViewItemsAttachedPrivate();
112140
113 void clearFlickablesList();141 void clearFlickablesList();
114 void buildFlickablesList();142 void buildFlickablesList();
115 void clearChangesList();143 void clearChangesList();
116 void buildChangesList(const QVariant &newValue);144 void buildChangesList(const QVariant &newValue);
117145
118 UCListItemAttached *q_ptr;146 UCViewItemsAttached *q_ptr;
119 bool globalDisabled;147 bool globalDisabled;
120 QList< QPointer<QQuickFlickable> > flickables;148 QList< QPointer<QQuickFlickable> > flickables;
121 QList< PropertyChange* > changes;149 QList< PropertyChange* > changes;
@@ -123,6 +151,41 @@
123 QPointer<UCListItem> disablerItem;151 QPointer<UCListItem> disablerItem;
124};152};
125153
154class UCActionPanel : public QObject
155{
156 Q_OBJECT
157public:
158 ~UCActionPanel();
159 static bool grabPanel(UCActionPanel **panel, UCListItem *item, bool leading);
160 static void ungrabPanel(UCActionPanel *panel);
161 static bool isConnected(UCActionPanel *panel);
162
163 UCListItemActions *actions();
164 QQuickItem *panel() const;
165 UCListItem::PanelStatus panelStatus()
166 {
167 return status;
168 }
169 bool isLeading() const
170 {
171 return leading;
172 }
173
174Q_SIGNALS:
175 void statusChanged();
176
177private:
178 UCActionPanel(UCListItem *item, bool leading);
179 bool createPanel(QQmlComponent *panelDelegate);
180 UCListItemAttached *attachedObject();
181
182 UCListItem *listItem;
183 QQuickItem *panelItem;
184 UCListItem::PanelStatus status;
185 bool leading:1;
186 bool connected:1;
187};
188
126class UCListItemDivider : public QObject189class UCListItemDivider : public QObject
127{190{
128 Q_OBJECT191 Q_OBJECT
@@ -159,8 +222,6 @@
159 void setColorTo(const QColor &color);222 void setColorTo(const QColor &color);
160223
161 bool m_visible:1;224 bool m_visible:1;
162 bool m_leftMarginChanged:1;
163 bool m_rightMarginChanged:1;
164 bool m_colorFromChanged:1;225 bool m_colorFromChanged:1;
165 bool m_colorToChanged:1;226 bool m_colorToChanged:1;
166 qreal m_thickness;227 qreal m_thickness;
@@ -187,6 +248,7 @@
187 ~UCListItemSnapAnimator();248 ~UCListItemSnapAnimator();
188249
189 bool snap(qreal to);250 bool snap(qreal to);
251 void stop();
190 void complete();252 void complete();
191253
192public Q_SLOTS:254public Q_SLOTS:
193255
=== modified file 'modules/Ubuntu/Components/plugin/uclistitemactions.cpp'
--- modules/Ubuntu/Components/plugin/uclistitemactions.cpp 2014-12-01 14:50:13 +0000
+++ modules/Ubuntu/Components/plugin/uclistitemactions.cpp 2015-01-16 14:53:38 +0000
@@ -27,167 +27,13 @@
2727
28UCListItemActionsPrivate::UCListItemActionsPrivate()28UCListItemActionsPrivate::UCListItemActionsPrivate()
29 : QObjectPrivate()29 : QObjectPrivate()
30 , status(UCListItemActions::Disconnected)
31 , offsetDragged(0)
32 , optionSlotWidth(0.0)
33 , delegate(0)30 , delegate(0)
34 , panelDelegate(0)
35 , panelItem(0)
36{31{
37}32}
38UCListItemActionsPrivate::~UCListItemActionsPrivate()33UCListItemActionsPrivate::~UCListItemActionsPrivate()
39{34{
40}35}
4136
42void UCListItemActionsPrivate::_q_updateDraggedOffset()
43{
44 UCListItem *listItem = qobject_cast<UCListItem*>(panelItem->parentItem());
45 if (!listItem) {
46 return;
47 }
48
49 Q_Q(UCListItemActions);
50 offsetDragged = (status == UCListItemActions::Leading) ? panelItem->width() + panelItem->x() :
51 listItem->width() - panelItem->x();
52 if (offsetDragged < 0.0) {
53 offsetDragged = 0.0;
54 }
55}
56
57UCListItemActionsAttached *UCListItemActionsPrivate::attachedObject()
58{
59 if (!panelItem) {
60 return 0;
61 }
62 return static_cast<UCListItemActionsAttached*>(
63 qmlAttachedPropertiesObject<UCListItemActions>(panelItem, false));
64}
65
66/*
67 * Connects a ListItem to the ListItemActions' panel and returns true upon successful connection.
68 * Connection may fail if there is a different ListItem connected. In this case the new ListItem
69 * will be queued and automatically connected when the previous ListItem disconnects.
70 * The panel is only re-created when a different Component is used to create it.
71 * FIXME - despite each ListItem uses the same document to create the panel, theming engine
72 * provides different Component objects for each, due to not caching the components created.
73 * This must be fixed to optimize memory usage.
74 */
75bool UCListItemActionsPrivate::connectToListItem(UCListItemActions *actions, UCListItem *listItem, bool leading)
76{
77 UCListItemActionsPrivate *_this = get(actions);
78 if (!_this) {
79 return false;
80 }
81 // do we have a panel created already?
82 if (_this->panelItem) {
83 if (isConnectedTo(actions, listItem)) {
84 return true;
85 }
86 if (_this->panelItem->parentItem() && _this->panelItem->parentItem() != listItem) {
87 // set the requesting listItem as queuedItem
88 _this->queuedItem = listItem;
89 return false;
90 }
91 }
92 // no parent set or panelItem yet, proceed with panel creation
93 UCListItemPrivate *pItem = UCListItemPrivate::get(listItem);
94 pItem->initStyleItem();
95 if (!pItem->styleItem || (pItem->styleItem && !_this->createPanelItem(pItem->styleItem->m_actionsDelegate))) {
96 return false;
97 }
98
99 // check if the panel is still connected to a ListItem
100 // this may happen if there is a swipe over an other item while the previous
101 // one is rebounding
102 _this->panelItem->setParentItem(listItem);
103 if (_this->attachedObject()) {
104 _this->attachedObject()->connectListItem(listItem, true);
105 }
106 _this->offsetDragged = 0.0;
107 _this->status = leading ? UCListItemActions::Leading : UCListItemActions::Trailing;
108 Q_EMIT actions->statusChanged(_this->status);
109 return true;
110}
111
112void UCListItemActionsPrivate::disconnectFromListItem(UCListItemActions *actions)
113{
114 UCListItemActionsPrivate *_this = get(actions);
115 if (!_this || !_this->panelItem || !_this->panelItem->parentItem()) {
116 return;
117 }
118
119 if (_this->attachedObject()) {
120 _this->attachedObject()->connectListItem(static_cast<UCListItem*>(_this->panelItem->parentItem()), false);
121 }
122 _this->panelItem->setParentItem(0);
123 _this->status = UCListItemActions::Disconnected;
124 Q_EMIT actions->statusChanged(_this->status);
125 // if there was a queuedItem, make it grab the actions list
126 if (_this->queuedItem) {
127 UCListItemPrivate::get(_this->queuedItem.data())->grabPanel(actions, true);
128 // remove item from queue
129 _this->queuedItem.clear();
130 }
131}
132
133bool UCListItemActionsPrivate::isConnectedTo(UCListItemActions *actions, UCListItem *listItem)
134{
135 UCListItemActionsPrivate *_this = get(actions);
136 return _this && _this->panelItem &&
137 (_this->status != UCListItemActions::Disconnected) &&
138 (_this->panelItem->parentItem() == listItem);
139}
140
141QQuickItem *UCListItemActionsPrivate::createPanelItem(QQmlComponent *panel)
142{
143 if (panelItem && panelDelegate == panel) {
144 return panelItem;
145 }
146 // delete the panel if the next item's actionsDelegate differs from the
147 // one this panel was created from
148 if (panelDelegate != panel) {
149 delete panelItem;
150 panelItem = 0;
151 }
152
153 Q_Q(UCListItemActions);
154 if (!panel) {
155 qmlInfo(q) << UbuntuI18n::instance().tr("actionsDelegate not set!");
156 return 0;
157 }
158
159 panelDelegate = panel;
160 if (!panelDelegate->isError()) {
161 panelItem = qobject_cast<QQuickItem*>(panelDelegate->beginCreate(qmlContext(q)));
162 if (panelItem) {
163 QQml_setParent_noEvent(panelItem, q);
164 // add panelItem to data so we can access it in case is needed (i.e. tests)
165 data.append(panelItem);
166 // create attached property!
167 UCListItemActionsAttached *attached = static_cast<UCListItemActionsAttached*>(
168 qmlAttachedPropertiesObject<UCListItemActions>(panelItem));
169 if (!attached->container()) {
170 attached->setList(q);
171 } else {
172 // container is set, but we need to emit the signal again so we get the
173 // attached props updated for those cases when the attached property is
174 // created before the statement above
175 Q_EMIT attached->containerChanged();
176 }
177 panelDelegate->completeCreate();
178
179 // calculate option's slot size
180 offsetDragged = 0.0;
181 // connect to panel to catch dragging
182 QObject::connect(panelItem, SIGNAL(xChanged()), q, SLOT(_q_updateDraggedOffset()));
183 }
184 } else {
185 qmlInfo(q) << panelDelegate->errorString();
186 }
187
188 return panelItem;
189}
190
191/*!37/*!
192 * \qmltype ListItemActions38 * \qmltype ListItemActions
193 * \instantiates UCListItemActions39 * \instantiates UCListItemActions
@@ -199,86 +45,22 @@
199 *45 *
200 * ListItem accepts actions that can be configured to appear when swiped to left46 * ListItem accepts actions that can be configured to appear when swiped to left
201 * or right. The API does not limit the number of actions to be assigned for leading47 * or right. The API does not limit the number of actions to be assigned for leading
202 * or trailing actions, however the design constrains are allowing a maximum of48 * or trailing actions, however the design constraints are allowing a maximum of
203 * 1 action on leading- and a maximum of 3 actions on trailing side of the ListItem.49 * 1 action on leading- and a maximum of 3 actions on trailing side of the ListItem.
204 *50 *
205 * The \l actions are Action instances or elements derived from Action. The default51 * The \l actions are Action instances or elements derived from Action. The default
206 * visualization of the actions can be overridden using the \l delegate property,52 * visualization of the actions can be overridden using the \l delegate property,
207 * and the default implementation uses the \c name property of the Action.53 * and the default implementation uses the \c name property of the Action.
208 *54 *
209 * The leading and trailing actions are placed on a panel item, which is created
210 * the first time the actions are accessed. The colors of the panel is taken from
211 * the theme's palette.
212 *
213 * When swiped, panels reveal the actions one by one. In case an action is revealed
214 * more than 50%, the action will be snapped and revealed completely. This is also
215 * valid for the case when the action is visible less than 50%, in which case the
216 * action is hidden. Actions can be triggered by tapping.
217 *
218 * \note You can use the same ListItemActions for leading and for trailing actions
219 * the same time only if the instance is used by different groups of list items,
220 * where one group uses it as leading and other group as trailing. In any other
221 * circumstances use separate ListItemActions for leading and trailing actions.
222 * \qml
223 * import QtQuick 2.2
224 * import Ubuntu.Components 1.2
225 * MainView {
226 * width: units.gu(40)
227 * height: units.gu(71)
228 *
229 * ListItemActions {
230 * id: sharedActions
231 * actions: [
232 * Action {
233 * iconName: "search"
234 * },
235 * Action {
236 * iconName: "edit"
237 * },
238 * Action {
239 * iconName: "copy"
240 * }
241 * ]
242 * }
243 *
244 * Column {
245 * ListItem {
246 * leadingActions: sharedActions
247 * }
248 * UbuntuListView {
249 * anchors.fill: parent
250 * model: 10000
251 * delegate: ListItem {
252 * trailingActions: sharedActions
253 * }
254 * }
255 * }
256 * }
257 * \endqml
258 *
259 * \section3 Using with ListViews55 * \section3 Using with ListViews
260 * ListItemActions instances can be shared between ListItem instances within the56 * ListItemActions instances can be shared between ListItem instances within the
261 * same view. When shared, the memory footprint of the view will be lot smaller,57 * same view. When shared, the memory footprint of the view will be lot smaller,
262 * as there will be no individual panel created for each list's actions visualization.58 * as there will be no individual action container created for each list's actions.
263 * Depending on how long the initialization of the component used in \l {ListItemStyle::actionsDelegate}
264 * {actionsDelegate} takes, creation time will be also reduced to one time per view.
265 * However, this implies that swiping a new ListItem content while another one is
266 * swiped will result in showing the newly swiped item's panel delayed, as the
267 * panel can be shown only after the previous item's snapping is completed. Depending
268 * on the \l {ListItemStyle::snapAnimation}{snapAnimation} duration, this may take some time, and the
269 * response time of the UI can become unacceptable.
270 *
271 * Having individual ListItemActions instances increases the memory footprint,59 * Having individual ListItemActions instances increases the memory footprint,
272 * however the UI will be more responsive as swiping individual ListItems will60 * and also has performance impact on kinetic scrolling.
273 * not have to wait till the previous ListItem's panel is snapped out (rebound).
274 * On the other hand, memory consumption will increase significantly due to
275 * separate panel creation, and performance may decrease with up to 40%, depending
276 * on what way are the actions declared, within the ListItemActions or as shared
277 * actions.
278 *61 *
279 * The example above illustrates how to share ListItemActions between ListItem62 * The examples below illustrate the worst and best practice when used in a ListView.
280 * delegates, which can be the worst-performant but most lightwaight memory consumer63 * The worst case:
281 * setup. The following example illustrates the worst case:
282 * \qml64 * \qml
283 * import QtQuick 2.265 * import QtQuick 2.2
284 * import Ubuntu.Components 1.266 * import Ubuntu.Components 1.2
@@ -323,33 +105,33 @@
323 * width: units.gu(40)105 * width: units.gu(40)
324 * height: units.gu(71)106 * height: units.gu(71)
325 *107 *
326 * property list<Action> leading: [108 * ListItemActions {
327 * Action {109 * id: leading
110 * actions: Action {
328 * iconName: "delete"111 * iconName: "delete"
329 * }112 * }
330 * ]113 * }
331 * property list<Action> trailing: [114 * ListItemActions {
332 * Action {115 * id: trailing
333 * iconName: "search"116 * actions: [
334 * },117 * Action {
335 * Action {118 * iconName: "search"
336 * iconName: "edit"119 * },
337 * },120 * Action {
338 * Action {121 * iconName: "edit"
339 * iconName: "copy"122 * },
340 * }123 * Action {
341 * ]124 * iconName: "copy"
125 * }
126 * ]
127 * }
342 *128 *
343 * UbuntuListView {129 * UbuntuListView {
344 * anchors.fill: parent130 * anchors.fill: parent
345 * model: 10000131 * model: 10000
346 * delegate: ListItem {132 * delegate: ListItem {
347 * leadingActions: ListItemActions {133 * leadingActions: leading
348 * actions: leading134 * trailingActions: trailing
349 * }
350 * trailingActions: ListItemActions {
351 * actions: trailing
352 * }
353 * }135 * }
354 * }136 * }
355 * }137 * }
@@ -362,11 +144,6 @@
362 * parameter to identify the instance of the ListItem on which it was executed,144 * parameter to identify the instance of the ListItem on which it was executed,
363 * in which case ListItem will change the type from \c Actions.None to \c Actions.Integer145 * in which case ListItem will change the type from \c Actions.None to \c Actions.Integer
364 * when it is triggered.146 * when it is triggered.
365 *
366 * \section3 Attached properties
367 * ListItemActions provides a set of attached properties to the panels visualizing
368 * the actions. These properties can be used by implementations visualizing the
369 * actions.
370 */147 */
371148
372UCListItemActions::UCListItemActions(QObject *parent)149UCListItemActions::UCListItemActions(QObject *parent)
@@ -377,28 +154,6 @@
377{154{
378}155}
379156
380UCListItemActionsAttached *UCListItemActions::qmlAttachedProperties(QObject *owner)
381{
382 /*
383 * Detect the attachee, whether is it a child item of the panelItem. The panelItem
384 * itself cannot be detected, as the object can be attached during the call of
385 * component.beginCreate().
386 */
387 UCListItemActionsAttached *attached = new UCListItemActionsAttached(owner);
388 QQuickItem *item = qobject_cast<QQuickItem*>(owner);
389 while (item) {
390 // has item our attached property?
391 UCListItemActionsAttached *itemAttached = static_cast<UCListItemActionsAttached*>(
392 qmlAttachedPropertiesObject<UCListItemActions>(item, false));
393 if (itemAttached) {
394 attached->setList(itemAttached->container());
395 break;
396 }
397 item = item->parentItem();
398 }
399 return attached;
400}
401
402/*!157/*!
403 * \qmlproperty Component ListItemActions::delegate158 * \qmlproperty Component ListItemActions::delegate
404 * The property holds the custom delegate to visualize the actions listed in the159 * The property holds the custom delegate to visualize the actions listed in the
@@ -461,7 +216,7 @@
461 * }216 * }
462 * \endqml217 * \endqml
463 * \note Putting a Rectangle in the delegate can be used to override the color218 * \note Putting a Rectangle in the delegate can be used to override the color
464 * of the panel.219 * of the panel. Also all ListItem attached properties can be used in the delegates.
465 *220 *
466 * Defaults to null.221 * Defaults to null.
467 */222 */
468223
=== modified file 'modules/Ubuntu/Components/plugin/uclistitemactions.h'
--- modules/Ubuntu/Components/plugin/uclistitemactions.h 2014-12-01 12:20:02 +0000
+++ modules/Ubuntu/Components/plugin/uclistitemactions.h 2015-01-16 14:53:38 +0000
@@ -22,7 +22,6 @@
2222
23class QQmlComponent;23class QQmlComponent;
24class UCAction;24class UCAction;
25class UCListItemActionsAttached;
26class UCListItemActionsPrivate;25class UCListItemActionsPrivate;
27class UCListItemActions : public QObject26class UCListItemActions : public QObject
28{27{
@@ -31,18 +30,10 @@
31 Q_PROPERTY(QQmlListProperty<UCAction> actions READ actions CONSTANT)30 Q_PROPERTY(QQmlListProperty<UCAction> actions READ actions CONSTANT)
32 Q_PROPERTY(QQmlListProperty<QObject> data READ data)31 Q_PROPERTY(QQmlListProperty<QObject> data READ data)
33 Q_CLASSINFO("DefaultProperty", "data")32 Q_CLASSINFO("DefaultProperty", "data")
34 Q_ENUMS(Status)
35public:33public:
36 enum Status {
37 Disconnected,
38 Leading,
39 Trailing
40 };
41 explicit UCListItemActions(QObject *parent = 0);34 explicit UCListItemActions(QObject *parent = 0);
42 ~UCListItemActions();35 ~UCListItemActions();
4336
44 static UCListItemActionsAttached *qmlAttachedProperties(QObject *owner);
45
46 QQmlComponent *delegate() const;37 QQmlComponent *delegate() const;
47 void setDelegate(QQmlComponent *delegate);38 void setDelegate(QQmlComponent *delegate);
48 QQmlListProperty<UCAction> actions();39 QQmlListProperty<UCAction> actions();
@@ -50,64 +41,9 @@
5041
51Q_SIGNALS:42Q_SIGNALS:
52 void delegateChanged();43 void delegateChanged();
53 void statusChanged(Status status);
5444
55private:45private:
56 Q_DECLARE_PRIVATE(UCListItemActions)46 Q_DECLARE_PRIVATE(UCListItemActions)
57 Q_PRIVATE_SLOT(d_func(), void _q_updateDraggedOffset())47};
58};
59
60class UCListItemActionsAttached : public QObject
61{
62 Q_OBJECT
63 Q_PROPERTY(UCListItemActions *container READ container NOTIFY containerChanged)
64 Q_PROPERTY(QQmlListProperty<UCAction> visibleActions READ visibleActions NOTIFY visibleActionsChanged)
65 Q_PROPERTY(UCListItem *listItem READ listItem NOTIFY listItemChanged)
66 Q_PROPERTY(int listItemIndex READ listItemIndex NOTIFY listItemIndexChanged)
67 Q_PROPERTY(qreal offset READ offset NOTIFY offsetChanged)
68 Q_PROPERTY(UCListItemActions::Status status READ status NOTIFY statusChanged)
69 Q_PROPERTY(bool swiping READ swiping NOTIFY swipingChanged)
70public:
71 UCListItemActionsAttached(QObject *parent = 0);
72 ~UCListItemActionsAttached();
73 void setList(UCListItemActions *list);
74 void connectListItem(UCListItem *item, bool connect);
75
76 UCListItemActions *container() const
77 {
78 return m_container.data();
79 }
80 QQmlListProperty<UCAction> visibleActions();
81 UCListItem *listItem();
82 int listItemIndex();
83 bool swiping();
84 qreal offset();
85 UCListItemActions::Status status();
86
87
88public Q_SLOTS:
89 void snapToPosition(qreal position);
90
91Q_SIGNALS:
92 void containerChanged();
93 void visibleActionsChanged();
94 void listItemChanged();
95 void listItemIndexChanged();
96 void offsetChanged();
97 void statusChanged();
98 void swipingChanged();
99
100private:
101 QPointer<UCListItemActions> m_container;
102 QList<UCAction*> m_visibleActions;
103 bool m_swiping;
104 friend class UCListItemAction;
105
106private Q_SLOTS:
107 void updateVisibleActions();
108 void updateSwipeState();
109};
110
111QML_DECLARE_TYPEINFO(UCListItemActions, QML_HAS_ATTACHED_PROPERTIES)
11248
113#endif // UCLISTITEMACTIONS_H49#endif // UCLISTITEMACTIONS_H
11450
=== modified file 'modules/Ubuntu/Components/plugin/uclistitemactions_p.h'
--- modules/Ubuntu/Components/plugin/uclistitemactions_p.h 2014-12-01 13:42:47 +0000
+++ modules/Ubuntu/Components/plugin/uclistitemactions_p.h 2015-01-16 14:53:38 +0000
@@ -32,30 +32,14 @@
32 return actions ? actions->d_func() : 0;32 return actions ? actions->d_func() : 0;
33 }33 }
3434
35 UCListItemActions::Status status;
36 qreal offsetDragged;
37 qreal optionSlotWidth;
38
39 QQmlComponent *delegate;35 QQmlComponent *delegate;
40 QQmlComponent *panelDelegate;
41 QQuickItem *panelItem;
42 QList<UCAction*> actions;36 QList<UCAction*> actions;
43 QList<QObject*> data;37 QList<QObject*> data;
44 QPointer<UCListItem> queuedItem;
45
46 void _q_updateDraggedOffset();
47 UCListItemActionsAttached *attachedObject();
48
49 static bool connectToListItem(UCListItemActions *options, UCListItem *listItem, bool leading);
50 static void disconnectFromListItem(UCListItemActions *options);
51 static bool isConnectedTo(UCListItemActions *options, UCListItem *listItem);
5238
53 static int actions_count(QQmlListProperty<UCAction> *p);39 static int actions_count(QQmlListProperty<UCAction> *p);
54 static void actions_append(QQmlListProperty<UCAction> *p, UCAction *v);40 static void actions_append(QQmlListProperty<UCAction> *p, UCAction *v);
55 static UCAction *actions_at(QQmlListProperty<UCAction>*, int);41 static UCAction *actions_at(QQmlListProperty<UCAction>*, int);
56 static void actions_clear(QQmlListProperty<UCAction>*);42 static void actions_clear(QQmlListProperty<UCAction>*);
57
58 QQuickItem *createPanelItem(QQmlComponent *delegate);
59};43};
6044
61#endif // UCLISTITEMACTIONS_P_H45#endif // UCLISTITEMACTIONS_P_H
6246
=== renamed file 'modules/Ubuntu/Components/plugin/uclistitemactionsattached.cpp' => 'modules/Ubuntu/Components/plugin/uclistitemattached.cpp'
--- modules/Ubuntu/Components/plugin/uclistitemactionsattached.cpp 2014-12-18 10:08:56 +0000
+++ modules/Ubuntu/Components/plugin/uclistitemattached.cpp 2015-01-16 14:53:38 +0000
@@ -21,218 +21,154 @@
21#include "ucunits.h"21#include "ucunits.h"
22#include "ucaction.h"22#include "ucaction.h"
2323
24UCListItemActionsAttached::UCListItemActionsAttached(QObject *parent)24UCListItemAttached::UCListItemAttached(QObject *parent)
25 : QObject(parent)25 : QObject(*(new UCListItemAttachedPrivate()), parent)
26 , m_swiping(false)26{
27{27}
28}28
2929UCListItemAttached::~UCListItemAttached()
30UCListItemActionsAttached::~UCListItemActionsAttached()30{
31{31}
32}32
3333void UCListItemAttached::connectToAttached(UCListItemAttached *parentAttached)
34/*!34{
35 * \qmlattachedproperty ListItemActions ListItemActions::container35 bool visualizeActions = UCListItemAttachedPrivate::get(parentAttached)->panel;
36 * \readonly36 bool isLeading = visualizeActions ? UCListItemAttachedPrivate::get(parentAttached)->panel->isLeading() : false;
37 * The property holds the instance of the \l ListItemActions the ListItem's actions37 setList(parentAttached->item(), isLeading, visualizeActions);
38 * panel is visualizing.38}
39 */39
40void UCListItemActionsAttached::setList(UCListItemActions *list)40void UCListItemAttached::setList(UCListItem *list, bool leading, bool visualizeActions)
41{41{
42 if (list == m_container) {42 Q_D(UCListItemAttached);
43 if (d->listItem == list) {
43 return;44 return;
44 }45 }
45 m_container = list;46 d->listItem = list;
46 if (!m_container.isNull()) {47 Q_EMIT itemChanged();
48
49 if (visualizeActions) {
50 d->panel = leading ? UCListItemPrivate::get(d->listItem)->leadingPanel : UCListItemPrivate::get(d->listItem)->trailingPanel;
51 } else {
52 d->panel = 0;
53 }
54 if (d->panel) {
47 // connect statusChanged() to update status, listItem, listItemIndex and overshoot values55 // connect statusChanged() to update status, listItem, listItemIndex and overshoot values
48 QObject::connect(m_container.data(), &UCListItemActions::statusChanged,56 QObject::connect(d->panel, &UCActionPanel::statusChanged,
49 this, &UCListItemActionsAttached::statusChanged);57 this, &UCListItemAttached::panelStatusChanged);
50 QObject::connect(m_container.data(), &UCListItemActions::statusChanged,
51 this, &UCListItemActionsAttached::listItemChanged);
52 QObject::connect(m_container.data(), &UCListItemActions::statusChanged,
53 this, &UCListItemActionsAttached::listItemIndexChanged);
54
55 UCListItemActionsPrivate *actions = UCListItemActionsPrivate::get(m_container.data());
56 // connect panel's xChanged to update the dragged offset
57 QObject::connect(actions->panelItem, &QQuickItem::xChanged,
58 this, &UCListItemActionsAttached::offsetChanged);
5958
60 // connect actions to get updates about visible changes59 // connect actions to get updates about visible changes
61 Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(m_container)->actions) {60 Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(d->panel->actions())->actions) {
62 QObject::connect(action, &UCAction::visibleChanged,61 QObject::connect(action, &UCAction::visibleChanged,
63 this, &UCListItemActionsAttached::updateVisibleActions);62 this, &UCListItemAttached::updateVisibleActions);
64 }63 }
65 updateVisibleActions();64 updateVisibleActions();
66 }65 Q_EMIT actionsChanged();
67 Q_EMIT containerChanged();66 Q_EMIT visibleActionsChanged();
68 Q_EMIT visibleActionsChanged();
69}
70
71void UCListItemActionsAttached::connectListItem(UCListItem *item, bool connect)
72{
73 if (!item) {
74 return;
75 }
76 if (connect) {
77 QObject::connect(item, &UCListItem::highlightedChanged,
78 this, &UCListItemActionsAttached::updateSwipeState);
79 QObject::connect(item, &UCListItem::contentMovingChanged,
80 this, &UCListItemActionsAttached::updateSwipeState);
81 } else {
82 QObject::disconnect(item, &UCListItem::highlightedChanged,
83 this, &UCListItemActionsAttached::updateSwipeState);
84 QObject::disconnect(item, &UCListItem::contentMovingChanged,
85 this, &UCListItemActionsAttached::updateSwipeState);
86 }67 }
87}68}
8869
89// private slot to update visible actions70// private slot to update visible actions
90void UCListItemActionsAttached::updateVisibleActions()71void UCListItemAttached::updateVisibleActions()
91{72{
92 m_visibleActions.clear();73 Q_D(UCListItemAttached);
93 if (!m_container.isNull()) {74 if (d->panel) {
94 Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(m_container)->actions) {75 d->visibleActions.clear();
76 Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(d->panel->actions())->actions) {
95 if (action->m_visible) {77 if (action->m_visible) {
96 m_visibleActions << action;78 d->visibleActions << action;
97 }79 }
98 }80 }
81 Q_EMIT visibleActionsChanged();
99 }82 }
100 Q_EMIT visibleActionsChanged();
101}83}
10284
103// private slot updating swipe state85/*!
104void UCListItemActionsAttached::updateSwipeState()86 * \qmlattachedproperty ListItemActions ListItem::actions
87 * \readonly
88 * The property holds the instance of the \l ListItemActions the ListItem's actions
89 * panel is visualizing. The property holds a valid value only when attached to
90 * the action visualizing panel defined in \l ListItemStyle::actionsDelegate style
91 * property.
92 */
93UCListItemActions *UCListItemAttached::actions() const
105{94{
106 if (m_container.isNull()) {95 Q_D(const UCListItemAttached);
107 return;96 return d->panel ? d->panel->actions() : 0;
108 }
109 QQuickItem *panelItem = UCListItemActionsPrivate::get(m_container)->panelItem;
110 if (!panelItem || !panelItem->parentItem()) {
111 return;
112 }
113 UCListItem *item = static_cast<UCListItem*>(panelItem->parentItem());
114 UCListItemPrivate *listItem = UCListItemPrivate::get(item);
115 bool swiped = listItem->highlighted && listItem->contentMoved;
116 if (swiped != m_swiping) {
117 m_swiping = swiped;
118 Q_EMIT swipingChanged();
119 }
120}97}
12198
122/*!99/*!
123 * \qmlattachedproperty list<Action> ListItemActions::visibleActions100 * \qmlattachedproperty list<Action> ListItem::visibleActions
124 * Holds the list of visible actions. This is a convenience property to help action101 * Holds the list of visible actions. This is a convenience property to help action
125 * visualization panel implementations to consider only visible actions.102 * visualization panel implementations to consider only visible actions. Similar to
103 * \l actions attached property, it is only valid when attached to \l ListItemStyle::actionsDelegate
104 * component.
126 */105 */
127QQmlListProperty<UCAction> UCListItemActionsAttached::visibleActions()106QQmlListProperty<UCAction> UCListItemAttached::visibleActions()
128{107{
129 return QQmlListProperty<UCAction>(this, m_visibleActions);108 Q_D(UCListItemAttached);
109 return QQmlListProperty<UCAction>(this, d->visibleActions);
130}110}
131111
132/*!112/*!
133 * \qmlattachedproperty ListItem ListItemActions::listItem113 * \qmlattachedproperty ListItem ListItem::item
134 * \readonly114 * \readonly
135 * The property reports the connected \l ListItem to the list of actions.115 * The property reports the connected \l ListItem to the panel. Valid in every attachee.
136 */116 */
137UCListItem *UCListItemActionsAttached::listItem()117UCListItem *UCListItemAttached::item()
138{118{
139 if (m_container.isNull()) {119 Q_D(UCListItemAttached);
140 return NULL;120 return d->listItem;
141 }
142 QQuickItem *panelItem = UCListItemActionsPrivate::get(m_container)->panelItem;
143 if (!panelItem) {
144 return NULL;
145 }
146 QQuickItem *listItem = panelItem->parentItem();
147 return static_cast<UCListItem*>(listItem);
148}121}
149122
150/*!123/*!
151 * \qmlattachedproperty int ListItemActions::listItemIndex124 * \qmlattachedproperty int ListItem::index
152 * \readonly125 * \readonly
153 * Holds the index of the \l ListItem within a view, if the \l ListItem is used126 * Holds the index of the \l ListItem within a view, if the \l ListItem is used
154 * in a model driven view. Otherwise it is set to -1.127 * in a model driven view, or the child index otherwise. Valid in every attachee.
155 */128 */
156int UCListItemActionsAttached::listItemIndex() {129int UCListItemAttached::index() {
157 if (m_container.isNull()) {130 Q_D(UCListItemAttached);
158 return -1;131 return d->listItem ? UCListItemPrivate::get(d->listItem)->index() : -1;
159 }132}
160 QQuickItem *panelItem = UCListItemActionsPrivate::get(m_container)->panelItem;133
161 if (!panelItem) {134/*!
162 return -1;135 * \qmlattachedproperty enum ListItem::panelStatus
163 }
164 QQuickItem *listItem = panelItem->parentItem();
165 return listItem ? UCListItemPrivate::get(static_cast<UCListItem*>(listItem))->index() : -1;
166}
167
168/*!
169 * \qmlattachedproperty bool ListItemActions::swiping
170 * \readonly
171 * The property notifies whether the panel is swiped or not. The property does
172 * not notify the rebounding.
173 */
174bool UCListItemActionsAttached::swiping()
175{
176 return m_swiping;
177}
178
179/*!
180 * \qmlattachedproperty real ListItemActions::offset
181 * The property returns the offset the panel item holding the visualized actions
182 * is visible. This can be used to do different animations on the panel and on
183 * the action visualizations.
184 */
185qreal UCListItemActionsAttached::offset()
186{
187 if (m_container.isNull()) {
188 return 0.0;
189 }
190 return UCListItemActionsPrivate::get(m_container)->offsetDragged;
191}
192
193/*!
194 * \qmlattachedproperty enum ListItemActions::status
195 * \readonly136 * \readonly
196 * The property holds the status of the ListItemActions, whether is connected137 * The property holds the status of the ListItemActions, whether is connected
197 * as leading or as trailing action list to a \l ListItem. Possible valueas are:138 * as leading or as trailing action list to a \l ListItem. Possible valueas are:
198 * \list A139 * \list A
199 * \li \b Disconnected - default, the actions list is not connected to any \l ListItem140 * \li \b None - default, the actions list is not connected to any \l ListItem
200 * \li \b Leading - the actions list is connected as leading list141 * \li \b Leading - the actions list is connected as leading list
201 * \li \b Trailing - the actions list is connected as trailing list142 * \li \b Trailing - the actions list is connected as trailing list
202 * \endlist143 * \endlist
144 * The property is valid only when attached to \l ListItemStyle::actionsDelegate component.
203 */145 */
204UCListItemActions::Status UCListItemActionsAttached::status()146UCListItem::PanelStatus UCListItemAttached::panelStatus()
205{147{
206 if (m_container.isNull()) {148 Q_D(UCListItemAttached);
207 return UCListItemActions::Disconnected;149 if (!d->panel) {
150 return UCListItem::None;
208 }151 }
209 return UCListItemActionsPrivate::get(m_container)->status;152 return d->panel->panelStatus();
210}153}
211154
212/*!155/*!
213 * \qmlattachedmethod void ListItemActions::snapToPosition(real position)156 * \qmlattachedmethod void ListItem::snapToPosition(real position)
214 * The function can be used to perform custom snapping, or to execute rebounding157 * The function can be used to perform custom snapping, or to execute rebounding
215 * and also disconnecting from the connected \l ListItem. This can be achieved by158 * and also disconnecting from the connected \l ListItem. This can be achieved by
216 * calling the function with 0.0 value.159 * calling the function with 0.0 value. The slot has effect only when used from
160 * \l ListItemStyle::actionsDelegate component.
217 */161 */
218void UCListItemActionsAttached::snapToPosition(qreal position)162void UCListItemAttached::snapToPosition(qreal position)
219{163{
164 UCListItem::PanelStatus itemStatus = panelStatus();
165 Q_D(UCListItemAttached);
220 //if it is disconnected, leave (this also includes the case when m_container is null)166 //if it is disconnected, leave (this also includes the case when m_container is null)
221 if (status() == UCListItemActions::Disconnected) {167 if (!d->listItem || !d->panel || itemStatus == UCListItem::None) {
222 return;168 return;
223 }169 }
224 QQuickItem *panelItem = UCListItemActionsPrivate::get(m_container)->panelItem;170 UCListItemPrivate *listItem = UCListItemPrivate::get(d->listItem);
225 if (!panelItem) {171 position *= (itemStatus == UCListItem::Leading) ? 1 : -1;
226 // we don't have the panel created yet
227 return;
228 }
229 UCListItem *item = static_cast<UCListItem*>(panelItem->parentItem());
230 if (!item) {
231 // no ListItem attached
232 return;
233 }
234 UCListItemPrivate *listItem = UCListItemPrivate::get(item);
235 position *= (status() == UCListItemActions::Leading) ? 1 : -1;
236 if (position == 0.0) {172 if (position == 0.0) {
237 listItem->_q_rebound();173 listItem->_q_rebound();
238 } else {174 } else {
@@ -243,5 +179,3 @@
243 }179 }
244 }180 }
245}181}
246
247
248182
=== modified file 'modules/Ubuntu/Components/plugin/uclistitemstyle.h'
--- modules/Ubuntu/Components/plugin/uclistitemstyle.h 2014-12-01 11:13:10 +0000
+++ modules/Ubuntu/Components/plugin/uclistitemstyle.h 2015-01-16 14:53:38 +0000
@@ -46,7 +46,7 @@
46 qreal m_swipeOvershoot;46 qreal m_swipeOvershoot;
4747
48 friend class UCListItemPrivate;48 friend class UCListItemPrivate;
49 friend class UCListItemActionsPrivate;49 friend class UCActionPanel;
50 friend class UCListItemSnapAnimator;50 friend class UCListItemSnapAnimator;
51};51};
5252
5353
=== renamed file 'modules/Ubuntu/Components/plugin/uclistitemattached.cpp' => 'modules/Ubuntu/Components/plugin/ucviewitemsattached.cpp'
--- modules/Ubuntu/Components/plugin/uclistitemattached.cpp 2014-11-18 15:27:08 +0000
+++ modules/Ubuntu/Components/plugin/ucviewitemsattached.cpp 2015-01-16 14:53:38 +0000
@@ -28,34 +28,34 @@
28 * in this way the controlling of the interactive flag of the Flickable and all28 * in this way the controlling of the interactive flag of the Flickable and all
29 * its ascendant Flickables.29 * its ascendant Flickables.
30 */30 */
31UCListItemAttachedPrivate::UCListItemAttachedPrivate(UCListItemAttached *qq)31UCViewItemsAttachedPrivate::UCViewItemsAttachedPrivate(UCViewItemsAttached *qq)
32 : q_ptr(qq)32 : q_ptr(qq)
33 , globalDisabled(false)33 , globalDisabled(false)
34{34{
35}35}
3636
37UCListItemAttachedPrivate::~UCListItemAttachedPrivate()37UCViewItemsAttachedPrivate::~UCViewItemsAttachedPrivate()
38{38{
39 clearChangesList();39 clearChangesList();
40 clearFlickablesList();40 clearFlickablesList();
41}41}
4242
43// disconnect all flickables43// disconnect all flickables
44void UCListItemAttachedPrivate::clearFlickablesList()44void UCViewItemsAttachedPrivate::clearFlickablesList()
45{45{
46 Q_Q(UCListItemAttached);46 Q_Q(UCViewItemsAttached);
47 Q_FOREACH(const QPointer<QQuickFlickable> &flickable, flickables) {47 Q_FOREACH(const QPointer<QQuickFlickable> &flickable, flickables) {
48 if (flickable.data())48 if (flickable.data())
49 QObject::disconnect(flickable.data(), &QQuickFlickable::movementStarted,49 QObject::disconnect(flickable.data(), &QQuickFlickable::movementStarted,
50 q, &UCListItemAttached::unbindItem);50 q, &UCViewItemsAttached::unbindItem);
51 }51 }
52 flickables.clear();52 flickables.clear();
53}53}
5454
55// connect all flickables55// connect all flickables
56void UCListItemAttachedPrivate::buildFlickablesList()56void UCViewItemsAttachedPrivate::buildFlickablesList()
57{57{
58 Q_Q(UCListItemAttached);58 Q_Q(UCViewItemsAttached);
59 QQuickItem *item = qobject_cast<QQuickItem*>(q->parent());59 QQuickItem *item = qobject_cast<QQuickItem*>(q->parent());
60 if (!item) {60 if (!item) {
61 return;61 return;
@@ -65,17 +65,17 @@
65 QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(item);65 QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(item);
66 if (flickable) {66 if (flickable) {
67 QObject::connect(flickable, &QQuickFlickable::movementStarted,67 QObject::connect(flickable, &QQuickFlickable::movementStarted,
68 q, &UCListItemAttached::unbindItem);68 q, &UCViewItemsAttached::unbindItem);
69 flickables << flickable;69 flickables << flickable;
70 }70 }
71 item = item->parentItem();71 item = item->parentItem();
72 }72 }
73}73}
7474
75void UCListItemAttachedPrivate::clearChangesList()75void UCViewItemsAttachedPrivate::clearChangesList()
76{76{
77 // clear property change objects77 // clear property change objects
78 Q_Q(UCListItemAttached);78 Q_Q(UCViewItemsAttached);
79 Q_FOREACH(PropertyChange *change, changes) {79 Q_FOREACH(PropertyChange *change, changes) {
80 // deleting PropertyChange will restore the saved property80 // deleting PropertyChange will restore the saved property
81 // to its original binding/value81 // to its original binding/value
@@ -84,10 +84,10 @@
84 changes.clear();84 changes.clear();
85}85}
8686
87void UCListItemAttachedPrivate::buildChangesList(const QVariant &newValue)87void UCViewItemsAttachedPrivate::buildChangesList(const QVariant &newValue)
88{88{
89 // collect all ascendant flickables89 // collect all ascendant flickables
90 Q_Q(UCListItemAttached);90 Q_Q(UCViewItemsAttached);
91 QQuickItem *item = qobject_cast<QQuickItem*>(q->parent());91 QQuickItem *item = qobject_cast<QQuickItem*>(q->parent());
92 if (!item) {92 if (!item) {
93 return;93 return;
@@ -104,22 +104,27 @@
104 }104 }
105}105}
106106
107UCListItemAttached::UCListItemAttached(QObject *owner)107UCViewItemsAttached::UCViewItemsAttached(QObject *owner)
108 : QObject(owner)108 : QObject(owner)
109 , d_ptr(new UCListItemAttachedPrivate(this))109 , d_ptr(new UCViewItemsAttachedPrivate(this))
110{110{
111}111}
112112
113UCListItemAttached::~UCListItemAttached()113UCViewItemsAttached::~UCViewItemsAttached()
114{114{
115}
116
117UCViewItemsAttached *UCViewItemsAttached::qmlAttachedProperties(QObject *owner)
118{
119 return new UCViewItemsAttached(owner);
115}120}
116121
117// register item to be rebound122// register item to be rebound
118bool UCListItemAttached::listenToRebind(UCListItem *item, bool listen)123bool UCViewItemsAttached::listenToRebind(UCListItem *item, bool listen)
119{124{
120 // we cannot bind the item until we have an other one bound125 // we cannot bind the item until we have an other one bound
121 bool result = false;126 bool result = false;
122 Q_D(UCListItemAttached);127 Q_D(UCViewItemsAttached);
123 if (listen) {128 if (listen) {
124 if (d->boundItem.isNull() || (d->boundItem == item)) {129 if (d->boundItem.isNull() || (d->boundItem == item)) {
125 d->boundItem = item;130 d->boundItem = item;
@@ -135,9 +140,9 @@
135}140}
136141
137// reports true if any of the ascendant flickables is moving142// reports true if any of the ascendant flickables is moving
138bool UCListItemAttached::isMoving()143bool UCViewItemsAttached::isMoving()
139{144{
140 Q_D(UCListItemAttached);145 Q_D(UCViewItemsAttached);
141 Q_FOREACH(const QPointer<QQuickFlickable> &flickable, d->flickables) {146 Q_FOREACH(const QPointer<QQuickFlickable> &flickable, d->flickables) {
142 if (flickable && flickable->isMoving()) {147 if (flickable && flickable->isMoving()) {
143 return true;148 return true;
@@ -147,9 +152,9 @@
147}152}
148153
149// returns true if the given ListItem is bound to listen on moving changes154// returns true if the given ListItem is bound to listen on moving changes
150bool UCListItemAttached::isBoundTo(UCListItem *item)155bool UCViewItemsAttached::isBoundTo(UCListItem *item)
151{156{
152 Q_D(UCListItemAttached);157 Q_D(UCViewItemsAttached);
153 return d->boundItem == item;158 return d->boundItem == item;
154}159}
155160
@@ -161,9 +166,9 @@
161 * When disabled, always the last item disabling will be kept as active disabler,166 * When disabled, always the last item disabling will be kept as active disabler,
162 * and only the active disabler can enable (restore) the interactive flag state.167 * and only the active disabler can enable (restore) the interactive flag state.
163 */168 */
164void UCListItemAttached::disableInteractive(UCListItem *item, bool disable)169void UCViewItemsAttached::disableInteractive(UCListItem *item, bool disable)
165{170{
166 Q_D(UCListItemAttached);171 Q_D(UCViewItemsAttached);
167 if (disable) {172 if (disable) {
168 // disabling or re-disabling173 // disabling or re-disabling
169 d->disablerItem = item;174 d->disablerItem = item;
@@ -188,9 +193,9 @@
188 }193 }
189}194}
190195
191void UCListItemAttached::unbindItem()196void UCViewItemsAttached::unbindItem()
192{197{
193 Q_D(UCListItemAttached);198 Q_D(UCViewItemsAttached);
194 if (d->boundItem) {199 if (d->boundItem) {
195 // depending on content item's X coordinate, we either do animated or prompt rebind200 // depending on content item's X coordinate, we either do animated or prompt rebind
196 if (d->boundItem->contentItem()->x() != 0.0) {201 if (d->boundItem->contentItem()->x() != 0.0) {
197202
=== modified file 'tests/resources/listitems/ListItemTest.qml'
--- tests/resources/listitems/ListItemTest.qml 2014-12-04 13:23:18 +0000
+++ tests/resources/listitems/ListItemTest.qml 2015-01-16 14:53:38 +0000
@@ -16,6 +16,7 @@
1616
17import QtQuick 2.217import QtQuick 2.2
18import Ubuntu.Components 1.218import Ubuntu.Components 1.2
19import Ubuntu.Components.Styles 1.2
1920
20MainView {21MainView {
21 id: main22 id: main
@@ -109,7 +110,7 @@
109 width: units.gu(3)110 width: units.gu(3)
110 height: width111 height: width
111 name: action.iconName112 name: action.iconName
112 color: "blue"113 color: pressed ? "blue" : "pink"
113 anchors.horizontalCenter: parent.horizontalCenter114 anchors.horizontalCenter: parent.horizontalCenter
114 }115 }
115 Label {116 Label {
@@ -131,13 +132,16 @@
131132
132 ListItem {133 ListItem {
133 Label {134 Label {
135 id: label2
134 anchors.fill: parent136 anchors.fill: parent
135 text: "Another standalone ListItem"137 text: "Another standalone ListItem\nStarted with custom style, reset to theme style on first click"
136 }138 }
137 leadingActions: testItem.leadingActions139 leadingActions: testItem.leadingActions
138 trailingActions: ListItemActions {140 trailingActions: ListItemActions {
139 actions: leading.actions141 actions: leading.actions
140 }142 }
143 style: ListItemStyle {}
144 onClicked: { style = undefined; label2.text = "Another standalone ListItem" }
141 }145 }
142146
143 ListView {147 ListView {
@@ -152,6 +156,7 @@
152 id: listItem156 id: listItem
153 onClicked: print(" clicked")157 onClicked: print(" clicked")
154 leadingActions: leading158 leadingActions: leading
159 trailingActions: leadingActions
155 Label {160 Label {
156 text: modelData + " item"161 text: modelData + " item"
157 }162 }
@@ -179,7 +184,7 @@
179184
180 Column {185 Column {
181 id: column186 id: column
182 width: view.width187 width: flicker.width
183 property alias count: repeater.count188 property alias count: repeater.count
184 Repeater {189 Repeater {
185 id: repeater190 id: repeater
186191
=== modified file 'tests/unit_x11/tst_components/tst_listitem.qml'
--- tests/unit_x11/tst_components/tst_listitem.qml 2014-12-19 06:32:11 +0000
+++ tests/unit_x11/tst_components/tst_listitem.qml 2015-01-16 14:53:38 +0000
@@ -18,11 +18,12 @@
18import QtTest 1.018import QtTest 1.0
19import Ubuntu.Test 1.019import Ubuntu.Test 1.0
20import Ubuntu.Components 1.220import Ubuntu.Components 1.2
21import Ubuntu.Components.Styles 1.2
2122
22Item {23Item {
23 id: main24 id: main
24 width: units.gu(40)25 width: units.gu(50)
25 height: units.gu(71)26 height: units.gu(100)
2627
27 Action {28 Action {
28 id: stockAction29 id: stockAction
@@ -192,8 +193,8 @@
192 compare(defaults.highlighted, false, "Not highlighted by default");193 compare(defaults.highlighted, false, "Not highlighted by default");
193 compare(defaults.swipeOvershoot, 0.0, "No overshoot till the style is loaded!");194 compare(defaults.swipeOvershoot, 0.0, "No overshoot till the style is loaded!");
194 compare(defaults.divider.visible, true, "divider is visible by default");195 compare(defaults.divider.visible, true, "divider is visible by default");
195 compare(defaults.divider.leftMargin, units.dp(2), "divider's left margin is 2GU");196 compare(defaults.divider.leftMargin, 0, "divider's left margin is 0");
196 compare(defaults.divider.rightMargin, units.dp(2), "divider's right margin is 2GU");197 compare(defaults.divider.rightMargin, 0, "divider's right margin is 0");
197 compare(defaults.divider.colorFrom, "#000000", "colorFrom differs.");198 compare(defaults.divider.colorFrom, "#000000", "colorFrom differs.");
198 fuzzyCompare(defaults.divider.colorFrom.a, 0.14, 0.01, "colorFrom alpha differs");199 fuzzyCompare(defaults.divider.colorFrom.a, 0.14, 0.01, "colorFrom alpha differs");
199 compare(defaults.divider.colorTo, "#ffffff", "colorTo differs.");200 compare(defaults.divider.colorTo, "#ffffff", "colorTo differs.");
@@ -206,6 +207,14 @@
206 compare(actionsDefault.actions.length, 0, "ListItemActions has no actions set.");207 compare(actionsDefault.actions.length, 0, "ListItemActions has no actions set.");
207 }208 }
208209
210 Component { id: customStyle; ListItemStyle {} }
211
212 function test_style_reset() {
213 testItem.style = customStyle;
214 testItem.style = undefined;
215 verify(testItem.style != 0 && testItem.style.objectName == "ListItemThemeStyle", "Style set back to theme");
216 }
217
209 function test_children_in_content_item() {218 function test_children_in_content_item() {
210 compare(bodyItem.parent, testItem.contentItem, "Content is not in the right holder!");219 compare(bodyItem.parent, testItem.contentItem, "Content is not in the right holder!");
211 }220 }

Subscribers

People subscribed via source and target branches