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