@@ -66,11 +66,6 @@ Item {
66 onPressed: d.dismissAll()
66 onPressed: d.dismissAll()
71− color: Qt.rgba(1,0,0,0.4)
76 spacing: units.gu(2)
71 spacing: units.gu(2)
@@ -82,9 +77,17 @@ Item {
82 active: !d.currentItem && enableKeyFilter
77 active: !d.currentItem && enableKeyFilter
81+ target: root.unityMenuModel
82+ onModelReset: d.firstInvisibleIndex = undefined
85 Repeater {
85 Repeater {
86 id: rowRepeater
86 id: rowRepeater
88+ onItemAdded: d.recalcFirstInvisibleIndexAdded(index, item)
89+ onCountChanged: d.recalcFirstInvisibleIndex()
89 id: visualItem
92 id: visualItem
90 objectName: root.objectName + "-item" + __ownIndex
93 objectName: root.objectName + "-item" + __ownIndex
@@ -92,8 +95,8 @@ Item {
92 readonly property int __ownIndex: index
95 readonly property int __ownIndex: index
93 property Item __popup: null;
96 property Item __popup: null;
94 property bool popupVisible: __popup && __popup.visible
97 property bool popupVisible: __popup && __popup.visible
95− property bool shouldDisplay: x + width + ((index < rowRepeater.count-1) ? units.gu(1) : 0) <
98+ property bool shouldDisplay: x + width + ((__ownIndex < rowRepeater.count-1) ? units.gu(2) : 0) <
96− (root.overflowWidth - (overflowButton.visible ? overflowButton.width : 0))
99+ root.overflowWidth - ((__ownIndex < rowRepeater.count-1) ? overflowButton.width : 0)
98 implicitWidth: column.implicitWidth
101 implicitWidth: column.implicitWidth
99 implicitHeight: row.height
102 implicitHeight: row.height
@@ -129,6 +132,18 @@ Item {
136+ if (!visible && __popup) dismiss();
139+ Component.onCompleted: {
140+ shouldDisplayChanged.connect(function() {
141+ if ((!shouldDisplay && d.firstInvisibleIndex == undefined) || __ownIndex <= d.firstInvisibleIndex) {
142+ d.recalcFirstInvisibleIndex();
132 Connections {
147 Connections {
133 target: d
148 target: d
134 onDismissAll: visualItem.dismiss()
149 onDismissAll: visualItem.dismiss()
@@ -167,6 +182,7 @@ Item {
167 height: _title.height
182 height: _title.height
169 action: Action {
184 action: Action {
185+ enabled: visualItem.enabled
170 // FIXME - SDK Action:text modifies menu text with html underline for mnemonic
186 // FIXME - SDK Action:text modifies menu text with html underline for mnemonic
171 text: model.label.replace("_", "&").replace("<u>", "&").replace("</u>", "")
187 text: model.label.replace("_", "&").replace("<u>", "&").replace("</u>", "")
@@ -187,23 +203,6 @@ Item {
187 } // Repeater
203 } // Repeater
192− visible: root.implicitWidth > root.width
193− height: parent.height
195− anchors.right: parent.right
201− anchors.centerIn: parent
202− color: theme.palette.normal.overlayText
203− name: "toolkit_chevron-down_2gu"
207 MouseArea {
206 MouseArea {
208 anchors.fill: parent
207 anchors.fill: parent
209 hoverEnabled: d.currentItem
208 hoverEnabled: d.currentItem
@@ -226,12 +225,109 @@ Item {
226 if (!d.hoveredItem || !d.currentItem || !d.hoveredItem.contains(Qt.point(pos.x - d.currentItem.x, pos.y - d.currentItem.y))) {
225 if (!d.hoveredItem || !d.currentItem || !d.hoveredItem.contains(Qt.point(pos.x - d.currentItem.x, pos.y - d.currentItem.y))) {
227 d.hoveredItem = row.childAt(pos.x, pos.y);
226 d.hoveredItem = row.childAt(pos.x, pos.y);
228 if (!d.hoveredItem || !d.hoveredItem.enabled)
227 if (!d.hoveredItem || !d.hoveredItem.enabled)
229− return false;
228+ return;
230 if (d.currentItem != d.hoveredItem) {
229 if (d.currentItem != d.hoveredItem) {
231 d.currentItem = d.hoveredItem;
230 d.currentItem = d.hoveredItem;
238+ objectName: "overflow"
240+ hoverEnabled: d.currentItem
241+ onEntered: d.currentItem = this
242+ onPositionChanged: d.currentItem = this
243+ onClicked: d.currentItem = this
245+ property Item __popup: null;
246+ property bool popupVisible: __popup && __popup.visible
247+ property Item firstInvisibleItem: d.firstInvisibleIndex !== undefined ? rowRepeater.itemAt(d.firstInvisibleIndex) : null
249+ visible: d.firstInvisibleIndex != undefined
250+ x: firstInvisibleItem ? firstInvisibleItem.x : 0
252+ height: parent.height
256+ if (!visible && __popup) dismiss();
263+ anchors.centerIn: parent
264+ color: theme.palette.normal.overlayText
265+ name: "toolkit_chevron-down_2gu"
270+ __popup = overflowComponent.createObject(root, { objectName: overflowButton.objectName + "-menu" });
271+ // force the current item to be the newly popped up menu
275+ d.currentItem = overflowButton;
281+ if (d.currentItem === overflowButton) {
282+ d.currentItem = null;
286+ function dismiss() {
291+ if (d.currentItem === overflowButton) {
292+ d.currentItem = null;
299+ onDismissAll: overflowButton.dismiss()
303+ id: overflowComponent
306+ x: overflowButton.x - units.gu(1)
307+ anchors.top: parent.bottom
308+ unityMenuModel: overflowModel
310+ ExpressionFilterModel {
312+ sourceModel: root.unityMenuModel
313+ matchExpression: function(index) {
314+ if (d.firstInvisibleIndex === undefined) return false;
315+ return index >= d.firstInvisibleIndex;
318+ function submenu(index) {
319+ return sourceModel.submenu(mapRowToSource(index));
321+ function activate(index) {
322+ return sourceModel.activate(mapRowToSource(index));
328+ onFirstInvisibleIndexChanged: overflowModel.invalidate()
@@ -251,18 +347,43 @@ Item {
252 objectName: "d"
348 objectName: "d"
253 itemView: rowRepeater
349 itemView: rowRepeater
350+ hasOverflow: overflowButton.visible
255 property Item currentItem: null
352 property Item currentItem: null
256 property Item hoveredItem: null
353 property Item hoveredItem: null
257 property Item prevCurrentItem: null
354 property Item prevCurrentItem: null
259− readonly property int currentIndex: currentItem ? currentItem.__ownIndex : -1
261 property bool altPressed: false
355 property bool altPressed: false
262 property bool longAltPressed: false
356 property bool longAltPressed: false
357+ property var firstInvisibleIndex: undefined
359+ readonly property int currentIndex: currentItem && currentItem.hasOwnProperty("__ownIndex") ? currentItem.__ownIndex : -1
264 signal dismissAll()
361 signal dismissAll()
363+ function recalcFirstInvisibleIndexAdded(index, item) {
364+ if (firstInvisibleIndex === undefined) {
365+ if (!item.shouldDisplay) {
366+ firstInvisibleIndex = index;
368+ } else if (index <= firstInvisibleIndex) {
369+ if (!item.shouldDisplay) {
370+ firstInvisibleIndex = index;
372+ firstInvisibleIndex++;
377+ function recalcFirstInvisibleIndex() {
378+ for (var i = 0; i < rowRepeater.count; i++) {
379+ if (!rowRepeater.itemAt(i).shouldDisplay) {
380+ firstInvisibleIndex = i;
384+ firstInvisibleIndex = undefined;
266 onSelect: {
387 onSelect: {
267 var delegate = rowRepeater.itemAt(index);
388 var delegate = rowRepeater.itemAt(index);
268 if (delegate) {
389 if (delegate) {
@@ -270,6 +391,10 @@ Item {
395+ d.currentItem = overflowButton;
273 onCurrentItemChanged: {
398 onCurrentItemChanged: {
274 if (prevCurrentItem && prevCurrentItem != currentItem) {
399 if (prevCurrentItem && prevCurrentItem != currentItem) {
275 if (currentItem) {
400 if (currentItem) {