Merge lp:~nick-dedekind/unity8/indicator-menuitems-lp1253810 into lp:unity8

Proposed by Nick Dedekind
Status: Merged
Approved by: Michał Sawicz
Approved revision: 593
Merged at revision: 590
Proposed branch: lp:~nick-dedekind/unity8/indicator-menuitems-lp1253810
Merge into: lp:unity8
Diff against target: 581 lines (+223/-142)
3 files modified
plugins/Unity/Indicators/Messaging/qml/MessageMenuItemFactory.qml (+79/-47)
plugins/Unity/Indicators/qml/IndicatorPage.qml (+6/-4)
plugins/Unity/Indicators/qml/MenuItemFactory.qml (+138/-91)
To merge this branch: bzr merge lp:~nick-dedekind/unity8/indicator-menuitems-lp1253810
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michał Sawicz Approve
Review via email: mp+198597@code.launchpad.net

Commit message

Fixed up connections for changes to model data

Description of the change

Renamed model/modelIndex/menu to make a bit more sense.
Fixed up connections for changes to model data.

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

FAILED: Continuous integration, rev:584
http://jenkins.qa.ubuntu.com/job/unity8-ci/1871/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/1615
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/1559
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/637
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/394
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/395
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/395/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/394
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/1430
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1615
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1615/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1559
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1559/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/4077
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/2244

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1871/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

I'd like to add some tests here. To start with - targeted at the issue from the bug, something of the sort:

QtObject {
  id: menuData
...
}

ListModel {
  id: menuModel
...
}

QtObject {
  id: extAttrib
...
}

Column {
  id: column
  property QtObject menuData: null
  property var menuModel: undefined
  property var extAttrib: undefined

...

  ICNetwork.AccessPoint {
    id: accessPoint
    menuData: column.menuData
    menuModel: column.menuModel
    extAttrib: column.extAttrib
  }

  ICMessaging.GroupedMessage {
    id: groupedMessage
    menuData: column.menuData
    menuModel: column.menuModel
    extAttrib: column.extAttrib
  }
}

function initTestCase() {
  column.menuData = menuData;
  column.menuModel = menuModel;
  column.extAttrib = extAttrib;
}

function cleanup() {
  column.menuData = null;
  column.menuModel = undefined;
  column.extAttrib = undefined;
}

function test_accessPoint_data() {
  return [
    { tag: "CheckBox", objectName: "checkBox", property: "checked", value: true },
    ...
  ];
}

function test_accessPoint(data) {
  var obj = findChild(accessPoint, data.objectName);

  tryCompare(obj, data.property, data.value);
}

...

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

Eh. Indicator tests are all in the ubuntu-settings-components ported unity8 branch now.
I'll try sort something out decoupling the tests from usc changes, but it'll be in a separate branch from this, as it's quite a significant amount of code.

Revision history for this message
Michał Sawicz (saviq) wrote :
Download full text (4.6 KiB)

 15 + property var extAttrib: menuData && menuData.ext ? menuData.ext : undefined

Can we think of a better (non-abbreviated) name of extAttrib? "extendedData"? "extended"?

=====

 28 + menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64',
 29 + 'x-canonical-text': 'string',
 30 + 'x-canonical-message-actions': 'variant',
 31 + 'icon': 'icon',
 32 + 'x-canonical-app-icon': 'icon'});

Please fix indent.

=====

 16 + property var actionsDescription: extAttrib && extAttrib.hasOwnProperty("xCanonicalMessageActions") ? extAttrib.xCanonicalMessageActions : undefined

Think abstracting this into a function get(object, name, default) would be desirable? There seems to be a *lot* of && : ? everywhere...

158 + title: menuData && menuData.label ? menuData.label : ""
159 + time: extAttrib && extAttrib.hasOwnProperty("xCanonicalTime") ? extAttrib.xCanonicalTime : ""
160 + message: extAttrib && extAttrib.hasOwnProperty("xCanonicalText") ? extAttrib.xCanonicalText : ""
161 + actionButtonText: activateActionDescription !== undefined && activateActionDescription.hasOwnProperty("label") ? activateActionDescription.label : "Call back"
162 + replyButtonText: replyActionDescription !== undefined && replyActionDescription.hasOwnProperty("label") ? replyActionDescription.label : "Send"
163 + replyMessages: replyActionDescription !== undefined && replyActionDescription.hasOwnProperty("parameter-hint") ? replyActionDescription["parameter-hint"] : ""

167 + avatar: extAttrib && extAttrib.hasOwnProperty("icon") ? extAttrib.icon : "qrc:/indicators/artwork/messaging/default_contact.png"
168 + appIcon: extAttrib && extAttrib.hasOwnProperty("xCanonicalAppIcon") ? extAttrib.xCanonicalAppIcon : "qrc:/indicators/artwork/messaging/default_app.svg"

Or... maybe even something of the sort:

Item {
  id: item

  property QtObject extMap: {
    time: ["xCanonicalTime", ""],
    message: ["xCanonicalText", ""],
    avatar: ["icon", "qrc:/indicators/artwork/messaging/default_contact.png"]
  }

  onExtAttribChanged: update(object, extAttrib, extMap)
}

Where there's a lot of those? You could have multiple maps for different objects, if wanted - obviously that assumes that extAttrib only changes atomically - which is not the case for menuData, for example - so it makes sense to keep menuData explicit, while moving extAttrib and maybe some others.

Or well, menuData could be handled as well, by means of Qt.binding(), I think.

=====

BTW,

255 + text: menuData && menuData.label ? menuData.label : ""

Can be simplified to:

text: menuData && menuData.label || ""

Only I'm not sure it's better for readability :)

=====

250 + property QtObject menuData: null
251 + property var menuModel: menuFactory.menuModel
252 + property var menuIndex: undefined

Really don't want to abstract those into an int...

Read more...

review: Needs Fixing
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :
Download full text (5.3 KiB)

> 15 + property var extAttrib: menuData && menuData.ext ? menuData.ext :
> undefined
>
> Can we think of a better (non-abbreviated) name of extAttrib? "extendedData"?
> "extended"?

Done

>
> =====
>
> 28 + menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time':
> 'int64',
> 29 + 'x-canonical-text':
> 'string',
> 30 + 'x-canonical-message-
> actions': 'variant',
> 31 + 'icon': 'icon',
> 32 + 'x-canonical-app-icon':
> 'icon'});
>
> Please fix indent.

Done

>
> =====
>
> 16 + property var actionsDescription: extAttrib &&
> extAttrib.hasOwnProperty("xCanonicalMessageActions") ?
> extAttrib.xCanonicalMessageActions : undefined
>
> Think abstracting this into a function get(object, name, default) would be
> desirable? There seems to be a *lot* of && : ? everywhere...
>

Done.

>
> 158 + title: menuData && menuData.label ? menuData.label : ""
> 159 + time: extAttrib &&
> extAttrib.hasOwnProperty("xCanonicalTime") ? extAttrib.xCanonicalTime : ""
> 160 + message: extAttrib &&
> extAttrib.hasOwnProperty("xCanonicalText") ? extAttrib.xCanonicalText : ""
> 161 + actionButtonText: activateActionDescription !== undefined
> && activateActionDescription.hasOwnProperty("label") ?
> activateActionDescription.label : "Call back"
> 162 + replyButtonText: replyActionDescription !== undefined &&
> replyActionDescription.hasOwnProperty("label") ? replyActionDescription.label
> : "Send"
> 163 + replyMessages: replyActionDescription !== undefined &&
> replyActionDescription.hasOwnProperty("parameter-hint") ?
> replyActionDescription["parameter-hint"] : ""
>
> 167 + avatar: extAttrib && extAttrib.hasOwnProperty("icon") ?
> extAttrib.icon : "qrc:/indicators/artwork/messaging/default_contact.png"
> 168 + appIcon: extAttrib &&
> extAttrib.hasOwnProperty("xCanonicalAppIcon") ? extAttrib.xCanonicalAppIcon :
> "qrc:/indicators/artwork/messaging/default_app.svg"
>
>
> Or... maybe even something of the sort:
>
> Item {
> id: item
>
> property QtObject extMap: {
> time: ["xCanonicalTime", ""],
> message: ["xCanonicalText", ""],
> avatar: ["icon", "qrc:/indicators/artwork/messaging/default_contact.png"]
> }
>
> onExtAttribChanged: update(object, extAttrib, extMap)
> }
>
> Where there's a lot of those? You could have multiple maps for different
> objects, if wanted - obviously that assumes that extAttrib only changes
> atomically - which is not the case for menuData, for example - so it makes
> sense to keep menuData explicit, while moving extAttrib and maybe some others.
>
> Or well, menuData could be handled as well, by means of Qt.binding(), I think.
>

used getProperty function

> =====
>
> BTW,
>
> 255 + text: menuData && menuData.label ? menuData.label : ""
>
> Can be simplified to:
>
> text: menuData && menuData.label || ""
>
> Only I'm not sure it's better for readability :)
> ...

Read more...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:587
http://jenkins.qa.ubuntu.com/job/unity8-ci/1880/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/1645
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/1585
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/648
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/403
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/404
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/404/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/403
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/1457
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1645
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1645/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1585
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1585/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/4099
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/2275

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1880/rebuild

review: Approve (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

On 12.12.2013 10:32, Nick Dedekind wrote:
> Eh. Indicator tests are all in the ubuntu-settings-components ported unity8 branch now.
> I'll try sort something out decoupling the tests from usc changes, but it'll be in a separate branch from this, as it's quite a significant amount of code.

Okie.

On 12.12.2013 13:21, Nick Dedekind wrote:

> used getProperty function

That changed over the course of today, I expect...

> I really don't want to put model info or impl specific stuff (actions) in a base class in this case. At least until qml supports multiple inheritance! If we do, when we move across to using ubuntu-system-components, we wont be able to reuse the components in settings as they mostly use gsetting backends. I removed it all and abstracted ALL this indicator specific impl stuff from the menu items explicitly for this purpose.
>
> So NoNoNo :)

;(

I agree that there's a lack of multi-inheritance/interfaces... A
somewhat uglier approach we used in the Dash is:

FooComponent.qml
DashBase.qml

DashFooComponent.qml:

DashBase {
   propC: component.propC
   FooComponent {
     id: component
     propA: parent.propA
     propB: parent.propB
   }
}

Obviously not great, but *I* believe still better than c&p :/

/me thinks the bindings should be doable somewhat automagically, by
looking at the children[0] maybe... Challenge accepted...

Revision history for this message
Michał Sawicz (saviq) wrote :

Afraid this is not helping:

file:///home/phablet/shell/builddir/plugins/Unity/Indicators/MenuItemFactory.qml:216: Unable to assign [undefined]
 to UnityMenuModel*
file:///home/phablet/shell/builddir/plugins/Unity/Indicators/MenuItemFactory.qml:216: Unable to assign [undefined]
 to UnityMenuModel*
file:///home/phablet/shell/builddir/plugins/Unity/Indicators/MenuItemFactory.qml:216: Unable to assign [undefined]
 to UnityMenuModel*
file:///home/phablet/shell/builddir/plugins/Unity/Indicators/MenuItemFactory.qml:216: Unable to assign [undefined]
 to UnityMenuModel*

And could reproduce the issue still.

review: Needs Fixing
Revision history for this message
Michał Sawicz (saviq) wrote :

Steps to reproduce with this code:

* wait for indicators to go unload (results in a lot of indexActive binding loops being reported)
* call the phone
* hang up the call
* open the Incoming indicator
* data sometimes not there
* rinse & repeat

review: Needs Fixing
Revision history for this message
Michał Sawicz (saviq) wrote :

I take that back, was missing fixed qmenumodel.

Warning unrelated, would be good to fix, though.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

Ooh wait, warning fix incoming!

593. By Nick Dedekind

Fixed warning for model object being assigned undefined

Revision history for this message
Michał Sawicz (saviq) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:593
http://jenkins.qa.ubuntu.com/job/unity8-ci/1884/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty/1662
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-trusty-touch/1602
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-trusty/655
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-amd64-ci/407
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/408
        deb: http://jenkins.qa.ubuntu.com/job/unity8-trusty-armhf-ci/408/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-trusty-i386-ci/407
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-trusty/1472
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1662
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-amd64/1662/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1602
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-trusty-armhf/1602/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/4113
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/2292

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/1884/rebuild

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/Unity/Indicators/Messaging/qml/MessageMenuItemFactory.qml'
2--- plugins/Unity/Indicators/Messaging/qml/MessageMenuItemFactory.qml 2013-12-11 11:45:12 +0000
3+++ plugins/Unity/Indicators/Messaging/qml/MessageMenuItemFactory.qml 2013-12-12 17:14:19 +0000
4@@ -24,13 +24,40 @@
5 import QMenuModel 0.1 as QMenuModel
6
7 Indicators.BaseMenuItem {
8- id: menuItem
9- property var actionsDescription: menu ? menu.ext.xCanonicalMessageActions : undefined
10+ id: messageFactoryItem
11+ property var menuModel: null
12+ property QtObject menuData: null
13+ property int menuIndex: -1
14+
15+ property var extendedData: menuData && menuData.ext || undefined
16+ property var actionsDescription: getExtendedProperty(extendedData, "xCanonicalMessageActions", undefined)
17+
18+ onMenuModelChanged: {
19+ loadAttributes();
20+ }
21+ onMenuIndexChanged: {
22+ loadAttributes();
23+ }
24+
25+ function loadAttributes() {
26+ if (!menuModel || menuIndex == undefined) return;
27+
28+ menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64',
29+ 'x-canonical-text': 'string',
30+ 'x-canonical-message-actions': 'variant',
31+ 'icon': 'icon',
32+ 'x-canonical-app-icon': 'icon'});
33+ }
34+
35+ function getExtendedProperty(object, propertyName, defaultValue) {
36+ if (object && object.hasOwnProperty(propertyName)) {
37+ return object[propertyName];
38+ }
39+ return defaultValue;
40+ }
41
42 implicitHeight: contents.status == Loader.Ready ? contents.item.implicitHeight : 0
43
44- property var model: null
45-
46 Loader {
47 id: contents
48 anchors.fill: parent
49@@ -41,96 +68,101 @@
50 id: simpleTextMessage
51 SimpleTextMessage {
52 // text
53- title: menu && menu.label ? menu.label : ""
54- time: menu ? menu.ext.xCanonicalTime : 0
55- message: menu && menu.ext.xCanonicalText ? menu.ext.xCanonicalText : ""
56+ title: menuData && menuData.label || ""
57+ time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
58+ message: getExtendedProperty(extendedData, "xCanonicalText", "")
59 // icons
60- avatar: menu && menu.ext.icon !== undefined ? menu.ext.icon : "qrc:/indicators/artwork/messaging/default_contact.png"
61- appIcon: menu && menu.ext.xCanonicalAppIcon !== undefined ? menu.ext.xCanonicalAppIcon : "qrc:/indicators/artwork/messaging/default_app.svg"
62+ avatar: getExtendedProperty(extendedData, "icon", "qrc:/indicators/artwork/messaging/default_contact.png")
63+ appIcon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "qrc:/indicators/artwork/messaging/default_app.svg")
64
65 onActivateApp: {
66- menuItem.model.activate(modelIndex, true);
67+ menuModel.activate(menuIndex, true);
68 shell.hideIndicatorMenu(UbuntuAnimation.FastDuration);
69 }
70 onDismiss: {
71- menuItem.model.activate(modelIndex, false);
72+ menuModel.activate(menuIndex, false);
73 }
74
75- menuSelected: menuItem.menuSelected
76- onSelectMenu: menuItem.selectMenu()
77- onDeselectMenu: menuItem.deselectMenu()
78+ menuSelected: messageFactoryItem.menuSelected
79+ onSelectMenu: messageFactoryItem.selectMenu()
80+ onDeselectMenu: messageFactoryItem.deselectMenu()
81 }
82 }
83 Component {
84 id: textMessage
85 TextMessage {
86+ property var replyActionDescription: actionsDescription && actionsDescription.length > 0 ? actionsDescription[0] : undefined
87+
88 property var replyAction: QMenuModel.UnityMenuAction {
89- model: menuItem.model
90- index: modelIndex
91- name: menu && actionsDescription[0].name ? actionsDescription[0].name : ""
92+ model: menuModel
93+ index: menuIndex
94+ name: getExtendedProperty(replyActionDescription, "name", "")
95 }
96
97 // text
98- title: menu && menu.label ? menu.label : ""
99- time: menu ? menu.ext.xCanonicalTime : 0
100- message: menu && menu.ext.xCanonicalText ? menu.ext.xCanonicalText : ""
101- replyButtonText: actionsDescription && actionsDescription[0].label ? actionsDescription[0].label : "Send"
102+ title: menuData && menuData.label || ""
103+ time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
104+ message: getExtendedProperty(extendedData, "xCanonicalText", "")
105+ replyButtonText: getExtendedProperty(replyActionDescription, "label", "Send")
106 // icons
107- avatar: menu && menu.ext.icon !== undefined ? menu.ext.icon : "qrc:/indicators/artwork/messaging/default_contact.png"
108- appIcon: menu && menu.ext.xCanonicalAppIcon !== undefined ? menu.ext.xCanonicalAppIcon : "qrc:/indicators/artwork/messaging/default_app.svg"
109+ avatar: getExtendedProperty(extendedData, "icon", "qrc:/indicators/artwork/messaging/default_contact.png")
110+ appIcon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "qrc:/indicators/artwork/messaging/default_app.svg")
111 // actions
112 replyEnabled: replyAction.valid && replyAction.enabled
113
114 onActivateApp: {
115- menuItem.model.activate(modelIndex, true);
116+ menuModel.activate(menuIndex, true);
117 shell.hideIndicatorMenu(UbuntuAnimation.FastDuration);
118 }
119 onDismiss: {
120- menuItem.model.activate(modelIndex, false);
121+ menuModel.activate(menuIndex, false);
122 }
123 onReply: {
124 replyAction.activate(value);
125 }
126
127- menuSelected: menuItem.menuSelected
128- onSelectMenu: menuItem.selectMenu()
129- onDeselectMenu: menuItem.deselectMenu()
130+ menuSelected: messageFactoryItem.menuSelected
131+ onSelectMenu: messageFactoryItem.selectMenu()
132+ onDeselectMenu: messageFactoryItem.deselectMenu()
133 }
134 }
135 Component {
136 id: snapDecision
137 SnapDecision {
138+ property var activateActionDescription: actionsDescription && actionsDescription.length > 0 ? actionsDescription[0] : undefined
139+ property var replyActionDescription: actionsDescription && actionsDescription.length > 1 ? actionsDescription[1] : undefined
140+
141 property var activateAction: QMenuModel.UnityMenuAction {
142- model: menuItem.model
143- index: modelIndex
144- name: menu && actionsDescription[0].name ? actionsDescription[0].name : ""
145+ model: menuModel
146+ index: menuIndex
147+ name: getExtendedProperty(activateActionDescription, "name", "")
148 }
149 property var replyAction: QMenuModel.UnityMenuAction {
150- model: menuItem.model
151- index: modelIndex
152- name: menu && actionsDescription[1].name ? actionsDescription[1].name : ""
153+ model: menuModel
154+ index: menuIndex
155+ name: getExtendedProperty(replyActionDescription, "name", "")
156 }
157
158 // text
159- title: menu && menu.label ? menu.label : ""
160- time: menu ? menu.ext.xCanonicalTime : ""
161- message: menu && menu.ext.xCanonicalText ? menu.ext.xCanonicalText : ""
162- actionButtonText: actionsDescription && actionsDescription[0].label ? actionsDescription[0].label : "Call back"
163- replyButtonText: actionsDescription && actionsDescription[1].label ? actionsDescription[1].label : "Send"
164- replyMessages: actionsDescription && actionsDescription[1]["parameter-hint"] ? actionsDescription[1]["parameter-hint"] : ""
165+ title: menuData && menuData.label || ""
166+ time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
167+ message: getExtendedProperty(extendedData, "xCanonicalText", "")
168+ actionButtonText: getExtendedProperty(activateActionDescription, "label", "Call back")
169+ replyButtonText: getExtendedProperty(replyActionDescription, "label", "Send")
170+ replyMessages: getExtendedProperty(replyActionDescription, "parameter-hint", "")
171 // icons
172- avatar: menu && menu.ext.icon !== undefined ? menu.ext.icon : "qrc:/indicators/artwork/messaging/default_contact.png"
173- appIcon: menu && menu.ext.xCanonicalAppIcon !== undefined ? menu.ext.xCanonicalAppIcon : "qrc:/indicators/artwork/messaging/default_app.svg"
174+ avatar: getExtendedProperty(extendedData, "icon", "qrc:/indicators/artwork/messaging/default_contact.png")
175+ appIcon: getExtendedProperty(extendedData, "xCanonicalAppIcon", "qrc:/indicators/artwork/messaging/default_app.svg")
176 // actions
177 activateEnabled: activateAction.valid && activateAction.enabled
178 replyEnabled: replyAction.valid && replyAction.enabled
179
180 onActivateApp: {
181- menuItem.model.activate(modelIndex, true);
182+ menuModel.activate(menuIndex, true);
183 shell.hideIndicatorMenu(UbuntuAnimation.FastDuration);
184 }
185 onDismiss: {
186- menuItem.model.activate(modelIndex, false);
187+ menuModel.activate(menuIndex, false);
188 }
189 onActivate: {
190 activateAction.activate();
191@@ -139,9 +171,9 @@
192 replyAction.activate(value);
193 }
194
195- menuSelected: menuItem.menuSelected
196- onSelectMenu: menuItem.selectMenu()
197- onDeselectMenu: menuItem.deselectMenu()
198+ menuSelected: messageFactoryItem.menuSelected
199+ onSelectMenu: messageFactoryItem.selectMenu()
200+ onDeselectMenu: messageFactoryItem.deselectMenu()
201 }
202 }
203 }
204
205=== modified file 'plugins/Unity/Indicators/qml/IndicatorPage.qml'
206--- plugins/Unity/Indicators/qml/IndicatorPage.qml 2013-11-20 10:37:30 +0000
207+++ plugins/Unity/Indicators/qml/IndicatorPage.qml 2013-12-12 17:14:19 +0000
208@@ -144,9 +144,11 @@
209 item.selectMenu.connect(function() { mainMenu.selectedIndex = index; });
210 item.deselectMenu.connect(function() { mainMenu.selectedIndex = -1; });
211 }
212-
213- if (item.hasOwnProperty("menu")) {
214- item.menu = Qt.binding(function() { return model; });
215+ if (item.hasOwnProperty("menuData")) {
216+ item.menuData = Qt.binding(function() { return model; });
217+ }
218+ if (item.hasOwnProperty("menuIndex")) {
219+ item.menuIndex = Qt.binding(function() { return modelIndex; });
220 }
221 }
222
223@@ -172,7 +174,7 @@
224
225 MenuItemFactory {
226 id: factory
227- model: mainMenu.model
228+ menuModel: mainMenu.model ? mainMenu.model : null
229 }
230
231 Components.Label {
232
233=== modified file 'plugins/Unity/Indicators/qml/MenuItemFactory.qml'
234--- plugins/Unity/Indicators/qml/MenuItemFactory.qml 2013-10-28 22:09:26 +0000
235+++ plugins/Unity/Indicators/qml/MenuItemFactory.qml 2013-12-12 17:14:19 +0000
236@@ -27,7 +27,7 @@
237 Item {
238 id: menuFactory
239
240- property var model: null
241+ property var menuModel: null
242
243 property var _map: {
244 "unity.widgets.systemsettings.tablet.volumecontrol" : sliderMenu,
245@@ -50,38 +50,55 @@
246 "unity.widgets.systemsettings.tablet.accesspoint" : accessPoint,
247 }
248
249+ function getExtendedProperty(object, propertyName, defaultValue) {
250+ if (object && object.hasOwnProperty(propertyName)) {
251+ return object[propertyName];
252+ }
253+ return defaultValue;
254+ }
255+
256 Component { id: divMenu; Indicators.DivMenuItem {} }
257
258 Component {
259 id: sliderMenu;
260 Indicators.SliderMenuItem {
261- property QtObject menu: null
262-
263- text: menu && menu.label ? menu.label : ""
264- icon: menu && menu.icon ? menu.icon : ""
265- minIcon: menu && menu.ext.minIcon ? menu.ext.minIcon : ""
266- maxIcon: menu && menu.ext.maxIcon ? menu.ext.maxIcon : ""
267-
268- minimumValue: menu.ext.minValue ? menu.ext.minValue : 0.0
269+ property QtObject menuData: null
270+ property var menuModel: menuFactory.menuModel
271+ property int menuIndex: -1
272+ property var extendedData: menuData && menuData.ext || undefined
273+
274+ text: menuData && menuData.label || ""
275+ iconSource: menuData && menuData.icon || ""
276+ minIcon: getExtendedProperty(extendedData, "minIcon", "")
277+ maxIcon: getExtendedProperty(extendedData, "maxIcon", "")
278+
279+ minimumValue: getExtendedProperty(extendedData, "minValue", 0.0)
280 maximumValue: {
281- var maximum = menu.ext.maxValue ? menu.ext.maxValue : 1.0
282+ var maximum = getExtendedProperty(extendedData, "maxValue", 1.0);
283 if (maximum <= minimumValue) {
284 return minimumValue + 1;
285 }
286 return maximum;
287 }
288- value: menu ? menu.actionState : 0.0
289- enabled: menu ? menu.sensitive : false
290-
291- Component.onCompleted: {
292- model.loadExtendedAttributes(modelIndex, {'min-value': 'double',
293- 'max-value': 'double',
294- 'min-icon': 'icon',
295- 'max-icon': 'icon'});
296- }
297-
298+ value: menuData && menuData.actionState || 0.0
299+ enabled: menuData && menuData.sensitive || false
300+
301+ onMenuModelChanged: {
302+ loadAttributes();
303+ }
304+ onMenuIndexChanged: {
305+ loadAttributes();
306+ }
307 onChangeState: {
308- model.changeState(modelIndex, value);
309+ menuModel.changeState(menuIndex, value);
310+ }
311+
312+ function loadAttributes() {
313+ if (!menuModel || menuIndex == undefined) return;
314+ menuModel.loadExtendedAttributes(menuIndex, {'min-value': 'double',
315+ 'max-value': 'double',
316+ 'min-icon': 'icon',
317+ 'max-icon': 'icon'});
318 }
319 }
320 }
321@@ -89,13 +106,15 @@
322 Component {
323 id: buttonMenu;
324 Indicators.ButtonMenuItem {
325- property QtObject menu: null
326+ property QtObject menuData: null
327+ property var menuModel: menuFactory.menuModel
328+ property int menuIndex: -1
329
330- text: menu && menu.label ? menu.label : ""
331- enabled: menu ? menu.sensitive : false
332+ text: menuData && menuData.label || ""
333+ enabled: menuData && menuData.sensitive || false
334
335 onActivate: {
336- model.activate(modelIndex);
337+ menuModel.activate(menuIndex);
338 shell.hideIndicatorMenu(UbuntuAnimation.FastDuration);
339 }
340 }
341@@ -103,37 +122,40 @@
342 Component {
343 id: sectionMenu;
344 Indicators.SectionMenuItem {
345- property QtObject menu: null
346+ property QtObject menuData: null
347+ property var menuIndex: undefined
348
349- text: menu && menu.label ? menu.label : ""
350+ text: menuData && menuData.label || ""
351 }
352 }
353
354 Component {
355 id: progressMenu;
356 Indicators.ProgressMenuItem {
357- property QtObject menu: null
358+ property QtObject menuData: null
359+ property int menuIndex: -1
360
361- text: menu && menu.label ? menu.label : ""
362- icon: menu ? menu.icon : ""
363- value : menu ? menu.actionState : 0.0
364- enabled: menu ? menu.sensitive : false
365+ text: menuData && menuData.label || ""
366+ iconSource: menuData && menuData.icon || ""
367+ value : menuData && menuData.actionState || 0.0
368+ enabled: menuData && menuData.sensitive || false
369 }
370 }
371
372 Component {
373 id: standardMenu;
374 Indicators.StandardMenuItem {
375- property QtObject menu: null
376+ property QtObject menuData: null
377+ property int menuIndex: -1
378
379- text: menu && menu.label ? menu.label : ""
380- icon: menu && menu.icon ? menu.icon : ""
381- checkable: menu ? (menu.isCheck || menu.isRadio) : false
382- checked: checkable ? menu.isToggled : false
383- enabled: menu ? menu.sensitive : false
384+ text: menuData && menuData.label || ""
385+ iconSource: menuData && menuData.icon || ""
386+ enabled: menuData && menuData.sensitive || false
387+ checkable: menuData ? (menuData.isCheck || menuData.isRadio) : false
388+ checked: checkable ? menuData.isToggled : false
389
390 onActivate: {
391- model.activate(modelIndex);
392+ menuModel.activate(menuIndex);
393 shell.hideIndicatorMenu(UbuntuAnimation.BriskDuration);
394 }
395 }
396@@ -142,15 +164,16 @@
397 Component {
398 id: switchMenu;
399 Indicators.SwitchMenuItem {
400- property QtObject menu: null
401+ property QtObject menuData: null
402+ property int menuIndex: -1
403
404- text: menu && menu.label ? menu.label : ""
405- icon: menu && menu.icon ? menu.icon : ""
406- checked: menu ? menu.isToggled : false
407- enabled: menu ? menu.sensitive : false
408+ text: menuData && menuData.label || ""
409+ iconSource: menuData && menuData.icon || ""
410+ enabled: menuData && menuData.sensitive || false
411+ checked: menuData ? menuData.isToggled : false
412
413 onActivate: {
414- model.activate(modelIndex);
415+ menuModel.activate(menuIndex);
416 shell.hideIndicatorMenu(UbuntuAnimation.BriskDuration);
417 }
418 }
419@@ -159,13 +182,24 @@
420 Component {
421 id: wifiSection;
422 Indicators.SectionMenuItem {
423- property QtObject menu: null
424-
425- text: menu && menu.label ? menu.label : ""
426- busy: menu ? menu.ext.xCanonicalBusyAction : false
427-
428- Component.onCompleted: {
429- model.loadExtendedAttributes(modelIndex, {'x-canonical-busy-action': 'bool'});
430+ property QtObject menuData: null
431+ property var menuModel: menuFactory.menuModel
432+ property int menuIndex: -1
433+ property var extendedData: menuData && menuData.ext || undefined
434+
435+ text: menuData && menuData.label || ""
436+ busy: getExtendedProperty(extendedData, "xCanonicalBusyAction", false)
437+
438+ onMenuModelChanged: {
439+ loadAttributes();
440+ }
441+ onMenuIndexChanged: {
442+ loadAttributes();
443+ }
444+
445+ function loadAttributes() {
446+ if (!menuModel || menuIndex == undefined) return;
447+ menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-busy-action': 'bool'})
448 }
449 }
450 }
451@@ -173,67 +207,81 @@
452 Component {
453 id: accessPoint;
454 ICNetwork.AccessPoint {
455- property QtObject menu: null
456+ property QtObject menuData: null
457+ property var menuModel: menuFactory.menuModel
458+ property int menuIndex: -1
459+ property var extendedData: menuData && menuData.ext || undefined
460+
461 property var strengthAction: QMenuModel.UnityMenuAction {
462- model: menuFactory.model ? menuFactory.model : null
463- index: modelIndex
464- name: menu ? menu.ext.xCanonicalWifiApStrengthAction : ""
465+ model: menuModel
466+ index: menuIndex
467+ name: getExtendedProperty(extendedData, "xCanonicalWifiApStrengthAction", "")
468 }
469
470- text: menu && menu.label ? menu.label : ""
471- secure: menu ? menu.ext.xCanonicalWifiApIsSecure : false
472- adHoc: menu ? menu.ext.xCanonicalWifiApIsAdhoc : false
473- checked: menu ? menu.isToggled : false
474+ text: menuData && menuData.label || ""
475+ enabled: menuData && menuData.sensitive || false
476+ secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
477+ adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
478+ checked: menuData ? menuData.isToggled : false
479 signalStrength: strengthAction.valid ? strengthAction.state : 0
480- enabled: menu ? menu.sensitive : false
481
482- Component.onCompleted: {
483- model.loadExtendedAttributes(modelIndex, {'x-canonical-wifi-ap-is-adhoc': 'bool',
484- 'x-canonical-wifi-ap-is-secure': 'bool',
485- 'x-canonical-wifi-ap-strength-action': 'string'});
486+ onMenuModelChanged: {
487+ loadAttributes();
488+ }
489+ onMenuIndexChanged: {
490+ loadAttributes();
491 }
492 onActivate: {
493- model.activate(modelIndex);
494+ menuModel.activate(menuIndex);
495 shell.hideIndicatorMenu(UbuntuAnimation.BriskDuration);
496 }
497+
498+ function loadAttributes() {
499+ if (!menuModel || menuIndex == undefined) return;
500+ menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-wifi-ap-is-adhoc': 'bool',
501+ 'x-canonical-wifi-ap-is-secure': 'bool',
502+ 'x-canonical-wifi-ap-strength-action': 'string'});
503+ }
504 }
505 }
506
507 Component {
508 id: messageItem
509 ICMessaging.MessageMenuItemFactory {
510-
511- property QtObject menu: null
512- model: menuFactory.model ? menuFactory.model : null
513-
514- Component.onCompleted: {
515- model.loadExtendedAttributes(modelIndex, {'x-canonical-time': 'int64',
516- 'x-canonical-text': 'string',
517- 'x-canonical-message-actions': 'variant',
518- 'icon': 'icon',
519- 'x-canonical-app-icon': 'icon'});
520- }
521+ menuModel: menuFactory.menuModel
522 }
523 }
524
525 Component {
526 id: groupedMessage
527 ICMessaging.GroupedMessage {
528- property QtObject menu: null
529-
530- title: menu && menu.label ? menu.label : ""
531- count: menu && menu.actionState[0] ? menu.actionState[0] : "0"
532- appIcon: menu && menu.ext.icon !== undefined ? menu.ext.icon : "qrc:/indicators/artwork/messaging/default_app.svg"
533-
534- Component.onCompleted: {
535- model.loadExtendedAttributes(modelIndex, {'icon': 'icon'});
536+ property QtObject menuData: null
537+ property var menuModel: menuFactory.menuModel
538+ property int menuIndex: -1
539+ property var extendedData: menuData && menuData.ext || undefined
540+
541+ title: menuData && menuData.label || ""
542+ appIcon: getExtendedProperty(extendedData, "icon", "qrc:/indicators/artwork/messaging/default_app.svg")
543+ count: menuData && menuData.actionState.length > 0 ? menuData.actionState[0] : "0"
544+ enabled: menuData && menuData.sensitive || false
545+
546+ onMenuModelChanged: {
547+ loadAttributes();
548+ }
549+ onMenuIndexChanged: {
550+ loadAttributes();
551 }
552 onActivateApp: {
553- model.activate(modelIndex, true);
554+ menuModel.activate(menuIndex, true);
555 shell.hideIndicatorMenu(UbuntuAnimation.FastDuration);
556 }
557 onDismiss: {
558- model.activate(modelIndex, false);
559+ menuModel.activate(menuIndex, false);
560+ }
561+
562+ function loadAttributes() {
563+ if (!menuModel || menuIndex == undefined) return;
564+ menuModel.loadExtendedAttributes(modelIndex, {'icon': 'icon'});
565 }
566 }
567 }
568@@ -244,10 +292,9 @@
569 if (component !== undefined) {
570 return component;
571 }
572- } else {
573- if (modelData.isSeparator) {
574- return divMenu;
575- }
576+ }
577+ if (modelData.isSeparator) {
578+ return divMenu;
579 }
580 return standardMenu;
581 }

Subscribers

People subscribed via source and target branches