@@ -66,11 +66,6 @@ Item {
6666 onPressed: d.dismissAll()
6767 }
6868
69− Rectangle {
70− anchors.fill: row
71− color: Qt.rgba(1,0,0,0.4)
72− }
73−
7469 Row {
7570 id: row
7671 spacing: units.gu(2)
@@ -82,9 +77,17 @@ Item {
8277 active: !d.currentItem && enableKeyFilter
8378 }
8479
80+ Connections {
81+ target: root.unityMenuModel
82+ onModelReset: d.firstInvisibleIndex = undefined
83+ }
84+
8585 Repeater {
8686 id: rowRepeater
8787
88+ onItemAdded: d.recalcFirstInvisibleIndexAdded(index, item)
89+ onCountChanged: d.recalcFirstInvisibleIndex()
90+
8891 Item {
8992 id: visualItem
9093 objectName: root.objectName + "-item" + __ownIndex
@@ -92,8 +95,8 @@ Item {
9295 readonly property int __ownIndex: index
9396 property Item __popup: null;
9497 property bool popupVisible: __popup && __popup.visible
95− property bool shouldDisplay: x + width + ((index < rowRepeater.count-1) ? units.gu(1) : 0) <
96− (root.overflowWidth - (overflowButton.visible ? overflowButton.width : 0))
98+ property bool shouldDisplay: x + width + ((__ownIndex < rowRepeater.count-1) ? units.gu(2) : 0) <
99+ root.overflowWidth - ((__ownIndex < rowRepeater.count-1) ? overflowButton.width : 0)
97100
98101 implicitWidth: column.implicitWidth
99102 implicitHeight: row.height
@@ -129,6 +132,18 @@ Item {
129132 }
130133 }
131134
135+ onVisibleChanged: {
136+ if (!visible && __popup) dismiss();
137+ }
138+
139+ Component.onCompleted: {
140+ shouldDisplayChanged.connect(function() {
141+ if ((!shouldDisplay && d.firstInvisibleIndex == undefined) || __ownIndex <= d.firstInvisibleIndex) {
142+ d.recalcFirstInvisibleIndex();
143+ }
144+ });
145+ }
146+
132147 Connections {
133148 target: d
134149 onDismissAll: visualItem.dismiss()
@@ -167,6 +182,7 @@ Item {
167182 height: _title.height
168183
169184 action: Action {
185+ enabled: visualItem.enabled
170186 // FIXME - SDK Action:text modifies menu text with html underline for mnemonic
171187 text: model.label.replace("_", "&").replace("<u>", "&").replace("</u>", "")
172188
@@ -187,23 +203,6 @@ Item {
187203 } // Repeater
188204 } // Row
189205
190− MouseArea {
191− id: overflowButton
192− visible: root.implicitWidth > root.width
193− height: parent.height
194− width: units.gu(4)
195− anchors.right: parent.right
196−
197− Icon {
198− id: icon
199− width: units.gu(2)
200− height: units.gu(2)
201− anchors.centerIn: parent
202− color: theme.palette.normal.overlayText
203− name: "toolkit_chevron-down_2gu"
204− }
205− }
206−
207206 MouseArea {
208207 anchors.fill: parent
209208 hoverEnabled: d.currentItem
@@ -226,12 +225,109 @@ Item {
226225 if (!d.hoveredItem || !d.currentItem || !d.hoveredItem.contains(Qt.point(pos.x - d.currentItem.x, pos.y - d.currentItem.y))) {
227226 d.hoveredItem = row.childAt(pos.x, pos.y);
228227 if (!d.hoveredItem || !d.hoveredItem.enabled)
229− return false;
228+ return;
230229 if (d.currentItem != d.hoveredItem) {
231230 d.currentItem = d.hoveredItem;
232231 }
233232 }
234− return true;
233+ }
234+ }
235+
236+ MouseArea {
237+ id: overflowButton
238+ objectName: "overflow"
239+
240+ hoverEnabled: d.currentItem
241+ onEntered: d.currentItem = this
242+ onPositionChanged: d.currentItem = this
243+ onClicked: d.currentItem = this
244+
245+ property Item __popup: null;
246+ property bool popupVisible: __popup && __popup.visible
247+ property Item firstInvisibleItem: d.firstInvisibleIndex !== undefined ? rowRepeater.itemAt(d.firstInvisibleIndex) : null
248+
249+ visible: d.firstInvisibleIndex != undefined
250+ x: firstInvisibleItem ? firstInvisibleItem.x : 0
251+
252+ height: parent.height
253+ width: units.gu(4)
254+
255+ onVisibleChanged: {
256+ if (!visible && __popup) dismiss();
257+ }
258+
259+ Icon {
260+ id: icon
261+ width: units.gu(2)
262+ height: units.gu(2)
263+ anchors.centerIn: parent
264+ color: theme.palette.normal.overlayText
265+ name: "toolkit_chevron-down_2gu"
266+ }
267+
268+ function show() {
269+ if (!__popup) {
270+ __popup = overflowComponent.createObject(root, { objectName: overflowButton.objectName + "-menu" });
271+ // force the current item to be the newly popped up menu
272+ } else {
273+ __popup.show();
274+ }
275+ d.currentItem = overflowButton;
276+ }
277+ function hide() {
278+ if (__popup) {
279+ __popup.hide();
280+
281+ if (d.currentItem === overflowButton) {
282+ d.currentItem = null;
283+ }
284+ }
285+ }
286+ function dismiss() {
287+ if (__popup) {
288+ __popup.destroy();
289+ __popup = null;
290+
291+ if (d.currentItem === overflowButton) {
292+ d.currentItem = null;
293+ }
294+ }
295+ }
296+
297+ Connections {
298+ target: d
299+ onDismissAll: overflowButton.dismiss()
300+ }
301+
302+ Component {
303+ id: overflowComponent
304+ MenuPopup {
305+ id: overflowPopup
306+ x: overflowButton.x - units.gu(1)
307+ anchors.top: parent.bottom
308+ unityMenuModel: overflowModel
309+
310+ ExpressionFilterModel {
311+ id: overflowModel
312+ sourceModel: root.unityMenuModel
313+ matchExpression: function(index) {
314+ if (d.firstInvisibleIndex === undefined) return false;
315+ return index >= d.firstInvisibleIndex;
316+ }
317+
318+ function submenu(index) {
319+ return sourceModel.submenu(mapRowToSource(index));
320+ }
321+ function activate(index) {
322+ return sourceModel.activate(mapRowToSource(index));
323+ }
324+ }
325+
326+ Connections {
327+ target: d
328+ onFirstInvisibleIndexChanged: overflowModel.invalidate()
329+ }
330+ }
235331 }
236332 }
237333
@@ -251,18 +347,43 @@ Item {
251347 id: d
252348 objectName: "d"
253349 itemView: rowRepeater
350+ hasOverflow: overflowButton.visible
254351
255352 property Item currentItem: null
256353 property Item hoveredItem: null
257354 property Item prevCurrentItem: null
258−
259− readonly property int currentIndex: currentItem ? currentItem.__ownIndex : -1
260−
261355 property bool altPressed: false
262356 property bool longAltPressed: false
357+ property var firstInvisibleIndex: undefined
358+
359+ readonly property int currentIndex: currentItem && currentItem.hasOwnProperty("__ownIndex") ? currentItem.__ownIndex : -1
263360
264361 signal dismissAll()
265362
363+ function recalcFirstInvisibleIndexAdded(index, item) {
364+ if (firstInvisibleIndex === undefined) {
365+ if (!item.shouldDisplay) {
366+ firstInvisibleIndex = index;
367+ }
368+ } else if (index <= firstInvisibleIndex) {
369+ if (!item.shouldDisplay) {
370+ firstInvisibleIndex = index;
371+ } else {
372+ firstInvisibleIndex++;
373+ }
374+ }
375+ }
376+
377+ function recalcFirstInvisibleIndex() {
378+ for (var i = 0; i < rowRepeater.count; i++) {
379+ if (!rowRepeater.itemAt(i).shouldDisplay) {
380+ firstInvisibleIndex = i;
381+ return;
382+ }
383+ }
384+ firstInvisibleIndex = undefined;
385+ }
386+
266387 onSelect: {
267388 var delegate = rowRepeater.itemAt(index);
268389 if (delegate) {
@@ -270,6 +391,10 @@ Item {
270391 }
271392 }
272393
394+ onOverflow: {
395+ d.currentItem = overflowButton;
396+ }
397+
273398 onCurrentItemChanged: {
274399 if (prevCurrentItem && prevCurrentItem != currentItem) {
275400 if (currentItem) {